package order

import (
	"context"
	"time"

	"github.com/break/junhong_cmp_fiber/internal/model"
	"github.com/break/junhong_cmp_fiber/internal/model/dto"
	"github.com/break/junhong_cmp_fiber/internal/service/purchase_validation"
	"github.com/break/junhong_cmp_fiber/internal/store"
	"github.com/break/junhong_cmp_fiber/internal/store/postgres"
	"github.com/break/junhong_cmp_fiber/pkg/constants"
	"github.com/break/junhong_cmp_fiber/pkg/errors"
	"github.com/break/junhong_cmp_fiber/pkg/middleware"
	"github.com/break/junhong_cmp_fiber/pkg/queue"
	"github.com/break/junhong_cmp_fiber/pkg/utils"
	"github.com/break/junhong_cmp_fiber/pkg/wechat"
	"github.com/bytedance/sonic"
	"go.uber.org/zap"
	"gorm.io/gorm"
)

type Service struct {
	db                        *gorm.DB
	orderStore                *postgres.OrderStore
	orderItemStore            *postgres.OrderItemStore
	walletStore               *postgres.WalletStore
	purchaseValidationService *purchase_validation.Service
	allocationConfigStore     *postgres.ShopSeriesAllocationConfigStore
	seriesAllocationStore     *postgres.ShopSeriesAllocationStore
	iotCardStore              *postgres.IotCardStore
	deviceStore               *postgres.DeviceStore
	wechatPayment             wechat.PaymentServiceInterface
	queueClient               *queue.Client
	logger                    *zap.Logger
}

func New(
	db *gorm.DB,
	orderStore *postgres.OrderStore,
	orderItemStore *postgres.OrderItemStore,
	walletStore *postgres.WalletStore,
	purchaseValidationService *purchase_validation.Service,
	allocationConfigStore *postgres.ShopSeriesAllocationConfigStore,
	seriesAllocationStore *postgres.ShopSeriesAllocationStore,
	iotCardStore *postgres.IotCardStore,
	deviceStore *postgres.DeviceStore,
	wechatPayment wechat.PaymentServiceInterface,
	queueClient *queue.Client,
	logger *zap.Logger,
) *Service {
	return &Service{
		db:                        db,
		orderStore:                orderStore,
		orderItemStore:            orderItemStore,
		walletStore:               walletStore,
		purchaseValidationService: purchaseValidationService,
		allocationConfigStore:     allocationConfigStore,
		seriesAllocationStore:     seriesAllocationStore,
		iotCardStore:              iotCardStore,
		deviceStore:               deviceStore,
		wechatPayment:             wechatPayment,
		queueClient:               queueClient,
		logger:                    logger,
	}
}

func (s *Service) Create(ctx context.Context, req *dto.CreateOrderRequest, buyerType string, buyerID uint) (*dto.OrderResponse, error) {
	var validationResult *purchase_validation.PurchaseValidationResult
	var err error

	if req.OrderType == model.OrderTypeSingleCard {
		if req.IotCardID == nil {
			return nil, errors.New(errors.CodeInvalidParam, "单卡购买必须指定IoT卡ID")
		}
		validationResult, err = s.purchaseValidationService.ValidateCardPurchase(ctx, *req.IotCardID, req.PackageIDs)
	} else if req.OrderType == model.OrderTypeDevice {
		if req.DeviceID == nil {
			return nil, errors.New(errors.CodeInvalidParam, "设备购买必须指定设备ID")
		}
		validationResult, err = s.purchaseValidationService.ValidateDevicePurchase(ctx, *req.DeviceID, req.PackageIDs)
	} else {
		return nil, errors.New(errors.CodeInvalidParam, "无效的订单类型")
	}

	if err != nil {
		return nil, err
	}

	forceRechargeCheck := s.checkForceRechargeRequirement(validationResult)
	if forceRechargeCheck.NeedForceRecharge && validationResult.TotalPrice < forceRechargeCheck.ForceRechargeAmount {
		return nil, errors.New(errors.CodeForceRechargeRequired, "首次购买需满足最低充值要求")
	}

	userID := middleware.GetUserIDFromContext(ctx)
	configVersion := s.snapshotCommissionConfig(ctx, validationResult.Allocation.ID)

	orderBuyerType := buyerType
	orderBuyerID := buyerID
	totalAmount := validationResult.TotalPrice
	paymentMethod := req.PaymentMethod
	paymentStatus := model.PaymentStatusPending
	var paidAt *time.Time
	isPurchaseOnBehalf := false

	var seriesID *uint
	var sellerShopID *uint
	var sellerCostPrice int64

	if validationResult.Allocation != nil {
		seriesID = &validationResult.Allocation.SeriesID
		sellerShopID = &validationResult.Allocation.ShopID
	}

	if req.PaymentMethod == model.PaymentMethodOffline {
		purchaseBuyerID, buyerCostPrice, purchasePaidAt, err := s.resolvePurchaseOnBehalfInfo(ctx, validationResult)
		if err != nil {
			return nil, err
		}
		orderBuyerType = model.BuyerTypeAgent
		orderBuyerID = purchaseBuyerID
		totalAmount = buyerCostPrice
		paymentMethod = model.PaymentMethodOffline
		paymentStatus = model.PaymentStatusPaid
		paidAt = purchasePaidAt
		isPurchaseOnBehalf = true
		sellerCostPrice = buyerCostPrice
	} else if validationResult.Allocation != nil {
		sellerCostPrice = utils.CalculateCostPrice(validationResult.Allocation, validationResult.TotalPrice)
	}

	order := &model.Order{
		BaseModel: model.BaseModel{
			Creator: userID,
			Updater: userID,
		},
		OrderNo:                 s.orderStore.GenerateOrderNo(),
		OrderType:               req.OrderType,
		BuyerType:               orderBuyerType,
		BuyerID:                 orderBuyerID,
		IotCardID:               req.IotCardID,
		DeviceID:                req.DeviceID,
		TotalAmount:             totalAmount,
		PaymentMethod:           paymentMethod,
		PaymentStatus:           paymentStatus,
		PaidAt:                  paidAt,
		CommissionStatus:        model.CommissionStatusPending,
		CommissionConfigVersion: configVersion,
		SeriesID:                seriesID,
		SellerShopID:            sellerShopID,
		SellerCostPrice:         sellerCostPrice,
		IsPurchaseOnBehalf:      isPurchaseOnBehalf,
	}

	items := s.buildOrderItems(userID, validationResult.Packages)

	if req.PaymentMethod == model.PaymentMethodOffline {
		if err := s.createOrderWithActivation(ctx, order, items); err != nil {
			return nil, err
		}
		s.enqueueCommissionCalculation(ctx, order.ID)
		return s.buildOrderResponse(order, items), nil
	}

	if err := s.orderStore.Create(ctx, order, items); err != nil {
		return nil, err
	}

	return s.buildOrderResponse(order, items), nil
}

func (s *Service) resolvePurchaseOnBehalfInfo(ctx context.Context, result *purchase_validation.PurchaseValidationResult) (uint, int64, *time.Time, error) {
	var resourceShopID *uint
	if result.Card != nil {
		resourceShopID = result.Card.ShopID
	} else if result.Device != nil {
		resourceShopID = result.Device.ShopID
	}

	if resourceShopID == nil || *resourceShopID == 0 {
		return 0, 0, nil, errors.New(errors.CodeInvalidParam, "资源未分配给代理商，无法代购")
	}

	buyerAllocation, err := s.seriesAllocationStore.GetByShopAndSeries(ctx, *resourceShopID, result.Allocation.SeriesID)
	if err != nil {
		return 0, 0, nil, errors.New(errors.CodeInvalidParam, "买家没有该套餐系列的分配配置")
	}

	buyerCostPrice := utils.CalculateCostPrice(buyerAllocation, result.TotalPrice)
	now := time.Now()
	return *resourceShopID, buyerCostPrice, &now, nil
}

func (s *Service) buildOrderItems(operatorID uint, packages []*model.Package) []*model.OrderItem {
	items := make([]*model.OrderItem, 0, len(packages))
	for _, pkg := range packages {
		item := &model.OrderItem{
			BaseModel: model.BaseModel{
				Creator: operatorID,
				Updater: operatorID,
			},
			PackageID:   pkg.ID,
			PackageName: pkg.PackageName,
			Quantity:    1,
			UnitPrice:   pkg.SuggestedRetailPrice,
			Amount:      pkg.SuggestedRetailPrice,
		}
		items = append(items, item)
	}

	return items
}

func (s *Service) createOrderWithActivation(ctx context.Context, order *model.Order, items []*model.OrderItem) error {
	return s.db.WithContext(ctx).Transaction(func(tx *gorm.DB) error {
		if err := tx.Create(order).Error; err != nil {
			return errors.Wrap(errors.CodeDatabaseError, err, "创建代购订单失败")
		}

		for _, item := range items {
			item.OrderID = order.ID
		}
		if err := tx.CreateInBatches(items, 100).Error; err != nil {
			return errors.Wrap(errors.CodeDatabaseError, err, "创建订单明细失败")
		}

		return s.activatePackage(ctx, tx, order)
	})
}

func (s *Service) Get(ctx context.Context, id uint) (*dto.OrderResponse, error) {
	order, items, err := s.orderStore.GetByIDWithItems(ctx, id)
	if err != nil {
		if err == gorm.ErrRecordNotFound {
			return nil, errors.New(errors.CodeNotFound, "订单不存在")
		}
		return nil, err
	}

	return s.buildOrderResponse(order, items), nil
}

func (s *Service) List(ctx context.Context, req *dto.OrderListRequest, buyerType string, buyerID uint) (*dto.OrderListResponse, error) {
	page := req.Page
	pageSize := req.PageSize
	if page == 0 {
		page = 1
	}
	if pageSize == 0 {
		pageSize = constants.DefaultPageSize
	}

	opts := &store.QueryOptions{
		Page:     page,
		PageSize: pageSize,
	}

	filters := map[string]any{
		"buyer_type": buyerType,
		"buyer_id":   buyerID,
	}
	if req.PaymentStatus != nil {
		filters["payment_status"] = *req.PaymentStatus
	}
	if req.OrderType != "" {
		filters["order_type"] = req.OrderType
	}
	if req.OrderNo != "" {
		filters["order_no"] = req.OrderNo
	}
	if req.StartTime != nil {
		filters["start_time"] = req.StartTime
	}
	if req.EndTime != nil {
		filters["end_time"] = req.EndTime
	}

	orders, total, err := s.orderStore.List(ctx, opts, filters)
	if err != nil {
		return nil, err
	}

	var orderIDs []uint
	for _, o := range orders {
		orderIDs = append(orderIDs, o.ID)
	}

	itemsMap := make(map[uint][]*model.OrderItem)
	if len(orderIDs) > 0 {
		allItems, err := s.orderItemStore.ListByOrderIDs(ctx, orderIDs)
		if err != nil {
			return nil, err
		}
		for _, item := range allItems {
			itemsMap[item.OrderID] = append(itemsMap[item.OrderID], item)
		}
	}

	var list []*dto.OrderResponse
	for _, o := range orders {
		list = append(list, s.buildOrderResponse(o, itemsMap[o.ID]))
	}

	totalPages := int(total) / pageSize
	if int(total)%pageSize > 0 {
		totalPages++
	}

	return &dto.OrderListResponse{
		List:       list,
		Total:      total,
		Page:       page,
		PageSize:   pageSize,
		TotalPages: totalPages,
	}, nil
}

func (s *Service) Cancel(ctx context.Context, id uint, buyerType string, buyerID uint) error {
	order, err := s.orderStore.GetByID(ctx, id)
	if err != nil {
		if err == gorm.ErrRecordNotFound {
			return errors.New(errors.CodeNotFound, "订单不存在")
		}
		return err
	}

	if order.BuyerType != buyerType || order.BuyerID != buyerID {
		return errors.New(errors.CodeForbidden, "无权操作此订单")
	}

	if order.PaymentStatus != model.PaymentStatusPending {
		return errors.New(errors.CodeInvalidStatus, "只能取消待支付的订单")
	}

	return s.orderStore.UpdatePaymentStatus(ctx, id, model.PaymentStatusCancelled, nil)
}

func (s *Service) WalletPay(ctx context.Context, orderID uint, buyerType string, buyerID uint) error {
	order, err := s.orderStore.GetByID(ctx, orderID)
	if err != nil {
		if err == gorm.ErrRecordNotFound {
			return errors.New(errors.CodeNotFound, "订单不存在")
		}
		return err
	}

	if order.BuyerType != buyerType || order.BuyerID != buyerID {
		return errors.New(errors.CodeForbidden, "无权操作此订单")
	}

	if order.IsPurchaseOnBehalf {
		return errors.New(errors.CodeInvalidStatus, "代购订单无需支付")
	}

	var resourceType string
	var resourceID uint

	if buyerType == model.BuyerTypePersonal {
		if order.OrderType == model.OrderTypeSingleCard && order.IotCardID != nil {
			resourceType = "iot_card"
			resourceID = *order.IotCardID
		} else if order.OrderType == model.OrderTypeDevice && order.DeviceID != nil {
			resourceType = "device"
			resourceID = *order.DeviceID
		} else {
			return errors.New(errors.CodeInvalidParam, "无法确定钱包归属")
		}
	} else if buyerType == model.BuyerTypeAgent {
		resourceType = "shop"
		resourceID = buyerID
	} else {
		return errors.New(errors.CodeInvalidParam, "不支持的买家类型")
	}

	wallet, err := s.walletStore.GetByResourceTypeAndID(ctx, resourceType, resourceID, "main")
	if err != nil {
		if err == gorm.ErrRecordNotFound {
			return errors.New(errors.CodeWalletNotFound, "钱包不存在")
		}
		return err
	}

	if wallet.Balance < order.TotalAmount {
		return errors.New(errors.CodeInsufficientBalance, "余额不足")
	}

	now := time.Now()
	err = s.db.WithContext(ctx).Transaction(func(tx *gorm.DB) error {
		result := tx.Model(&model.Order{}).
			Where("id = ? AND payment_status = ?", orderID, model.PaymentStatusPending).
			Updates(map[string]any{
				"payment_status": model.PaymentStatusPaid,
				"payment_method": model.PaymentMethodWallet,
				"paid_at":        now,
			})
		if result.Error != nil {
			return errors.Wrap(errors.CodeDatabaseError, result.Error, "更新订单支付状态失败")
		}

		if result.RowsAffected == 0 {
			var currentOrder model.Order
			if err := tx.First(&currentOrder, orderID).Error; err != nil {
				return errors.Wrap(errors.CodeDatabaseError, err, "查询订单失败")
			}

			switch currentOrder.PaymentStatus {
			case model.PaymentStatusPaid:
				return nil
			case model.PaymentStatusCancelled:
				return errors.New(errors.CodeInvalidStatus, "订单已取消，无法支付")
			case model.PaymentStatusRefunded:
				return errors.New(errors.CodeInvalidStatus, "订单已退款，无法支付")
			default:
				return errors.New(errors.CodeInvalidStatus, "订单状态异常")
			}
		}

		walletResult := tx.Model(&model.Wallet{}).
			Where("id = ? AND balance >= ? AND version = ?", wallet.ID, order.TotalAmount, wallet.Version).
			Updates(map[string]any{
				"balance": gorm.Expr("balance - ?", order.TotalAmount),
				"version": gorm.Expr("version + 1"),
			})
		if walletResult.Error != nil {
			return errors.Wrap(errors.CodeDatabaseError, walletResult.Error, "扣减钱包余额失败")
		}
		if walletResult.RowsAffected == 0 {
			return errors.New(errors.CodeInsufficientBalance, "余额不足或并发冲突")
		}

		return s.activatePackage(ctx, tx, order)
	})

	if err != nil {
		return err
	}

	s.enqueueCommissionCalculation(ctx, orderID)
	return nil
}

func (s *Service) HandlePaymentCallback(ctx context.Context, orderNo string, paymentMethod string) error {
	order, err := s.orderStore.GetByOrderNo(ctx, orderNo)
	if err != nil {
		if err == gorm.ErrRecordNotFound {
			return errors.New(errors.CodeNotFound, "订单不存在")
		}
		return err
	}

	now := time.Now()
	err = s.db.WithContext(ctx).Transaction(func(tx *gorm.DB) error {
		result := tx.Model(&model.Order{}).
			Where("id = ? AND payment_status = ?", order.ID, model.PaymentStatusPending).
			Updates(map[string]any{
				"payment_status": model.PaymentStatusPaid,
				"payment_method": paymentMethod,
				"paid_at":        now,
			})
		if result.Error != nil {
			return errors.Wrap(errors.CodeDatabaseError, result.Error, "更新订单支付状态失败")
		}

		if result.RowsAffected == 0 {
			var currentOrder model.Order
			if err := tx.First(&currentOrder, order.ID).Error; err != nil {
				return errors.Wrap(errors.CodeDatabaseError, err, "查询订单失败")
			}

			switch currentOrder.PaymentStatus {
			case model.PaymentStatusPaid:
				return nil
			case model.PaymentStatusCancelled:
				return errors.New(errors.CodeInvalidStatus, "订单已取消，无法支付")
			case model.PaymentStatusRefunded:
				return errors.New(errors.CodeInvalidStatus, "订单已退款，无法支付")
			default:
				return errors.New(errors.CodeInvalidStatus, "订单状态异常")
			}
		}

		return s.activatePackage(ctx, tx, order)
	})

	if err != nil {
		return err
	}

	s.enqueueCommissionCalculation(ctx, order.ID)
	return nil
}

func (s *Service) activatePackage(ctx context.Context, tx *gorm.DB, order *model.Order) error {
	var items []*model.OrderItem
	if err := tx.Where("order_id = ?", order.ID).Find(&items).Error; err != nil {
		return errors.Wrap(errors.CodeDatabaseError, err, "查询订单明细失败")
	}

	now := time.Now()
	for _, item := range items {
		var existingUsage model.PackageUsage
		err := tx.Where("order_id = ? AND package_id = ?", order.ID, item.PackageID).
			First(&existingUsage).Error
		if err == nil {
			s.logger.Warn("套餐使用记录已存在，跳过创建",
				zap.Uint("order_id", order.ID),
				zap.Uint("package_id", item.PackageID))
			continue
		}
		if err != gorm.ErrRecordNotFound {
			return errors.Wrap(errors.CodeDatabaseError, err, "检查套餐使用记录失败")
		}

		var pkg model.Package
		if err := tx.First(&pkg, item.PackageID).Error; err != nil {
			return errors.Wrap(errors.CodeDatabaseError, err, "查询套餐信息失败")
		}

		usage := &model.PackageUsage{
			BaseModel: model.BaseModel{
				Creator: order.Creator,
				Updater: order.Creator,
			},
			OrderID:     order.ID,
			PackageID:   item.PackageID,
			UsageType:   order.OrderType,
			DataLimitMB: pkg.DataAmountMB,
			ActivatedAt: now,
			ExpiresAt:   now.AddDate(0, pkg.DurationMonths, 0),
			Status:      1,
		}

		if order.OrderType == model.OrderTypeSingleCard && order.IotCardID != nil {
			usage.IotCardID = *order.IotCardID
		} else if order.OrderType == model.OrderTypeDevice && order.DeviceID != nil {
			usage.DeviceID = *order.DeviceID
		}

		if err := tx.Create(usage).Error; err != nil {
			return errors.Wrap(errors.CodeDatabaseError, err, "创建套餐使用记录失败")
		}
	}

	return nil
}

func (s *Service) snapshotCommissionConfig(ctx context.Context, allocationID uint) int {
	if s.allocationConfigStore == nil {
		return 0
	}
	config, err := s.allocationConfigStore.GetEffective(ctx, allocationID, time.Now())
	if err != nil || config == nil {
		return 0
	}
	return config.Version
}

func (s *Service) enqueueCommissionCalculation(ctx context.Context, orderID uint) {
	if s.queueClient == nil {
		s.logger.Warn("队列客户端未初始化，跳过佣金计算任务入队", zap.Uint("order_id", orderID))
		return
	}

	payload := map[string]interface{}{
		"order_id": orderID,
	}

	payloadBytes, err := sonic.Marshal(payload)
	if err != nil {
		s.logger.Error("佣金计算任务载荷序列化失败",
			zap.Uint("order_id", orderID),
			zap.Error(err))
		return
	}

	if err := s.queueClient.EnqueueTask(ctx, constants.TaskTypeCommission, payloadBytes); err != nil {
		s.logger.Error("佣金计算任务入队失败",
			zap.Uint("order_id", orderID),
			zap.Error(err),
			zap.String("task_type", constants.TaskTypeCommission))
		return
	}

	s.logger.Info("佣金计算任务已入队",
		zap.Uint("order_id", orderID),
		zap.String("task_type", constants.TaskTypeCommission))
}

func (s *Service) buildOrderResponse(order *model.Order, items []*model.OrderItem) *dto.OrderResponse {
	var itemResponses []*dto.OrderItemResponse
	for _, item := range items {
		itemResponses = append(itemResponses, &dto.OrderItemResponse{
			ID:          item.ID,
			PackageID:   item.PackageID,
			PackageName: item.PackageName,
			Quantity:    item.Quantity,
			UnitPrice:   item.UnitPrice,
			Amount:      item.Amount,
		})
	}

	statusText := ""
	switch order.PaymentStatus {
	case model.PaymentStatusPending:
		statusText = "待支付"
	case model.PaymentStatusPaid:
		statusText = "已支付"
	case model.PaymentStatusCancelled:
		statusText = "已取消"
	case model.PaymentStatusRefunded:
		statusText = "已退款"
	}

	return &dto.OrderResponse{
		ID:                      order.ID,
		OrderNo:                 order.OrderNo,
		OrderType:               order.OrderType,
		BuyerType:               order.BuyerType,
		BuyerID:                 order.BuyerID,
		IotCardID:               order.IotCardID,
		DeviceID:                order.DeviceID,
		TotalAmount:             order.TotalAmount,
		PaymentMethod:           order.PaymentMethod,
		PaymentStatus:           order.PaymentStatus,
		PaymentStatusText:       statusText,
		PaidAt:                  order.PaidAt,
		IsPurchaseOnBehalf:      order.IsPurchaseOnBehalf,
		CommissionStatus:        order.CommissionStatus,
		CommissionConfigVersion: order.CommissionConfigVersion,
		Items:                   itemResponses,
		CreatedAt:               order.CreatedAt,
		UpdatedAt:               order.UpdatedAt,
	}
}

// WechatPayJSAPI 发起微信 JSAPI 支付
func (s *Service) WechatPayJSAPI(ctx context.Context, orderID uint, openID string, buyerType string, buyerID uint) (*dto.WechatPayJSAPIResponse, error) {
	if s.wechatPayment == nil {
		s.logger.Error("微信支付服务未配置")
		return nil, errors.New(errors.CodeWechatPayFailed, "微信支付服务未配置")
	}

	order, err := s.orderStore.GetByID(ctx, orderID)
	if err != nil {
		if err == gorm.ErrRecordNotFound {
			return nil, errors.New(errors.CodeNotFound, "订单不存在")
		}
		return nil, errors.Wrap(errors.CodeInternalError, err, "查询订单失败")
	}

	if order.BuyerType != buyerType || order.BuyerID != buyerID {
		return nil, errors.New(errors.CodeForbidden, "无权操作此订单")
	}

	if order.PaymentStatus != model.PaymentStatusPending {
		return nil, errors.New(errors.CodeInvalidStatus, "订单状态不允许支付")
	}

	items, err := s.orderItemStore.ListByOrderIDs(ctx, []uint{orderID})
	if err != nil {
		return nil, errors.Wrap(errors.CodeInternalError, err, "查询订单明细失败")
	}
	description := "套餐购买"
	if len(items) > 0 {
		description = items[0].PackageName
	}

	result, err := s.wechatPayment.CreateJSAPIOrder(ctx, order.OrderNo, description, openID, int(order.TotalAmount))
	if err != nil {
		s.logger.Error("创建 JSAPI 支付失败",
			zap.Uint("order_id", orderID),
			zap.String("order_no", order.OrderNo),
			zap.Error(err),
		)
		return nil, err
	}

	s.logger.Info("创建 JSAPI 支付成功",
		zap.Uint("order_id", orderID),
		zap.String("order_no", order.OrderNo),
		zap.String("prepay_id", result.PrepayID),
	)

	payConfig, _ := result.PayConfig.(map[string]interface{})
	return &dto.WechatPayJSAPIResponse{
		PrepayID:  result.PrepayID,
		PayConfig: payConfig,
	}, nil
}

// WechatPayH5 发起微信 H5 支付
func (s *Service) WechatPayH5(ctx context.Context, orderID uint, sceneInfo *dto.WechatH5SceneInfo, buyerType string, buyerID uint) (*dto.WechatPayH5Response, error) {
	if s.wechatPayment == nil {
		s.logger.Error("微信支付服务未配置")
		return nil, errors.New(errors.CodeWechatPayFailed, "微信支付服务未配置")
	}

	order, err := s.orderStore.GetByID(ctx, orderID)
	if err != nil {
		if err == gorm.ErrRecordNotFound {
			return nil, errors.New(errors.CodeNotFound, "订单不存在")
		}
		return nil, errors.Wrap(errors.CodeInternalError, err, "查询订单失败")
	}

	if order.BuyerType != buyerType || order.BuyerID != buyerID {
		return nil, errors.New(errors.CodeForbidden, "无权操作此订单")
	}

	if order.PaymentStatus != model.PaymentStatusPending {
		return nil, errors.New(errors.CodeInvalidStatus, "订单状态不允许支付")
	}

	items, err := s.orderItemStore.ListByOrderIDs(ctx, []uint{orderID})
	if err != nil {
		return nil, errors.Wrap(errors.CodeInternalError, err, "查询订单明细失败")
	}
	description := "套餐购买"
	if len(items) > 0 {
		description = items[0].PackageName
	}

	h5SceneInfo := &wechat.H5SceneInfo{
		PayerClientIP: sceneInfo.PayerClientIP,
		H5Type:        sceneInfo.H5Info.Type,
	}

	result, err := s.wechatPayment.CreateH5Order(ctx, order.OrderNo, description, int(order.TotalAmount), h5SceneInfo)
	if err != nil {
		s.logger.Error("创建 H5 支付失败",
			zap.Uint("order_id", orderID),
			zap.String("order_no", order.OrderNo),
			zap.Error(err),
		)
		return nil, err
	}

	s.logger.Info("创建 H5 支付成功",
		zap.Uint("order_id", orderID),
		zap.String("order_no", order.OrderNo),
		zap.String("h5_url", result.H5URL),
	)

	return &dto.WechatPayH5Response{
		H5URL: result.H5URL,
	}, nil
}

type ForceRechargeRequirement struct {
	NeedForceRecharge   bool
	ForceRechargeAmount int64
	TriggerType         string
}

func (s *Service) checkForceRechargeRequirement(result *purchase_validation.PurchaseValidationResult) *ForceRechargeRequirement {
	if result.Allocation == nil {
		return &ForceRechargeRequirement{NeedForceRecharge: false}
	}

	allocation := result.Allocation
	if !allocation.EnableOneTimeCommission {
		return &ForceRechargeRequirement{NeedForceRecharge: false}
	}

	var firstCommissionPaid bool
	if result.Card != nil {
		firstCommissionPaid = result.Card.FirstCommissionPaid
	} else if result.Device != nil {
		firstCommissionPaid = result.Device.FirstCommissionPaid
	}

	if firstCommissionPaid {
		return &ForceRechargeRequirement{NeedForceRecharge: false}
	}

	if allocation.OneTimeCommissionTrigger == model.OneTimeCommissionTriggerSingleRecharge {
		return &ForceRechargeRequirement{
			NeedForceRecharge:   true,
			ForceRechargeAmount: allocation.OneTimeCommissionThreshold,
			TriggerType:         model.OneTimeCommissionTriggerSingleRecharge,
		}
	}

	if allocation.EnableForceRecharge {
		forceAmount := allocation.ForceRechargeAmount
		if forceAmount == 0 {
			forceAmount = allocation.OneTimeCommissionThreshold
		}
		return &ForceRechargeRequirement{
			NeedForceRecharge:   true,
			ForceRechargeAmount: forceAmount,
			TriggerType:         model.OneTimeCommissionTriggerAccumulatedRecharge,
		}
	}

	return &ForceRechargeRequirement{NeedForceRecharge: false}
}

func (s *Service) GetPurchaseCheck(ctx context.Context, req *dto.PurchaseCheckRequest) (*dto.PurchaseCheckResponse, error) {
	var validationResult *purchase_validation.PurchaseValidationResult
	var err error

	if req.OrderType == model.OrderTypeSingleCard {
		validationResult, err = s.purchaseValidationService.ValidateCardPurchase(ctx, req.ResourceID, req.PackageIDs)
	} else if req.OrderType == model.OrderTypeDevice {
		validationResult, err = s.purchaseValidationService.ValidateDevicePurchase(ctx, req.ResourceID, req.PackageIDs)
	} else {
		return nil, errors.New(errors.CodeInvalidParam, "无效的订单类型")
	}

	if err != nil {
		return nil, err
	}

	forceRechargeCheck := s.checkForceRechargeRequirement(validationResult)

	response := &dto.PurchaseCheckResponse{
		TotalPackageAmount:  validationResult.TotalPrice,
		NeedForceRecharge:   forceRechargeCheck.NeedForceRecharge,
		ForceRechargeAmount: forceRechargeCheck.ForceRechargeAmount,
		ActualPayment:       validationResult.TotalPrice,
		WalletCredit:        validationResult.TotalPrice,
	}

	if forceRechargeCheck.NeedForceRecharge {
		if validationResult.TotalPrice < forceRechargeCheck.ForceRechargeAmount {
			response.ActualPayment = forceRechargeCheck.ForceRechargeAmount
			response.WalletCredit = forceRechargeCheck.ForceRechargeAmount
			response.Message = "首次购买需满足最低充值要求"
		}
	}

	return response, nil
}
