package auth

import (
	"context"
	"testing"

	"hyapp/services/user-service/internal/testutil/mysqlschema"
)

func TestDisplayUserIDPermutationProducesUniqueSevenDigitValues(t *testing.T) {
	// 内部序号经过 3000x3000 Feistel 置换后仍是一一映射；这里抽样覆盖格式和前段序号不重复。
	seen := make(map[string]struct{}, 10000)
	for ordinal := int64(0); ordinal < 10000; ordinal++ {
		displayUserID, err := displayUserIDFromOrdinal("lalu", ordinal)
		if err != nil {
			t.Fatalf("displayUserIDFromOrdinal(%d) failed: %v", ordinal, err)
		}
		if len(displayUserID) != 7 || displayUserID[0] < '1' || displayUserID[0] > '9' {
			t.Fatalf("display_user_id must be 7 digits and start with 1-9, got %q", displayUserID)
		}
		if _, ok := seen[displayUserID]; ok {
			t.Fatalf("display_user_id %s duplicated at ordinal %d", displayUserID, ordinal)
		}
		seen[displayUserID] = struct{}{}
	}
}

func TestAllocateDisplayUserIDUsesSequencePermutationAndSkipsOccupiedCandidate(t *testing.T) {
	// 迁移前可能已经有随机号或人工种子号；分配器必须锁住内部序号并跳过已占用的置换结果。
	ctx := context.Background()
	schema := mysqlschema.New(t)
	repository := New(schema.DB)
	firstCandidate, err := displayUserIDFromOrdinal("lalu", 0)
	if err != nil {
		t.Fatalf("first candidate failed: %v", err)
	}
	secondCandidate, err := displayUserIDFromOrdinal("lalu", 1)
	if err != nil {
		t.Fatalf("second candidate failed: %v", err)
	}
	if _, err := schema.DB.ExecContext(ctx, `
		INSERT INTO user_display_user_ids (
			app_code,
			display_user_id,
			user_id,
			display_user_id_kind,
			status,
			assigned_at_ms,
			activated_at_ms,
			created_at_ms,
			updated_at_ms
		)
		VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
	`, "lalu", firstCandidate, int64(1), "default", "active", int64(1000), int64(1000), int64(1000), int64(1000)); err != nil {
		t.Fatalf("seed occupied display_user_id failed: %v", err)
	}

	got, err := repository.AllocateDisplayUserID(ctx, "lalu")
	if err != nil {
		t.Fatalf("AllocateDisplayUserID failed: %v", err)
	}
	if got != secondCandidate {
		t.Fatalf("allocated display_user_id = %s, want %s", got, secondCandidate)
	}

	var nextValue int64
	if err := schema.DB.QueryRowContext(ctx, `
		SELECT next_value
		FROM display_user_id_sequences
		WHERE app_code = ?
	`, "lalu").Scan(&nextValue); err != nil {
		t.Fatalf("query sequence failed: %v", err)
	}
	if nextValue != 2 {
		t.Fatalf("sequence next_value = %d, want 2", nextValue)
	}
}
