package sql_test

import (
	"context"
	"testing"
	"tercul/internal/data/sql"
	"tercul/internal/domain"
	"tercul/internal/platform/config"
	"time"

	"github.com/stretchr/testify/assert"
	"github.com/stretchr/testify/require"
	"gorm.io/driver/sqlite"
	"gorm.io/gorm"
)

// newTestAuthRepoWithSQLite sets up an in-memory SQLite database for auth repository testing.
func newTestAuthRepoWithSQLite(t *testing.T) (domain.AuthRepository, *gorm.DB) {
	db, err := gorm.Open(sqlite.Open("file::memory:?cache=shared"), &gorm.Config{})
	require.NoError(t, err)

	// Auto-migrate the necessary schemas
	err = db.AutoMigrate(
		&domain.User{},
		&domain.UserSession{},
	)
	require.NoError(t, err)

	cfg := &config.Config{}
	repo := sql.NewAuthRepository(db, cfg)

	// Clean up the database after the test
	t.Cleanup(func() {
		sqlDB, err := db.DB()
		require.NoError(t, err)
		err = sqlDB.Close()
		require.NoError(t, err)
	})

	return repo, db
}

func TestAuthRepository_StoreToken(t *testing.T) {
	repo, db := newTestAuthRepoWithSQLite(t)
	ctx := context.Background()

	// Setup: Create a user
	user := domain.User{Username: "authuser", Email: "auth@test.com"}
	require.NoError(t, db.Create(&user).Error)

	token := "my-secret-token"
	expiresAt := time.Now().Add(1 * time.Hour)

	err := repo.StoreToken(ctx, user.ID, token, expiresAt)
	require.NoError(t, err)

	var session domain.UserSession
	err = db.Where("token = ?", token).First(&session).Error
	require.NoError(t, err)

	assert.Equal(t, user.ID, session.UserID)
	assert.Equal(t, token, session.Token)
	// Truncate to a reasonable precision for comparison
	assert.WithinDuration(t, expiresAt, session.ExpiresAt, time.Second)
}

func TestAuthRepository_DeleteToken(t *testing.T) {
	repo, db := newTestAuthRepoWithSQLite(t)
	ctx := context.Background()

	// Setup: Create a user and a session
	user := domain.User{Username: "authuser2", Email: "auth2@test.com"}
	require.NoError(t, db.Create(&user).Error)
	token := "token-to-delete"
	session := &domain.UserSession{
		UserID:    user.ID,
		Token:     token,
		ExpiresAt: time.Now().Add(1 * time.Hour),
	}
	require.NoError(t, db.Create(session).Error)

	// Delete the token
	err := repo.DeleteToken(ctx, token)
	require.NoError(t, err)

	// Verify it's gone
	var deletedSession domain.UserSession
	err = db.Where("token = ?", token).First(&deletedSession).Error
	assert.Error(t, err)
	assert.Equal(t, gorm.ErrRecordNotFound, err)
}