package service

import (
	"testing"
	"time"

	"system-altrak/internal/domain"

	"github.com/glebarez/sqlite"
	"gorm.io/gorm"
)

func newBlacklistTestDB(t *testing.T) *gorm.DB {
	t.Helper()

	db, err := gorm.Open(sqlite.Open(":memory:"), &gorm.Config{})
	if err != nil {
		t.Fatalf("failed to open sqlite database: %v", err)
	}
	if err := db.AutoMigrate(&domain.RevokedToken{}); err != nil {
		t.Fatalf("failed to migrate revoked token schema: %v", err)
	}
	return db
}

func TestDBTokenBlacklistLifecycle(t *testing.T) {
	db := newBlacklistTestDB(t)
	blacklist := NewDBTokenBlacklist(db)

	future := time.Now().Add(2 * time.Hour)
	if err := blacklist.Add("token-a", future); err != nil {
		t.Fatalf("failed to add active token: %v", err)
	}
	if !blacklist.IsBlacklisted("token-a") {
		t.Fatal("expected token-a to be blacklisted")
	}
	if got := blacklist.Size(); got != 1 {
		t.Fatalf("expected active size 1, got %d", got)
	}

	later := time.Now().Add(4 * time.Hour)
	if err := blacklist.Add("token-a", later); err != nil {
		t.Fatalf("failed to upsert token-a: %v", err)
	}
	if got := blacklist.Size(); got != 1 {
		t.Fatalf("expected upsert to keep active size 1, got %d", got)
	}

	expired := time.Now().Add(-1 * time.Hour)
	if err := blacklist.Add("token-expired", expired); err != nil {
		t.Fatalf("failed to add expired token: %v", err)
	}
	if blacklist.IsBlacklisted("token-expired") {
		t.Fatal("expected expired token not to be blacklisted")
	}
	if got := blacklist.Size(); got != 1 {
		t.Fatalf("expected active size to remain 1, got %d", got)
	}

	if err := blacklist.Cleanup(); err != nil {
		t.Fatalf("cleanup returned error: %v", err)
	}

	var totalRows int64
	if err := db.Model(&domain.RevokedToken{}).Count(&totalRows).Error; err != nil {
		t.Fatalf("failed counting revoked tokens: %v", err)
	}
	if totalRows != 1 {
		t.Fatalf("expected cleanup to leave 1 row, got %d", totalRows)
	}
}

func TestDBTokenBlacklistUnknownTokenReturnsFalse(t *testing.T) {
	db := newBlacklistTestDB(t)
	blacklist := NewDBTokenBlacklist(db)

	if blacklist.IsBlacklisted("missing-token") {
		t.Fatal("expected missing token to return false")
	}
	if got := blacklist.Size(); got != 0 {
		t.Fatalf("expected empty blacklist size, got %d", got)
	}
}
