package usecase

import (
	"context"
	"time"

	member "gateway/internal/model/member/domain"
	domrepo "gateway/internal/model/member/domain/repository"
	domusecase "gateway/internal/model/member/domain/usecase"
)

type verifyRateUseCase struct {
	store domrepo.VerifyRateStore
}

// VerifyRateUseCaseParam wires VerifyRateUseCase.
type VerifyRateUseCaseParam struct {
	Store domrepo.VerifyRateStore
}

// MustVerifyRateUseCase constructs VerifyRateUseCase.
func MustVerifyRateUseCase(param VerifyRateUseCaseParam) domusecase.VerifyRateUseCase {
	if param.Store == nil {
		panic("member: verify rate store is required")
	}
	return &verifyRateUseCase{store: param.Store}
}

func (uc *verifyRateUseCase) AssertResendAllowed(ctx context.Context, key string, cooldown time.Duration) error {
	if key == "" {
		return errb.InputMissingRequired("rate limit key is required")
	}
	ok, err := uc.store.TryResendLock(ctx, key, cooldown)
	if err != nil {
		return errb.DBError("rate limit check failed").WithCause(err)
	}
	if !ok {
		return errb.SysTooManyRequest("resend cooldown active").WithCause(member.ErrResendCooldown)
	}
	return nil
}

func (uc *verifyRateUseCase) AssertDailyAllowed(ctx context.Context, key string, window time.Duration, limit int) error {
	if key == "" {
		return errb.InputMissingRequired("daily limit key is required")
	}
	count, err := uc.store.IncrDaily(ctx, key, window)
	if err != nil {
		return errb.DBError("daily limit check failed").WithCause(err)
	}
	if count > int64(limit) {
		return errb.ResInsufficientQuota("daily verification limit exceeded").WithCause(member.ErrDailyLimit)
	}
	return nil
}
