package exceltool

import (
	"errors"
	"fmt"
	"math/rand"
	"time"

	excelize "github.com/360EntSecGroup-Skylar/excelize/v2"
	"github.com/astaxie/beego/orm"
)

//(新)ExcelMaker 构建excel文档
type ExcelMaker struct {
	Xlsx     *excelize.File
	FileName string
}

//NewExcelMaker ....
func NewExcelMaker() *ExcelMaker {
	return &ExcelMaker{
		Xlsx: excelize.NewFile(),
	}
}

//MakeListExcel 根据列表形式的数据创建excel文档
//@sourData []map[string]string; 原始数据,要输入excel文档的数据
//@xlsxHeader [][]string{ {"数据字段英文名",""excel字段中文描述"},{"数据字段英文名",""excel字段中文描述"} }
func (e *ExcelMaker) MakeListExcel(sourData []map[string]string, xlsxHeader [][]string) (err error) {
	if len(xlsxHeader) == 0 {
		return errors.New("xlsHeader 数据格式错误")
	}
	headEn := []string{}     //数据字段英文名
	headCn := []string{}     //excel字段中文描述
	alphaSlice := []string{} //excel列字母索引
	for key, val := range xlsxHeader {
		if len(val) != 2 {
			return errors.New("xlsHeader 数据格式错误")
		}
		headEn = append(headEn, xlsxHeader[key][0])
		headCn = append(headCn, xlsxHeader[key][1])
		//alpha, err := excelize.ColumnNumberToName(key)
		//if err != nil {
		//	return err
		//}
		alpha := ToAlphaString(key)
		alphaSlice = append(alphaSlice, alpha)
	}

	//设置excel文档第一行的字段中文描述
	for index, _ := range headCn {
		//索引转列名,索引从0开始
		cellAlpha := fmt.Sprintf("%s%d", alphaSlice[index], 1) // 单元格行坐标从1开始,如:a1,指第一行a列。
		e.Xlsx.SetCellStr("Sheet1", cellAlpha, headCn[index])

	}
	//从excel第二行开始设置实际数据的值
	for key1, _ := range sourData {
		for i := 0; i < len(headEn); i++ {
			cellAlpha := fmt.Sprintf("%s%d", alphaSlice[i], key1+2) // 单元格行坐标从1开始,如:a1,指第一行a列。
			e.Xlsx.SetCellStr("Sheet1", cellAlpha, sourData[key1][headEn[i]])
		}
	}
	e.FileName = GetRandomString(8) + ".xlsx"
	return nil
}

//MakeListExcel 根据数据创建列表形式的excel文档
//@sourData []orm.Params; 原始数据,要输入excel文档的数据
//@xlsxHeader [][]string{ {"数据字段英文名",""excel字段中文描述"},{"数据字段英文名",""excel字段中文描述"} }
func (e *ExcelMaker) MakeListExcelForBeego(sourData []orm.Params, xlsxHeader [][]string) (err error) {
	if len(xlsxHeader) == 0 {
		return errors.New("xlsHeader 数据格式错误")
	}
	headEn := []string{}     //数据字段英文名
	headCn := []string{}     //excel字段中文描述
	alphaSlice := []string{} //excel列字母索引
	for key, val := range xlsxHeader {
		if len(val) != 2 {
			return errors.New("xlsHeader 数据格式错误")
		}
		headEn = append(headEn, xlsxHeader[key][0])
		headCn = append(headCn, xlsxHeader[key][1])
		alpha, err := excelize.ColumnNumberToName(key)
		if err != nil {
			return err
		}
		alphaSlice = append(alphaSlice, alpha)
	}

	//设置excel文档第一行的字段中文描述
	for index, _ := range headCn {
		//索引转列名,索引从0开始
		cellAlpha := fmt.Sprintf("%s%d", alphaSlice[index], 1) // 单元格行坐标从1开始,如:a1,指第一行a列。
		e.Xlsx.SetCellStr("Sheet1", cellAlpha, headCn[index])

	}
	//从excel第二行开始设置实际数据的值
	for key1, _ := range sourData {
		for i := 0; i < len(headEn); i++ {
			cellAlpha := fmt.Sprintf("%s%d", alphaSlice[i], key1+2) // 单元格行坐标从1开始,如:a1,指第一行a列。
			if sourData[key1][headEn[i]] == nil {
				sourData[key1][headEn[i]] = ""
			}
			e.Xlsx.SetCellStr("Sheet1", cellAlpha, fmt.Sprintf("%s", sourData[key1][headEn[i]]))
		}
	}
	e.FileName = GetRandomString(8) + ".xlsx"
	return nil
}

//生成随机字符串
func GetRandomString(lenght int) string {
	str := "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
	bytes := []byte(str)
	result := []byte{}
	r := rand.New(rand.NewSource(time.Now().UnixNano()))
	for i := 0; i < lenght; i++ {
		result = append(result, bytes[r.Intn(len(bytes))])
	}
	return string(result)
}

func ToAlphaString(value int) string {
	if value < 0 {
		return ""
	}
	var ans string
	i := value + 1
	for i > 0 {
		ans = string((i-1)%26+65) + ans
		i = (i - 1) / 26
	}
	return ans
}