package postgres

import (
	"context"
	"time"

	"github.com/break/junhong_cmp_fiber/internal/model"
	"github.com/redis/go-redis/v9"
	"gorm.io/gorm"
)

type RechargeStore struct {
	db    *gorm.DB
	redis *redis.Client
}

// NewRechargeStore 创建充值订单 Store 实例
func NewRechargeStore(db *gorm.DB, redis *redis.Client) *RechargeStore {
	return &RechargeStore{
		db:    db,
		redis: redis,
	}
}

// Create 创建充值订单
func (s *RechargeStore) Create(ctx context.Context, recharge *model.RechargeRecord) error {
	return s.db.WithContext(ctx).Create(recharge).Error
}

// GetByRechargeNo 根据充值订单号查询充值订单
// 不存在时返回 nil, nil
func (s *RechargeStore) GetByRechargeNo(ctx context.Context, rechargeNo string) (*model.RechargeRecord, error) {
	var recharge model.RechargeRecord
	err := s.db.WithContext(ctx).Where("recharge_no = ?", rechargeNo).First(&recharge).Error
	if err != nil {
		if err == gorm.ErrRecordNotFound {
			return nil, nil
		}
		return nil, err
	}
	return &recharge, nil
}

// GetByID 根据 ID 查询充值订单
func (s *RechargeStore) GetByID(ctx context.Context, id uint) (*model.RechargeRecord, error) {
	var recharge model.RechargeRecord
	if err := s.db.WithContext(ctx).First(&recharge, id).Error; err != nil {
		return nil, err
	}
	return &recharge, nil
}

// ListRechargeParams 充值订单列表查询参数
type ListRechargeParams struct {
	Page      int        // 页码（从 1 开始）
	PageSize  int        // 每页数量
	UserID    *uint      // 用户 ID 筛选
	WalletID  *uint      // 钱包 ID 筛选
	Status    *int       // 状态筛选
	StartTime *time.Time // 开始时间
	EndTime   *time.Time // 结束时间
}

// List 查询充值订单列表（支持分页和筛选）
func (s *RechargeStore) List(ctx context.Context, params *ListRechargeParams) ([]*model.RechargeRecord, int64, error) {
	var recharges []*model.RechargeRecord
	var total int64

	query := s.db.WithContext(ctx).Model(&model.RechargeRecord{})

	// 应用筛选条件
	if params.UserID != nil {
		query = query.Where("user_id = ?", *params.UserID)
	}
	if params.WalletID != nil {
		query = query.Where("wallet_id = ?", *params.WalletID)
	}
	if params.Status != nil {
		query = query.Where("status = ?", *params.Status)
	}
	if params.StartTime != nil {
		query = query.Where("created_at >= ?", *params.StartTime)
	}
	if params.EndTime != nil {
		query = query.Where("created_at <= ?", *params.EndTime)
	}

	// 统计总数
	if err := query.Count(&total).Error; err != nil {
		return nil, 0, err
	}

	// 分页查询
	page := params.Page
	if page < 1 {
		page = 1
	}
	pageSize := params.PageSize
	if pageSize < 1 {
		pageSize = 20
	}

	offset := (page - 1) * pageSize
	if err := query.Order("id DESC").Offset(offset).Limit(pageSize).Find(&recharges).Error; err != nil {
		return nil, 0, err
	}

	return recharges, total, nil
}

// UpdateStatus 更新充值订单状态（支持乐观锁检查）
// oldStatus: 原状态（用于乐观锁检查，传 nil 则跳过检查）
// newStatus: 新状态
// paidAt: 支付时间（状态变为已支付时传入）
// completedAt: 完成时间（状态变为已完成时传入）
func (s *RechargeStore) UpdateStatus(ctx context.Context, id uint, oldStatus *int, newStatus int, paidAt *time.Time, completedAt *time.Time) error {
	updates := map[string]interface{}{
		"status": newStatus,
	}
	if paidAt != nil {
		updates["paid_at"] = paidAt
	}
	if completedAt != nil {
		updates["completed_at"] = completedAt
	}

	query := s.db.WithContext(ctx).Model(&model.RechargeRecord{}).Where("id = ?", id)

	// 乐观锁检查
	if oldStatus != nil {
		query = query.Where("status = ?", *oldStatus)
	}

	result := query.Updates(updates)
	if result.Error != nil {
		return result.Error
	}
	if result.RowsAffected == 0 {
		return gorm.ErrRecordNotFound
	}
	return nil
}

// UpdatePaymentInfo 更新支付信息
func (s *RechargeStore) UpdatePaymentInfo(ctx context.Context, id uint, paymentChannel *string, paymentTransactionID *string) error {
	updates := map[string]interface{}{}
	if paymentChannel != nil {
		updates["payment_channel"] = paymentChannel
	}
	if paymentTransactionID != nil {
		updates["payment_transaction_id"] = paymentTransactionID
	}

	if len(updates) == 0 {
		return nil
	}

	result := s.db.WithContext(ctx).Model(&model.RechargeRecord{}).Where("id = ?", id).Updates(updates)
	if result.Error != nil {
		return result.Error
	}
	if result.RowsAffected == 0 {
		return gorm.ErrRecordNotFound
	}
	return nil
}
