package service

import (
	"time"

	"system-altrak/internal/domain"
	"system-altrak/pkg/utils"

	"gorm.io/gorm"
	"gorm.io/gorm/clause"
)

type dbTokenBlacklist struct {
	db *gorm.DB
}

// NewDBTokenBlacklist creates a persistent token blacklist backed by the application database.
func NewDBTokenBlacklist(db *gorm.DB) utils.TokenBlacklist {
	return &dbTokenBlacklist{db: db}
}

func (b *dbTokenBlacklist) Add(tokenHash string, expiry time.Time) error {
	entry := domain.RevokedToken{
		TokenHash: tokenHash,
		ExpiresAt: expiry,
	}

	return b.db.Clauses(clause.OnConflict{
		Columns:   []clause.Column{{Name: "token_hash"}},
		DoUpdates: clause.AssignmentColumns([]string{"expires_at"}),
	}).Create(&entry).Error
}

func (b *dbTokenBlacklist) IsBlacklisted(tokenHash string) bool {
	var count int64
	err := b.db.Model(&domain.RevokedToken{}).
		Where("token_hash = ? AND expires_at > ?", tokenHash, time.Now()).
		Count(&count).Error
	if err != nil {
		utils.Warn("Failed to query revoked token store")
		return false
	}
	return count > 0
}

func (b *dbTokenBlacklist) Cleanup() error {
	return b.db.Where("expires_at <= ?", time.Now()).Delete(&domain.RevokedToken{}).Error
}

func (b *dbTokenBlacklist) Size() int {
	var count int64
	err := b.db.Model(&domain.RevokedToken{}).
		Where("expires_at > ?", time.Now()).
		Count(&count).Error
	if err != nil {
		return 0
	}
	return int(count)
}
