package handlers

import (
	"fmt"
	"math"
	"net/http"
	"strconv"
	"time"

	"sale/internal/models"
	"sale/internal/schemas"
	"sale/internal/utils"

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

type CartHandler struct{}

func NewCartHandler() *CartHandler {
	return &CartHandler{}
}

func (h *CartHandler) List(c *gin.Context) {
	userID := c.GetUint("user_id")
	var carts []models.Cart
	utils.DB.Where("user_id = ?", userID).Preload("Product").Find(&carts)
	c.JSON(http.StatusOK, gin.H{"data": carts})
}

func (h *CartHandler) Add(c *gin.Context) {
	userID := c.GetUint("user_id")
	var req schemas.AddToCartRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
	}

	// 获取商品信息
	var product models.Product
	if err := utils.DB.First(&product, req.ProductID).Error; err != nil {
		c.JSON(http.StatusNotFound, gin.H{"error": "Product not found"})
		return
	}

	// 检查商品是否上架
	if !product.IsActive {
		c.JSON(http.StatusBadRequest, gin.H{"error": "Product is not available"})
		return
	}

	// 检查购物资格（需要资格的商品，每个订单消耗1个资格）
	if product.RequireCredit {
		var user models.User
		utils.DB.First(&user, userID)
		if user.PurchaseCredits < 1 {
			c.JSON(http.StatusBadRequest, gin.H{"error": "Insufficient purchase credits. This product requires 1 credit per order."})
			return
		}
	}

	// 检查库存
	var inventory models.Inventory
	if err := utils.DB.Where("product_id = ?", req.ProductID).First(&inventory).Error; err == nil {
		if inventory.Quantity < req.Quantity {
			c.JSON(http.StatusBadRequest, gin.H{"error": "Insufficient stock. Available: " + strconv.Itoa(inventory.Quantity)})
			return
		}
	}

	// 检查购物车中是否已存在该商品
	var existingCart models.Cart
	var totalQuantity int
	result := utils.DB.Where("user_id = ? AND product_id = ?", userID, req.ProductID).First(&existingCart)
	if result.Error == nil {
		totalQuantity = existingCart.Quantity + req.Quantity
	} else {
		totalQuantity = req.Quantity
	}

	// 检查最大购买数量
	if product.MaxPurchase != nil && *product.MaxPurchase > 0 && totalQuantity > *product.MaxPurchase {
		c.JSON(http.StatusBadRequest, gin.H{"error": "Maximum purchase quantity is " + strconv.Itoa(*product.MaxPurchase)})
		return
	}

	// 添加或更新购物车
	var cart models.Cart
	if result.Error == nil {
		existingCart.Quantity = totalQuantity
		utils.DB.Save(&existingCart)
		cart = existingCart
	} else {
		cart = models.Cart{
			UserID:    userID,
			ProductID: req.ProductID,
			Quantity:  req.Quantity,
		}
		utils.DB.Create(&cart)
	}

	utils.DB.Preload("Product").First(&cart, cart.ID)
	c.JSON(http.StatusOK, gin.H{"data": cart})
}

func (h *CartHandler) Update(c *gin.Context) {
	userID := c.GetUint("user_id")
	id, _ := strconv.Atoi(c.Param("id"))

	var cart models.Cart
	if err := utils.DB.Where("id = ? AND user_id = ?", id, userID).First(&cart).Error; err != nil {
		c.JSON(http.StatusNotFound, gin.H{"error": "Cart item not found"})
		return
	}

	var req schemas.UpdateCartRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
	}

	cart.Quantity = req.Quantity
	utils.DB.Save(&cart)
	utils.DB.Preload("Product").First(&cart, cart.ID)
	c.JSON(http.StatusOK, gin.H{"data": cart})
}

func (h *CartHandler) Delete(c *gin.Context) {
	userID := c.GetUint("user_id")
	id, _ := strconv.Atoi(c.Param("id"))

	if err := utils.DB.Where("id = ? AND user_id = ?", id, userID).Delete(&models.Cart{}).Error; err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to delete cart item"})
		return
	}

	c.JSON(http.StatusOK, gin.H{"message": "Cart item deleted successfully"})
}

type OrderHandler struct{}

func NewOrderHandler() *OrderHandler {
	return &OrderHandler{}
}

func checkOrderExpired(order *models.Order) {
	if order.Status != models.OrderStatusPendingPayment || order.PaymentExpiresAt == nil {
		return
	}
	if time.Now().After(*order.PaymentExpiresAt) {
		tx := utils.DB.Begin()
		tx.Model(order).Update("status", models.OrderStatusCancelled)
		for _, item := range order.OrderItems {
			var inventory models.Inventory
			if err := tx.Where("product_id = ?", item.ProductID).First(&inventory).Error; err == nil {
				tx.Model(&inventory).UpdateColumn("quantity", inventory.Quantity+item.Quantity)
			}
			var product models.Product
			if err := tx.First(&product, item.ProductID).Error; err == nil {
				if product.RequireCredit {
					tx.Model(&models.User{}).Where("id = ?", order.UserID).
						UpdateColumn("purchase_credits", utils.DB.Raw("purchase_credits + 1"))
				}
				if product.CreditReward > 0 {
					tx.Model(&models.User{}).Where("id = ?", order.UserID).
						UpdateColumn("purchase_credits", utils.DB.Raw("purchase_credits - ?", product.CreditReward*item.Quantity))
				}
			}
		}
		tx.Commit()
		order.Status = models.OrderStatusCancelled
	}
}

func checkOrdersExpired(orders []models.Order) {
	for i := range orders {
		checkOrderExpired(&orders[i])
	}
}

// getPaymentExpiryTime 获取支付过期时间（当前时间 + 30分钟）
func getPaymentExpiryTime() *time.Time {
	t := time.Now().Add(30 * time.Minute)
	return &t
}

func (h *OrderHandler) List(c *gin.Context) {
	userID := c.GetUint("user_id")
	role, _ := c.Get("role")

	var orders []models.Order
	query := utils.DB.Model(&models.Order{})

	if role == "user" {
		query = query.Where("user_id = ?", userID)
	} else if role == "supplier" {
		query = query.Where("supplier_id = ?", userID)
	}

	query.Preload("OrderItems.Product").Preload("ShippingAddress").
		Order("created_at DESC").Find(&orders)

	checkOrdersExpired(orders)

	c.JSON(http.StatusOK, gin.H{"data": orders})
}

func (h *OrderHandler) GetByID(c *gin.Context) {
	userID := c.GetUint("user_id")
	role, _ := c.Get("role")
	id, _ := strconv.Atoi(c.Param("id"))

	var order models.Order
	query := utils.DB.Preload("OrderItems.Product").Preload("ShippingAddress").Preload("User")

	if role == "user" {
		query = query.Where("user_id = ?", userID)
	} else if role == "supplier" {
		query = query.Where("supplier_id = ?", userID)
	}

	if err := query.First(&order, id).Error; err != nil {
		c.JSON(http.StatusNotFound, gin.H{"error": "Order not found"})
		return
	}

	checkOrderExpired(&order)

	c.JSON(http.StatusOK, gin.H{"data": order})
}

func (h *OrderHandler) Create(c *gin.Context) {
	userID := c.GetUint("user_id")
	var req schemas.CreateOrderRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
	}

	var carts []models.Cart
	cartQuery := utils.DB.Where("user_id = ?", userID).Preload("Product")
	if len(req.CartItemIDs) > 0 {
		cartQuery = cartQuery.Where("id IN ?", req.CartItemIDs)
	}
	cartQuery.Find(&carts)

	if len(carts) == 0 {
		c.JSON(http.StatusBadRequest, gin.H{"error": "Cart is empty"})
		return
	}

	var subtotal float64
	var totalQuantity int
	var totalWeight float64
	var orderItems []models.OrderItem
	supplierMap := make(map[uint]bool)

	for _, cart := range carts {
		if !cart.Product.IsActive {
			c.JSON(http.StatusBadRequest, gin.H{"error": "Product " + cart.Product.Name + " is no longer available"})
			return
		}

		if cart.Product.MinPurchase > 0 && cart.Quantity < cart.Product.MinPurchase {
			c.JSON(http.StatusBadRequest, gin.H{"error": cart.Product.Name + " minimum purchase is " + strconv.Itoa(cart.Product.MinPurchase)})
			return
		}
		if cart.Product.MaxPurchase != nil && *cart.Product.MaxPurchase > 0 && cart.Quantity > *cart.Product.MaxPurchase {
			c.JSON(http.StatusBadRequest, gin.H{"error": cart.Product.Name + " maximum purchase is " + strconv.Itoa(*cart.Product.MaxPurchase)})
			return
		}

		if cart.Product.RequireCredit {
			var user models.User
			utils.DB.First(&user, userID)
			if user.PurchaseCredits < 1 {
				c.JSON(http.StatusBadRequest, gin.H{"error": "Insufficient purchase credits for " + cart.Product.Name})
				return
			}
		}

		var inventory models.Inventory
		if err := utils.DB.Where("product_id = ?", cart.ProductID).First(&inventory).Error; err != nil {
			c.JSON(http.StatusBadRequest, gin.H{"error": "No inventory record for " + cart.Product.Name})
			return
		}
		if inventory.Quantity < cart.Quantity {
			c.JSON(http.StatusBadRequest, gin.H{"error": "Insufficient stock for " + cart.Product.Name + ". Available: " + strconv.Itoa(inventory.Quantity)})
			return
		}

		subtotal += cart.Product.Price * float64(cart.Quantity)
		totalQuantity += cart.Quantity
			totalWeight += cart.Product.Weight * float64(cart.Quantity)
		orderItems = append(orderItems, models.OrderItem{
			ProductID: cart.ProductID,
			Quantity:  cart.Quantity,
			Price:     cart.Product.Price,
		})

		if inventory.SupplierID != 0 {
			supplierMap[inventory.SupplierID] = true
		}
	}

	var supplierID *uint
	for sid := range supplierMap {
		sid := sid
		supplierID = &sid
		break
	}

	// 获取收货地址省份
	var shippingAddress models.Address
	var province string
	if err := utils.DB.First(&shippingAddress, req.ShippingAddressID).Error; err == nil {
		province = shippingAddress.Province
	}

	// 使用运费模板计算运费
	shippingFee := 0.0

	// 按运费模板分组计算
	type TemplateGroup struct {
		TemplateID *uint
		Weight     float64
		Quantity   int
		Subtotal   float64
	}
	templateGroups := make(map[uint]*TemplateGroup)
	noTemplateGroup := &TemplateGroup{Subtotal: 0, Weight: 0, Quantity: 0}

	for _, cart := range carts {
		var templateID uint
		if cart.Product.ShippingTemplateID != nil {
			templateID = *cart.Product.ShippingTemplateID
		}

		if templateID == 0 {
			// 没有运费模板，累加到无模板组
			noTemplateGroup.Weight += cart.Product.Weight * float64(cart.Quantity)
			noTemplateGroup.Quantity += cart.Quantity
			noTemplateGroup.Subtotal += cart.Product.Price * float64(cart.Quantity)
		} else {
			if _, ok := templateGroups[templateID]; !ok {
				templateGroups[templateID] = &TemplateGroup{
					TemplateID: &templateID,
					Weight:     0,
					Quantity:   0,
					Subtotal:   0,
				}
			}
			templateGroups[templateID].Weight += cart.Product.Weight * float64(cart.Quantity)
			templateGroups[templateID].Quantity += cart.Quantity
			templateGroups[templateID].Subtotal += cart.Product.Price * float64(cart.Quantity)
		}
	}

	// 计算有模板的运费
	for _, group := range templateGroups {
		fee, _ := CalculateShippingFee(group.TemplateID, group.Weight, group.Quantity, group.Subtotal, province)
		shippingFee += fee
	}

	// 计算无模板的运费（使用旧的系统设置）
	if noTemplateGroup.Subtotal > 0 {
		var shippingFeeFirstWeight, shippingFeePerGram float64
		var setting models.SystemSetting
		if err := utils.DB.Where("`key` = ?", "shipping_fee_first_weight").First(&setting).Error; err == nil {
			shippingFeeFirstWeight, _ = strconv.ParseFloat(setting.Value, 64)
		}
		if err := utils.DB.Where("`key` = ?", "shipping_fee_per_gram").First(&setting).Error; err == nil {
			shippingFeePerGram, _ = strconv.ParseFloat(setting.Value, 64)
		}
		if noTemplateGroup.Subtotal < 99 && shippingFeeFirstWeight > 0 {
			fee := shippingFeeFirstWeight
			if noTemplateGroup.Weight > 500 {
				fee += shippingFeePerGram * (noTemplateGroup.Weight - 500)
			}
			shippingFee += fee
		}
	}

	// 获取其他费率
	var serviceFeeRate, channelFeeRate, packagingFee, internationalFeeRate float64
	var setting models.SystemSetting
	if err := utils.DB.Where("`key` = ?", "service_fee_rate").First(&setting).Error; err == nil {
		serviceFeeRate, _ = strconv.ParseFloat(setting.Value, 64)
	}
	if err := utils.DB.Where("`key` = ?", "payment_channel_fee_rate").First(&setting).Error; err == nil {
		channelFeeRate, _ = strconv.ParseFloat(setting.Value, 64)
	}
	if err := utils.DB.Where("`key` = ?", "packaging_fee").First(&setting).Error; err == nil {
		packagingFee, _ = strconv.ParseFloat(setting.Value, 64)
	}
	if err := utils.DB.Where("`key` = ?", "international_fee_rate").First(&setting).Error; err == nil {
		internationalFeeRate, _ = strconv.ParseFloat(setting.Value, 64)
	}

	serviceFee := subtotal * serviceFeeRate / 100
	channelFee := subtotal * channelFeeRate / 100
	internationalFee := subtotal * internationalFeeRate / 100
	totalAmount := subtotal + shippingFee + serviceFee + channelFee + packagingFee + internationalFee

	order := models.Order{
		UserID:            userID,
		SupplierID:        supplierID,
		Subtotal:          subtotal,
		ShippingFee:       shippingFee,
		ServiceFee:        serviceFee,
		ChannelFee:        channelFee,
		PackagingFee:      packagingFee,
		InternationalFee:  internationalFee,
		TotalAmount:       totalAmount,
		Status:            models.OrderStatusPendingPayment,
		ShippingAddressID: &req.ShippingAddressID,
		PaymentMethod:     req.PaymentMethod,
		PaymentExpiresAt:  getPaymentExpiryTime(),
	}

	tx := utils.DB.Begin()
	if err := tx.Create(&order).Error; err != nil {
		tx.Rollback()
		c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to create order"})
		return
	}

	for i := range orderItems {
		orderItems[i].OrderID = order.ID
	}
	if err := tx.Create(&orderItems).Error; err != nil {
		tx.Rollback()
		c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to create order items"})
		return
	}

	for _, cart := range carts {
		if cart.Product.RequireCredit {
			if err := tx.Model(&models.User{}).Where("id = ?", userID).
				UpdateColumn("purchase_credits", utils.DB.Raw("purchase_credits - 1")).Error; err != nil {
				tx.Rollback()
				c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to deduct credits"})
				return
			}
		}
		if cart.Product.CreditReward > 0 {
			tx.Model(&models.User{}).Where("id = ?", userID).
				UpdateColumn("purchase_credits", utils.DB.Raw("purchase_credits + ?", cart.Product.CreditReward*cart.Quantity))
		}

		var inventory models.Inventory
		if err := tx.Where("product_id = ?", cart.ProductID).First(&inventory).Error; err == nil {
			if inventory.Quantity >= cart.Quantity {
				tx.Model(&inventory).UpdateColumn("quantity", inventory.Quantity-cart.Quantity)
			}
		}
	}

	cartIDs := make([]uint, len(carts))
	for i, cart := range carts {
		cartIDs[i] = cart.ID
	}
	if err := tx.Where("id IN ? AND user_id = ?", cartIDs, userID).Delete(&models.Cart{}).Error; err != nil {
		tx.Rollback()
		c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to clear cart"})
		return
	}

	tx.Commit()

	utils.DB.Preload("OrderItems.Product").Preload("ShippingAddress").First(&order, order.ID)
	c.JSON(http.StatusCreated, gin.H{"data": order})
}

func (h *OrderHandler) Refund(c *gin.Context) {
	userID := c.GetUint("user_id")
	id, _ := strconv.Atoi(c.Param("id"))

	var order models.Order
	if err := utils.DB.Where("id = ? AND user_id = ?", id, userID).First(&order).Error; err != nil {
		c.JSON(http.StatusNotFound, gin.H{"error": "Order not found"})
		return
	}

	if order.Status == models.OrderStatusShipped || order.Status == models.OrderStatusCompleted {
		c.JSON(http.StatusBadRequest, gin.H{"error": "Cannot refund a shipped or completed order"})
		return
	}

	if order.RefundStatus == models.RefundStatusPending {
		c.JSON(http.StatusBadRequest, gin.H{"error": "Refund already requested"})
		return
	}

	var req schemas.RefundRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
	}

	utils.DB.Model(&order).Updates(map[string]interface{}{
		"refund_status": models.RefundStatusPending,
		"refund_reason": req.Reason,
		"status":        models.OrderStatusRefunding,
	})

	c.JSON(http.StatusOK, gin.H{"message": "Refund request submitted successfully"})
}

func (h *OrderHandler) ConfirmOrder(c *gin.Context) {
	userID := c.GetUint("user_id")
	id, _ := strconv.Atoi(c.Param("id"))

	var order models.Order
	if err := utils.DB.Where("id = ? AND supplier_id = ?", id, userID).First(&order).Error; err != nil {
		c.JSON(http.StatusNotFound, gin.H{"error": "Order not found"})
		return
	}

	if order.Status != models.OrderStatusPendingConfirm {
		c.JSON(http.StatusBadRequest, gin.H{"error": "Order cannot be confirmed"})
		return
	}

	utils.DB.Model(&order).Update("status", models.OrderStatusPendingShip)
	c.JSON(http.StatusOK, gin.H{"message": "Order confirmed successfully"})
}

func (h *OrderHandler) ShipOrder(c *gin.Context) {
	userID := c.GetUint("user_id")
	id, _ := strconv.Atoi(c.Param("id"))

	var order models.Order
	if err := utils.DB.Where("id = ? AND supplier_id = ?", id, userID).First(&order).Error; err != nil {
		c.JSON(http.StatusNotFound, gin.H{"error": "Order not found"})
		return
	}

	if order.Status != models.OrderStatusPendingShip {
		c.JSON(http.StatusBadRequest, gin.H{"error": "Order cannot be shipped"})
		return
	}

	var req schemas.ShipOrderRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
	}

	utils.DB.Model(&order).Updates(map[string]interface{}{
		"status":          models.OrderStatusShipped,
		"tracking_number": req.TrackingNumber,
		"shipping_photo":  req.ShippingPhoto,
		"express_photo":   req.ExpressPhoto,
		"customs_photo":   req.CustomsPhoto,
	})

	c.JSON(http.StatusOK, gin.H{"message": "Order shipped successfully"})
}

func (h *OrderHandler) AdminList(c *gin.Context) {
	page, _ := strconv.Atoi(c.DefaultQuery("page", "1"))
	pageSize, _ := strconv.Atoi(c.DefaultQuery("page_size", "20"))

	var total int64
	utils.DB.Model(&models.Order{}).Count(&total)

	var orders []models.Order
	offset := (page - 1) * pageSize
	utils.DB.Preload("OrderItems.Product").Preload("ShippingAddress").Preload("User").
		Order("created_at DESC").Offset(offset).Limit(pageSize).Find(&orders)

	checkOrdersExpired(orders)

	totalPages := int(math.Ceil(float64(total) / float64(pageSize)))
	c.JSON(http.StatusOK, gin.H{
		"data": orders,
		"pagination": gin.H{
			"page":       page,
			"page_size":  pageSize,
			"total":      total,
			"total_pages": totalPages,
		},
	})
}

func (h *OrderHandler) AdminGetByID(c *gin.Context) {
	id, _ := strconv.Atoi(c.Param("id"))

	var order models.Order
	if err := utils.DB.Preload("OrderItems.Product").Preload("ShippingAddress").Preload("User").First(&order, id).Error; err != nil {
		c.JSON(http.StatusNotFound, gin.H{"error": "Order not found"})
		return
	}

	checkOrderExpired(&order)

	c.JSON(http.StatusOK, gin.H{"data": order})
}

func (h *OrderHandler) ProcessRefund(c *gin.Context) {
	id, _ := strconv.Atoi(c.Param("id"))

	var order models.Order
	if err := utils.DB.Preload("OrderItems").First(&order, id).Error; err != nil {
		c.JSON(http.StatusNotFound, gin.H{"error": "Order not found"})
		return
	}

	var req schemas.ProcessRefundRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
	}

	if req.Status == "approved" {
		var setting models.SystemSetting
		feeRate := 0.0
		if err := utils.DB.Where("`key` = ?", "payment_channel_fee_rate").First(&setting).Error; err == nil {
			feeRate, _ = strconv.ParseFloat(setting.Value, 64)
		}

		refundAmount := order.TotalAmount * (1 - feeRate/100)

		tx := utils.DB.Begin()

		tx.Model(&order).Updates(map[string]interface{}{
			"refund_status": models.RefundStatusCompleted,
			"refund_amount": refundAmount,
			"status":        models.OrderStatusRefunded,
		})

		for _, item := range order.OrderItems {
			var product models.Product
			if err := tx.First(&product, item.ProductID).Error; err == nil {
				if product.RequireCredit {
					tx.Model(&models.User{}).Where("id = ?", order.UserID).
						UpdateColumn("purchase_credits", utils.DB.Raw("purchase_credits + 1"))
				}
				if product.CreditReward > 0 {
					tx.Model(&models.User{}).Where("id = ?", order.UserID).
						UpdateColumn("purchase_credits", utils.DB.Raw("purchase_credits - ?", product.CreditReward*item.Quantity))
				}
			}

			var inventory models.Inventory
			if err := tx.Where("product_id = ?", item.ProductID).First(&inventory).Error; err == nil {
				tx.Model(&inventory).UpdateColumn("quantity", inventory.Quantity+item.Quantity)
			}
		}

		tx.Commit()
	} else {
		utils.DB.Model(&order).Updates(map[string]interface{}{
			"refund_status": models.RefundStatusRejected,
			"status":        models.OrderStatusPendingConfirm,
		})
	}

	c.JSON(http.StatusOK, gin.H{"message": "Refund processed successfully"})
}

func (h *OrderHandler) Export(c *gin.Context) {
	var orders []models.Order
	utils.DB.Preload("OrderItems.Product").Preload("ShippingAddress").Preload("User").
		Order("created_at DESC").Find(&orders)

	// 创建 Excel 文件
	f := excelize.NewFile()
	defer f.Close()

	sheetName := "订单列表"
	f.SetSheetName("Sheet1", sheetName)

	// 设置表头
	headers := []string{"订单ID", "用户名", "订单状态", "商品信息", "商品金额", "运费", "服务费", "通道费", "包装费", "国际计算手续费", "订单总额", "收货人", "联系电话", "收货地址", "快递单号", "创建时间"}
	for i, header := range headers {
		cell, _ := excelize.CoordinatesToCellName(i+1, 1)
		f.SetCellValue(sheetName, cell, header)
	}

	// 设置表头样式
	headerStyle, _ := f.NewStyle(&excelize.Style{
		Font:      &excelize.Font{Bold: true},
		Fill:      excelize.Fill{Type: "pattern", Color: []string{"#4472C4"}, Pattern: 1},
		Alignment: &excelize.Alignment{Horizontal: "center", Vertical: "center"},
	})
	f.SetRowStyle(sheetName, 1, 1, headerStyle)

	// 状态映射
	statusMap := map[string]string{
		"pending_payment": "待支付", "pending_confirm": "待确认", "pending_ship": "待发货",
		"shipped": "已发货", "completed": "已完成", "refunding": "退款中", "refunded": "已退款", "cancelled": "已取消",
	}

	// 填充数据
	for i, order := range orders {
		row := i + 2

		// 商品信息
		var productsStr string
		for _, item := range order.OrderItems {
			if productsStr != "" {
				productsStr += "; "
			}
			productsStr += fmt.Sprintf("%s x%d", item.Product.Name, item.Quantity)
		}

		// 收货地址
		var addressStr string
		if order.ShippingAddress != nil {
			addressStr = order.ShippingAddress.Province + order.ShippingAddress.City + order.ShippingAddress.District + order.ShippingAddress.Address
		}

		// 填充单元格
		f.SetCellValue(sheetName, fmt.Sprintf("A%d", row), order.ID)
		f.SetCellValue(sheetName, fmt.Sprintf("B%d", row), order.User.Username)
		f.SetCellValue(sheetName, fmt.Sprintf("C%d", row), statusMap[order.Status])
		f.SetCellValue(sheetName, fmt.Sprintf("D%d", row), productsStr)
		f.SetCellValue(sheetName, fmt.Sprintf("E%d", row), order.Subtotal)
		f.SetCellValue(sheetName, fmt.Sprintf("F%d", row), order.ShippingFee)
		f.SetCellValue(sheetName, fmt.Sprintf("G%d", row), order.ServiceFee)
		f.SetCellValue(sheetName, fmt.Sprintf("H%d", row), order.ChannelFee)
		f.SetCellValue(sheetName, fmt.Sprintf("I%d", row), order.PackagingFee)
		f.SetCellValue(sheetName, fmt.Sprintf("J%d", row), order.InternationalFee)
		f.SetCellValue(sheetName, fmt.Sprintf("K%d", row), order.TotalAmount)
		if order.ShippingAddress != nil {
			f.SetCellValue(sheetName, fmt.Sprintf("L%d", row), order.ShippingAddress.Name)
			f.SetCellValue(sheetName, fmt.Sprintf("M%d", row), order.ShippingAddress.Phone)
			f.SetCellValue(sheetName, fmt.Sprintf("N%d", row), addressStr)
		}
		f.SetCellValue(sheetName, fmt.Sprintf("O%d", row), order.TrackingNumber)
		f.SetCellValue(sheetName, fmt.Sprintf("P%d", row), order.CreatedAt.Format("2006-01-02 15:04:05"))
	}

	// 设置列宽
	f.SetColWidth(sheetName, "A", "A", 10)
	f.SetColWidth(sheetName, "B", "B", 15)
	f.SetColWidth(sheetName, "C", "C", 10)
	f.SetColWidth(sheetName, "D", "D", 40)
	f.SetColWidth(sheetName, "E", "K", 12)
	f.SetColWidth(sheetName, "L", "M", 15)
	f.SetColWidth(sheetName, "N", "N", 40)
	f.SetColWidth(sheetName, "O", "O", 20)
	f.SetColWidth(sheetName, "P", "P", 20)

	// 设置响应头
	filename := fmt.Sprintf("orders_%s.xlsx", time.Now().Format("20060102150405"))
	c.Header("Content-Type", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet")
	c.Header("Content-Disposition", fmt.Sprintf("attachment; filename=%s", filename))
	c.Header("Content-Transfer-Encoding", "binary")

	// 写入响应
	buf, err := f.WriteToBuffer()
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to generate Excel file"})
		return
	}

	c.Data(http.StatusOK, "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", buf.Bytes())
}

func (h *OrderHandler) CancelOrder(c *gin.Context) {
	userID := c.GetUint("user_id")
	id, _ := strconv.Atoi(c.Param("id"))

	var order models.Order
	if err := utils.DB.Preload("OrderItems").Where("id = ? AND user_id = ?", id, userID).First(&order).Error; err != nil {
		c.JSON(http.StatusNotFound, gin.H{"error": "Order not found"})
		return
	}

	if order.Status != models.OrderStatusPendingPayment && order.Status != models.OrderStatusPendingConfirm {
		c.JSON(http.StatusBadRequest, gin.H{"error": "Order cannot be cancelled"})
		return
	}

	tx := utils.DB.Begin()
	tx.Model(&order).Update("status", models.OrderStatusCancelled)

	for _, item := range order.OrderItems {
		var product models.Product
		if err := tx.First(&product, item.ProductID).Error; err == nil {
			if product.RequireCredit {
				tx.Model(&models.User{}).Where("id = ?", order.UserID).
					UpdateColumn("purchase_credits", utils.DB.Raw("purchase_credits + 1"))
			}
			if product.CreditReward > 0 {
				tx.Model(&models.User{}).Where("id = ?", order.UserID).
					UpdateColumn("purchase_credits", utils.DB.Raw("purchase_credits - ?", product.CreditReward*item.Quantity))
			}
		}

		var inventory models.Inventory
		if err := tx.Where("product_id = ?", item.ProductID).First(&inventory).Error; err == nil {
			tx.Model(&inventory).UpdateColumn("quantity", inventory.Quantity+item.Quantity)
		}
	}

	tx.Commit()
	c.JSON(http.StatusOK, gin.H{"message": "Order cancelled successfully"})
}

func (h *OrderHandler) ConfirmReceipt(c *gin.Context) {
	userID := c.GetUint("user_id")
	id, _ := strconv.Atoi(c.Param("id"))

	var order models.Order
	if err := utils.DB.Where("id = ? AND user_id = ?", id, userID).First(&order).Error; err != nil {
		c.JSON(http.StatusNotFound, gin.H{"error": "Order not found"})
		return
	}

	if order.Status != models.OrderStatusShipped {
		c.JSON(http.StatusBadRequest, gin.H{"error": "Order cannot be confirmed"})
		return
	}

	utils.DB.Model(&order).Update("status", models.OrderStatusCompleted)
	c.JSON(http.StatusOK, gin.H{"message": "Order confirmed successfully"})
}

func (h *OrderHandler) AdminUpdateStatus(c *gin.Context) {
	id, _ := strconv.Atoi(c.Param("id"))

	var order models.Order
	if err := utils.DB.First(&order, id).Error; err != nil {
		c.JSON(http.StatusNotFound, gin.H{"error": "Order not found"})
		return
	}

	var req struct {
		Status         string `json:"status" binding:"required"`
		TrackingNumber string `json:"tracking_number"`
	}
	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
	}

	validStatuses := []string{
		models.OrderStatusPendingPayment,
		models.OrderStatusPendingConfirm,
		models.OrderStatusPendingShip,
		models.OrderStatusShipped,
		models.OrderStatusCompleted,
		models.OrderStatusRefunding,
		models.OrderStatusRefunded,
		models.OrderStatusCancelled,
	}
	valid := false
	for _, s := range validStatuses {
		if s == req.Status {
			valid = true
			break
		}
	}
	if !valid {
		c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid status"})
		return
	}

	updates := map[string]interface{}{"status": req.Status}
	if req.TrackingNumber != "" {
		updates["tracking_number"] = req.TrackingNumber
	}

	utils.DB.Model(&order).Updates(updates)
	c.JSON(http.StatusOK, gin.H{"message": "Order status updated successfully"})
}
