package withdrawal

import (
	"context"
	"errors"
)

var (
	ErrDependencyUnavailable = errors.New("dependency unavailable")
	ErrWithdrawalNotFound    = errors.New("withdrawal not found")
	ErrInvalidAmount         = errors.New("invalid amount")
	ErrInsufficientBalance   = errors.New("insufficient balance")
	ErrMinWithdrawalAmount   = errors.New("amount below minimum withdrawal")
	ErrMaxWithdrawalAmount   = errors.New("amount exceeds maximum withdrawal")
	ErrWithdrawalLocked      = errors.New("withdrawal status locked")
	ErrUnauthorized          = errors.New("unauthorized")
)

const (
	MinWithdrawalAmountCent = 1000   // 最低提现金额：10元 = 1000分
	MaxWithdrawalAmountCent = 500000 // 单笔最高提现金额：5000元 = 500000分
	WithdrawalFeeRate       = 0.0    // 手续费率（暂时0%）
)

type Service struct {
	repo *Repository
}

func NewService(repo *Repository) *Service {
	return &Service{repo: repo}
}

// 用户端方法
func (s *Service) Create(ctx context.Context, userID uint64, req CreateWithdrawalRequest) (*WithdrawalDTO, error) {
	if s.repo == nil {
		return nil, ErrDependencyUnavailable
	}

	// 验证金额
	if req.AmountCent < MinWithdrawalAmountCent {
		return nil, ErrMinWithdrawalAmount
	}
	if req.AmountCent > MaxWithdrawalAmountCent {
		return nil, ErrMaxWithdrawalAmount
	}

	return s.repo.Create(ctx, userID, req)
}

func (s *Service) List(ctx context.Context, userID uint64, page, pageSize int) (*PaginatedResult, error) {
	if s.repo == nil {
		return nil, ErrDependencyUnavailable
	}
	if page < 1 {
		page = 1
	}
	if pageSize < 1 || pageSize > 100 {
		pageSize = 20
	}
	return s.repo.List(ctx, userID, page, pageSize)
}

func (s *Service) FindByID(ctx context.Context, userID, id uint64) (*WithdrawalDTO, error) {
	if s.repo == nil {
		return nil, ErrDependencyUnavailable
	}
	return s.repo.FindByID(ctx, userID, id)
}

func (s *Service) Cancel(ctx context.Context, userID, id uint64) error {
	if s.repo == nil {
		return ErrDependencyUnavailable
	}
	return s.repo.Cancel(ctx, userID, id)
}

// 管理员端方法
func (s *Service) AdminList(ctx context.Context, query AdminListQuery) (*AdminPaginatedResult, error) {
	if s.repo == nil {
		return nil, ErrDependencyUnavailable
	}
	if query.Page < 1 {
		query.Page = 1
	}
	if query.Size < 1 || query.Size > 100 {
		query.Size = 20
	}
	return s.repo.AdminList(ctx, query)
}

func (s *Service) AdminFindByID(ctx context.Context, id uint64) (*WithdrawalDetailDTO, error) {
	if s.repo == nil {
		return nil, ErrDependencyUnavailable
	}
	return s.repo.AdminFindByID(ctx, id)
}

func (s *Service) Review(ctx context.Context, adminID, id uint64, req ReviewWithdrawalRequest) (*WithdrawalDetailDTO, error) {
	if s.repo == nil {
		return nil, ErrDependencyUnavailable
	}
	return s.repo.Review(ctx, adminID, id, req)
}

func (s *Service) ConfirmPayment(ctx context.Context, adminID, id uint64, req ConfirmPaymentRequest) (*WithdrawalDetailDTO, error) {
	if s.repo == nil {
		return nil, ErrDependencyUnavailable
	}
	return s.repo.ConfirmPayment(ctx, adminID, id, req)
}
