package bundle

import (
	"context"
	"errors"
	"fmt"
	"fonchain-fiee/api/accountFiee"
	"fonchain-fiee/api/bundle"
	"fonchain-fiee/api/order"
	"fonchain-fiee/pkg/cache"
	"fonchain-fiee/pkg/model/login"
	"fonchain-fiee/pkg/service"
	"fonchain-fiee/pkg/service/bundle/common"
	"fonchain-fiee/pkg/service/bundle/logic"
	"fonchain-fiee/pkg/service/bundle/model"
	bundleModel "fonchain-fiee/pkg/service/bundle/model"
	"fonchain-fiee/pkg/service/upload"
	"strconv"
	"strings"
	"time"

	"github.com/360EntSecGroup-Skylar/excelize"
	"github.com/gin-gonic/gin"
	"github.com/gin-gonic/gin/binding"
)

const ContractUrl = "https://e-cdn.fontree.cn/fonchain-main/prod/file/contract/saas/template-25122501.pdf"

func DeleteBundleOrder(c *gin.Context) {
	var req bundle.DeleteValueAddServiceRequest
	if err := c.ShouldBindBodyWith(&req, binding.JSON); err != nil {
		service.Error(c, err)
		return
	}
	userInfo := login.GetUserInfoFromC(c)
	req.UserID = userInfo.ID
	res, err := service.BundleProvider.DeleteValueAddService(context.Background(), &req)
	if err != nil {
		service.Error(c, err)
		return
	}
	service.Success(c, res)
	return
}

func CreateBundleOrderAddSignature(c *gin.Context) {
	var req bundle.OrderAddRecord

	if err := c.ShouldBindBodyWith(&req, binding.JSON); err != nil {
		service.Error(c, err)
		return
	}
	if req.Language == "" {
		req.Language = c.GetHeader("Accept-Language")
		if req.Language == "" {
			service.Error(c, errors.New(common.MissLanguageTypes))
			return
		}
	}
	if req.BundleUuid == "" {
		service.Error(c, errors.New(common.MissOrderNo))
		return
	}
	// 获取用户信息
	userInfo := login.GetUserInfoFromC(c)
	if msg, exists := map[int32]string{
		1: common.Unnamed,
		2: common.UnderReview,
		3: common.ReviewFailed,
	}[userInfo.Status]; userInfo.Status != 4 {
		if exists {
			service.Error(c, errors.New(msg))
		} else {
			service.Error(c, errors.New(common.UnknownStatus))
		}
		return
	}

	// 校验套餐是否已购买
	orderRecordReq := bundle.OrderRecordsDetailRequest{
		BundleUUID: req.BundleUuid,
		CustomerID: strconv.FormatUint(userInfo.ID, 10),
	}
	orderRecordResp, err := service.BundleProvider.OrderRecordsDetail(context.Background(), &orderRecordReq)
	if err != nil {
		service.Error(c, err)
		return
	}
	if orderRecordResp.OrderRecord.ExpirationTime == "" || orderRecordResp.OrderRecord.ExpirationTime < time.Now().Format("2006-01-02") {
		service.Error(c, errors.New(common.ThePackageHasExpired))
		return
	}
	// 获取套餐详情（待替换逻辑）
	//bundleDetail, err := service.BundleProvider.BundleDetail(context.Background(), &bundle.BundleDetailRequest{
	//	Uuid: req.BundleUuid,
	//})
	//if err != nil {
	//	service.Error(c, err)
	//	return
	//}
	// todo 需要判断购买的增值服务是否为可用时长  如果为可以用时长  合同截止日期为购买时长时间  否则合同截止日期为主套餐截止日期
	// 处理多个增值服务
	type ValueAddServiceInfo struct {
		Service *bundle.ValueAddServiceLang
		Options *bundle.ValueAddPriceOptions
		ID      int32
	}
	// 计算总金额和确定截止日期
	//var expirationDate string
	var addPriceList []*bundle.AddPriceOptionsInfo
	var totalAmount float32
	for _, svc := range req.AddPriceOptionsList {
		valueAddInfo, err := service.BundleProvider.ValueAddServiceLangByUuidAndLanguage(context.Background(), &bundle.ValueAddServiceDetailRequest{
			Uuid:     svc.ValueUid,
			Language: req.Language,
		})
		if err != nil {
			service.Error(c, err)
			return
		}
		valuePrice, err := service.BundleProvider.CalculatePrice(context.Background(), &bundle.CalculatePriceRequest{
			Uuid:     svc.ValueUid,
			Num:      svc.Num,
			Language: req.Language,
		})
		if err != nil {
			service.Error(c, err)
			return
		}
		totalAmount += valuePrice.Price
		addPriceList = append(addPriceList, &bundle.AddPriceOptionsInfo{
			ValueUid:     valueAddInfo.Uuid,
			ServiceType:  valueAddInfo.ServiceType,
			CurrencyType: valueAddInfo.PriceType,
			Amount:       valuePrice.Price,
			Num:          svc.Num,
			Unit:         valueAddInfo.Unit,
		})
		// 如果是可用时长服务，计算新的截止日期 todo 不需要计算到期时间 在完成支付时添加
		/*if valueAddInfo.ServiceType == 5 {
			endDate := orderRecordResp.OrderRecord.ExpirationTime
			if endDate == "9999-12-31" {
				service.Error(c, errors.New(common.ErrorPermanentPackage))
				return
			}
			t, err := time.Parse("2006-01-02", endDate)
			if err != nil {
				fmt.Println("解析时间出错:", err)
				return
			}
			newDeadline := calculateExpirationDate(t, svc.Num, valueAddInfo.Unit)
			expirationDate = newDeadline
			//}
		}*/
	}
	// 如果没有可用时长服务，使用主套餐截止日期
	//if expirationDate == "" {
	//	expirationDate = orderRecordResp.OrderRecord.ExpirationTime
	//}
	req.CustomerNum = userInfo.SubNum
	req.CustomerName = userInfo.Name
	req.CustomerID = strconv.FormatUint(userInfo.ID, 10)
	req.Source = 2
	//req.SignedTime = common.GetBeijingTime()
	//req.ExpirationDate = expirationDate
	req.AddPriceOptionsList = addPriceList
	req.OrderUUID = orderRecordResp.OrderRecord.Uuid
	// 当前 未将 签名 写入合同中 todo 购买增值服务取消签约合同
	//signContract, signContractErr := logic.SignContractV2(req.CustomerNum, bundleDetail.Bundle.Contract, totalAmount, expirationDate)
	//if signContractErr != nil {
	//	service.Error(c, signContractErr)
	//	return
	//}
	//req.SignContract = signContract
	// 创建增值服务订单记录
	res, err := service.BundleProvider.CreateOrderAddRecord(context.Background(), &req)
	if err != nil {
		service.Error(c, err)
		return
	}
	service.Success(c, res)
}

// 计算截止日期辅助函数
func calculateExpirationDate(startDate time.Time, num int32, unit string) string {
	//now := time.Now()
	switch unit {
	case "天":
		return startDate.AddDate(0, 0, int(num)).Format("2006-01-02")
	case "月":
		return startDate.AddDate(0, int(num), 0).Format("2006-01-02")
	case "年":
		return startDate.AddDate(int(num), 0, 0).Format("2006-01-02")
	default:
		return ""
	}
}
func CreateBundleOrderSignature(c *gin.Context) {
	var req bundle.OrderCreateRecord
	if err := c.ShouldBindBodyWith(&req, binding.JSON); err != nil {
		service.Error(c, err)
		return
	}

	// 参数校验
	if err := logic.ValidateRequest(c, &req); err != nil {
		service.Error(c, err)
		return
	}

	// 获取用户信息并校验状态
	userInfo := login.GetUserInfoFromC(c)
	if err := logic.ValidateUserStatus(userInfo); err != nil {
		service.Error(c, err)
		return
	}

	// Redis 防重复提交：同一用户5秒内只能提交一次订单
	lockKey := fmt.Sprintf("create_bundle_order_%d", userInfo.ID)
	reply := cache.RedisClient.SetNX(lockKey, 1, 5*time.Second)
	if !reply.Val() {
		service.Error(c, errors.New("请勿重复提交订单，请稍后再试"))
		return
	}

	// 校验套餐是否已购买
	if err := logic.CheckUserOrder(userInfo.ID); err != nil {
		service.Error(c, err)
		return
	}

	// 获取最后一次合同编号
	lastContractNo, err := logic.GetLastContractNo()
	if err != nil {
		service.Error(c, err)
		return
	}

	// 获取套餐详情
	bundleDetail, err := logic.GetBundleDetail(req.BundleUuid, req.Language)
	if err != nil {
		service.Error(c, err)
		return
	}

	// 组装服务内容（套餐权益 + 附加权益）
	addRecords, addTotalPrice, expirationDay, err := logic.BuildServiceRecords(&req, bundleDetail)
	if err != nil {
		service.Error(c, err)
		return
	}
	startDate := time.Now().Format("2006-01-02")
	// 签合同（金额 + 有效期）
	signContract, err := logic.SignContractV2(req.CustomerNum, bundleDetail.Contract, bundleDetail.Price+addTotalPrice, expirationDay, userInfo.Name, userInfo.IdNumber, userInfo.PlaceOfResidence, startDate)
	if err != nil {
		service.Error(c, err)
		return
	}
	if userInfo.InviterID != 0 && logic.CheckUserFirstOrder(userInfo.ID) {
		req.InviterId = userInfo.InviterID
	}
	// 组装订单信息
	if err := logic.BuildOrderRequest(&req, userInfo, bundleDetail, addRecords, addTotalPrice, lastContractNo, signContract); err != nil {
		service.Error(c, err)
		return
	}
	// 校验发布平台
	if len(req.PlatformIds) == 0 {
		req.PlatformIds = []uint32{1, 4, 5}
	}
	// 创建订单
	res, err := service.BundleProvider.CreateOrderRecord(context.Background(), &req)
	if err != nil {
		service.Error(c, err)
		return
	}
	service.Success(c, res)
	return
}
func VerificationSignature(c *gin.Context) {
	type VerificationSignature struct {
		Signature    bool   `json:"signature"`
		SignatureUrl string `json:"signature_url"`
	}
	res := VerificationSignature{Signature: false}
	userInfo := login.GetUserInfoFromC(c)

	// 添加用户信息验证
	if userInfo.ID == 0 {
		service.Success(c, res)
		return
	}

	req := bundle.OrderRecordsDetailRequest{
		CustomerID: strconv.FormatUint(userInfo.ID, 10),
	}

	records, err := service.BundleProvider.OrderRecordsDetail(c, &req)
	if err != nil {
		// 添加错误日志但继续返回false（业务逻辑）
		service.Success(c, res)
		return
	}

	// 优化空值判断链
	if records == nil || records.OrderRecord == nil {
		service.Success(c, res)
		return
	}
	order := records.OrderRecord

	customerID, err := strconv.ParseUint(order.CustomerID, 10, 64)
	if err != nil || customerID != userInfo.ID {
		service.Success(c, res)
		return
	}
	//
	//if order.Status != bundleModel.OrderPaid {
	//	service.Success(c, res)
	//	return
	//}
	expirationTime, err := time.Parse("2006-01-02 15:04:05", order.ExpirationTime)
	if err != nil {
		service.Success(c, res)
		return
	}
	payTime, err := time.Parse("2006-01-02 15:04:05", order.PayTime)
	if err != nil {
		service.Success(c, res)
		return
	}
	if expirationTime.Before(time.Now()) {
		service.Success(c, res)
		return
	}
	if order.ReSignature == 1 {
		res.Signature = true
		contract := ContractUrl
		expirationDate := expirationTime.Format("2006-01-02")
		payDate := payTime.Format("2006-01-02")
		signContract, err := logic.SignContractV2(userInfo.SubNum, contract, 0, expirationDate, userInfo.Name, userInfo.IdNumber, userInfo.PlaceOfResidence, payDate)
		if err != nil {
			service.Error(c, err)
			return
		}
		res.SignatureUrl = signContract
	}

	service.Success(c, res)
}
func RestartSignature(c *gin.Context) {
	userInfo := login.GetUserInfoFromC(c)

	req := bundle.OrderRecordsDetailRequest{
		CustomerID: strconv.FormatUint(userInfo.ID, 10),
	}
	records, err := service.BundleProvider.OrderRecordsDetail(c, &req)
	if err != nil {
		service.Error(c, errors.New("获取订单信息失败"))
		return
	}
	// 优化空值判断链
	if records == nil || records.OrderRecord == nil {
		service.Error(c, errors.New("获取订单信息失败"))
		return
	}

	order := records.OrderRecord
	expirationTime, err := time.Parse("2006-01-02 15:04:05", order.ExpirationTime)
	if err != nil {
		service.Error(c, errors.New("获取订单过期日期错误"))
		return
	}

	payTime, err := time.Parse("2006-01-02 15:04:05", order.PayTime)
	if err != nil {
		service.Error(c, errors.New("获取订单支付日期错误"))
		return
	}
	if expirationTime.Before(time.Now()) {
		service.Error(c, errors.New("订单已过期"))
		return
	}
	expirationDate := expirationTime.Format("2006-01-02")
	payDate := payTime.Format("2006-01-02")

	if order.ReSignature == 2 {
		service.Error(c, errors.New("订单无需重新签署"))
		return
	}
	// 获取最后一次合同编号
	lastContractNo, err := logic.GetLastContractNo()
	if err != nil {
		service.Error(c, err)
		return
	}
	contract := ContractUrl
	signContract, err := logic.SignContractV2(userInfo.SubNum, contract, 0, expirationDate, userInfo.Name, userInfo.IdNumber, userInfo.PlaceOfResidence, payDate)
	if err != nil {
		service.Error(c, err)
		return
	}
	res, err := service.BundleProvider.ReSignTheContract(c, &bundle.ReSignTheContractRequest{
		OrderNo:      records.OrderRecord.OrderNo,
		ContractNo:   lastContractNo,
		SignContract: signContract,
	})
	if err != nil {
		service.Error(c, err)
		return
	}
	service.Success(c, res)
	return
}
func UpdateBundleOrderStatusPaid(c *gin.Context) {
	var req bundle.OrderRecord

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

	// 获取 用户信息
	userInfo := login.GetUserInfoFromC(c)

	if req.Uuid == "" {
		service.Error(c, errors.New(common.MissOrderUUID))
		return
	}

	detail, detailErr := service.BundleProvider.OrderRecordsDetail(context.Background(), &bundle.OrderRecordsDetailRequest{
		Uuid: req.Uuid,
	})

	if detailErr != nil {
		service.Error(c, detailErr)
		return
	}

	// 判断 是否是 本人操作
	if strconv.FormatUint(userInfo.ID, 10) != detail.OrderRecord.CustomerID {
		service.Error(c, errors.New(common.NotMatchOrderInfo))
		return
	}

	// 如果 当前订单 是 已签未支付  且 存在 checkoutSessionId 需要 查询 支付结果
	if detail.OrderRecord.Status == bundleModel.OrderSigned && detail.OrderRecord.CheckoutSessionId != "" && detail.OrderRecord.PayTime == "" {
		// 查询支付结果
		stripeInfosRes, stripeInfosErr := service.OrderProvider.QueryStripeInfoByCheckSessionIds(context.Background(), &order.QueryStripeInfoRequest{
			CheckoutSessionIds: []string{detail.OrderRecord.CheckoutSessionId},
		})

		if stripeInfosErr != nil {
			service.Error(c, errors.New(common.ErrorQueryStripeInfo))
			return
		}

		totalStripe := 0

		if stripeInfosRes != nil && len(stripeInfosRes.StripeInfos) > 0 {
			totalStripe = len(stripeInfosRes.StripeInfos)
			for _, stripeInfo := range stripeInfosRes.StripeInfos {
				if stripeInfo.OutTradeNo == detail.OrderRecord.OrderNo && stripeInfo.PaymentIntentStatus == "paid" {
					_, updateOrderRecordErr := service.BundleProvider.UpdateOrderRecord(context.Background(), &bundle.OrderRecord{
						Uuid:    detail.OrderRecord.Uuid,
						Status:  bundleModel.OrderPaid,
						PayTime: common.GetBeijingTime(),
					})
					if updateOrderRecordErr != nil {
						service.Error(c, detailErr)
						return
					}
					totalStripe--
				}
			}
		}

		if totalStripe != 0 && totalStripe == len(stripeInfosRes.StripeInfos) {
			_, updateOrderRecordErr := service.BundleProvider.UpdateOrderRecord(context.Background(), &bundle.OrderRecord{
				Uuid:               detail.OrderRecord.Uuid,
				CheckoutSessionId:  "",
				CheckoutSessionUrl: "",
			})
			if updateOrderRecordErr != nil {
				service.Error(c, detailErr)
				return
			}
		}
	}

	service.Success(c, nil)
}
func OrderRecordsListV2(c *gin.Context) {
	var req bundle.OrderRecordsRequestV2
	if err := c.ShouldBindBodyWith(&req, binding.JSON); err != nil {
		service.Error(c, err)
		return
	}

	res := &bundle.OrderRecordsResponseV2{}

	// Step 1: 如果有姓名/电话筛选，先查用户列表
	if req.CustomerName != "" {
		userListResp, err := service.AccountFieeProvider.UserList(context.Background(), &accountFiee.UserListRequest{
			BlurNameTel: req.CustomerName,
			Domain:      "app",
		})
		if err != nil {
			service.Error(c, err)
			return
		}

		if len(userListResp.UserList) == 0 {
			// 没查到用户，直接返回空结果
			res.Page = req.Page
			res.PageSize = req.PageSize
			res.Total = 0
			service.Success(c, res)
			return
		}

		// 提取用户ID列表
		for _, u := range userListResp.UserList {
			req.UserIds = append(req.UserIds, int64(u.Id))
		}
	}

	// Step 2: 查询订单列表
	orderList, err := service.BundleProvider.OrderRecordsListV2(context.Background(), &req)
	if err != nil {
		service.Error(c, err)
		return
	}

	// Step 3: 如果订单不为空，查一次用户信息填充（只查一次）
	if len(orderList.BundleInfo) > 0 {
		// 收集订单里的所有用户ID
		userIdSet := make(map[int64]struct{})
		for _, i := range orderList.BundleInfo {
			userIdSet[i.CustomerId] = struct{}{}
		}

		var userIds []int64
		for id := range userIdSet {
			userIds = append(userIds, id)
		}
		userListResp, err := service.AccountFieeProvider.UserList(context.Background(), &accountFiee.UserListRequest{
			Ids:    userIds,
			Domain: "app",
		})
		if err != nil {
			service.Error(c, err)
			return
		}

		// 建立用户ID -> 用户信息映射
		userMap := make(map[int64]*accountFiee.UserListInfo, len(userListResp.UserList))
		for _, u := range userListResp.UserList {
			userMap[int64(u.Id)] = u
		}

		// 填充订单中的用户信息
		for _, item := range orderList.BundleInfo {
			if u, ok := userMap[item.CustomerId]; ok {
				item.CustomerName = u.Name
				item.TelNum = u.TelNum
				item.SubNum = u.SubNum
				if item.InviterId != 0 {
					item.InviterCode = u.InviterCode
					item.InviterName = u.InviterName
				}
			}
		}
	}

	service.Success(c, orderList)
}
func OrderRecordsListDownload(c *gin.Context) {
	var req bundle.OrderRecordsRequestV2
	if err := c.ShouldBindBodyWith(&req, binding.JSON); err != nil {
		service.Error(c, err)
		return
	}

	res := &bundle.OrderRecordsResponseV2{}

	// Step 1: 如果有姓名/电话筛选，先查用户列表
	if req.CustomerName != "" {
		userListResp, err := service.AccountFieeProvider.UserList(context.Background(), &accountFiee.UserListRequest{
			BlurNameTel: req.CustomerName,
			Domain:      "app",
		})
		if err != nil {
			service.Error(c, err)
			return
		}

		if len(userListResp.UserList) == 0 {
			// 没查到用户，直接返回空结果
			res.Page = req.Page
			res.PageSize = req.PageSize
			res.Total = 0
			service.Success(c, res)
			return
		}

		// 提取用户ID列表
		for _, u := range userListResp.UserList {
			req.UserIds = append(req.UserIds, int64(u.Id))
		}
	}

	// Step 2: 查询订单列表
	orderList, err := service.BundleProvider.OrderRecordsListV2(context.Background(), &req)
	if err != nil {
		service.Error(c, err)
		return
	}

	// Step 3: 如果订单不为空，查一次用户信息填充（只查一次）
	if len(orderList.BundleInfo) > 0 {
		// 收集订单里的所有用户ID
		userIdSet := make(map[int64]struct{})
		for _, i := range orderList.BundleInfo {
			userIdSet[i.CustomerId] = struct{}{}
		}

		var userIds []int64
		for id := range userIdSet {
			userIds = append(userIds, id)
		}

		userListResp, err := service.AccountFieeProvider.UserList(context.Background(), &accountFiee.UserListRequest{
			Ids:    userIds,
			Domain: "app",
		})
		if err != nil {
			service.Error(c, err)
			return
		}

		// 建立用户ID -> 用户信息映射
		userMap := make(map[int64]*accountFiee.UserListInfo, len(userListResp.UserList))
		for _, u := range userListResp.UserList {
			userMap[int64(u.Id)] = u
		}

		// 填充订单中的用户信息
		for _, item := range orderList.BundleInfo {
			if u, ok := userMap[item.CustomerId]; ok {
				item.CustomerName = u.Name
				item.TelNum = u.TelNum
				item.SubNum = u.SubNum
				if item.InviterId != 0 {
					item.InviterCode = u.InviterCode
					item.InviterName = u.InviterName
				}
			}
		}
	}
	excelFile, err := exportExcel(orderList.BundleInfo)
	if err != nil {
		service.Error(c, err)
		return
	}

	// 返回 Excel 文件流给前端
	c.Header("Content-Type", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet")
	c.Header("Content-Disposition", "attachment; filename=order_list.xlsx")
	c.Header("File-Name", "order_list.xlsx")
	c.Header("Access-Control-Expose-Headers", "File-Name")
	_ = excelFile.Write(c.Writer)

}
func OrderRecordsListPasswordFreeDownload(c *gin.Context) {
	var req bundle.OrderRecordsRequestV2
	if err := c.ShouldBindBodyWith(&req, binding.JSON); err != nil {
		service.Error(c, err)
		return
	}

	res := &bundle.OrderRecordsResponseV2{}

	// Step 1: 如果有姓名/电话筛选，先查用户列表
	if req.CustomerName != "" {
		userListResp, err := service.AccountFieeProvider.UserList(context.Background(), &accountFiee.UserListRequest{
			BlurNameTel: req.CustomerName,
			Domain:      "app",
		})
		if err != nil {
			service.Error(c, err)
			return
		}

		if len(userListResp.UserList) == 0 {
			// 没查到用户，直接返回空结果
			res.Page = req.Page
			res.PageSize = req.PageSize
			res.Total = 0
			service.Success(c, res)
			return
		}

		// 提取用户ID列表
		for _, u := range userListResp.UserList {
			req.UserIds = append(req.UserIds, int64(u.Id))
		}
	}

	// Step 2: 查询订单列表
	orderList, err := service.BundleProvider.OrderRecordsListV2(context.Background(), &req)
	if err != nil {
		service.Error(c, err)
		return
	}

	// Step 3: 如果订单不为空，查一次用户信息填充（只查一次）
	if len(orderList.BundleInfo) > 0 {
		// 先过滤掉 InviterId == 0 的记录
		var filtered []*bundle.OrderBundleRecordInfo
		for _, item := range orderList.BundleInfo {
			if item.InviterId != 0 {
				filtered = append(filtered, item)
			}
		}

		// 如果过滤后为空，直接导出空结果
		if len(filtered) == 0 {
			excelFile, err := exportExcel(filtered)
			if err != nil {
				service.Error(c, err)
				return
			}
			c.Header("Content-Type", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet")
			c.Header("Content-Disposition", "attachment; filename=order_list.xlsx")
			c.Header("File-Name", "order_list.xlsx")
			c.Header("Access-Control-Expose-Headers", "File-Name")
			_ = excelFile.Write(c.Writer)
			return
		}

		// 收集订单里的所有用户ID（仅限过滤后的）
		userIdSet := make(map[int64]struct{})
		for _, i := range filtered {
			userIdSet[i.CustomerId] = struct{}{}
		}
		var userIds []int64
		for id := range userIdSet {
			userIds = append(userIds, id)
		}

		userListResp, err := service.AccountFieeProvider.UserList(context.Background(), &accountFiee.UserListRequest{
			Ids:    userIds,
			Domain: "app",
		})
		if err != nil {
			service.Error(c, err)
			return
		}

		// 建立用户ID -> 用户信息映射
		userMap := make(map[int64]*accountFiee.UserListInfo, len(userListResp.UserList))
		for _, u := range userListResp.UserList {
			userMap[int64(u.Id)] = u
		}

		// 填充订单中的用户信息（仅限过滤后的）
		for _, item := range filtered {
			if u, ok := userMap[item.CustomerId]; ok {
				item.CustomerName = u.Name
				item.TelNum = u.TelNum
				item.SubNum = u.SubNum
				if item.InviterId != 0 {
					item.InviterCode = u.InviterCode
					item.InviterName = u.InviterName
				}
			}
		}

		// 用过滤后的数据覆盖原数据用于导出
		orderList.BundleInfo = filtered
	}
	excelFile, err := exportExcel(orderList.BundleInfo)
	if err != nil {
		service.Error(c, err)
		return
	}

	// 返回 Excel 文件流给前端
	c.Header("Content-Type", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet")
	c.Header("Content-Disposition", "attachment; filename=order_list.xlsx")
	c.Header("File-Name", "order_list.xlsx")
	c.Header("Access-Control-Expose-Headers", "File-Name")
	_ = excelFile.Write(c.Writer)

}

func exportExcel(orderList []*bundle.OrderBundleRecordInfo) (*excelize.File, error) {
	f := excelize.NewFile()
	sheetName := "Sheet1"
	f.SetSheetName("Sheet1", sheetName)

	headers := []string{
		"套餐订单号", "套餐类型", "购买类型", "套餐付款状态", "艺人手机号", "用户编号", "艺人", "套餐订单创建时间", "套餐支付时间", "套餐金额",
		"增值服务订单号", "增值税服务金额", "支付金额", "币种", "手续费", "增值订单创建时间", "增值付款状态", "邀请码", "邀请码所属人",
	}
	for i, h := range headers {
		cell := fmt.Sprintf("%s%d", string(rune('A'+i)), 1)
		f.SetCellValue(sheetName, cell, h)
	}

	rowIndex := 2
	for _, bundleInfo := range orderList {
		addCount := len(bundleInfo.AddBundleInfo)
		mergeRows := 1
		if addCount > 1 {
			mergeRows = addCount
		}

		// 写入主订单信息并合并单元格
		for i := 0; i < 7; i++ {
			col := string(rune('A' + i))
			startCell := fmt.Sprintf("%s%d", col, rowIndex)
			endCell := fmt.Sprintf("%s%d", col, rowIndex+mergeRows-1)
			if mergeRows > 1 {
				f.MergeCell(sheetName, startCell, endCell)
			}
		}

		f.SetCellValue(sheetName, fmt.Sprintf("A%d", rowIndex), bundleInfo.OrderNo)
		f.SetCellValue(sheetName, fmt.Sprintf("B%d", rowIndex), bundleInfo.BundleName)
		f.SetCellValue(sheetName, fmt.Sprintf("C%d", rowIndex), GetPurchaseType(bundleInfo.PurchaseType))
		f.SetCellValue(sheetName, fmt.Sprintf("D%d", rowIndex), GetPayStatusText(bundleInfo.PayStatus))
		f.SetCellValue(sheetName, fmt.Sprintf("E%d", rowIndex), bundleInfo.TelNum)
		f.SetCellValue(sheetName, fmt.Sprintf("F%d", rowIndex), bundleInfo.SubNum)
		f.SetCellValue(sheetName, fmt.Sprintf("G%d", rowIndex), bundleInfo.CustomerName)
		f.SetCellValue(sheetName, fmt.Sprintf("H%d", rowIndex), bundleInfo.BundleCreateAt)
		f.SetCellValue(sheetName, fmt.Sprintf("I%d", rowIndex), bundleInfo.PayTime)
		f.SetCellValue(sheetName, fmt.Sprintf("J%d", rowIndex), bundleInfo.Amount)
		f.SetCellValue(sheetName, fmt.Sprintf("R%d", rowIndex), bundleInfo.InviterCode)
		f.SetCellValue(sheetName, fmt.Sprintf("S%d", rowIndex), bundleInfo.InviterName)

		if addCount > 0 {
			for i, add := range bundleInfo.AddBundleInfo {
				r := rowIndex + i
				f.SetCellValue(sheetName, fmt.Sprintf("K%d", r), add.OrderAddNo)
				f.SetCellValue(sheetName, fmt.Sprintf("L%d", r), add.Amount)
				f.SetCellValue(sheetName, fmt.Sprintf("M%d", r), add.SettlementAmount)
				f.SetCellValue(sheetName, fmt.Sprintf("N%d", r), GetCurrencyTypeText(add.CurrencyType))
				f.SetCellValue(sheetName, fmt.Sprintf("O%d", r), add.HandlingFee)
				f.SetCellValue(sheetName, fmt.Sprintf("P%d", r), add.OrderAddCreateAt)
				f.SetCellValue(sheetName, fmt.Sprintf("Q%d", r), GetPayStatusText(add.AddPayStatus))
			}
		} else {
			for i := 8; i <= 15; i++ {
				col := string(rune('A' + i))
				f.SetCellValue(sheetName, fmt.Sprintf("%s%d", col, rowIndex), "")
			}
		}

		rowIndex += mergeRows
	}

	return f, nil
}
func GetPayStatusText(status int32) string {
	switch status {
	case 1:
		return "未支付"
	case 2:
		return "已支付"
	default:
		return strconv.Itoa(int(status))
	}
}
func GetPurchaseType(status uint64) string {
	switch status {
	case 1:
		return "新购"
	case 2:
		return "续费"
	default:
		return strconv.Itoa(int(status))
	}
}

// 辅助函数：获取货币类型文本
func GetCurrencyTypeText(currencyType int32) string {
	switch currencyType {
	case 1:
		return "人民币"
	case 2:
		return "美元"
	default:
		return strconv.Itoa(int(currencyType))
	}
}
func GetUserStatusText(status int32) string {
	switch status {
	case 1:
		return "未实名"
	case 2:
		return "审核中"
	case 3:
		return "审核失败"
	case 4:
		return "审核通过"
	default:
		return strconv.Itoa(int(status))
	}
}
func GetDocumentTypeText(documentType int32) string {
	switch documentType {
	case 1:
		return "护照"
	case 2:
		return "身份证"
	case 3:
		return "驾驶证"
	case 4:
		return "居住证"
	case 5:
		return "自拍照"
	case 6:
		return "社保卡"
	default:
		return ""
	}
}
func OrderRecordsList(c *gin.Context) {
	var req bundle.OrderRecordsRequest

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

	// 获取 用户信息
	//userInfo := login.GetUserInfoFromC(c)

	//req.CustomerID = strconv.FormatUint(userInfo.ID, 10)

	res, err := service.BundleProvider.OrderRecordsList(context.Background(), &req)
	if err != nil {
		service.Error(c, err)
		return
	}

	for _, orderRecord := range res.OrderRecords {
		if orderRecord.CustomerID != "" {
			var userID uint64
			userID, err = strconv.ParseUint(orderRecord.CustomerID, 10, 64)
			if err != nil {
				err = nil
				continue
			}

			userInfo, _ := service.AccountFieeProvider.Info(context.Background(), &accountFiee.InfoRequest{
				Domain: "app",
				ID:     userID,
			})
			if userInfo != nil {
				orderRecord.Sex = userInfo.Sex
				orderRecord.Nationality = userInfo.Nationality
				orderRecord.CertificatePicture = userInfo.CertificatePicture
				orderRecord.PlaceOfResidence = userInfo.PlaceOfResidence
				orderRecord.GroupPhoto = userInfo.GroupPhoto
				orderRecord.TelNum = userInfo.TelNum
			}
		}

	}

	service.Success(c, res)
}

func OrderRecordsDetail(c *gin.Context) {
	var req bundle.OrderRecordsDetailRequest

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

	// 获取 用户信息
	userInfo := login.GetUserInfoFromC(c)

	req.CustomerID = strconv.FormatUint(userInfo.ID, 10)

	res, err := service.BundleProvider.OrderRecordsDetail(context.Background(), &req)
	if err != nil {
		service.Error(c, err)
		return
	}

	service.Success(c, res)
}

// web
func UpdateFinancialConfirmationStatus(c *gin.Context) {
	var req bundle.FinancialConfirmationRequest

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

	// 不限制 支付状态  未支付 也可确认
	//detail, err := service.BundleProvider.OrderRecordsDetail(context.Background(), &bundle.OrderRecordsDetailRequest{
	//	OrderNo: req.OrderNo,
	//})
	//if err != nil {
	//	service.Error(c, err)
	//	return
	//}
	//if detail.OrderRecord.Status != bundleModel.OrderPaid {
	//	service.Error(c, errors.New("订单未支付,不可确认"))
	//	return
	//}

	res, err := service.BundleProvider.UpdateFinancialConfirmationStatus(context.Background(), &req)
	if err != nil {
		service.Error(c, err)
		return
	}

	service.Success(c, res)
}

func ExportOrderInfo(c *gin.Context) {
	var req bundle.OrderRecordsRequest

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

	res, err := service.BundleProvider.OrderRecordsList(context.Background(), &req)
	if err != nil {
		service.Error(c, err)
		return
	}

	rows := make([][]interface{}, 0)

	for _, orderRecord := range res.OrderRecords {
		if orderRecord.CustomerID != "" {
			var userID uint64
			userID, err = strconv.ParseUint(orderRecord.CustomerID, 10, 64)
			if err != nil {
				err = nil
				continue
			}

			userInfo, _ := service.AccountFieeProvider.Info(context.Background(), &accountFiee.InfoRequest{
				Domain: "app",
				ID:     userID,
			})
			if userInfo != nil {
				orderRecord.Sex = userInfo.Sex
				orderRecord.Nationality = userInfo.Nationality
				orderRecord.TelNum = userInfo.TelNum
			}
		}

		status := ""
		if orderRecord.Status == bundleModel.OrderSigned {
			status = "未支付"
		} else if orderRecord.Status == bundleModel.OrderPaid {
			status = "已支付"
		}
		financialConfirmation := ""
		if orderRecord.FinancialConfirmation == bundleModel.UnConfirm {
			financialConfirmation = "未确认"
		} else if orderRecord.FinancialConfirmation == bundleModel.Confirmed {
			financialConfirmation = "已确认"
		}

		rows = append(rows, []interface{}{
			orderRecord.OrderNo,
			orderRecord.CustomerNum,
			orderRecord.CustomerName,
			orderRecord.Sex,
			orderRecord.TelNum,
			orderRecord.Nationality,
			orderRecord.BundleName,
			orderRecord.SignedTime,
			orderRecord.Amount,
			orderRecord.Num,
			orderRecord.ValueAddBundleAmount,
			orderRecord.TotalAmount,
			status,
			orderRecord.PayTime,
			financialConfirmation,
		})
	}

	dirPath := "./runtime"

	filePath, err := logic.WriteToExcel(dirPath, rows)
	if err != nil {
		service.Error(c, err)
		return
	}

	var httpType string = "http" // Default to http

	// Safely check if Origin exists in c.Keys
	if origin, exists := c.Keys["Origin"]; exists && origin != nil {
		originStr, ok := origin.(string)
		if ok && originStr != "" {
			fmt.Printf("c.Request.Origin %+v\n", originStr)
			parts := strings.Split(originStr, ":")
			if len(parts) > 0 {
				httpType = parts[0]
			}
		}
	} else {
		// Fallback: Check if the request was made over TLS
		if c.Request.TLS != nil || c.Request.Header.Get("X-Forwarded-Proto") == "https" {
			httpType = "https"
		}
	}

	var exportUrl = strings.Replace(strings.Replace(filePath, ".", fmt.Sprintf("%s://%s", httpType, c.Request.Host), 1), "runtime", "api/fiee/static", 1)
	//var exportUrl = fmt.Sprintf("%s%s/%s", httpType, c.Request.Host, dirPath + path)
	fmt.Println("exportUrl : ", exportUrl)
	service.Success(c, &bundleModel.ExportResponse{ExportUrl: exportUrl})
}

func ExportOrderInfoOss(c *gin.Context) {
	var req bundle.OrderRecordsRequest

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

	res, err := service.BundleProvider.OrderRecordsList(context.Background(), &req)
	if err != nil {
		service.Error(c, err)
		return
	}

	rows := make([][]interface{}, 0)

	for _, orderRecord := range res.OrderRecords {
		if orderRecord.CustomerID != "" {
			var userID uint64
			userID, err = strconv.ParseUint(orderRecord.CustomerID, 10, 64)
			if err != nil {
				err = nil
				continue
			}

			userInfo, _ := service.AccountFieeProvider.Info(context.Background(), &accountFiee.InfoRequest{
				Domain: "app",
				ID:     userID,
			})
			if userInfo != nil {
				orderRecord.Sex = userInfo.Sex
				orderRecord.Nationality = userInfo.Nationality
				orderRecord.TelNum = userInfo.TelNum
			}
		}

		status := ""
		if orderRecord.Status == bundleModel.OrderSigned {
			status = "未支付"
		} else if orderRecord.Status == bundleModel.OrderPaid {
			status = "已支付"
		}
		financialConfirmation := ""
		if orderRecord.FinancialConfirmation == bundleModel.UnConfirm {
			financialConfirmation = "未确认"
		} else if orderRecord.FinancialConfirmation == bundleModel.Confirmed {
			financialConfirmation = "已确认"
		}

		rows = append(rows, []interface{}{
			orderRecord.OrderNo,
			orderRecord.CustomerNum,
			orderRecord.CustomerName,
			orderRecord.Sex,
			orderRecord.TelNum,
			orderRecord.Nationality,
			orderRecord.BundleName,
			orderRecord.SignedTime,
			orderRecord.Amount,
			orderRecord.Num,
			orderRecord.ValueAddBundleAmount,
			orderRecord.TotalAmount,
			status,
			orderRecord.PayTime,
			financialConfirmation,
		})
	}

	dirPath := "./runtime"

	filePath, err := logic.WriteToExcel(dirPath, rows)
	if err != nil {
		service.Error(c, err)
		return
	}

	exportUrl, err := upload.PutBos(filePath, "excel", true)
	if err != nil {
		service.Error(c, err)
		return
	}

	service.Success(c, &bundleModel.ExportResponse{ExportUrl: exportUrl})
}

func CreatInvoice(c *gin.Context) {
	var orderInof model.InvoiceInfo
	if err := c.ShouldBindBodyWith(&orderInof, binding.JSON); err != nil {
		service.Error(c, err)
		return
	}

	//生成发票
	orderRecord, err := service.BundleProvider.GetOrderInfoByOrderNo(context.Background(), &bundle.GetOrderInfoByOrderNoReq{
		Uuid: orderInof.OrderUUID,
	})
	if err != nil {
		service.Error(c, err)
		return
	}
	amountType := strconv.FormatInt(orderRecord.AmountType, 10)
	applyTime := orderInof.ApplyTime
	payTime, _ := time.Parse("2006-01-02 15:04:05", applyTime)
	payTimeString := payTime.Format("20060102")
	fmt.Println("发票payTimeString :", payTimeString, "发票applyTime :", applyTime, "发票payTime :", payTime)
	fmt.Println("发票时间数据获取完成")
	err = createInvoice(orderRecord.UserId, orderRecord.UserNum, orderRecord.UserName, orderRecord.Address, orderRecord.Phone, orderRecord.BundleName, orderRecord.OrderNo, "1", amountType, orderRecord.TotalAmount, payTimeString, payTimeString, applyTime)
	if err != nil {
		fmt.Println("生成发票失败:", err)
		service.Error(c, errors.New("生成发票失败:"+err.Error()))
		return
	}
	service.Success(c, "生成发票成功")
}

func CreateDownloadInvoice(c *gin.Context) {
	var orderInof model.InvoiceDownloadInfo
	if err := c.ShouldBindBodyWith(&orderInof, binding.JSON); err != nil {
		service.Error(c, err)
		return
	}
	fmt.Println("下载对应发票订单编号 :", orderInof.OrderNo)
	//生成发票
	orderRecord, err := service.BundleProvider.GetOrderInfoByOrderNo(context.Background(), &bundle.GetOrderInfoByOrderNoReq{
		OrderNo: orderInof.OrderNo,
	})
	if err != nil {
		service.Error(c, err)
		return
	}
	amountType := strconv.FormatInt(orderRecord.AmountType, 10)
	applyTime := orderRecord.PayTime
	payTime, _ := time.Parse("2006-01-02 15:04:05", applyTime)
	payTimeString := payTime.Format("20060102")
	fmt.Println("发票payTimeString :", payTimeString, "发票applyTime :", applyTime, "发票payTime :", payTime)
	fmt.Println("发票时间数据获取完成")
	invoiceUrl, err := createDownloadInvoice(orderRecord.UserId, orderRecord.UserNum, orderRecord.UserName, orderRecord.Address, orderRecord.Phone, orderRecord.BundleName, orderRecord.OrderNo, "1", amountType, orderRecord.TotalAmount, payTimeString, payTimeString, applyTime)
	if err != nil {
		fmt.Println("生成发票失败:", err)
		service.Error(c, errors.New("生成发票失败:"+err.Error()))
		return
	}
	service.Success(c, &bundleModel.ExportResponse{ExportUrl: invoiceUrl})
}
