package auth

import (
	"fmt"
	"testing"

	"github.com/glebarez/sqlite"
	"github.com/stretchr/testify/require"
	"gorm.io/gorm"
	"senlinai-agent/backend/internal/models"
)

func TestRegisterWithInviteCreatesUser(t *testing.T) {
	newTestDB(t)
	service := NewService("test-secret")
	token, err := service.CreateInvite(1, "lead@example.com")
	require.NoError(t, err)

	user, err := service.RegisterWithInvite(token, "lead@example.com", "Lead", "password123")

	require.NoError(t, err)
	require.Equal(t, "lead@example.com", user.Email)
	require.NotEmpty(t, user.PasswordHash)
	require.NotEqual(t, "password123", user.PasswordHash)
}

func TestRegisterWithInviteRejectsWrongEmail(t *testing.T) {
	newTestDB(t)
	service := NewService("test-secret")
	token, err := service.CreateInvite(1, "lead@example.com")
	require.NoError(t, err)

	_, err = service.RegisterWithInvite(token, "other@example.com", "Other", "password123")

	require.ErrorContains(t, err, "invite email mismatch")
}

func TestLoginRejectsInvalidPassword(t *testing.T) {
	newTestDB(t)
	service := NewService("test-secret")
	token, err := service.CreateInvite(1, "lead@example.com")
	require.NoError(t, err)
	_, err = service.RegisterWithInvite(token, "lead@example.com", "Lead", "password123")
	require.NoError(t, err)

	_, err = service.Login("lead@example.com", "wrong-password")

	require.ErrorContains(t, err, "invalid credentials")
}

func TestLoginReturnsSignedSessionToken(t *testing.T) {
	newTestDB(t)
	service := NewService("test-secret")
	token, err := service.CreateInvite(1, "lead@example.com")
	require.NoError(t, err)
	user, err := service.RegisterWithInvite(token, "lead@example.com", "Lead", "password123")
	require.NoError(t, err)

	sessionToken, err := service.Login("lead@example.com", "password123")
	require.NoError(t, err)
	userID, err := service.VerifySession(sessionToken)

	require.NoError(t, err)
	require.Equal(t, user.ID, userID)
	require.NotEqual(t, fmt.Sprintf("user:%d", user.ID), sessionToken)
}

func TestVerifySessionRejectsForgeableLegacyToken(t *testing.T) {
	newTestDB(t)
	service := NewService("test-secret")

	_, err := service.VerifySession("user:1")

	require.ErrorContains(t, err, "invalid token")
}

func newTestDB(t *testing.T) *gorm.DB {
	t.Helper()
	database, err := gorm.Open(sqlite.Open(fmt.Sprintf("file:%s?mode=memory&cache=shared", t.Name())), &gorm.Config{})
	require.NoError(t, err)
	require.NoError(t, models.AutoMigrate(database))
	models.DBService = database
	return database
}
