package excel

import (
	"encoding/json"
	"eta/eta_api/utils"
	"fmt"
	"github.com/shopspring/decimal"
	"github.com/xuri/excelize/v2"
	"sync"
	"time"
)

// ConvToLuckySheet 普通的excel转luckySheet数据
func ConvToLuckySheet(filePath string) (err error) {
	defer func() {
		if err != nil {
			fmt.Println(err)
		}
	}()
	f, err := excelize.OpenFile(filePath)
	if err != nil {
		fmt.Println(err)
		return
	}
	sheetDataList := make([]SimpleLuckySheetData, 0)
	// 获取所有sheet
	sheetList := f.GetSheetList()
	fmt.Println("读取完成后", time.Now().Format(utils.FormatDateTime))

	for sheetIndex, sheetName := range sheetList {
		sheetData, tmpErr := getLuckySheetData(f, sheetIndex, sheetName)
		if tmpErr != nil {
			err = tmpErr
			return
		}
		sheetDataList = append(sheetDataList, sheetData)
	}

	byteS, err := json.Marshal(sheetDataList)
	if err != nil {
		return
	}
	utils.FileLog.Info(string(byteS))

	return
}

// SimpleLuckySheetData sheet表格数据
type SimpleLuckySheetData struct {
	Name  string `json:"name" description:"工作表名称"`
	Index int    `json:"index" description:"工作表索引"`
	//Row      int                        `json:"row" description:"行数"`
	//Column   int                        `json:"column" description:"列数"`
	CellData  []SimpleLuckySheetCellData `json:"celldata" description:"单元格数据"`
	Config    SimpleLuckySheetDataConfig `json:"config" description:""`
	CalcChain []CalcChain                `json:"calcChain" description:"公式链"`
	//Status            int64   `json:"status" description:"激活状态"`
}

type CalcChain struct {
	Col   int64         `json:"c"`     //列数
	Row   int64         `json:"r"`     //行数
	Index int           `json:"index"` //工作表id
	Func  []interface{} `json:"func"`  //公式信息，包含公式计算结果和公式字符串
	Color string        `json:"color"` //"w"：采用深度优先算法 "b":普通计算
	//Parent  interface{}   `json:"parent"`
	//Chidren struct {
	//} `json:"chidren"`
	Times int `json:"times"`
}

// SimpleLuckySheetDataConfig sheet表单的配置
type SimpleLuckySheetDataConfig struct {
	BorderInfo []LuckySheetDataConfigBorderInfo `json:"borderInfo" description:"边框"`
	Colhidden  map[string]int64                 `json:"colhidden" description:"隐藏列，示例值：\"colhidden\":{\"30\":0,\"31\":0}"`
	//CustomHeight struct {
	//	Zero int64 `json:"0"`
	//} `json:"customHeight" description:""`
	//CustomWidth struct {
	//	Two int64 `json:"2" description:""`
	//} `json:"customWidth" description:""`
	Merge map[string]LuckySheetDataConfigMerge `json:"merge" description:"合并单元格"`
	//Rowlen map[string]float64                   `json:"rowlen" description:"每个单元格的行高"`
	Columnlen map[string]float64 `json:"columnlen" description:"每个单元格的列宽"`
}

// SimpleLuckySheetCellData 单个单元格数据
type SimpleLuckySheetCellData struct {
	Col int64 `json:"c" description:"列"`
	Row int64 `json:"r" description:"行"`
	//Value SimpleLuckySheetDataValue `json:"v" description:"单元格内值的数据"`
	Value interface{} `json:"v" description:"单元格内值的数据"`
}

// SimpleLuckySheetDataValue 单元格内值的数据
type SimpleLuckySheetDataValue struct {
	CellType LuckySheetDataCellType `json:"ct" description:"单元格值格式：文本、时间等	"`
	Value    interface{}            `json:"v" description:"原始值"`
	//Monitor  string                 `json:"m" description:"显示值"`
	//Fontsize       int                    `description:"字体大小，14"`
	//TextBeak int         `description:"文本换行，	0 截断、1溢出、2 自动换行"`
	//Tb       interface{} `json:"tb" description:"文本换行，	0 截断、1溢出、2 自动换行"`
	//Ps        LuckySheetDataCellComment `json:"ps" description:"批注"`
	Function string `json:"f" description:"公式"`
	//MergeCell LuckySheetDataConfigMerge `json:"mc" description:"合并单元格信息"`
}

func getLuckySheetData(f *excelize.File, sheetIndex int, sheetName string) (sheetData SimpleLuckySheetData, err error) {
	cellData := make([]SimpleLuckySheetCellData, 0)         // excel数据
	mergeData := make(map[string]LuckySheetDataConfigMerge) //合并单元格数据
	calcChainList := make([]CalcChain, 0)                   //公式链信息

	sheetData = SimpleLuckySheetData{
		Name:  sheetName,
		Index: sheetIndex,
		//Row:      0,
		//Column:   0,
		CellData: cellData,
		Config:   SimpleLuckySheetDataConfig{},
	}
	fmt.Println("开始读取sheet数据：", time.Now().Format(utils.FormatDateTime))
	rows, tmpErr := f.GetRows(sheetName)
	if tmpErr != nil {
		err = tmpErr
		return
	}
	fmt.Println("读取完sheet数据：", time.Now().Format(utils.FormatDateTime))
	lenRow := len(rows)
	fmt.Println("总共：", lenRow, "条数据")
	if lenRow <= 0 {
		return
	}

	//sheetData.Row = len(rows)
	//sheetData.Column = len(Column)

	// 最大单元格数
	maxColumnIndex := 0

	wg := sync.WaitGroup{}
	wg.Add(1)
	// 协程处理合并单元格
	go func() {
		defer func() {
			wg.Done()
		}()
		mergeCellList, err := f.GetMergeCells(sheetName)
		if err != nil {
			return
		}
		for _, v := range mergeCellList {
			// 左上角单元格位置
			cStartIndex, rStartIndex, tmpErr := excelize.CellNameToCoordinates(v.GetStartAxis())
			if tmpErr != nil {
				err = tmpErr
				return
			}
			// 右下角单元格位置
			cEndIndex, rEndIndex, tmpErr := excelize.CellNameToCoordinates(v.GetEndAxis())
			if tmpErr != nil {
				err = tmpErr
				return
			}
			//fmt.Println(v.GetEndAxis())
			tmpLuckySheetDataConfigMerge := LuckySheetDataConfigMerge{
				Row:    rStartIndex - 1,
				Column: cStartIndex - 1,
				Rs:     rEndIndex - rStartIndex + 1,
				Cs:     cEndIndex - cStartIndex + 1,
			}
			mergeData[fmt.Sprint(rStartIndex-1, "_", cStartIndex-1)] = tmpLuckySheetDataConfigMerge
		}
		sheetData.Config.Merge = mergeData
	}()

	colWidthMap := make(map[string]float64)

	// 每次分割就是5000条
	splitNum := 500
	splitLen := lenRow / splitNum
	residue := lenRow % splitNum
	if residue > 0 {
		splitLen += 1
	}

	for i := 0; i < splitLen; i++ {
		wg.Add(1)

		startRow := i * splitNum
		endRow := (i + 1) * splitNum
		if i == splitLen-1 && residue > 0 {
			endRow = lenRow
		}

		go func(currStartRow, currEndRow int) {
			defer func() {
				wg.Done()
			}()

			for rIndex := currStartRow; rIndex < currEndRow; rIndex++ {
				row := rows[rIndex]
				for cIndex, colCell := range row {
					if rIndex == 0 {
						//colName, tmpErr := excelize.ColumnNumberToName(cIndex + 1)
						//if tmpErr != nil {
						//	err = tmpErr
						//	return
						//}
						//colWidth, tmpErr := f.GetColWidth(sheetName, colName)
						//if tmpErr != nil {
						//	err = tmpErr
						//	return
						//}
						//colWidthMap[fmt.Sprint(cIndex)] = emuToPx(colWidth)
					}
					if maxColumnIndex < cIndex {
						maxColumnIndex = cIndex
					}
					cellName, tmpErr := excelize.CoordinatesToCellName(cIndex+1, rIndex+1)
					if tmpErr != nil {
						err = tmpErr
						return
					}
					//cellType, tmpErr := f.GetCellType(sheetName, cellName)
					//if tmpErr != nil {
					//	err = tmpErr
					//	return
					//}
					cellFormula, tmpErr := f.GetCellFormula(sheetName, cellName)
					if tmpErr != nil {
						err = tmpErr
						return
					}

					//fmt.Println(cellName, ": ", "类型：", cellType, ",公式：", cellFormula, ",值", colCell, "\t")

					var colCellIntfac interface{}
					cellTypeT := "g"
					//colCell = utils.Tof
					tmpDec, tmpErr := decimal.NewFromString(colCell)
					if tmpErr != nil {
						colCellIntfac = colCell
					} else {
						colCellIntfac, _ = tmpDec.Float64()
						cellTypeT = "n"
					}

					if cellFormula != `` {
						cellFormula = `=` + cellFormula

						calcChainList = append(calcChainList, CalcChain{
							Col:   int64(cIndex),
							Row:   int64(rIndex),
							Index: sheetIndex,
							Func:  []interface{}{true, colCell, cellFormula},
							Color: "w",
							Times: 0,
						})
					}
					//CellType LuckySheetDataCellType `json:"ct" description:"单元格值格式：文本、时间等	"`
					//Value    interface{}            `json:"v" description:"原始值"`
					////Monitor  string                 `json:"m" description:"显示值"`
					////Fontsize       int                    `description:"字体大小，14"`
					////TextBeak int         `description:"文本换行，	0 截断、1溢出、2 自动换行"`
					////Tb       interface{} `json:"tb" description:"文本换行，	0 截断、1溢出、2 自动换行"`
					////Ps        LuckySheetDataCellComment `json:"ps" description:"批注"`
					//Function string `json:"f" description:"公式"`

					valueMap := make(map[string]interface{})
					valueMap["ct"] = LuckySheetDataCellType{
						Fa: "General",
						T:  cellTypeT,
					}
					valueMap["v"] = colCellIntfac
					if cellFormula != `` {
						valueMap["f"] = cellFormula
					}
					cellData = append(cellData, SimpleLuckySheetCellData{
						Col:   int64(cIndex),
						Row:   int64(rIndex),
						Value: valueMap,
					})
				}
			}
		}(startRow, endRow)
	}
	wg.Wait()

	fmt.Println("解析完sheet数据：", time.Now().Format(utils.FormatDateTime))
	//for rIndex, row := range rows {
	//	for cIndex, colCell := range row {
	//		if rIndex == 0 {
	//			//colName, tmpErr := excelize.ColumnNumberToName(cIndex + 1)
	//			//if tmpErr != nil {
	//			//	err = tmpErr
	//			//	return
	//			//}
	//			//colWidth, tmpErr := f.GetColWidth(sheetName, colName)
	//			//if tmpErr != nil {
	//			//	err = tmpErr
	//			//	return
	//			//}
	//			//colWidthMap[fmt.Sprint(cIndex)] = emuToPx(colWidth)
	//		}
	//		if maxColumnIndex < cIndex {
	//			maxColumnIndex = cIndex
	//		}
	//		cellName, tmpErr := excelize.CoordinatesToCellName(cIndex+1, rIndex+1)
	//		if tmpErr != nil {
	//			err = tmpErr
	//			return
	//		}
	//		//cellType, tmpErr := f.GetCellType(sheetName, cellName)
	//		//if tmpErr != nil {
	//		//	err = tmpErr
	//		//	return
	//		//}
	//		cellFormula, tmpErr := f.GetCellFormula(sheetName, cellName)
	//		if tmpErr != nil {
	//			err = tmpErr
	//			return
	//		}
	//
	//		//fmt.Println(cellName, ": ", "类型：", cellType, ",公式：", cellFormula, ",值", colCell, "\t")
	//
	//		var colCellIntfac interface{}
	//		cellTypeT := "g"
	//		//colCell = utils.Tof
	//		tmpDec, tmpErr := decimal.NewFromString(colCell)
	//		if tmpErr != nil {
	//			colCellIntfac = colCell
	//		} else {
	//			colCellIntfac, _ = tmpDec.Float64()
	//			cellTypeT = "n"
	//		}
	//
	//		if cellFormula != `` {
	//			cellFormula = `=` + cellFormula
	//
	//			calcChainList = append(calcChainList, CalcChain{
	//				Col:   int64(cIndex),
	//				Row:   int64(rIndex),
	//				Index: sheetIndex,
	//				Func:  []interface{}{true, colCell, cellFormula},
	//				Color: "w",
	//				Times: 0,
	//			})
	//		}
	//
	//		cellData = append(cellData, SimpleLuckySheetCellData{
	//			Col: int64(cIndex),
	//			Row: int64(rIndex),
	//			Value: SimpleLuckySheetDataValue{
	//				CellType: LuckySheetDataCellType{
	//					Fa: "General",
	//					T:  cellTypeT,
	//				},
	//				Value:    colCellIntfac,
	//				Monitor:  colCell,
	//				Function: cellFormula,
	//				//MergeCell: LuckySheetDataConfigMerge{},
	//			},
	//		})
	//	}
	//}

	sheetData.Config.Columnlen = colWidthMap

	sheetData.CellData = cellData
	sheetData.CalcChain = calcChainList
	//sheetData.Column = maxColumnIndex + 1

	return
}

// emuToPx 计量单位emu转px
func emuToPx(num float64) float64 {
	return num * 15
}
