package postgres

import (
	"context"

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

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

func NewWalletStore(db *gorm.DB, redis *redis.Client) *WalletStore {
	return &WalletStore{
		db:    db,
		redis: redis,
	}
}

func (s *WalletStore) GetByResourceTypeAndID(ctx context.Context, resourceType string, resourceID uint, walletType string) (*model.Wallet, error) {
	var wallet model.Wallet
	err := s.db.WithContext(ctx).
		Where("resource_type = ? AND resource_id = ? AND wallet_type = ?", resourceType, resourceID, walletType).
		First(&wallet).Error
	if err != nil {
		return nil, err
	}
	return &wallet, nil
}

func (s *WalletStore) GetShopCommissionWallet(ctx context.Context, shopID uint) (*model.Wallet, error) {
	return s.GetByResourceTypeAndID(ctx, "shop", shopID, "commission")
}

type ShopCommissionSummary struct {
	ShopID        uint
	Balance       int64
	FrozenBalance int64
}

func (s *WalletStore) GetShopCommissionSummaryBatch(ctx context.Context, shopIDs []uint) (map[uint]*ShopCommissionSummary, error) {
	if len(shopIDs) == 0 {
		return make(map[uint]*ShopCommissionSummary), nil
	}

	var wallets []model.Wallet
	err := s.db.WithContext(ctx).
		Where("resource_type = ? AND resource_id IN ? AND wallet_type = ?", "shop", shopIDs, "commission").
		Find(&wallets).Error
	if err != nil {
		return nil, err
	}

	result := make(map[uint]*ShopCommissionSummary)
	for _, w := range wallets {
		result[w.ResourceID] = &ShopCommissionSummary{
			ShopID:        w.ResourceID,
			Balance:       w.Balance,
			FrozenBalance: w.FrozenBalance,
		}
	}

	return result, nil
}

func (s *WalletStore) GetByID(ctx context.Context, id uint) (*model.Wallet, error) {
	var wallet model.Wallet
	if err := s.db.WithContext(ctx).First(&wallet, id).Error; err != nil {
		return nil, err
	}
	return &wallet, nil
}

func (s *WalletStore) DeductFrozenBalanceWithTx(ctx context.Context, tx *gorm.DB, walletID uint, amount int64) error {
	result := tx.WithContext(ctx).
		Model(&model.Wallet{}).
		Where("id = ? AND frozen_balance >= ?", walletID, amount).
		Updates(map[string]interface{}{
			"frozen_balance": gorm.Expr("frozen_balance - ?", amount),
		})
	if result.Error != nil {
		return result.Error
	}
	if result.RowsAffected == 0 {
		return gorm.ErrRecordNotFound
	}
	return nil
}

func (s *WalletStore) UnfreezeBalanceWithTx(ctx context.Context, tx *gorm.DB, walletID uint, amount int64) error {
	result := tx.WithContext(ctx).
		Model(&model.Wallet{}).
		Where("id = ? AND frozen_balance >= ?", walletID, amount).
		Updates(map[string]interface{}{
			"balance":        gorm.Expr("balance + ?", amount),
			"frozen_balance": gorm.Expr("frozen_balance - ?", amount),
		})
	if result.Error != nil {
		return result.Error
	}
	if result.RowsAffected == 0 {
		return gorm.ErrRecordNotFound
	}
	return nil
}
