package repository

import (
	"baron-sso-backend/internal/domain"
	"context"
	"errors"
	"testing"
	"time"

	"github.com/stretchr/testify/assert"
	"github.com/stretchr/testify/require"
)

func TestUserProjectionRepository_ReplaceAllFromKratosMarksReadyAndRemovesStaleUsers(t *testing.T) {
	ctx := context.Background()
	repo := NewUserProjectionRepository(testDB)

	require.NoError(t, testDB.Exec("DELETE FROM user_projection_states").Error)
	require.NoError(t, testDB.Exec("DELETE FROM user_login_ids").Error)
	require.NoError(t, testDB.Exec("DELETE FROM users").Error)

	tenantID := "10000000-0000-0000-0000-000000000001"
	tenantSlug := "projection-saman"
	require.NoError(t, testDB.Create(&domain.Tenant{
		ID:     tenantID,
		Name:   "Projection Saman",
		Slug:   tenantSlug,
		Type:   domain.TenantTypeCompany,
		Status: domain.TenantStatusActive,
	}).Error)
	stale := &domain.User{
		ID:          "00000000-0000-0000-0000-000000000099",
		Email:       "stale@example.com",
		Name:        "Stale",
		CompanyCode: tenantSlug,
	}
	require.NoError(t, NewUserRepository(testDB).Create(ctx, stale))

	users := []domain.User{
		{
			ID:          "00000000-0000-0000-0000-000000000101",
			Email:       "one@example.com",
			Name:        "One",
			CompanyCode: tenantSlug,
			TenantID:    &tenantID,
			CreatedAt:   time.Now(),
			UpdatedAt:   time.Now(),
		},
		{
			ID:        "00000000-0000-0000-0000-000000000102",
			Email:     "two@example.com",
			Name:      "Two",
			TenantID:  &tenantID,
			CreatedAt: time.Now(),
			UpdatedAt: time.Now(),
		},
	}

	require.NoError(t, repo.ReplaceAllFromKratos(ctx, users))

	ready, err := repo.IsReady(ctx)
	require.NoError(t, err)
	assert.True(t, ready)

	counts, err := repo.CountTenantMembers(ctx, []domain.Tenant{
		{ID: tenantID, Slug: tenantSlug},
	})
	require.NoError(t, err)
	assert.Equal(t, int64(2), counts[tenantID])

	var activeCount int64
	require.NoError(t, testDB.Model(&domain.User{}).Count(&activeCount).Error)
	assert.Equal(t, int64(2), activeCount)
}

func TestUserProjectionRepository_MarkFailedMakesProjectionNotReady(t *testing.T) {
	ctx := context.Background()
	repo := NewUserProjectionRepository(testDB)

	require.NoError(t, testDB.Exec("DELETE FROM user_projection_states").Error)

	require.NoError(t, repo.MarkFailed(ctx, errors.New("kratos down")))

	ready, err := repo.IsReady(ctx)
	require.NoError(t, err)
	assert.False(t, ready)
}
