// Parity tests for the TS port of `pkg/util/string.go.ValidateTypeName`.
// Cases are aligned with `pkg/util/string_test.go.TestValidateString`
// so the client-side and server-side validators reject the same set
// of inputs — a name that's locally valid is always accepted at the
// wire level.

import { describe, expect, test } from "vitest";

import {
	validateEntityName,
	type EntityNameInvalidReason,
} from "../src/lib/util/entity-name";

describe("validateEntityName", () => {
	const valid: { name: string; input: string; expected: string }[] = [
		{ name: "latin + digits", input: "Hello_World-123", expected: "Hello_World-123" },
		{ name: "cyrillic", input: "Привет_мир-42", expected: "Привет_мир-42" },
		{ name: "greek", input: "Αλφα_Βητα-2024", expected: "Αλφα_Βητα-2024" },
		{ name: "arabic", input: "مرحبا_العالم-7", expected: "مرحبا_العالم-7" },
		{ name: "japanese katakana", input: "テスト_ケース-1", expected: "テスト_ケース-1" },
		{ name: "chinese", input: "你好_世界-123", expected: "你好_世界-123" },
		{ name: "hindi (combining marks)", input: "नमस्ते_दुनिया-456", expected: "नमस्ते_दुनिया-456" },
		{ name: "thai (combining marks)", input: "สวัสดี_โลก-789", expected: "สวัสดี_โลก-789" },
		{ name: "korean", input: "안녕하세요_세계-101", expected: "안녕하세요_세계-101" },
		{ name: "trim outer whitespace", input: "  Earth  ", expected: "Earth" },
		{ name: "valid consecutive specials", input: "Valid_(special)_Chars", expected: "Valid_(special)_Chars" },
		{ name: "all allowed specials", input: "A@#b$%c^*d-_e=+f~(g)[h]{i}j", expected: "A@#b$%c^*d-_e=+f~(g)[h]{i}j" },
	];
	for (const tc of valid) {
		test(`accepts: ${tc.name}`, () => {
			const result = validateEntityName(tc.input);
			expect(result.ok).toBe(true);
			if (result.ok) {
				expect(result.value).toBe(tc.expected);
			}
		});
	}

	const invalid: {
		name: string;
		input: string;
		reason: EntityNameInvalidReason;
	}[] = [
		{ name: "empty after trim", input: "     ", reason: "empty" },
		{ name: "explicitly empty", input: "", reason: "empty" },
		{ name: "too long", input: "ValidatedStringHasTooManyCharacters", reason: "too_long" },
		{ name: "internal space", input: "Test 123", reason: "whitespace" },
		{ name: "internal tab", input: "Test\tName", reason: "whitespace" },
		{ name: "internal newline", input: "Test\nName", reason: "whitespace" },
		{ name: "starts with special after trim", input: "  -Test123", reason: "starts_with_special" },
		{ name: "ends with special after trim", input: "Test123-   ", reason: "ends_with_special" },
		{ name: "emoji", input: "Test🙂Name", reason: "disallowed_character" },
		{ name: "starts with special $", input: "$pecialString", reason: "starts_with_special" },
		{ name: "ends with special _", input: "SpecialString_", reason: "ends_with_special" },
		{ name: "too many consecutive specials", input: "Too_Many_(special[_]Chars", reason: "consecutive_specials" },
	];
	for (const tc of invalid) {
		test(`rejects: ${tc.name}`, () => {
			const result = validateEntityName(tc.input);
			expect(result.ok).toBe(false);
			if (!result.ok) {
				expect(result.reason).toBe(tc.reason);
			}
		});
	}
});
