package cast

import (
	"context"
	"errors"
	"fmt"
	"fonchain-fiee/api/accountFiee"
	"fonchain-fiee/api/bundle"
	"fonchain-fiee/api/cast"
	"fonchain-fiee/cmd/config"
	"fonchain-fiee/pkg/cache"
	"fonchain-fiee/pkg/e"
	modelCast "fonchain-fiee/pkg/model/cast"
	"fonchain-fiee/pkg/model/login"
	"fonchain-fiee/pkg/service"
	"fonchain-fiee/pkg/service/upload"
	"fonchain-fiee/pkg/utils"
	"os"
	"path/filepath"
	"strconv"
	"time"

	"dubbo.apache.org/dubbo-go/v3/common/constant"
	"github.com/gin-gonic/gin"
	"github.com/xuri/excelize/v2"
	"go.uber.org/zap"
)

// CreateCompetitiveReport 创建竞品报告
func CreateCompetitiveReport(ctx *gin.Context) {
	var req *cast.CreateCompetitiveReportReq
	var err error
	if err = ctx.ShouldBind(&req); err != nil {
		service.Error(ctx, err)
		return
	}

	loginInfo := login.GetUserInfoFromC(ctx)
	lockKey := fmt.Sprintf("lock_create_competitive_report_%d", loginInfo.ID)
	reply := cache.RedisClient.SetNX(lockKey, time.Now().Format("2006-01-02 15:04:05"), time.Second*5)
	if !reply.Val() {
		service.Error(ctx, errors.New("请勿重复提交"))
		return
	}
	defer func() {
		cache.RedisClient.Del(lockKey)
	}()

	newCtx := NewCtxWithUserInfo(ctx)
	artistID, _ := strconv.ParseUint(req.ArtistID, 10, 64)

	// 通过接口查询艺人信息，自动填充艺人名字、手机号等信息
	var infoResp *accountFiee.UserInfoResponse
	if config.AppConfig.System.AppMode != "dev" {
		infoResp, err = service.AccountFieeProvider.Info(context.Background(), &accountFiee.InfoRequest{
			ID:     artistID,
			Domain: "app",
		})
		zap.L().Info("CreateCompetitiveReport", zap.Any("infoResp", infoResp))
		if err != nil {
			service.Error(ctx, err)
			return
		}
	} else {
		infoResp = &accountFiee.UserInfoResponse{
			Name:   "小波",
			TelNum: "18288888888",
			SubNum: "FE00000",
		}
	}

	// 填充艺人信息到请求中
	req.ArtistName = infoResp.Name
	req.ArtistPhone = infoResp.TelNum
	req.SubNum = infoResp.SubNum
	req.Source = 1

	if _, err = CheckUserBundleBalance(int32(artistID), modelCast.BalanceTypeCompetitiveValue); err != nil {
		if err != nil && err.Error() == e.ErrorBalanceInsufficient {
			service.Error(ctx, errors.New("该艺人竞品报告可用次数为0"))
			return
		}
		service.Error(ctx, err)
		return
	}

	if req.ReportContent == "" || req.ImageUrl == "" {
		err = errors.New("报告内容和图片不能同时为空")
		service.Error(ctx, err)
		return
	}

	// 如果提供了报告内容和图片URL，则生成PDF并上传
	if req.ReportContent != "" {
		// 生成临时PDF文件路径
		pdfFileName := fmt.Sprintf("competitive_report_%s_%d.pdf", req.ArtistID, time.Now().UnixMicro())
		pdfFilePath := "./runtime/report_pdf/" + pdfFileName

		// 确保目录存在
		_, err = utils.CheckDirPath("./runtime/report_pdf/", true)
		if err != nil {
			service.Error(ctx, fmt.Errorf("创建PDF目录失败: %v", err))
			return
		}

		// 生成PDF文件
		fontPath := "./data/simfang.ttf"
		err = utils.GeneratePDF(req.ReportContent, req.ImageUrl, pdfFilePath, fontPath)
		if err != nil {
			fmt.Println("生成PDF失败", err)
			zap.L().Error("生成PDF失败", zap.Error(err))
			service.Error(ctx, errors.New("生成PDF失败"))
			return
		}
		fmt.Println("生成PDF成功", pdfFilePath)

		defer func() {
			// 检查文件是否存在，存在才删除
			if _, err := os.Stat(pdfFilePath); err == nil {
				if err := os.Remove(pdfFilePath); err != nil {
					zap.L().Warn("删除临时PDF文件失败", zap.String("path", pdfFilePath), zap.Error(err))
				} else {
					zap.L().Info("删除临时PDF文件成功", zap.String("path", pdfFilePath))
				}
			}
		}()

		// 上传PDF到OSS
		pdfUrl, uploadErr := upload.PutBos(pdfFilePath, upload.PdfType, true)
		if uploadErr != nil {
			zap.L().Error("上传PDF失败: %v", zap.Error(uploadErr))
			service.Error(ctx, errors.New("上传PDF失败"))
			return
		}

		// 将上传后的PDF链接设置到请求中
		req.PdfUrl = pdfUrl
	} else {
		req.PdfUrl = req.ImageUrl
	}

	resp, err := service.CastProvider.CreateCompetitiveReport(newCtx, req)
	if err != nil {
		service.Error(ctx, err)
		return
	}
	service.Success(ctx, resp)
	return
}

// ImportCompetitiveReportBatch 批量导入竞品报告
func ImportCompetitiveReportBatch(ctx *gin.Context) {
	// 获取上传的Excel文件
	excelFile, err := ctx.FormFile("file")
	if err != nil {
		service.Error(ctx, err)
		return
	}

	loginInfo := login.GetUserInfoFromC(ctx)
	lockKey := fmt.Sprintf("import_competitive_report_batch:%d", loginInfo.ID)
	replay := cache.RedisClient.SetNX(lockKey, time.Now().Format("20060102150405"), 5*time.Minute)
	if !replay.Val() {
		service.Error(ctx, errors.New("有导入任务正在进行，请稍后再试"))
		return
	}
	defer cache.RedisClient.Del(lockKey)

	tempDir := "./runtime/report"
	_, err = utils.CheckDirPath(tempDir, true)
	if err != nil {
		service.Error(ctx, err)
		return
	}

	// 生成文件名并保存文件
	fileName := fmt.Sprintf("%d_competitive_report.xlsx", time.Now().UnixMicro())
	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.ImportCompetitiveReportBatchReq{
		Reports: make([]*cast.CreateCompetitiveReportReq, 0),
	}

	// 生成结果文件URL
	urlHost := config.AppConfig.System.FieeHost
	urlResult := fmt.Sprintf("%s/api/fiee/static/report/%s", urlHost, fileName)

	// 记录每行数据对应的Excel行号（用于后续匹配失败记录）
	reportRowMap := make(map[*cast.CreateCompetitiveReportReq]int)

	for line, row := range rows {
		// 跳过表头
		if line == 0 {
			continue
		}
		// 跳过空行
		if len(row) == 0 {
			continue
		}

		// 创建报告请求对象
		temp := &cast.CreateCompetitiveReportReq{
			Source: 2, // 来源：2 导入
		}
		// 记录Excel行号（line+1是因为Excel行号从1开始，且跳过表头）
		excelRowNum := line + 1
		reportRowMap[temp] = excelRowNum

		// 解析艺人编号（B列，row[1]）
		var artistNum string
		if len(row) > 1 && utils.CleanString(row[1]) != "" {
			artistNum = utils.CleanString(row[1])
			artistSubNum := utils.CleanString(row[1])
			if artistSubNum == "" {
				temp.Remark = "艺人编号不能为空"
				req.Reports = append(req.Reports, temp)
				continue
			}
			var subInfoResp *accountFiee.UserInfoResponse
			subInfoResp, err := service.AccountFieeProvider.SubNumGetInfo(context.Background(), &accountFiee.SubNumGetInfoRequest{
				SubNum: artistSubNum,
				Domain: "app",
			})

			if err != nil {
				temp.Remark = fmt.Sprintf("自媒体用户查询失败：%s", err.Error())
				zap.L().Error("AccountFieeProvider.SubNumGetInfo", zap.Error(err))
				req.Reports = append(req.Reports, temp)
				continue
			}

			if subInfoResp == nil || subInfoResp.Id == 0 {
				temp.Remark = "自媒体用户不存在"
				zap.L().Error("AccountFieeProvider.SubNumGetInfo user not found", zap.String("subNum", artistSubNum))
				req.Reports = append(req.Reports, temp)
				continue
			}

			// 设置艺人信息
			temp.SubNum = artistSubNum
			temp.ArtistID = fmt.Sprint(subInfoResp.Id)
			temp.ArtistName = subInfoResp.Name
			temp.ArtistPhone = subInfoResp.TelNum

			// 这里根据 ArtistID 查询竞品报告余额
			artistID, _ := strconv.ParseUint(temp.ArtistID, 10, 64)
			if _, err = CheckUserBundleBalance(int32(artistID), modelCast.BalanceTypeCompetitiveValue); err != nil {
				if err != nil && err.Error() == e.ErrorBalanceInsufficient {
					temp.Remark = "该艺人竞品报告可用次数为0"
					req.Reports = append(req.Reports, temp)
					continue
				}
				if err != nil {
					temp.Remark = errors.New("查询竞品报告余额失败").Error()
					req.Reports = append(req.Reports, temp)
					continue
				}
			}
		}

		// 解析标题（C列，row[2]）
		if len(row) > 2 {
			temp.Title = utils.CleanString(row[2])
		}

		// 解析报告内容（D列，row[3]）
		if len(row) > 3 {
			temp.ReportContent = row[3]
		}

		// 解析图片URL（E列，row[4]）
		if len(row) > 4 && utils.CleanString(row[4]) != "" {
			temp.ImageUrl = utils.CleanString(row[4])
		}

		// 解析PDF URL（F列，row[5]），可选
		if len(row) > 5 && utils.CleanString(row[5]) != "" {
			temp.PdfUrl = utils.CleanString(row[5])
		}

		// 验证必填字段
		if artistNum == "" {
			temp.Remark = "艺人编号不能为空"
			req.Reports = append(req.Reports, temp)
			continue
		}

		if temp.PdfUrl == "" {
			temp.Remark = "PDF URL不能为空"
			req.Reports = append(req.Reports, temp)
			continue
		}

		req.Reports = append(req.Reports, temp)
	}

	// 检查是否有数据
	if len(req.Reports) == 0 {
		service.Error(ctx, errors.New(e.ErrNoData))
		return
	}

	// 调用批量导入接口
	newCtx := NewCtxWithUserInfo(ctx)
	resp, err := service.CastProvider.ImportCompetitiveReportBatch(newCtx, &req)
	if err != nil {
		service.Error(ctx, err)
		return
	}

	// 如果有失败的数据，生成结果文件
	if resp.FailCount > 0 {
		hasValueRows := make(map[int]bool, resp.FailCount)
		// 遍历响应结果，标记失败的行
		// resp.Reports的顺序应该与req.Reports的顺序一致
		for i, v := range resp.Reports {
			if !v.Success {
				// 根据索引找到对应的请求对象
				if i < len(req.Reports) {
					reqReport := req.Reports[i]
					// 通过请求对象找到对应的Excel行号
					if excelRowNum, ok := reportRowMap[reqReport]; ok {
						// 将错误信息写入最后一列（G列，可根据实际模板调整）
						excelData.SetCellValue("Sheet1", fmt.Sprintf("G%d", excelRowNum), v.Remark)
						hasValueRows[excelRowNum] = true
					}
				}
			}
		}

		// 删除成功的行（从后往前删除，避免行号变化）
		for i := len(rows) - 1; i >= 1; i-- {
			if !hasValueRows[i+1] {
				if err = excelData.RemoveRow("Sheet1", i+1); err != nil {
					continue
				}
			}
		}
		// 保存结果文件
		resultPath := fmt.Sprintf("./runtime/report/%s", fileName)
		if err = excelData.SaveAs(resultPath); err != nil {
			service.Error(ctx, err)
			return
		}
	}

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

// UpdateCompetitiveReportStatus 更新竞品报告状态
func UpdateCompetitiveReportStatus(ctx *gin.Context) {
	var req *cast.UpdateCompetitiveReportStatusReq
	var err error
	if err = ctx.ShouldBind(&req); err != nil {
		service.Error(ctx, err)
		return
	}
	newCtx := NewCtxWithUserInfo(ctx)
	_, err = service.CastProvider.UpdateCompetitiveReportStatus(newCtx, req)
	if err != nil {
		service.Error(ctx, err)
		return
	}
	service.Success(ctx, nil)
	return
}

// GetCompetitiveReport 获取竞品报告详情
func GetCompetitiveReport(ctx *gin.Context) {
	var req *cast.GetCompetitiveReportDetailReq
	var err error
	if err = ctx.ShouldBind(&req); err != nil {
		service.Error(ctx, err)
		return
	}
	newCtx := NewCtxWithUserInfo(ctx)
	resp, err := service.CastProvider.GetCompetitiveReport(newCtx, req)
	if err != nil {
		service.Error(ctx, err)
		return
	}
	service.Success(ctx, resp)
	return
}

// GetCompetitiveReportForApp 获取竞品报告详情（App端）
func GetCompetitiveReportForApp(ctx *gin.Context) {
	var req *cast.GetCompetitiveReportForAppReq
	var err error
	if err = ctx.ShouldBind(&req); err != nil {
		service.Error(ctx, err)
		return
	}
	newCtx := NewCtxWithUserInfo(ctx)
	resp, err := service.CastProvider.GetCompetitiveReportForApp(newCtx, req)
	if err != nil {
		service.Error(ctx, err)
		return
	}
	service.Success(ctx, resp)
	return
}

// ListCompetitiveReport 获取竞品报告列表
func ListCompetitiveReport(ctx *gin.Context) {
	var req *cast.ListCompetitiveReportReq
	var err error
	if err = ctx.ShouldBind(&req); err != nil {
		service.Error(ctx, err)
		return
	}
	newCtx := NewCtxWithUserInfo(ctx)
	resp, err := service.CastProvider.ListCompetitiveReport(newCtx, req)
	if err != nil {
		service.Error(ctx, err)
		return
	}
	RefreshCompetitiveReportApproval(ctx, resp.Data)
	service.Success(ctx, resp)
	return
}

// ListCompetitiveReportByArtistUuid 根据艺人UUID获取竞品报告列表（必须传ArtistUuid）
func ListCompetitiveReportByArtistUuid(ctx *gin.Context) {
	var req *cast.ListCompetitiveReportReq
	var err error
	if err = ctx.ShouldBind(&req); err != nil {
		service.Error(ctx, err)
		return
	}
	// 验证ArtistUuid必须存在
	if req.ArtistUuid == "" {
		service.Error(ctx, errors.New("ArtistUuid不能为空"))
		return
	}
	// 复用ListCompetitiveReport的逻辑
	newCtx := NewCtxWithUserInfo(ctx)
	resp, err := service.CastProvider.ListCompetitiveReport(newCtx, req)
	if err != nil {
		service.Error(ctx, err)
		return
	}
	// RefreshCompetitiveReportApproval(ctx, resp.Data)
	service.Success(ctx, resp)
	return
}

// DeleteCompetitiveReport 删除竞品报告
func DeleteCompetitiveReport(ctx *gin.Context) {
	var req *cast.DeleteCompetitiveReportReq
	var err error
	if err = ctx.ShouldBind(&req); err != nil {
		service.Error(ctx, err)
		return
	}
	newCtx := NewCtxWithUserInfo(ctx)
	_, err = service.CastProvider.DeleteCompetitiveReport(newCtx, req)
	if err != nil {
		service.Error(ctx, err)
		return
	}
	service.Success(ctx, nil)
	return
}

// UpdateCompetitiveReportApprovalID 更新竞品报告审批ID
func UpdateCompetitiveReportApprovalID(ctx *gin.Context) {
	var req *cast.UpdateCompetitiveReportApprovalIDReq
	var err error
	if err = ctx.ShouldBind(&req); err != nil {
		service.Error(ctx, err)
		return
	}
	newCtx := NewCtxWithUserInfo(ctx)
	_, err = service.CastProvider.UpdateCompetitiveReportApprovalID(newCtx, req)
	if err != nil {
		service.Error(ctx, err)
		return
	}
	service.Success(ctx, nil)
	return
}

// CountCompetitiveReportByWorkUuids 根据作品UUID统计竞品报告数量
func CountCompetitiveReportByWorkUuids(ctx *gin.Context) {
	var req *cast.CountCompetitiveReportByWorkUuidsReq
	var err error
	if err = ctx.ShouldBind(&req); err != nil {
		service.Error(ctx, err)
		return
	}
	newCtx := NewCtxWithUserInfo(ctx)
	resp, err := service.CastProvider.CountCompetitiveReportByWorkUuids(newCtx, req)
	if err != nil {
		service.Error(ctx, err)
		return
	}
	service.Success(ctx, resp)
	return
}

// getCompetitiveReportStatusText 获取竞品报告状态文本
func getCompetitiveReportStatusText(status uint32) string {
	switch status {
	case 1:
		return "待提交"
	case 2:
		return "审批中"
	case 3:
		return "审批驳回"
	case 4:
		return "待艺人验收"
	case 5:
		return "验收失败"
	case 6:
		return "待阅读"
	case 7:
		return "已阅读"
	default:
		return ""
	}
}

// ListCompetitiveReportExport 获取竞品报告列表并导出Excel
func ListCompetitiveReportExport(ctx *gin.Context) {
	var req *cast.ListCompetitiveReportReq
	var err error
	if err = ctx.ShouldBind(&req); err != nil {
		service.Error(ctx, err)
		return
	}
	req.Page = 1
	req.PageSize = 999999999

	newCtx := NewCtxWithUserInfo(ctx)
	resp, err := service.CastProvider.ListCompetitiveReport(newCtx, req)
	if err != nil {
		service.Error(ctx, err)
		return
	}

	titleList := []string{
		"标题", "艺人", "用户编号", "手机号", "状态", "验收确认类型", "原因", "状态变更时间", "提交时间", "操作人", "pdf链接",
	}

	var dataList []interface{}
	for _, i := range resp.Data {
		data := []any{
			i.Title,
			i.ArtistName,
			i.SubNum,
			i.ArtistPhone,
			getCompetitiveReportStatusText(i.WorkReportStatus),
			getComfirmTypeText(i.ComfirmType),
			i.Reason,
			i.StatusUpdateTime,
			i.SubmitTime,
			i.OperatorName,
			i.PdfUrl,
		}
		dataList = append(dataList, &data)
	}

	content, err := utils.ToExcelByType(titleList, dataList, "slice", "")
	if err != nil {
		service.Error(ctx, err)
		return
	}
	utils.ResponseXls(ctx, content, "竞品报告列表")
	return
}

// ListCompetitiveReportSingleExport 获取竞品报告列表并导出Excel（单个列表）
func ListCompetitiveReportSingleExport(ctx *gin.Context) {
	var req *cast.ListCompetitiveReportReq
	var err error
	if err = ctx.ShouldBind(&req); err != nil {
		service.Error(ctx, err)
		return
	}
	req.Page = 1
	req.PageSize = 999999999

	newCtx := NewCtxWithUserInfo(ctx)
	resp, err := service.CastProvider.ListCompetitiveReport(newCtx, req)
	if err != nil {
		service.Error(ctx, err)
		return
	}

	titleList := []string{
		"标题", "状态", "验收确认类型", "原因", "状态变更时间", "操作人", "提交时间", "pdf链接",
	}

	var dataList []interface{}
	for _, i := range resp.Data {
		data := []any{
			i.Title,
			getCompetitiveReportStatusText(i.WorkReportStatus),
			getComfirmTypeText(i.ComfirmType),
			i.Reason,
			i.StatusUpdateTime,
			i.OperatorName,
			i.SubmitTime,
			i.PdfUrl,
		}
		dataList = append(dataList, &data)
	}

	content, err := utils.ToExcelByType(titleList, dataList, "slice", "")
	if err != nil {
		service.Error(ctx, err)
		return
	}
	utils.ResponseXls(ctx, content, "竞品报告列表")
	return
}

// RefreshCompetitiveReportApproval 刷新竞品报告审批状态
func RefreshCompetitiveReportApproval(ctx *gin.Context, data []*cast.CompetitiveReportInfo) {
	if len(data) > 0 {
		var reportUuidApprovalIDMap = make(map[int]string)
		for _, v := range data {
			// 状态为2表示待审批，需要获取详情来获取ApprovalID
			if v.WorkReportStatus == 2 && v.ApprovalID != "" {
				zap.L().Info("RefreshCompetitiveReportApproval", zap.Any("approvalID", v.ApprovalID))
				approvalID, _ := strconv.ParseUint(v.ApprovalID, 10, 64)
				reportUuidApprovalIDMap[int(approvalID)] = v.Uuid
			}
		}
		if len(reportUuidApprovalIDMap) > 0 {
			_ = RefreshCompetitiveReportApprovalStatus(ctx, reportUuidApprovalIDMap)
		}
	}
}

// RefreshCompetitiveReportApprovalStatus 刷新竞品报告审批状态详情
func RefreshCompetitiveReportApprovalStatus(ctx *gin.Context, approvalIDReportUuidMap map[int]string) (err error) {
	var castS = new(CastService)
	var data = make(map[int]modelCast.Item)
	var approvalIDs []int
	for approvalId := range approvalIDReportUuidMap {
		approvalIDs = append(approvalIDs, approvalId)
	}
	if len(approvalIDs) == 0 {
		return
	}
	data, err = castS.ApprovalDetail(approvalIDs)
	if err != nil {
		return
	}
	// status: 1待审批 2审批通过 3审批不通过 6撤销发其中 7撤销完成
	var newData = make(map[int]modelCast.Item, len(approvalIDs))
	for _, v := range approvalIDs {
		newData[v] = data[v]
	}
	newCtx := NewCtxWithUserInfo(ctx)
	if len(newData) > 0 {
		for approvalId, v := range newData {
			if v.ID == 0 {
				_, _ = service.CastProvider.UpdateCompetitiveReportStatus(newCtx, &cast.UpdateCompetitiveReportStatusReq{
					WorkAction:    cast.WorkActionENUM_APPROVAL_DELETE,
					Uuid:          approvalIDReportUuidMap[approvalId],
					ApprovalID:    fmt.Sprint(approvalId),
					ApprovalReply: "",
				})
				continue
			}
			var workAction cast.WorkActionENUM
			if v.Status == 2 {
				workAction = cast.WorkActionENUM_APPROVAL_PASS
			} else if v.Status == 3 {
				workAction = cast.WorkActionENUM_APPROVAL_REJECT
			} else {
				continue
			}
			_, _ = service.CastProvider.UpdateCompetitiveReportStatus(newCtx, &cast.UpdateCompetitiveReportStatusReq{
				WorkAction:    workAction,
				Uuid:          approvalIDReportUuidMap[approvalId],
				ApprovalID:    fmt.Sprint(approvalId),
				ApprovalReply: v.Reply,
			})
		}
	}
	return
}

// ProcessReportTask 处理竞品报告自动确认任务
func ProcessReportTask(ctx context.Context, reportUuid string) {
	lockKey := fmt.Sprintf(modelCast.AutoConfirmReportLockKey, reportUuid)
	reply := cache.RedisClient.SetNX(lockKey, "1", 5*time.Minute)
	if !reply.Val() {
		zap.L().Warn("竞品报告任务正在被其他实例处理", zap.String("reportUuid", reportUuid))
		return
	}
	defer func() {
		cache.RedisClient.Del(lockKey)
	}()
	err := autoConfirmReport(ctx, reportUuid)
	if err != nil {
		zap.L().Error("竞品报告自动确认失败",
			zap.String("reportUuid", reportUuid),
			zap.Error(err))
		return
	}
	// 从队列中移除
	err = cache.RedisClient.ZRem(modelCast.AutoConfirmReportQueueKey, reportUuid).Err()
	if err != nil {
		zap.L().Error("从队列移除竞品报告任务失败",
			zap.String("reportUuid", reportUuid),
			zap.Error(err))
	}
	zap.L().Info("竞品报告自动确认成功", zap.String("reportUuid", reportUuid))
}

// autoConfirmReport 自动确认竞品报告
func autoConfirmReport(ctx context.Context, reportUuid string) (err error) {
	var confirmRemark string
	var isFailed bool
	var usedType uint32
	infoResp, err := service.CastProvider.GetCompetitiveReport(context.Background(), &cast.GetCompetitiveReportDetailReq{
		Uuid: reportUuid,
	})
	if err != nil {
		zap.L().Error("autoConfirmReport GetCompetitiveReport", zap.Any("err", err))
		confirmRemark = "获取竞品报告详情失败:" + err.Error()
		isFailed = true
		return
	}
	if infoResp == nil {
		zap.L().Error("autoConfirmReport GetCompetitiveReport返回nil")
		return
	}

	if infoResp.WorkReportStatus != 4 { // 4是待确认状态
		return
	}
	userID, _ := strconv.ParseInt(infoResp.ArtistID, 10, 64)
	balanceInfoRes, err := service.BundleProvider.GetBundleBalanceByUserId(context.Background(), &bundle.GetBundleBalanceByUserIdReq{
		UserId: int32(userID),
	})
	if err != nil {
		zap.L().Error("autoConfirmReport GetBundleBalanceByUserId", zap.Any("err", err))
		confirmRemark = "获取余额失败:" + err.Error()
		isFailed = true
	}

	var addBalanceReq bundle.AddBundleBalanceReq
	addBalanceReq.UserId = int32(userID)
	// 检查竞品报告余量
	if balanceInfoRes.CompetitiveExtendConsumptionNumber >= balanceInfoRes.CompetitiveExtendNumber {
		confirmRemark = "数据分析余量不足"
		isFailed = true
	}
	addBalanceReq.CompetitiveConsumptionNumber = 1

	zap.L().Info("autoConfirmReport AddBundleBalanceReq", zap.Any("addBalanceReq", &addBalanceReq))
	resp, err := service.BundleProvider.AddBundleBalance(context.Background(), &addBalanceReq)
	if err != nil {
		zap.L().Error("autoConfirmReport AddBundleBalance", zap.Any("err", err))
		confirmRemark = "扣除失败:" + err.Error()
		isFailed = true
	}
	zap.L().Info("autoConfirmReport AddBundleBalanceResp", zap.Any("resp", resp))
	var confirmStatus uint32 = 1
	if isFailed {
		usedType = 0
		confirmStatus = 3
	} else {
		usedType = resp.UsedType
		confirmRemark = "系统自动确认"
		confirmStatus = 1
	}
	var mm = make(map[string]interface{}, 3)
	mm["userid"] = 0
	mm["name"] = "系统自动确定"
	mm["phone"] = ""
	newCtx := context.WithValue(context.Background(), constant.DubboCtxKey("attachment"), mm)
	_, err = service.CastProvider.UpdateCompetitiveReportStatus(newCtx, &cast.UpdateCompetitiveReportStatusReq{
		WorkAction:    cast.WorkActionENUM_CONFIRM,
		Uuid:          reportUuid,
		ConfirmRemark: confirmRemark,
		CostType:      usedType,
		ConfirmStatus: confirmStatus,
		ConfirmType:   2,
	})
	if err != nil {
		return
	}
	return
}
