package cron

import (
	"context"
	"errors"
	"fmt"
	account "fonchain-fiee/api/accountFiee"
	"fonchain-fiee/api/cron"
	"fonchain-fiee/pkg/service"
	"fonchain-fiee/pkg/utils"
	"log"
	"os"
	"path/filepath"
	"strings"
	"time"

	"github.com/gin-gonic/gin"
	"github.com/gin-gonic/gin/binding"
	"github.com/xuri/excelize/v2"
	"google.golang.org/protobuf/types/known/emptypb"
)

func CreateScheduleTask(c *gin.Context) {
	var req cron.CreateScheduleTaskRequest
	if err := c.ShouldBindBodyWith(&req, binding.JSON); err != nil {
		service.Error(c, errors.New("参数错误"))
		return
	}
	res, err := service.CronProvider.CreateScheduleTask(context.Background(), &req)
	if err != nil {
		service.Error(c, errors.New("网络超时,请重试"))
		return
	}
	if res.Code != 200 {
		service.Error(c, errors.New(res.Message))
		return
	}
	service.Success(c, res)
}
func UpdateScheduleTask(c *gin.Context) {
	var req cron.UpdateScheduleTaskRequest
	if err := c.ShouldBindBodyWith(&req, binding.JSON); err != nil {
		service.Error(c, errors.New("参数错误"))
		return
	}
	res, err := service.CronProvider.UpdateScheduleTask(context.Background(), &req)
	if err != nil {
		service.Error(c, errors.New("网络超时,请重试"))
		return
	}
	if res.Code != 200 {
		service.Error(c, errors.New(res.Message))
		return
	}
	service.Success(c, res)
}

func GetListScheduleTask(c *gin.Context) {
	var req cron.GetListScheduleTaskRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		service.Error(c, errors.New("参数错误"))
		return
	}
	res, err := service.CronProvider.GetListScheduleTask(context.Background(), &req)
	if err != nil {
		service.Error(c, errors.New("网络超时,请重试"))
		return
	}
	if res.Code != 200 {
		service.Error(c, errors.New(res.Message))
		return
	}
	service.Success(c, res)
}

func GetListExecutionRecord(c *gin.Context) {
	var req cron.GetListExecutionRecordRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		service.Error(c, errors.New("参数错误"))
		return
	}
	res, err := service.CronProvider.GetListExecutionRecord(context.Background(), &req)
	if err != nil {
		service.Error(c, errors.New("网络超时,请重试"))
		return
	}
	if res.Code != 200 {
		service.Error(c, errors.New(res.Message))
		return
	}
	service.Success(c, res)
}
func GetListExecutionResult(c *gin.Context) {
	var req cron.GetListExecutionResultRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		service.Error(c, errors.New("参数错误"))
		return
	}
	res, err := service.CronProvider.GetListExecutionResult(context.Background(), &req)
	if err != nil {
		service.Error(c, errors.New("网络超时,请重试"))
		return
	}
	if res.Code != 200 {
		service.Error(c, errors.New(res.Message))
		return
	}
	service.Success(c, res)
}
func ExportExcelExecutionResult(c *gin.Context) {
	var req cron.GetListExecutionResultRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		service.Error(c, errors.New("参数错误"))
		return
	}
	res, err := service.CronProvider.GetListExecutionResult(context.Background(), &req)
	if err != nil {
		service.Error(c, errors.New("网络超时,请重试"))
		return
	}
	userListRes, err := service.AccountFieeProvider.UserList(context.Background(), &account.UserListRequest{
		Domain: "app",
	})
	if err != nil {
		service.Error(c, errors.New("用户查询失败"))
		return
	}
	idFindSubName := make(map[uint64]string)
	for _, v := range userListRes.UserList {
		idFindSubName[v.Id] = v.SubNum
	}

	titleList := []string{
		"开始时间", "任务标题", "艺人编号", "艺人姓名", "内容类型", "内容标题", "执行结果", "原因", "TIKTOK", "YOUTUBE", "INS", "DM", "BULESKY",
	}
	var dataList []interface{}
	for _, task := range res.Data {
		data := []interface{}{
			task.StartTime,
			task.TaskTitle,
			idFindSubName[uint64(task.ArtistId)],
			task.ArtistName,
			task.ContentTypeDescription,
			task.WorkTitle,
			task.ResultDescription,
			task.ResultDesc,
			task.TIKTOKStatusDesc,
			task.YOUTUBEStatusDesc,
			task.INSStatusDesc,
			task.DMStatusDesc,
			task.BULESKYStatusDesc,
		}
		dataList = append(dataList, &data)
	}

	content, err := utils.ToExcelByType(titleList, dataList, "slice", "")
	if err != nil {
		service.Error(c, errors.New("生成excel失败"))

	}
	utils.ResponseXls(c, content, fmt.Sprintf("失败任务报告_%s.xlsx", time.Now().Format("20060102150405")))
	return
}

func StartScheduleTask(c *gin.Context) {
	var req cron.CommonIDRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		service.Error(c, errors.New("参数错误"))
		return
	}
	res, err := service.CronProvider.StartScheduleTask(context.Background(), &req)
	if err != nil {
		service.Error(c, errors.New("网络超时,请重试"))
		return
	}
	if res.Code != 200 {
		service.Error(c, errors.New(res.Message))
		return
	}
	service.Success(c, res)
}
func RepublishScheduleTask(c *gin.Context) {
	var req cron.CommonIDRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		service.Error(c, errors.New("参数错误"))
		return
	}
	res, err := service.CronProvider.RepublishScheduleTask(context.Background(), &req)
	if err != nil {
		service.Error(c, errors.New("网络超时,请重试"))
		return
	}
	if res.Code != 200 {
		service.Error(c, errors.New(res.Message))
		return
	}
	service.Success(c, res)
}

func PauseScheduleTask(c *gin.Context) {
	var req cron.CommonIDRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		service.Error(c, errors.New("参数错误"))
		return
	}
	res, err := service.CronProvider.PauseScheduleTask(context.Background(), &req)
	if err != nil {
		service.Error(c, errors.New("网络超时,请重试"))
		return
	}
	if res.Code != 200 {
		service.Error(c, errors.New(res.Message))
		return
	}
	service.Success(c, res)
}

func DeleteScheduleTask(c *gin.Context) {
	var req cron.CommonIDRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		service.Error(c, errors.New("参数错误"))
		return
	}
	res, err := service.CronProvider.DeleteScheduleTask(context.Background(), &req)
	if err != nil {
		service.Error(c, errors.New("网络超时,请重试"))
		return
	}
	if res.Code != 200 {
		service.Error(c, errors.New(res.Message))
		return
	}
	service.Success(c, res)
}

func GetScheduleTaskStatus(c *gin.Context) {
	res, err := service.CronProvider.GetScheduleTaskStatus(context.Background(), &emptypb.Empty{})
	if err != nil {
		service.Error(c, errors.New("网络超时,请重试"))
		return
	}
	if res.Code != 200 {
		service.Error(c, errors.New(res.Message))
		return
	}
	service.Success(c, res)
}

func GetImportData(c *gin.Context) {
	defer func() {
		if r := recover(); r != nil {
			service.Error(c, errors.New("操作失败"))
		}
	}()

	// 导入excel
	excelFile, err := c.FormFile("excel")
	if err != nil {
		service.Error(c, errors.New("缺少excel文件"))
		return
	}

	// 创建临时文件
	tempDir := "tmp"
	if err = os.MkdirAll(tempDir, 0755); err != nil {
		service.Error(c, errors.New("创建临时目录失败"))
		return
	}
	defer os.RemoveAll(tempDir)

	// 保存excel
	excelPath := filepath.Join(tempDir, "excel.xlsx")
	if err = c.SaveUploadedFile(excelFile, excelPath); err != nil {
		service.Error(c, errors.New("保存excel文件失败"))
		return
	}

	// 读取excel
	readExcelResult, err := readExcel(excelPath)
	if err != nil {
		service.Error(c, fmt.Errorf("读取excel失败: %v", err))
		return
	}
	if len(readExcelResult) == 0 {
		service.Error(c, errors.New("请检查excel文件"))
		return
	}
	//去重操作
	set := make(map[string]struct{})
	var uniqueExcelData []excelData
	for _, data := range readExcelResult {
		if _, exists := set[data.SubName]; !exists {
			set[data.SubName] = struct{}{}
			uniqueExcelData = append(uniqueExcelData, data)
		}
	}
	res, err := service.AccountFieeProvider.UserList(context.Background(), &account.UserListRequest{
		Domain: "app",
	})
	if err != nil {
		service.Error(c, errors.New("用户查询失败"))
		return
	}
	//检查subname是否正确是否存在
	subNames := make(map[string]struct{}, len(res.UserList))
	for _, v := range res.UserList {
		subNames[v.SubNum] = struct{}{}
	}
	for _, v := range uniqueExcelData {
		if _, ok := subNames[v.SubName]; !ok {
			service.Error(c, errors.New(fmt.Sprintf("第 %d 行数据错误，请检查数据！", v.Line)))
			return
		}
	}
	//检查subname和name是否匹配
	subNameFindExcelData := make(map[string]excelData, len(uniqueExcelData))
	for _, v := range uniqueExcelData {
		subNameFindExcelData[v.SubName] = v
	}
	subNameFindID := make(map[string]uint64, len(uniqueExcelData))
	result := make([]excelDataResult, 0, len(uniqueExcelData))
	for _, v := range res.UserList {
		subNameFindID[v.SubNum] = v.Id
		if subNameFindExcelData[v.SubNum].Name != v.Name && subNameFindExcelData[v.SubNum].Name != "" {
			fmt.Println(subNameFindExcelData[v.SubNum], v.Name)
			service.Error(c, errors.New(fmt.Sprintf("第 %d 行数据错误，请检查数据！", subNameFindExcelData[v.SubNum].Line)))
			return
		}
	}
	for _, v := range uniqueExcelData {
		result = append(result, excelDataResult{
			Id:   subNameFindID[v.SubName],
			Name: v.Name,
		})
	}
	service.Success(c, result)
	return
}

type excelData struct {
	Line    uint   `json:"line"`
	SubName string `json:"subName"`
	Name    string `json:"name"`
}

type excelDataResult struct {
	Id   uint64 `json:"id"`
	Name string `json:"name"`
}

func readExcel(excelPath string) ([]excelData, error) {
	//打开excel
	f, err := excelize.OpenFile(excelPath)
	if err != nil {
		return nil, err
	}
	defer f.Close()

	//读取第一页
	sheetName := f.GetSheetName(0)
	if sheetName == "" {
		return nil, errors.New("excel文件中没有工作表")
	}

	//读取数据
	rows, err := f.GetRows(sheetName)
	if err != nil {
		return nil, fmt.Errorf("读取工作表失败: %v", err)
	}

	if len(rows) <= 1 {
		return nil, errors.New("excel文件没有数据行（只有表头或为空）")
	}
	var result []excelData
	for i := 1; i < len(rows); i++ { // 从第2行开始（跳过表头）
		row := rows[i]
		if len(row) == 0 {
			continue
		}

		subName := getCellValue(f, sheetName, i, 0)
		name := getCellValue(f, sheetName, i, 1)
		data := excelData{
			Line:    uint(i + 1),
			SubName: subName,
			Name:    name,
		}
		result = append(result, data)
	}

	return result, nil
}
func getCellValue(f *excelize.File, sheetName string, rowIndex, colIndex int) string {
	colName, _ := excelize.ColumnNumberToName(colIndex + 1)
	cell := fmt.Sprintf("%s%d", colName, rowIndex+1)

	value, err := f.GetCellValue(sheetName, cell)
	if err != nil {
		log.Printf("读取单元格 %s 失败: %v", cell, err)
		return ""
	}

	return strings.TrimSpace(value)
}
