package postgres

import (
	"context"

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

// AssetRechargeStore 资产充值记录数据访问层
type AssetRechargeStore struct {
	db    *gorm.DB
	redis *redis.Client
}

// NewAssetRechargeStore 创建资产充值记录 Store
func NewAssetRechargeStore(db *gorm.DB, redis *redis.Client) *AssetRechargeStore {
	return &AssetRechargeStore{
		db:    db,
		redis: redis,
	}
}

// Create 创建充值记录
func (s *AssetRechargeStore) Create(ctx context.Context, record *model.AssetRechargeRecord) error {
	return s.db.WithContext(ctx).Create(record).Error
}

// CreateWithTx 创建充值记录（带事务）
func (s *AssetRechargeStore) CreateWithTx(ctx context.Context, tx *gorm.DB, record *model.AssetRechargeRecord) error {
	return tx.WithContext(ctx).Create(record).Error
}

// GetByRechargeNo 根据充值订单号查询
func (s *AssetRechargeStore) GetByRechargeNo(ctx context.Context, rechargeNo string) (*model.AssetRechargeRecord, error) {
	var record model.AssetRechargeRecord
	err := s.db.WithContext(ctx).
		Where("recharge_no = ?", rechargeNo).
		First(&record).Error
	if err != nil {
		return nil, err
	}
	return &record, nil
}

// GetByID 根据 ID 查询
func (s *AssetRechargeStore) GetByID(ctx context.Context, id uint) (*model.AssetRechargeRecord, error) {
	var record model.AssetRechargeRecord
	if err := s.db.WithContext(ctx).First(&record, id).Error; err != nil {
		return nil, err
	}
	return &record, nil
}

// UpdateStatus 更新充值状态
func (s *AssetRechargeStore) UpdateStatus(ctx context.Context, id uint, status int) error {
	return s.db.WithContext(ctx).
		Model(&model.AssetRechargeRecord{}).
		Where("id = ?", id).
		Update("status", status).Error
}

// UpdateStatusWithTx 更新充值状态（带事务）
func (s *AssetRechargeStore) UpdateStatusWithTx(ctx context.Context, tx *gorm.DB, id uint, status int) error {
	return tx.WithContext(ctx).
		Model(&model.AssetRechargeRecord{}).
		Where("id = ?", id).
		Update("status", status).Error
}

// Update 更新充值记录
func (s *AssetRechargeStore) Update(ctx context.Context, record *model.AssetRechargeRecord) error {
	return s.db.WithContext(ctx).Save(record).Error
}

// UpdateWithTx 更新充值记录（带事务）
func (s *AssetRechargeStore) UpdateWithTx(ctx context.Context, tx *gorm.DB, record *model.AssetRechargeRecord) error {
	return tx.WithContext(ctx).Save(record).Error
}

// ListByResourceID 按资源查询充值记录（支持分页）
func (s *AssetRechargeStore) ListByResourceID(ctx context.Context, resourceType string, resourceID uint, offset, limit int) ([]*model.AssetRechargeRecord, error) {
	var records []*model.AssetRechargeRecord
	err := s.db.WithContext(ctx).
		Where("resource_type = ? AND resource_id = ?", resourceType, resourceID).
		Order("created_at DESC").
		Offset(offset).
		Limit(limit).
		Find(&records).Error
	if err != nil {
		return nil, err
	}
	return records, nil
}

// ListByUserID 按用户查询充值记录（支持分页）
func (s *AssetRechargeStore) ListByUserID(ctx context.Context, userID uint, offset, limit int) ([]*model.AssetRechargeRecord, error) {
	var records []*model.AssetRechargeRecord
	err := s.db.WithContext(ctx).
		Where("user_id = ?", userID).
		Order("created_at DESC").
		Offset(offset).
		Limit(limit).
		Find(&records).Error
	if err != nil {
		return nil, err
	}
	return records, nil
}

// ListByStatus 按状态查询充值记录（支持分页）
func (s *AssetRechargeStore) ListByStatus(ctx context.Context, status int, offset, limit int) ([]*model.AssetRechargeRecord, error) {
	var records []*model.AssetRechargeRecord
	err := s.db.WithContext(ctx).
		Where("status = ?", status).
		Order("created_at DESC").
		Offset(offset).
		Limit(limit).
		Find(&records).Error
	if err != nil {
		return nil, err
	}
	return records, nil
}

// ListAssetRechargeParams 充值记录列表查询参数
type ListAssetRechargeParams struct {
	Page          int
	PageSize      int
	UserID        *uint
	AssetWalletID *uint
	ResourceType  *string
	ResourceID    *uint
	Status        *int
	StartTime     interface{}
	EndTime       interface{}
}

// List 查询充值记录列表（支持分页和筛选）
func (s *AssetRechargeStore) List(ctx context.Context, params *ListAssetRechargeParams) ([]*model.AssetRechargeRecord, int64, error) {
	var records []*model.AssetRechargeRecord
	var total int64

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

	if params.UserID != nil {
		query = query.Where("user_id = ?", *params.UserID)
	}
	if params.AssetWalletID != nil {
		query = query.Where("asset_wallet_id = ?", *params.AssetWalletID)
	}
	if params.ResourceType != nil {
		query = query.Where("resource_type = ?", *params.ResourceType)
	}
	if params.ResourceID != nil {
		query = query.Where("resource_id = ?", *params.ResourceID)
	}
	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(&records).Error; err != nil {
		return nil, 0, err
	}

	return records, total, nil
}

// UpdatePaymentInfo 更新支付信息
func (s *AssetRechargeStore) UpdatePaymentInfo(ctx context.Context, id uint, paymentMethod *string, paymentTransactionID *string) error {
	return s.UpdatePaymentInfoWithDB(ctx, s.db, id, paymentMethod, paymentTransactionID)
}

// UpdatePaymentInfoWithDB 更新支付信息（支持传入事务 tx）
func (s *AssetRechargeStore) UpdatePaymentInfoWithDB(ctx context.Context, db *gorm.DB, id uint, paymentMethod *string, paymentTransactionID *string) error {
	updates := map[string]interface{}{}
	if paymentMethod != nil {
		updates["payment_method"] = paymentMethod
	}
	if paymentTransactionID != nil {
		updates["payment_transaction_id"] = paymentTransactionID
	}

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

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

// UpdateStatusWithOptimisticLock 更新充值状态（支持乐观锁）
func (s *AssetRechargeStore) UpdateStatusWithOptimisticLock(ctx context.Context, id uint, oldStatus *int, newStatus int, paidAt interface{}, completedAt interface{}) error {
	return s.UpdateStatusWithOptimisticLockDB(ctx, s.db, id, oldStatus, newStatus, paidAt, completedAt)
}

// UpdateStatusWithOptimisticLockDB 更新充值状态（支持传入事务 tx）
func (s *AssetRechargeStore) UpdateStatusWithOptimisticLockDB(ctx context.Context, db *gorm.DB, id uint, oldStatus *int, newStatus int, paidAt interface{}, completedAt interface{}) error {
	updates := map[string]interface{}{
		"status": newStatus,
	}
	if paidAt != nil {
		updates["paid_at"] = paidAt
	}
	if completedAt != nil {
		updates["completed_at"] = completedAt
	}

	query := db.WithContext(ctx).Model(&model.AssetRechargeRecord{}).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
}
