package storage

import (
	"fmt"

	"github.com/google/uuid"
	"gorm.io/gorm"

	"mengyastore-backend/internal/database"
	"mengyastore-backend/internal/models"
)

type OrderStore struct {
	db *gorm.DB
}

func NewOrderStore(db *gorm.DB) (*OrderStore, error) {
	return &OrderStore{db: db}, nil
}

func orderRowToModel(row database.OrderRow) models.Order {
	return models.Order{
		ID:             row.ID,
		ProductID:      row.ProductID,
		ProductName:    row.ProductName,
		UserAccount:    row.UserAccount,
		UserName:       row.UserName,
		Quantity:       row.Quantity,
		DeliveredCodes: row.DeliveredCodes,
		Status:         row.Status,
		DeliveryMode:   row.DeliveryMode,
		Note:           row.Note,
		ContactPhone:   row.ContactPhone,
		ContactEmail:   row.ContactEmail,
		NotifyEmail:    row.NotifyEmail,
		CreatedAt:      row.CreatedAt,
	}
}

func (s *OrderStore) Create(order models.Order) (models.Order, error) {
	if order.ID == "" {
		order.ID = uuid.NewString()
	}
	if len(order.DeliveredCodes) == 0 {
		order.DeliveredCodes = []string{}
	}
	row := database.OrderRow{
		ID:             order.ID,
		ProductID:      order.ProductID,
		ProductName:    order.ProductName,
		UserAccount:    order.UserAccount,
		UserName:       order.UserName,
		Quantity:       order.Quantity,
		DeliveredCodes: database.StringSlice(order.DeliveredCodes),
		Status:         order.Status,
		DeliveryMode:   order.DeliveryMode,
		Note:           order.Note,
		ContactPhone:   order.ContactPhone,
		ContactEmail:   order.ContactEmail,
		NotifyEmail:    order.NotifyEmail,
	}
	if err := s.db.Create(&row).Error; err != nil {
		return models.Order{}, err
	}
	order.CreatedAt = row.CreatedAt
	return order, nil
}

func (s *OrderStore) GetByID(id string) (models.Order, error) {
	var row database.OrderRow
	if err := s.db.First(&row, "id = ?", id).Error; err != nil {
		return models.Order{}, fmt.Errorf("order not found")
	}
	return orderRowToModel(row), nil
}

func (s *OrderStore) Confirm(id string) (models.Order, error) {
	var row database.OrderRow
	if err := s.db.First(&row, "id = ?", id).Error; err != nil {
		return models.Order{}, fmt.Errorf("order not found")
	}
	if err := s.db.Model(&row).Update("status", "completed").Error; err != nil {
		return models.Order{}, err
	}
	row.Status = "completed"
	return orderRowToModel(row), nil
}

func (s *OrderStore) ListByAccount(account string) ([]models.Order, error) {
	var rows []database.OrderRow
	if err := s.db.Where("user_account = ?", account).Order("created_at DESC").Find(&rows).Error; err != nil {
		return nil, err
	}
	orders := make([]models.Order, len(rows))
	for i, r := range rows {
		orders[i] = orderRowToModel(r)
	}
	return orders, nil
}

func (s *OrderStore) ListAll() ([]models.Order, error) {
	var rows []database.OrderRow
	if err := s.db.Order("created_at DESC").Find(&rows).Error; err != nil {
		return nil, err
	}
	orders := make([]models.Order, len(rows))
	for i, r := range rows {
		orders[i] = orderRowToModel(r)
	}
	return orders, nil
}

func (s *OrderStore) CountPurchasedByAccount(account, productID string) (int, error) {
	var total int64
	// 统计 pending（手动待发货）和 completed 两种状态，防止用户快速下单绕过购买数量限制。
	err := s.db.Model(&database.OrderRow{}).
		Where("user_account = ? AND product_id = ? AND status IN ?", account, productID, []string{"pending", "completed"}).
		Select("COALESCE(SUM(quantity), 0)").Scan(&total).Error
	return int(total), err
}

// Count 返回所有订单的总数量。
func (s *OrderStore) Count() (int, error) {
	var count int64
	if err := s.db.Model(&database.OrderRow{}).Count(&count).Error; err != nil {
		return 0, err
	}
	return int(count), nil
}

// Delete 根据 ID 删除单条订单。
func (s *OrderStore) Delete(id string) error {
	return s.db.Delete(&database.OrderRow{}, "id = ?", id).Error
}

// UpdateCodes 更新订单的已发货卡密列表。
func (s *OrderStore) UpdateCodes(id string, codes []string) error {
	return s.db.Model(&database.OrderRow{}).Where("id = ?", id).
		Update("delivered_codes", database.StringSlice(codes)).Error
}
