package postgres

import (
	"context"
	"time"

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

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

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

func (s *CommissionWithdrawalRequestStore) Create(ctx context.Context, req *model.CommissionWithdrawalRequest) error {
	return s.db.WithContext(ctx).Create(req).Error
}

func (s *CommissionWithdrawalRequestStore) GetByID(ctx context.Context, id uint) (*model.CommissionWithdrawalRequest, error) {
	var req model.CommissionWithdrawalRequest
	query := s.db.WithContext(ctx).Where("id = ?", id)
	// 应用数据权限过滤
	query = middleware.ApplyShopFilter(ctx, query)
	if err := query.First(&req).Error; err != nil {
		return nil, err
	}
	return &req, nil
}

func (s *CommissionWithdrawalRequestStore) Update(ctx context.Context, req *model.CommissionWithdrawalRequest) error {
	return s.db.WithContext(ctx).Save(req).Error
}

type WithdrawalRequestListFilters struct {
	ShopID       uint
	WithdrawalNo string
	StartTime    *time.Time
	EndTime      *time.Time
	Status       *int
}

func (s *CommissionWithdrawalRequestStore) ListByShopID(ctx context.Context, opts *store.QueryOptions, filters *WithdrawalRequestListFilters) ([]*model.CommissionWithdrawalRequest, int64, error) {
	var requests []*model.CommissionWithdrawalRequest
	var total int64

	query := s.db.WithContext(ctx).Model(&model.CommissionWithdrawalRequest{})
	// 应用数据权限过滤
	query = middleware.ApplyShopFilter(ctx, query)

	if filters != nil {
		if filters.ShopID > 0 {
			query = query.Where("shop_id = ?", filters.ShopID)
		}
		if filters.WithdrawalNo != "" {
			query = query.Where("withdrawal_no = ?", filters.WithdrawalNo)
		}
		if filters.StartTime != nil {
			query = query.Where("created_at >= ?", filters.StartTime)
		}
		if filters.EndTime != nil {
			query = query.Where("created_at <= ?", filters.EndTime)
		}
		if filters.Status != nil {
			query = query.Where("status = ?", *filters.Status)
		}
	}

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

	if opts == nil {
		opts = &store.QueryOptions{
			Page:     1,
			PageSize: constants.DefaultPageSize,
		}
	}
	offset := (opts.Page - 1) * opts.PageSize
	query = query.Offset(offset).Limit(opts.PageSize)

	if opts.OrderBy != "" {
		query = query.Order(opts.OrderBy)
	} else {
		query = query.Order("created_at DESC")
	}

	if err := query.Find(&requests).Error; err != nil {
		return nil, 0, err
	}

	return requests, total, nil
}

func (s *CommissionWithdrawalRequestStore) SumAmountByShopIDAndStatus(ctx context.Context, shopID uint, status int) (int64, error) {
	var sum struct {
		Total int64
	}
	err := s.db.WithContext(ctx).
		Model(&model.CommissionWithdrawalRequest{}).
		Select("COALESCE(SUM(amount), 0) as total").
		Where("shop_id = ? AND status = ?", shopID, status).
		Scan(&sum).Error
	if err != nil {
		return 0, err
	}
	return sum.Total, nil
}

func (s *CommissionWithdrawalRequestStore) SumAmountByShopIDsAndStatus(ctx context.Context, shopIDs []uint, status int) (map[uint]int64, error) {
	if len(shopIDs) == 0 {
		return make(map[uint]int64), nil
	}

	type sumResult struct {
		ShopID uint
		Total  int64
	}

	var results []sumResult
	err := s.db.WithContext(ctx).
		Model(&model.CommissionWithdrawalRequest{}).
		Select("shop_id, COALESCE(SUM(amount), 0) as total").
		Where("shop_id IN ? AND status = ?", shopIDs, status).
		Group("shop_id").
		Scan(&results).Error
	if err != nil {
		return nil, err
	}

	result := make(map[uint]int64)
	for _, r := range results {
		result[r.ShopID] = r.Total
	}

	return result, nil
}

func (s *CommissionWithdrawalRequestStore) List(ctx context.Context, opts *store.QueryOptions, filters *WithdrawalRequestListFilters) ([]*model.CommissionWithdrawalRequest, int64, error) {
	var requests []*model.CommissionWithdrawalRequest
	var total int64

	query := s.db.WithContext(ctx).Model(&model.CommissionWithdrawalRequest{})
	// 应用数据权限过滤
	query = middleware.ApplyShopFilter(ctx, query)

	if filters != nil {
		if filters.WithdrawalNo != "" {
			query = query.Where("withdrawal_no = ?", filters.WithdrawalNo)
		}
		if filters.StartTime != nil {
			query = query.Where("created_at >= ?", filters.StartTime)
		}
		if filters.EndTime != nil {
			query = query.Where("created_at <= ?", filters.EndTime)
		}
		if filters.Status != nil {
			query = query.Where("status = ?", *filters.Status)
		}
	}

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

	if opts == nil {
		opts = &store.QueryOptions{
			Page:     1,
			PageSize: constants.DefaultPageSize,
		}
	}
	offset := (opts.Page - 1) * opts.PageSize
	query = query.Offset(offset).Limit(opts.PageSize)

	if opts.OrderBy != "" {
		query = query.Order(opts.OrderBy)
	} else {
		query = query.Order("created_at DESC")
	}

	if err := query.Find(&requests).Error; err != nil {
		return nil, 0, err
	}

	return requests, total, nil
}

func (s *CommissionWithdrawalRequestStore) UpdateStatusWithTx(ctx context.Context, tx *gorm.DB, id uint, updates map[string]interface{}) error {
	return tx.WithContext(ctx).Model(&model.CommissionWithdrawalRequest{}).Where("id = ? AND status = ?", id, constants.WithdrawalStatusPending).Updates(updates).Error
}
