package excel

import (
	"eta/eta_chart_lib/models"
	"eta/eta_chart_lib/utils"
	"strconv"
	"strings"
	"time"
)

// HandleRuleToTableCell 根据管理规则渲染单元格数据
func HandleRuleToTableCell(excelInfoId int, oldTableData TableData) (newTableData TableData, err error) {
	newTableData = oldTableData
	excelRuleMappingList, err := models.GetExcelRuleMappingByExcelInfoId(excelInfoId)
	if err != nil {
		return
	}
	if len(excelRuleMappingList) == 0 {
		return
	}
	tableDataList := oldTableData.TableDataList
	excelRuleMap := make(map[int]*models.ExcelInfoRuleMappingView)
	for _, v := range excelRuleMappingList {
		excelRuleMap[v.ExcelInfoRuleMappingId] = v
	}
	ruleScopeMap := generateRuleScopeIndexMap(excelRuleMappingList)
	for row, scopeValues := range ruleScopeMap {
		for col, ruleId := range scopeValues {
			if v, ok := excelRuleMap[ruleId]; ok {
				if len(tableDataList) > row && len(tableDataList[row]) > col {
					// 符合管理规则要求,则进行字体和背景颜色的渲染
					if checkCellRule(v, tableDataList[row][col].Monitor, tableDataList) {
						tableDataList[row][col].Background = v.BackgroundColor
						tableDataList[row][col].FontColor = v.FontColor
					}
				} else {
					continue
				}
			} else {
				continue
			}
		}
	}
	return
}

func getCellValueByType(value string, valueType int, tableDataList [][]LuckySheetDataValue) (float64, bool) {
	if valueType == 2 {
		coords := strings.Split(value, ",")
		var coordIntArr []int
		for _, v := range coords {
			t, _ := strconv.Atoi(v)
			coordIntArr = append(coordIntArr, t)
		}
		if len(coordIntArr) == 2 {
			x, y := coordIntArr[0]-1, coordIntArr[1]-1
			conditionValue, err := strconv.ParseFloat(tableDataList[y][x].Monitor, 64)
			if err != nil {
				return 0, false
			}
			return conditionValue, true
		}
	} else {
		conditionValue, err := strconv.ParseFloat(value, 64)
		if err != nil {
			return 0, false
		}
		return conditionValue, true
	}
	return 0, false
}

func checkCellRule(ruleInfo *models.ExcelInfoRuleMappingView, value string, tableDataList [][]LuckySheetDataValue) bool {
	var tableValue float64
	var tableTime time.Time
	var err error

	if ruleInfo.RuleType == 5 {
		tableTime, err = time.ParseInLocation(utils.FormatDate, value, time.Local)
		if err != nil {
			return false
		}
	} else {
		tableValue, err = strconv.ParseFloat(value, 64)
		if err != nil {
			return false
		}
	}
	switch ruleInfo.RuleType {
	// 大于
	case 1:
		conditionValue, ok := getCellValueByType(ruleInfo.LeftValueBack, ruleInfo.LeftValueType, tableDataList)
		if !ok {
			return false
		}
		if tableValue > conditionValue {
			return true
		}
	// 小于
	case 2:
		conditionValue, ok := getCellValueByType(ruleInfo.LeftValueBack, ruleInfo.LeftValueType, tableDataList)
		if !ok {
			return false
		}
		if tableValue < conditionValue {
			return true
		}
	// 介于
	case 3:
		leftcondValue, ok := getCellValueByType(ruleInfo.LeftValueBack, ruleInfo.LeftValueType, tableDataList)
		if !ok {
			return false
		}
		rightcondValue, ok := getCellValueByType(ruleInfo.RightValue, ruleInfo.RightValueType, tableDataList)
		if !ok {
			return false
		}
		if leftcondValue <= tableValue && tableValue <= rightcondValue {
			return true
		}
	// 等于
	case 4:
		conditionValue, ok := getCellValueByType(ruleInfo.LeftValueBack, ruleInfo.LeftValueType, tableDataList)
		if !ok {
			return false
		}
		if tableValue == conditionValue {
			return true
		}
	// 发生日期
	case 5:
		// 发生日期
		var dateStart, dataEnd time.Time
		switch ruleInfo.LeftValueBack {
		// 今天
		case "today":
			// 获得今天的零点零分零秒
			dateStart = utils.Today()
			if tableTime == dateStart {
				return true
			}
		// 明天
		case "tomorrow":
			dateStart = utils.Tomorrow()
			if tableTime == dateStart {
				return true
			}
		// 最近7天
		case "last7days":
			dateStart, dataEnd = utils.Last7Days()
			if tableTime.After(dateStart) && tableTime.Before(dataEnd) {
				return true
			}
		// 上周
		case "lastweek":
			dateStart, dataEnd = utils.LastWeek()
			if tableTime.After(dateStart) && tableTime.Before(dataEnd) {
				return true
			}
		// 本周
		case "thisweek":
			dateStart, dataEnd = utils.ThisWeek()
			if tableTime.After(dateStart) && tableTime.Before(dataEnd) {
				return true
			}
		// 下周
		case "nextweek":
			dateStart, dataEnd = utils.NextWeek()
			if tableTime.After(dateStart) && tableTime.Before(dataEnd) {
				return true
			}
		// 上月
		case "lastmonth":
			dateStart, dataEnd = utils.LastMonth()
			if tableTime.After(dateStart) && tableTime.Before(dataEnd) {
				return true
			}
		// 本月
		case "thismonth":
			dateStart, dataEnd = utils.ThisMonth()
			if tableTime.After(dateStart) && tableTime.Before(dataEnd) {
				return true
			}
		// 下月
		case "nextmonth":
			dateStart, dataEnd = utils.NextMonth()
			if tableTime.After(dateStart) && tableTime.Before(dataEnd) {
				return true
			}
		default:
			return false
		}

	}
	return false
}

func generateRuleScopeIndexMap(items []*models.ExcelInfoRuleMappingView) (ruleScopeMap map[int]map[int]int) {
	ruleScopeMap = make(map[int]map[int]int)
	for _, item := range items {
		coords := strings.Split(item.ScopeCoord, ",")
		var coordIntArr []int
		for _, v := range coords {
			t, _ := strconv.Atoi(v)
			coordIntArr = append(coordIntArr, t)
		}

		if len(coords) == 4 {
			xmin, ymin, xmax, ymax := coordIntArr[0]-1, coordIntArr[1]-1, coordIntArr[2]-1, coordIntArr[3]-1
			for i := ymin; i <= ymax; i++ {
				for j := xmin; j <= xmax; j++ {
					if _, ok := ruleScopeMap[i]; !ok {
						ruleScopeMap[i] = make(map[int]int)
					}
					ruleScopeMap[i][j] = item.ExcelInfoRuleMappingId
				}
			}
		}
		if len(coords) == 2 {
			x, y := coordIntArr[0]-1, coordIntArr[1]-1
			if _, ok := ruleScopeMap[y]; !ok {
				ruleScopeMap[y] = make(map[int]int)
			}
			ruleScopeMap[y][x] = item.ExcelInfoRuleMappingId
		}
	}
	return
}