package bundle

import (
	"context"
	"encoding/json"
	"errors"
	"fmt"
	"fonchain-fiee/api/bundle"
	"fonchain-fiee/api/cast"
	"fonchain-fiee/pkg/service"
	"fonchain-fiee/pkg/service/bundle/common"
	"fonchain-fiee/pkg/utils"
	"io"
	"log"
	"strconv"
	"strings"
	"time"

	bundleModel "fonchain-fiee/pkg/model/bundle"
	"fonchain-fiee/pkg/model/login"

	"github.com/gin-gonic/gin"
	"github.com/samber/lo"
	"github.com/xuri/excelize/v2"
)

func BundleExtend(c *gin.Context) {
	var req bundle.BundleExtendRequest
	userInfo := login.GetUserInfoFromC(c)
	req.Type = 1 // 设置未手动扩展'
	req.OperatorName = userInfo.Name
	req.OperatorPhoneNumber = userInfo.TelNum
	req.OperatorId = userInfo.ID
	if err := c.ShouldBindJSON(&req); err != nil {
		service.Error(c, err)
		return
	}
	res, err := service.BundleProvider.BundleExtend(context.Background(), &req)
	if err != nil {
		service.Error(c, errors.New(common.BundleExtendFailed))
		return
	}
	service.Success(c, res)
}

func BundleExtendRecordsList(c *gin.Context) {
	var req bundle.BundleExtendRecordsListRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		service.Error(c, err)
		return
	}
	res, err := service.BundleProvider.BundleExtendRecordsList(context.Background(), &req)
	if err != nil {
		service.Error(c, errors.New(common.BundleExtendRecordsListFailed))
		return
	}
	service.Success(c, res)
}

func GetBundleBalance(c *gin.Context) {
	var req bundle.GetBundleBalanceListReq
	if err := c.ShouldBindJSON(&req); err != nil {
		service.Error(c, err)
		return
	}
	res, err := service.BundleProvider.GetBundleBalanceList(context.Background(), &req)
	if err != nil {
		service.Error(c, errors.New(common.GetBundleBalanceListFailed))
		return
	}
	service.Success(c, res)
}

func GetUsedRecordList(c *gin.Context) {
	var req bundle.GetUsedRecordListReq
	if err := c.ShouldBindJSON(&req); err != nil {
		service.Error(c, err)
		return
	}
	res, err := service.BundleProvider.GetUsedRecordList(context.Background(), &req)
	if err != nil {
		service.Error(c, errors.New(common.GetUsedRecordListFailed))
		return
	}
	service.Success(c, res)
}

func GetWorkDetail(c *gin.Context) {
	var req cast.WorkDetailReq
	if err := c.ShouldBindJSON(&req); err != nil {
		service.Error(c, err)
		return
	}
	// userInfo := login.GetUserInfoFromC(c)
	// res, err := service.BundleProvider.GetBundleBalanceByUserId(context.TODO(), &bundle.GetBundleBalanceByUserIdReq{
	// 	UserId: int32(userInfo.ID),
	// })
	// if err != nil {
	// 	service.Error(c, err)
	// 	return
	// }
	// if res.ExpiredTime <= time.Now().UnixMilli() {
	// 	service.Success(c, gin.H{
	// 		"status":  1,
	// 		"message": "套餐过期请重新购买",
	// 	})
	// 	return
	// }

	workRes, err := service.CastProvider.WorkDetail(context.Background(), &req)
	if err != nil {
		service.Error(c, err)
		return
	}

	// if len(workRes.Images) > 0 && res.ImageConsumptionNumber >= res.ImageNumber { // 图片用尽
	// 	service.Success(c, gin.H{
	// 		"status":  2,
	// 		"message": "增值服务已用尽",
	// 	})
	// 	return
	// } else {
	// 	if res.VideoConsumptionNumber >= res.VideoNumber { // 视频用尽
	// 		service.Success(c, gin.H{
	// 			"status":  2,
	// 			"message": "增值服务已用尽",
	// 		})
	// 		return
	// 	}
	// }

	service.Success(c, workRes)
}

func GetToBeComfirmedWorks(c *gin.Context) {
	var req bundle.ToBeComfirmedWorksReq
	if err := c.ShouldBindJSON(&req); err != nil {
		service.Error(c, err)
		return
	}
	userInfo := login.GetUserInfoFromC(c)
	req.ArtistUuid = strconv.Itoa(int(userInfo.ID))
	res, err := service.BundleProvider.ToBeComfirmedWorks(context.Background(), &req)
	if err != nil {
		service.Error(c, errors.New(common.ToBeComfirmedWorksFailed))
		return
	}
	service.Success(c, res)
}

func GetUserBalance(c *gin.Context) {
	userInfo := login.GetUserInfoFromC(c)
	res, err := service.BundleProvider.GetBundleBalanceByUserId(context.Background(), &bundle.GetBundleBalanceByUserIdReq{
		UserId: int32(userInfo.ID),
	})
	if err != nil {
		service.Error(c, errors.New(common.GetUserBalanceFailed))
		return
	}
	service.Success(c, res)
}

func WorkConfirm(c *gin.Context) { // 确认作品并扣除余量
	var req bundleModel.UserWorkConfirmReq

	if err := c.ShouldBindJSON(&req); err != nil {
		service.Error(c, err)
		return
	}
	log.Print("req.ConfirmRemark:", req.ConfirmRemark)
	if req.ConfirmStatus == 2 { // 驳回完直接结束
		res, err := service.CastProvider.UpdateStatus(c, &cast.UpdateStatusReq{
			WorkAction:    cast.WorkActionENUM_CONFIRM,
			WorkUuid:      req.WorkUuid,
			ConfirmRemark: req.ConfirmRemark,
			ConfirmStatus: 2,
		})
		if err != nil {
			service.Error(c, errors.New(common.UpdateWorkStatusFailed))
			return
		}
		service.Success(c, res)
		return
	}
	userInfo := login.GetUserInfoFromC(c)
	balanceInfoRes, err := service.BundleProvider.GetBundleBalanceByUserId(context.Background(), &bundle.GetBundleBalanceByUserIdReq{
		UserId: int32(userInfo.ID),
	})
	if err != nil {
		service.Error(c, errors.New(common.GetUserBalanceFailed))
		return
	}
	//判断套餐是否过期
	if balanceInfoRes.BundleStatus == common.BundleExpired {
		_, err = service.CastProvider.UpdateStatus(c, &cast.UpdateStatusReq{
			WorkAction:      cast.WorkActionENUM_CONFIRM,
			WorkUuid:        req.WorkUuid,
			ConfirmRemark:   req.ConfirmRemark,
			ConfirmStatus:   3,
			ConfirmFailType: cast.ConfirmFailENUM_ConfirmFailENUM_EXPIRED,
		})
		if err != nil {
			service.Error(c, errors.New(common.UpdateWorkStatusFailed))
			return
		}
		service.Error(c, errors.New("套餐已过期"))
		return
	}

	wordInfoRes, err := service.CastProvider.WorkDetail(c, &cast.WorkDetailReq{
		WorkUuid: req.WorkUuid,
	})
	if err != nil {
		service.Error(c, errors.New(common.GetWorkDetailFailed))
		return
	}

	if balanceInfoRes.BundleStatus == common.BundleExpired {
		_, err = service.CastProvider.UpdateStatus(c, &cast.UpdateStatusReq{
			WorkAction:    cast.WorkActionENUM_CONFIRM,
			WorkUuid:      req.WorkUuid,
			ConfirmRemark: req.ConfirmRemark,
			ConfirmStatus: 3,
		})
		service.Error(c, errors.New("套餐已过期"))
		return
	}

	if balanceInfoRes.PurchaseType == 1 {
		//判断作品对应订单是否相同
		if wordInfoRes.BundleOrderUuid != balanceInfoRes.OrderUUID {
			//订单号不相同
			//新购买的，直接扣除失败
			_, err = service.CastProvider.UpdateStatus(c, &cast.UpdateStatusReq{
				WorkAction:    cast.WorkActionENUM_CONFIRM,
				WorkUuid:      req.WorkUuid,
				ConfirmRemark: req.ConfirmRemark,
				ConfirmStatus: 3,
			})
			service.Error(c, errors.New("套餐为新套餐，确认失败"))
			return
		}
		//相同着正常走流程
	}
	if wordInfoRes.WorkStatus != 4 {
		service.Error(c, errors.New("作品不是待确认状态"))
		return
	}
	var workCategory = wordInfoRes.WorkCategory

	var addBalanceReq bundle.AddBundleBalanceReq
	addBalanceReq.UserId = int32(userInfo.ID)
	switch workCategory {
	case 1:
		{
			if balanceInfoRes.ImageExtendConsumptionNumber >= balanceInfoRes.ImageExtendNumber { // 图文余量不足
				_, err = service.CastProvider.UpdateStatus(context.Background(), &cast.UpdateStatusReq{
					WorkAction:      cast.WorkActionENUM_CONFIRM,
					WorkUuid:        req.WorkUuid,
					ConfirmRemark:   req.ConfirmRemark,
					ConfirmStatus:   3,
					ConfirmFailType: cast.ConfirmFailENUM_ConfirmFailENUM_NOTENOUGH,
				})
				if err != nil {
					service.Error(c, errors.New(common.UpdateWorkStatusFailed))
					return
				}
				service.Error(c, errors.New("图文余量不足"))
				return
			}
			addBalanceReq.ImageConsumptionNumber = 1
		}
	case 2:
		{
			if balanceInfoRes.VideoExtendConsumptionNumber >= balanceInfoRes.VideoExtendNumber { // 视频余量不足
				_, err = service.CastProvider.UpdateStatus(context.Background(), &cast.UpdateStatusReq{
					WorkAction:      cast.WorkActionENUM_CONFIRM,
					WorkUuid:        req.WorkUuid,
					ConfirmRemark:   req.ConfirmRemark,
					ConfirmStatus:   3,
					ConfirmFailType: cast.ConfirmFailENUM_ConfirmFailENUM_NOTENOUGH,
				})
				if err != nil {
					service.Error(c, errors.New(common.UpdateWorkStatusFailed))
					return
				}
				service.Error(c, errors.New("视频余量不足"))
				return
			}
			addBalanceReq.VideoConsumptionNumber = 1
		}
	default:
		service.Error(c, errors.New("不支持的类型"))
		return
	}
	resp, err := service.BundleProvider.AddBundleBalance(c, &addBalanceReq)
	if err != nil {
		service.Error(c, errors.New(common.AddBundleBalanceFailed))
		return
	}
	res, err := service.CastProvider.UpdateStatus(c, &cast.UpdateStatusReq{
		WorkAction:    cast.WorkActionENUM_CONFIRM,
		WorkUuid:      req.WorkUuid,
		ConfirmRemark: req.ConfirmRemark,
		CostType:      resp.UsedType,
		ConfirmStatus: 1,
	})
	if err != nil {
		service.Error(c, errors.New(common.UpdateWorkStatusFailed))
		return
	}
	service.Success(c, res)
}

func WorkAnalysisConfirm(c *gin.Context) { // 确认数据分析并扣除余量
	var req bundleModel.UserWorkAnalysisConfirmReq

	if err := c.ShouldBindJSON(&req); err != nil {
		service.Error(c, err)
		return
	}

	if req.ConfirmStatus == 2 { // 驳回完直接结束
		res, err := service.CastProvider.UpdateWorkAnalysisStatus(c, &cast.UpdateWorkAnalysisStatusReq{
			WorkAction:    cast.WorkActionENUM_CONFIRM,
			Uuid:          req.Uuid,
			ConfirmRemark: req.ConfirmRemark,
			ConfirmStatus: 2,
		})
		fmt.Println("res:", res)
		fmt.Println("err:", err)
		if err != nil {
			service.Error(c, errors.New("驳回失败"))
			return
		}
		service.Success(c, res)
		return
	}
	userInfo := login.GetUserInfoFromC(c)
	balanceInfoRes, err := service.BundleProvider.GetBundleBalanceByUserId(context.Background(), &bundle.GetBundleBalanceByUserIdReq{
		UserId: int32(userInfo.ID),
	})
	if err != nil {
		service.Error(c, errors.New(common.GetUserBalanceFailed))
		return
	}

	analysisInfoRes, err := service.CastProvider.GetWorkAnalysis(c, &cast.GetWorkAnalysisDetailReq{
		Uuid: req.Uuid,
	})
	if err != nil {
		service.Error(c, errors.New(common.GetWorkDetailFailed))
		return
	}
	if analysisInfoRes == nil {
		service.Error(c, errors.New("数据分析不存在"))
	}

	if balanceInfoRes.BundleStatus == common.BundleExpired {
		// 套餐过期的话直接失败
		_, err := service.CastProvider.UpdateWorkAnalysisStatus(c, &cast.UpdateWorkAnalysisStatusReq{
			WorkAction:    cast.WorkActionENUM_CONFIRM,
			Uuid:          req.Uuid,
			ConfirmRemark: req.ConfirmRemark,
			ConfirmStatus: 3,
		})
		if err != nil {
			service.Error(c, errors.New(common.UpdateWorkStatusFailed))
			return
		}
		service.Error(c, errors.New("套餐已过期"))
		return
	}

	if analysisInfoRes.WorkAnalysisStatus != 4 {
		service.Error(c, errors.New("数据分析不是待确认状态"))
		return
	}
	artistID, _ := strconv.ParseUint(analysisInfoRes.ArtistID, 10, 64)
	if artistID != uint64(userInfo.ID) {
		service.Error(c, errors.New("非本人数据分析，无法操作"))
		return
	}

	if balanceInfoRes.PurchaseType == 1 {
		// 判断数据分析对应订单是否相同
		if analysisInfoRes.BundleOrderUuid != balanceInfoRes.OrderUUID {
			// 订单号不同
			// 说明是新购买的，直接扣除失败
			_, err := service.CastProvider.UpdateWorkAnalysisStatus(c, &cast.UpdateWorkAnalysisStatusReq{
				WorkAction:    cast.WorkActionENUM_CONFIRM,
				Uuid:          req.Uuid,
				ConfirmRemark: req.ConfirmRemark,
				ConfirmStatus: 3,
			})
			if err != nil {
				service.Error(c, errors.New(common.UpdateWorkStatusFailed))
				return
			}
			service.Error(c, errors.New("套餐为新套餐，确认失败"))
			return
		}

	}

	var addBalanceReq bundle.AddBundleBalanceReq
	addBalanceReq.UserId = int32(userInfo.ID)
	// 检查数据分析余量
	if balanceInfoRes.DataAnalysisConsumptionNumber >= balanceInfoRes.DataAnalysisNumber {
		service.Error(c, errors.New("数据分析余量不足"))
		return
	}
	addBalanceReq.DataAnalysisConsumptionNumber = 1

	resp, err := service.BundleProvider.AddBundleBalance(c, &addBalanceReq)
	if err != nil {
		service.Error(c, errors.New(common.AddBundleBalanceFailed))
		return
	}
	res, err := service.CastProvider.UpdateWorkAnalysisStatus(c, &cast.UpdateWorkAnalysisStatusReq{
		WorkAction:    cast.WorkActionENUM_CONFIRM,
		Uuid:          req.Uuid,
		ConfirmRemark: req.ConfirmRemark,
		CostType:      resp.UsedType,
		ConfirmStatus: 1,
	})
	fmt.Println("res:", res)
	fmt.Println("err:", err)
	if err != nil {
		service.Error(c, errors.New("确认失败"))
		return
	}
	// 如果是艺人手动确认，确认操作后，自动标记为待阅读状态
	_, err = service.CastProvider.UpdateWorkAnalysisStatus(c, &cast.UpdateWorkAnalysisStatusReq{
		WorkAction: cast.WorkActionENUM_READ,
		Uuid:       req.Uuid,
	})
	if err != nil {
		service.Error(c, errors.New(common.UpdateWorkStatusFailed))
		return
	}
	service.Success(c, res)
}

func CastLogConfirm(ctx *gin.Context) {
	var req bundle.ConfirmWorkReq
	if err := ctx.ShouldBindJSON(&req); err != nil {
		service.Error(ctx, err)
		return
	}
	res, err := service.BundleProvider.ConfirmWork(context.Background(), &req)
	if err != nil {
		service.Error(ctx, errors.New(common.ConfirmWorkFailed))
		return
	}
	service.Success(ctx, res)
}

func BundleActivate(ctx *gin.Context) {
	var req bundle.BundleActivateReq
	if err := ctx.ShouldBindJSON(&req); err != nil {
		service.Error(ctx, err)
		return
	}
	res, err := service.BundleProvider.BundleActivate(context.Background(), &req)
	if err != nil {
		service.Error(ctx, errors.New(common.BundleActivateFailed))
		return
	}
	service.Success(ctx, res)
}

func BundleExport(ctx *gin.Context) {
	var req bundle.BundleBalanceExportReq
	if err := ctx.ShouldBindJSON(&req); err != nil {
		service.Error(ctx, err)
		return
	}

	userInfo := login.GetUserInfoFromC(ctx)
	exportFileName := fmt.Sprintf("%d月份余量信息.xlsx", time.Now().Month())
	filePath := fmt.Sprintf("./runtime/%d/%s", userInfo.ID, exportFileName)
	utils.CheckDirPath("./runtime/"+fmt.Sprint(userInfo.ID), true)
	res, err := service.BundleProvider.BundleBalanceExport(context.Background(), &req)
	if err != nil {
		service.Error(ctx, errors.New(common.BundleExportFailed))
		return
	}
	if err := writeToExcel(filePath, res.Data); err != nil {
		service.Error(ctx, errors.New(common.BundleExportFailed))
		return
	}
	var scheme string
	if ctx.GetHeader("X-Forwarded-Proto") == "https" {
		scheme = "https"
	} else {
		scheme = "http"
	}

	var exportUrl string = fmt.Sprintf("%s://%s/api/fiee/static/%s", scheme, ctx.Request.Host, strings.Replace(filePath, "./runtime/", "", 1))
	service.Success(ctx, gin.H{
		"url": exportUrl,
	})
}

func SetBalanceLayout(ctx *gin.Context) {
	b, _ := io.ReadAll(ctx.Request.Body)
	userInfo := login.GetUserInfoFromC(ctx)
	var req = bundle.SetBundleBalanceLayoutReq{
		Data:   string(b),
		UserId: uint32(userInfo.ID),
	}
	res, err := service.BundleProvider.SetBundleBalanceLayout(context.Background(), &req)
	if err != nil {
		service.Error(ctx, errors.New(common.SetBalanceLayoutFailed))
		return
	}
	service.Success(ctx, res)
}
func GetBalanceLayout(ctx *gin.Context) {
	userInfo := login.GetUserInfoFromC(ctx)
	var req = bundle.GetBundleBalanceLayoutReq{
		UserId: uint32(userInfo.ID),
	}
	res, err := service.BundleProvider.GetBundleBalanceLayout(context.Background(), &req)
	if err != nil {
		service.Error(ctx, errors.New(common.GetBalanceLayoutFailed))
		return
	}
	var j any
	json.Unmarshal([]byte(res.Data), &j)
	service.Success(ctx, j)
}

func writeToExcel(filename string, items []*bundle.BundleBalanceExportItem) error {
	f := excelize.NewFile()
	sheet := "Sheet1"

	// 手动表头（顺序与写入字段顺序必须一致）
	headers := []string{
		"所属月份", "用户编号", "姓名", "手机号", "购买套餐时间",
		"套餐金额", "增值服务金额", "支付金额", "币种", "手续费",
		"套餐视频总数", "增值服务视频总数", "套餐视频单价", "增值视频单价",
		"当月消耗套餐金额($)", "当月消耗增值金额($)",
		"套餐账号总数", "增值账号总数", "套餐账号使用数", "增值账号使用数",
		"当前可用套餐视频数", "当前可用增值视频数", "当前已用套餐视频数", "当前已用增值视频数", "当前作废套餐视频数", "当前作废增值视频数", "当月新增可用套餐视频数", "当月新增可用增值视频数", "当月使用套餐视频数", "当月使用增值视频数", "当月作废套餐视频数", "当月作废增值视频数",
		"当前可用套餐图文数", "当前可用增值图文数", "当前已用套餐图文数", "当前已用增值图文数", "当前作废套餐图文数", "当前作废增值图文数", "当月新增可用套餐图文数", "当月新增可用增值图文数", "当月使用套餐图文数", "当月使用增值图文数", "当月作废套餐图文数", "当月作废增值图文数",
		"当前可用套餐数据分析数", "当前可用增值数据分析数", "当前已用套餐数据分析数", "当前已用增值数据分析数", "当前作废套餐数据分析数", "当前作废增值数据分析数", "当月新增可用套餐数据分析数", "当月新增可用增值数据分析数", "当月使用套餐数据分析数", "当月使用增值数据分析数", "当月作废套餐数据分析数", "当月作废增值数据分析数",
		"当前可用套餐竞品数", "当前可用增值竞品数", "当前已用套餐竞品数", "当前已用增值竞品数", "当前作废套餐竞品数", "当前作废增值竞品数", "当月新增可用套餐竞品数", "当月新增可用增值竞品数", "当月使用套餐竞品数", "当月使用增值竞品数", "当月作废套餐竞品数", "当月作废增值竞品数",
		"当月手动扩展账号新增数", "当月手动扩展视频新增数", "当月手动扩展图文新增数", "当月手动扩展数据分析新增数", "当月新增手动扩展时长（天）", "当月手动扩展账号使用数", "当月手动扩展视频使用数", "当月手动扩展图文使用数", "当月手动扩展数据分析使用数", "当月手动扩展竞品数", "当月手动扩展竞品使用数",
	}

	// 写表头
	for i, h := range headers {
		col, _ := excelize.ColumnNumberToName(i + 1)
		cell := col + "1"
		if err := f.SetCellValue(sheet, cell, h); err != nil {
			return err
		}
	}

	// 从第2行开始写数据
	for r, it := range items {
		row := r + 2
		// 逐列写入（注意顺序必须和 headers 一致）
		write := func(colIdx int, v interface{}) error {
			col, _ := excelize.ColumnNumberToName(colIdx)
			cell := fmt.Sprintf("%s%d", col, row)
			return f.SetCellValue(sheet, cell, v)
		}
		_ = write(1, it.Month)
		_ = write(2, it.CustomerNum)
		_ = write(3, it.UserName)
		_ = write(4, it.UserPhoneNumber)
		_ = write(5, it.PayTime)
		_ = write(6, fmt.Sprintf("%.2f", it.BundleAmount))
		_ = write(7, fmt.Sprintf("%.2f", it.IncreaseAmount))
		_ = write(8, fmt.Sprintf("%.2f", it.TotalPayAmount))
		_ = write(9, it.Currency)
		_ = write(10, it.Fee)

		// 套餐视频数量及单价
		_ = write(11, int(it.BundleVideoNumber))
		_ = write(12, int(it.IncreaseVideoNumber))
		_ = write(13, fmt.Sprintf("%.2f", it.BundleVideoUnitPrice))
		_ = write(14, fmt.Sprintf("%.2f", it.IncreaseVideoUnitPrice))

		// 当月视频消耗金额($)
		monthlyBundleVideoConsumptionPrice, err := strconv.ParseFloat(it.MonthlyBundleVideoConsumptionPrice, 64)
		if err != nil {
			return err
		}
		monthlyIncreaseVideoConsumptionPrice, err := strconv.ParseFloat(it.MonthlyIncreaseVideoConsumptionPrice, 64)
		if err != nil {
			return err
		}
		_ = write(15, fmt.Sprintf("%.2f", monthlyBundleVideoConsumptionPrice))
		_ = write(16, fmt.Sprintf("%.2f", monthlyIncreaseVideoConsumptionPrice))

		// 账号类
		_ = write(17, int(it.BundleAccountNumber))
		_ = write(18, int(it.IncreaseAccountNumber))
		_ = write(19, int(it.BundleAccountConsumptionNumber))
		_ = write(20, int(it.IncreaseAccountConsumptionNumber))

		// 视频类
		_ = write(21, int(it.MonthlyBundleVideoNumber))
		_ = write(22, int(it.MonthlyIncreaseVideoNumber))
		_ = write(23, int(it.BundleVideoConsumptionNumber))
		_ = write(24, int(it.IncreaseVideoConsumptionNumber))
		_ = write(25, int(it.InvalidBundleVideoNumber))
		_ = write(26, int(it.InvalidIncreaseVideoNumber))
		_ = write(27, int(it.MonthlyNewBundleVideoNumber))
		_ = write(28, int(it.MonthlyNewIncreaseVideoNumber))
		_ = write(29, int(it.MonthlyBundleVideoConsumptionNumber))
		_ = write(30, int(it.MonthlyIncreaseVideoConsumptionNumber))
		_ = write(31, int(it.MonthlyInvalidBundleVideoNumber))
		_ = write(32, int(it.MonthlyInvalidIncreaseVideoNumber))

		// 图文类
		_ = write(33, int(it.MonthlyBundleImageNumber))
		_ = write(34, int(it.MonthlyIncreaseImageNumber))
		_ = write(35, int(it.BundleImageConsumptionNumber))
		_ = write(36, int(it.IncreaseImageConsumptionNumber))
		_ = write(37, int(it.InvalidBundleImageNumber))
		_ = write(38, int(it.InvalidIncreaseImageNumber))
		_ = write(39, int(it.MonthlyNewBundleImageNumber))
		_ = write(40, int(it.MonthlyNewIncreaseImageNumber))
		_ = write(41, int(it.MonthlyBundleImageConsumptionNumber))
		_ = write(42, int(it.MonthlyIncreaseImageConsumptionNumber))
		_ = write(43, int(it.MonthlyInvalidBundleImageNumber))
		_ = write(44, int(it.MonthlyInvalidIncreaseImageNumber))

		// 数据分析类
		_ = write(45, int(it.MonthlyBundleDataAnalysisNumber))
		_ = write(46, int(it.MonthlyIncreaseDataAnalysisNumber))
		_ = write(47, int(it.BundleDataAnalysisConsumptionNumber))
		_ = write(48, int(it.IncreaseDataAnalysisConsumptionNumber))
		_ = write(49, int(it.InvalidBundleDataAnalysisNumber))
		_ = write(50, int(it.InvalidIncreaseDataAnalysisNumber))
		_ = write(51, int(it.MonthlyNewBundleDataAnalysisNumber))
		_ = write(52, int(it.MonthlyNewIncreaseDataAnalysisNumber))
		_ = write(53, int(it.MonthlyBundleDataAnalysisConsumptionNumber))
		_ = write(54, int(it.MonthlyIncreaseDataAnalysisConsumptionNumber))
		_ = write(55, int(it.MonthlyInvalidBundleDataAnalysisNumber))
		_ = write(56, int(it.MonthlyInvalidIncreaseDataAnalysisNumber))

		// 竞品数
		_ = write(57, int(it.MonthlyBundleCompetitiveNumber))
		_ = write(58, int(it.MonthlyIncreaseCompetitiveNumber))
		_ = write(59, int(it.BundleCompetitiveConsumptionNumber))
		_ = write(60, int(it.IncreaseCompetitiveConsumptionNumber))
		_ = write(61, int(it.InvalidBundleCompetitiveNumber))
		_ = write(62, int(it.InvalidIncreaseCompetitiveNumber))
		_ = write(63, int(it.MonthlyNewBundleCompetitiveNumber))
		_ = write(64, int(it.MonthlyNewIncreaseCompetitiveNumber))
		_ = write(65, int(it.MonthlyBundleCompetitiveConsumptionNumber))
		_ = write(66, int(it.MonthlyIncreaseCompetitiveConsumptionNumber))
		_ = write(67, int(it.MonthlyInvalidBundleCompetitiveNumber))
		_ = write(68, int(it.MonthlyInvalidIncreaseCompetitiveNumber))

		// 手动扩展类
		_ = write(69, int(it.MonthlyNewManualAccountNumber))
		_ = write(70, int(it.MonthlyNewManualVideoNumber))
		_ = write(71, int(it.MonthlyNewManualImageNumber))
		_ = write(72, int(it.MonthlyNewManualDataAnalysisNumber))
		_ = write(73, int(it.MonthlyNewDurationNumber))
		_ = write(74, int(it.MonthlyManualAccountConsumptionNumber))
		_ = write(75, int(it.MonthlyManualVideoConsumptionNumber))
		_ = write(76, int(it.MonthlyManualImageConsumptionNumber))
		_ = write(77, int(it.MonthlyManualDataAnalysisConsumptionNumber))
		_ = write(78, int(it.MonthlyNewManualCompetitiveNumber))
		_ = write(79, int(it.MonthlyManualCompetitiveConsumptionNumber))

	}

	// 可选：设置列宽，使表格更美观
	_ = f.SetColWidth(sheet, "A", "BZ", 15)

	// 保存文件
	if err := f.SaveAs(filename); err != nil {
		return err
	}
	return nil
}

func GetAccountBundleBalance(c *gin.Context) {
	var req bundle.GetBundleBalanceListReq
	if err := c.ShouldBindJSON(&req); err != nil {
		service.Error(c, err)
		return
	}
	req.Month = []string{time.Now().Format("2006-01")}
	res, err := service.BundleProvider.GetBundleBalanceList(context.Background(), &req)
	if err != nil {
		service.Error(c, errors.New(common.GetBundleBalanceListFailed))
		return
	}
	result := bundleModel.GetBundleBalanceListResp{
		Total: res.Total,
	}
	result.Data = lo.Map(res.Data, func(item *bundle.BundleBalanceItem, index int) *bundleModel.BundleBalanceItem {
		return &bundleModel.BundleBalanceItem{
			UserId:                        item.UserId,
			UserName:                      item.UserName,
			UserPhoneNumber:               item.UserPhoneNumber,
			Status:                        item.Status,
			BundleName:                    item.BundleName,
			ExpiredTime:                   item.ExpiredTime,
			AccountNumber:                 item.BundleAccountNumber + item.IncreaseAccountNumber + item.ManualAccountNumber,
			AccountConsumptionNumber:      item.BundleAccountConsumptionNumber + item.IncreaseAccountConsumptionNumber + item.ManualAccountConsumptionNumber,
			VideoNumber:                   item.BundleVideoNumber + item.IncreaseVideoNumber + item.ManualVideoNumber,
			VideoConsumptionNumber:        item.BundleVideoConsumptionNumber + item.IncreaseVideoConsumptionNumber + item.ManualVideoConsumptionNumber,
			ImageNumber:                   item.BundleImageNumber + item.IncreaseImageNumber + item.ManualImageNumber,
			ImageConsumptionNumber:        item.BundleImageConsumptionNumber + item.IncreaseImageConsumptionNumber + item.ManualImageNumber,
			DataAnalysisNumber:            item.BundleDataAnalysisNumber + item.IncreaseDataAnalysisNumber + item.ManualDataAnalysisNumber,
			DataAnalysisConsumptionNumber: item.BundleDataAnalysisConsumptionNumber + item.IncreaseDataAnalysisConsumptionNumber + item.ManualDataAnalysisNumber,
			CompetitiveNumber:             item.BundleCompetitiveNumber + item.IncreaseCompetitiveNumber + item.ManualCompetitiveNumber,
			CompetitiveConsumptionNumber:  item.BundleCompetitiveConsumptionNumber + item.IncreaseCompetitiveConsumptionNumber + item.ManualCompetitiveConsumptionNumber,
			Bought:                        item.Bought,
		}
	})
	service.Success(c, result)
}

func writeToExcelCast(filename string, items []*bundle.WorkCastInfo) error {
	f := excelize.NewFile()
	sheet := "Sheet1"

	// 手动表头（顺序与写入字段顺序必须一致）
	headers := []string{
		"用户名称", "用户编号", "套餐名称", "下单时间",
		"作品标题", "消费类型", "作品类型", "验收类型",
		"作品上传时间", "艺人待确认时间", "艺人验收确认时间",
	}

	// 写表头
	for i, h := range headers {
		col, _ := excelize.ColumnNumberToName(i + 1)
		cell := col + "1"
		if err := f.SetCellValue(sheet, cell, h); err != nil {
			return err
		}
	}

	// 从第2行开始写数据
	for r, it := range items {
		row := r + 2
		// 逐列写入（注意顺序必须和 headers 一致）
		write := func(colIdx int, v interface{}) error {
			col, _ := excelize.ColumnNumberToName(colIdx)
			cell := fmt.Sprintf("%s%d", col, row)
			return f.SetCellValue(sheet, cell, v)
		}
		costType := ""
		if it.CostType == 1 {
			costType = "套餐"
		} else if it.CostType == 2 {
			costType = "增值"
		}
		workCategory := ""
		if it.WorkCategory == 1 {
			workCategory = "图文"
		} else if it.WorkCategory == 2 {
			workCategory = "视频"
		}
		confirmType := ""
		if it.ConfirmType == 2 {
			confirmType = "系统确认"
		} else if it.ConfirmType == 1 {
			confirmType = "艺人确认"
		} else {
			confirmType = "未确认"
		}
		_ = write(1, it.CustomerName)
		_ = write(2, it.CustomerNum)
		_ = write(3, it.BundleName)
		_ = write(4, it.SignedTime)
		_ = write(5, it.Title)
		_ = write(6, costType)
		_ = write(7, workCategory)
		_ = write(8, confirmType)
		_ = write(9, it.SubmitTime)
		_ = write(10, it.WaitingTime)
		_ = write(11, it.ConfirmTime)
	}

	// 可选：设置列宽，使表格更美观
	_ = f.SetColWidth(sheet, "A", "AZ", 15)

	// 保存文件
	if err := f.SaveAs(filename); err != nil {
		return err
	}
	return nil
}

func writeToExcelPriceInfo(filename string, items []*bundle.BundleBalanceExportItem) error {
	f := excelize.NewFile()
	sheet := "Sheet1"

	// 手动表头（顺序与写入字段顺序必须一致）
	headers := []string{
		"所属月份", "用户编号", "姓名", "手机号", "手续费",
		"套餐视频总数", "增值服务视频总数", "套餐视频单价", "增值视频单价",
		"当月使用套餐视频数", "当月使用增值视频数",
		"当月消耗套餐金额($)", "当月消耗增值金额($)",
	}

	// 写表头
	for i, h := range headers {
		col, _ := excelize.ColumnNumberToName(i + 1)
		cell := col + "1"
		if err := f.SetCellValue(sheet, cell, h); err != nil {
			return err
		}
	}

	// 从第2行开始写数据
	for r, it := range items {
		row := r + 2
		// 逐列写入（注意顺序必须和 headers 一致）
		write := func(colIdx int, v interface{}) error {
			col, _ := excelize.ColumnNumberToName(colIdx)
			cell := fmt.Sprintf("%s%d", col, row)
			return f.SetCellValue(sheet, cell, v)
		}
		_ = write(1, it.Month)
		_ = write(2, it.CustomerNum)
		_ = write(3, it.UserName)
		_ = write(4, it.UserPhoneNumber)
		_ = write(5, it.Fee)

		// 套餐视频数量及单价
		_ = write(6, int(it.BundleVideoNumber))
		_ = write(7, int(it.IncreaseVideoNumber))
		_ = write(8, fmt.Sprintf("%.2f", it.BundleVideoUnitPrice))
		_ = write(9, fmt.Sprintf("%.2f", it.IncreaseVideoUnitPrice))

		// 视频类
		_ = write(10, int(it.MonthlyBundleVideoConsumptionNumber))
		_ = write(11, int(it.MonthlyIncreaseVideoConsumptionNumber))

		// 当月视频消耗金额($)
		monthlyBundleVideoConsumptionPrice, err := strconv.ParseFloat(it.MonthlyBundleVideoConsumptionPrice, 64)
		if err != nil {
			return err
		}
		monthlyIncreaseVideoConsumptionPrice, err := strconv.ParseFloat(it.MonthlyIncreaseVideoConsumptionPrice, 64)
		if err != nil {
			return err
		}
		_ = write(12, fmt.Sprintf("%.2f", monthlyBundleVideoConsumptionPrice))
		_ = write(13, fmt.Sprintf("%.2f", monthlyIncreaseVideoConsumptionPrice))

	}

	// 可选：设置列宽，使表格更美观
	_ = f.SetColWidth(sheet, "A", "AZ", 15)

	// 保存文件
	if err := f.SaveAs(filename); err != nil {
		return err
	}
	return nil
}
