package identity

import (
	"context"
	"errors"
	"fmt"
	"sync"
	"testing"
	"time"

	"github.com/stretchr/testify/require"

	"github.com/tidbcloud/AgentTeam/internal/coredb"
	"github.com/tidbcloud/AgentTeam/internal/coredb/testkit"
)

func TestBootstrapInitialAdminSerializesConcurrentRequests(t *testing.T) {
	ctx := context.Background()
	rootDSN := identityTiDB.RootDSN(t)
	dsn := testkit.StartInitializedTiDBWithRootDSN(t, rootDSN)

	sqlDB, err := testkit.OpenTiDBContext(ctx, dsn)
	require.NoError(t, err)
	t.Cleanup(func() { _ = sqlDB.Close() })
	sqlDB.SetMaxOpenConns(8)
	sqlDB.SetMaxIdleConns(8)

	db := coredb.WrapSQLDB(sqlDB)
	store := New(db, Options{})

	const attempts = 8
	start := make(chan struct{})
	results := make(chan error, attempts)

	var wg sync.WaitGroup
	wg.Add(attempts)
	for i := 0; i < attempts; i++ {
		i := i
		go func() {
			defer wg.Done()
			<-start
			_, err := store.BootstrapInitialAdmin(
				ctx,
				fmt.Sprintf("bootstrap-concurrent-%d@example.com", i),
				fmt.Sprintf("bootstrap_concurrent_%d", i),
				fmt.Sprintf("Bootstrap Concurrent %d", i),
				"password-hash",
				fmt.Sprintf("bootstrap-token-%d", i),
				time.Now().Add(time.Hour),
			)
			results <- err
		}()
	}
	close(start)
	wg.Wait()
	close(results)

	successes := 0
	alreadyInitialized := 0
	for err := range results {
		switch {
		case err == nil:
			successes++
		case errors.Is(err, ErrSystemAlreadyInitialized):
			alreadyInitialized++
		default:
			t.Fatalf("BootstrapInitialAdmin returned unexpected error: %v", err)
		}
	}
	require.Equal(t, 1, successes)
	require.Equal(t, attempts-1, alreadyInitialized)

	var adminCount int
	require.NoError(t, db.QueryRow(ctx, `
SELECT COUNT(*)
FROM users
WHERE is_admin = TRUE
`).Scan(&adminCount))
	require.Equal(t, 1, adminCount)

	var sessionCount int
	require.NoError(t, db.QueryRow(ctx, `
SELECT COUNT(*)
FROM user_sessions
WHERE token_hash LIKE 'bootstrap-token-%'
`).Scan(&sessionCount))
	require.Equal(t, 1, sessionCount)
}
