package cast

import (
	"fmt"
	"fonchain-fiee/api/cast"
	"fonchain-fiee/cmd/config"
	"fonchain-fiee/pkg/model/login"
	"fonchain-fiee/pkg/service"
	"fonchain-fiee/pkg/utils"
	"path/filepath"
	"strings"
	"time"

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

// UpdateCastTag 更新话题标签
func UpdateCastTag(ctx *gin.Context) {
	var req *cast.UpdateCastTagReq
	var err error
	if err = ctx.ShouldBind(&req); err != nil {
		service.Error(ctx, err)
		return
	}
	newCtx := NewCtxWithUserInfo(ctx)
	resp, err := service.CastProvider.UpdateCastTag(newCtx, req)
	if err != nil {
		service.Error(ctx, err)
		return
	}
	service.Success(ctx, resp)
	return
}

// ListCastTags 获取话题标签列表
func ListCastTags(ctx *gin.Context) {
	var req *cast.ListCastTagsReq
	var err error
	if err = ctx.ShouldBind(&req); err != nil {
		service.Error(ctx, err)
		return
	}
	newCtx := NewCtxWithUserInfo(ctx)
	resp, err := service.CastProvider.ListCastTags(newCtx, req)
	if err != nil {
		service.Error(ctx, err)
		return
	}
	service.Success(ctx, resp)
	return
}

// ImportTagBatch 批量导入话题标签
func ImportTagBatch(ctx *gin.Context) {
	// 接收form表单的Excel保存到本地进行解析
	excelFile, err := ctx.FormFile("file")
	if err != nil {
		service.Error(ctx, err)
		return
	}
	tempDir := "./runtime/tag"
	_, err = utils.CheckDirPath(tempDir, true)
	fileName := time.Now().Format("20060102150405") + "_in_tag.xlsx"
	excelPath := filepath.Join(tempDir, fileName)
	if err = ctx.SaveUploadedFile(excelFile, excelPath); err != nil {
		service.Error(ctx, err)
		return
	}
	// 读取Excel中的数据
	excelData, err := excelize.OpenFile(excelPath)
	if err != nil {
		service.Error(ctx, err)
		return
	}
	defer excelData.Close()
	// 解析Excel中的数据
	rows, err := excelData.GetRows("Sheet1")
	if err != nil {
		service.Error(ctx, err)
		return
	}
	req := cast.UpdateCastTagBatchReq{
		Data: make([]*cast.CastTagInfo, 0),
	}
	userInfo := login.GetUserInfoFromC(ctx)
	for line, row := range rows {
		if line == 0 {
			continue
		}
		temp := cast.CastTagInfo{
			CreatorUuid: fmt.Sprint(userInfo.ID),
			CreatorName: userInfo.Name,
			Source:      1, // 固定来源：人工导入
			Status:      1, // 固定状态：有效
		}
		// 解析Excel列：A-话题标签，B-备注
		if len(row) > 0 {
			temp.HashTag = strings.TrimSpace(row[0])
		}
		if len(row) > 1 {
			temp.Remark = strings.TrimSpace(row[1])
		}
		zap.L().Info("ImportTagBatch row", zap.Int("line", line), zap.Strings("row", row))
		// 验证必填字段：话题标签不能为空
		if utils.CleanString(temp.HashTag) == "" {
			temp.Remark = "必填项未填"
			req.Data = append(req.Data, &temp)
			continue
		}
		req.Data = append(req.Data, &temp)
	}
	newCtx := NewCtxWithUserInfo(ctx)
	resp, _err := service.CastProvider.UpdateCastTagBatch(newCtx, &req)
	if _err != nil {
		service.Error(ctx, _err)
		return
	}
	// 打开模板 写入resp 返回的数据
	templatePath := "./data/话题标签导入模板.xlsx"
	template, err := excelize.OpenFile(templatePath)
	if err != nil {
		service.Error(ctx, err)
		return
	}
	defer template.Close()
	var urlResult string
	if resp.FailCount != 0 {
		rowIndex := 2 // 从第2行开始写入（第1行是表头）
		for _, v := range resp.Data {
			if v.Success {
				continue
			}
			// 写入失败的数据到Excel模板（只写入话题标签和备注两列）
			template.SetCellValue("Sheet1", fmt.Sprintf("A%d", rowIndex), v.HashTag)
			template.SetCellValue("Sheet1", fmt.Sprintf("B%d", rowIndex), v.Remark)
			rowIndex++
		}
		resultFilename := strings.Replace(fileName, "_in_tag.xlsx", "_out_tag.xlsx", -1)
		resultPath := fmt.Sprintf("./runtime/tag/%s", resultFilename)
		if err = template.SaveAs(resultPath); err != nil {
			service.Error(ctx, err)
			return
		}
		urlHost := config.AppConfig.System.FieeHost
		urlResult = fmt.Sprintf("%s/api/fiee/static/tag/%s", urlHost, resultFilename)
	}

	service.Success(ctx, map[string]interface{}{
		"successCount": resp.SuccessCount,
		"failCount":    resp.FailCount,
		"resultUrl":    urlResult,
	})
	return
}

// RecalculateCastTagQuoteCount 重新计算话题标签引用数量
func RecalculateCastTagQuoteCount(ctx *gin.Context) {
	newCtx := NewCtxWithUserInfo(ctx)
	// 创建空的请求对象
	req := &emptypb.Empty{}
	resp, err := service.CastProvider.RecalculateCastTagQuoteCount(newCtx, req)
	if err != nil {
		service.Error(ctx, err)
		return
	}
	service.Success(ctx, resp)
	return
}
