package commerce

import (
	"context"
	"errors"
	"fmt"
	"strings"

	"gorm.io/gorm"
)

func (s *Service) ListCartItems(ctx context.Context, userID int64) ([]CartItemResponse, error) {
	if err := s.requireDB(); err != nil {
		return nil, err
	}
	var items []CartItem
	if err := s.db.WithContext(ctx).
		Where("user_id = ?", userID).
		Order("created_at DESC").
		Find(&items).Error; err != nil {
		return nil, err
	}

	out := make([]CartItemResponse, 0, len(items))
	for _, item := range items {
		response, err := s.buildCartResponse(ctx, item)
		if err != nil {
			return nil, err
		}
		out = append(out, response)
	}
	return out, nil
}

func (s *Service) AddCartItem(ctx context.Context, userID int64, req CartItemCreateRequest) (CartItemResponse, error) {
	if err := s.requireDB(); err != nil {
		return CartItemResponse{}, err
	}
	if err := validateCartCreate(req); err != nil {
		return CartItemResponse{}, err
	}

	product, err := s.findProductByID(ctx, req.ProductID)
	if err != nil {
		if errors.Is(err, gorm.ErrRecordNotFound) {
			return CartItemResponse{}, NotFound("产品不存在或已下架")
		}
		return CartItemResponse{}, err
	}
	reserved, err := s.cartReservedQuantity(ctx, userID, req.ProductID, nil)
	if err != nil {
		return CartItemResponse{}, err
	}
	if err := s.ensureProductCanBeAdded(product, req.Quantity, reserved); err != nil {
		return CartItemResponse{}, err
	}
	if err := s.validatePluginCartFields(product, req.SliderValues); err != nil {
		return CartItemResponse{}, err
	}
	pricing, err := s.calculateCartPricing(ctx, product, req.Cycle, req.Quantity, req.SliderValues)
	if err != nil {
		return CartItemResponse{}, err
	}

	item := CartItem{
		UserID:       userID,
		ProductID:    req.ProductID,
		Cycle:        pricing.Cycle,
		Quantity:     req.Quantity,
		AutoRenew:    req.AutoRenew,
		Alias:        trimOptional(req.Alias),
		OSImage:      trimOptional(req.OSImage),
		UnitPrice:    pricing.UnitPrice,
		AddonPrice:   pricing.AddonPrice,
		SetupFee:     pricing.SetupFee,
		SliderValues: jsonRawFromMap(req.SliderValues),
	}
	if item.Quantity <= 0 {
		item.Quantity = 1
	}
	if err := s.db.WithContext(ctx).Create(&item).Error; err != nil {
		return CartItemResponse{}, err
	}
	return s.buildCartResponse(ctx, item)
}

func (s *Service) UpdateCartItem(ctx context.Context, userID int64, itemID int64, req CartItemUpdateRequest) (CartItemResponse, error) {
	if err := s.requireDB(); err != nil {
		return CartItemResponse{}, err
	}
	item, err := s.findCartItem(ctx, userID, itemID)
	if err != nil {
		if errors.Is(err, gorm.ErrRecordNotFound) {
			return CartItemResponse{}, NotFound("购物车项不存在")
		}
		return CartItemResponse{}, err
	}

	updates := map[string]any{}
	if req.Quantity != nil {
		if *req.Quantity < 1 {
			return CartItemResponse{}, BadRequest("购买数量至少为 1")
		}
		product, err := s.findProductByID(ctx, item.ProductID)
		if err != nil {
			if errors.Is(err, gorm.ErrRecordNotFound) {
				return CartItemResponse{}, NotFound("产品不存在或已下架")
			}
			return CartItemResponse{}, err
		}
		excludeID := item.ID
		reserved, err := s.cartReservedQuantity(ctx, userID, item.ProductID, &excludeID)
		if err != nil {
			return CartItemResponse{}, err
		}
		if err := s.ensureProductCanBeAdded(product, *req.Quantity, reserved); err != nil {
			return CartItemResponse{}, err
		}
		if err := s.validatePluginCartFields(product, jsonObject(item.SliderValues)); err != nil {
			return CartItemResponse{}, err
		}
		updates["quantity"] = *req.Quantity
		item.Quantity = *req.Quantity
	}
	if req.AutoRenew != nil {
		updates["auto_renew"] = *req.AutoRenew
		item.AutoRenew = *req.AutoRenew
	}
	if req.Alias != nil {
		updates["alias"] = trimOptional(req.Alias)
		item.Alias = trimOptional(req.Alias)
	}
	if len(updates) > 0 {
		if err := s.db.WithContext(ctx).Model(&CartItem{}).Where("id = ?", item.ID).Updates(updates).Error; err != nil {
			return CartItemResponse{}, err
		}
	}
	item, err = s.findCartItem(ctx, userID, itemID)
	if err != nil {
		return CartItemResponse{}, err
	}
	return s.buildCartResponse(ctx, item)
}

func (s *Service) DeleteCartItem(ctx context.Context, userID int64, itemID int64) error {
	if err := s.requireDB(); err != nil {
		return err
	}
	item, err := s.findCartItem(ctx, userID, itemID)
	if err != nil {
		if errors.Is(err, gorm.ErrRecordNotFound) {
			return NotFound("购物车项不存在")
		}
		return err
	}
	return s.db.WithContext(ctx).Delete(&item).Error
}

func (s *Service) ClearCart(ctx context.Context, userID int64) (map[string]int64, error) {
	if err := s.requireDB(); err != nil {
		return nil, err
	}
	var items []CartItem
	if err := s.db.WithContext(ctx).Where("user_id = ?", userID).Find(&items).Error; err != nil {
		return nil, err
	}
	for _, item := range items {
		if err := s.db.WithContext(ctx).Delete(&item).Error; err != nil {
			return nil, err
		}
	}
	return map[string]int64{"deleted": int64(len(items))}, nil
}

func (s *Service) buildCartResponse(ctx context.Context, item CartItem) (CartItemResponse, error) {
	product, err := s.findProductByID(ctx, item.ProductID)
	if errors.Is(err, gorm.ErrRecordNotFound) {
		return newCartItemResponse(item, nil), nil
	}
	if err != nil {
		return CartItemResponse{}, err
	}
	return newCartItemResponse(item, &product), nil
}

func (s *Service) findCartItem(ctx context.Context, userID int64, itemID int64) (CartItem, error) {
	var item CartItem
	err := s.db.WithContext(ctx).
		Where("id = ? AND user_id = ?", itemID, userID).
		First(&item).Error
	return item, err
}

func (s *Service) findProductByID(ctx context.Context, productID int64) (Product, error) {
	var product Product
	err := s.db.WithContext(ctx).Where("id = ?", productID).First(&product).Error
	return product, err
}

func (s *Service) cartReservedQuantity(ctx context.Context, userID int64, productID int64, excludeItemID *int64) (int, error) {
	var items []CartItem
	query := s.db.WithContext(ctx).
		Where("user_id = ? AND product_id = ?", userID, productID)
	if excludeItemID != nil {
		query = query.Where("id <> ?", *excludeItemID)
	}
	if err := query.Find(&items).Error; err != nil {
		return 0, err
	}
	total := 0
	for _, item := range items {
		total += item.Quantity
	}
	return total, nil
}

func (s *Service) ensureProductCanBeAdded(product Product, quantity int, reservedQuantity int) error {
	if product.Status != "active" {
		return NotFound("产品不存在或已下架")
	}
	if product.StockPolicy != "tracked" {
		return nil
	}
	available := product.Stock
	required := reservedQuantity + quantity
	if available <= 0 {
		return Conflict(fmt.Sprintf("产品「%s」已售罄", product.Name))
	}
	if required > available {
		detail := fmt.Sprintf("产品「%s」库存不足，当前仅剩 %d 台", product.Name, available)
		if reservedQuantity > 0 {
			detail += fmt.Sprintf("，购物车已选择 %d 台", reservedQuantity)
		}
		return Conflict(detail)
	}
	return nil
}

func validateCartCreate(req CartItemCreateRequest) error {
	if req.ProductID <= 0 {
		return BadRequest("产品不存在或已下架")
	}
	if strings.TrimSpace(req.Cycle) == "" || len(strings.TrimSpace(req.Cycle)) > 16 {
		return BadRequest("计费周期不正确")
	}
	if req.Quantity < 1 {
		return BadRequest("购买数量至少为 1")
	}
	return nil
}

func trimOptional(value *string) *string {
	if value == nil {
		return nil
	}
	trimmed := strings.TrimSpace(*value)
	if trimmed == "" {
		return nil
	}
	return &trimmed
}
