/**
 * i18n E2E Tests
 *
 * Tests the internationalization features in the admin UI:
 * - Locale column in content list
 * - Locale filter in content list
 * - Translations sidebar in content editor
 * - Creating translations via the admin UI
 * - Navigating between translations
 * - Slug correctness (no locale suffix accumulation)
 *
 * The e2e fixture has i18n configured with locales: en, fr, es
 * and defaultLocale: en.
 *
 * Seed data:
 *   - posts: "First Post" (en, published), "Second Post" (en, published), "Draft Post" (en, draft)
 *   - pages: "About" (en, published), "Contact" (en, draft)
 */

import { test, expect } from "../fixtures";

const CONTENT_EDIT_URL_PATTERN = /\/content\/posts\/[A-Z0-9]+$/;

test.describe("i18n", () => {
	test.beforeEach(async ({ admin }) => {
		await admin.devBypassAuth();
	});

	test.describe("Content List", () => {
		test("shows locale column when i18n is configured", async ({ admin }) => {
			await admin.goToContent("posts");
			await admin.waitForLoading();

			// The table should have a "Locale" column header
			const localeHeader = admin.page.locator("th", { hasText: "Locale" });
			await expect(localeHeader).toBeVisible();
		});

		test("displays locale badges for each content item", async ({ admin }) => {
			await admin.goToContent("posts");
			await admin.waitForLoading();

			// All seeded posts are English — should see EN badges
			const locales = await admin.getLocaleColumnValues();
			expect(locales.length).toBeGreaterThan(0);
			// All seeded content is "en"
			for (const locale of locales) {
				expect(locale.trim().toLowerCase()).toBe("en");
			}
		});

		test("has a locale filter switcher", async ({ admin }) => {
			await admin.goToContent("posts");
			await admin.waitForLoading();

			// Should have a select element for locale filtering
			const select = admin.page.locator("select").first();
			await expect(select).toBeVisible();

			// Should show available locale options
			const options = select.locator("option");
			const optionTexts = await options.allTextContents();
			// Expect EN, FR, ES options (may also have "All locales")
			expect(optionTexts.some((t) => t.includes("EN"))).toBe(true);
			expect(optionTexts.some((t) => t.includes("FR"))).toBe(true);
			expect(optionTexts.some((t) => t.includes("ES"))).toBe(true);
		});
	});

	test.describe("Content Editor", () => {
		test("shows translations sidebar for existing content", async ({ admin }) => {
			await admin.goToContent("posts");
			await admin.waitForLoading();

			// Click on any post to edit (use first link in table body)
			await admin.page.locator("table tbody tr a").first().click();
			await admin.waitForLoading();

			// Should see the Translations sidebar heading
			const translationsHeading = admin.page.locator("h3", {
				hasText: "Translations",
			});
			await expect(translationsHeading).toBeVisible();
		});

		test("shows all configured locales in translations sidebar", async ({ admin }) => {
			await admin.goToContent("posts");
			await admin.waitForLoading();

			await admin.page.locator("table tbody tr a").first().click();
			await admin.waitForLoading();

			// Should show en, fr, es in the sidebar
			const locales = await admin.getTranslationSidebarLocales();
			const normalized = locales.map((l) => l.trim().toLowerCase());
			expect(normalized).toContain("en");
			expect(normalized).toContain("fr");
			expect(normalized).toContain("es");
		});

		test("marks current locale in translations sidebar", async ({ admin }) => {
			await admin.goToContent("posts");
			await admin.waitForLoading();

			await admin.page.locator("table tbody tr a").first().click();
			await admin.waitForLoading();

			// The "current" marker should appear next to EN
			const currentMarker = admin.page.locator("span.text-kumo-brand", {
				hasText: "current",
			});
			await expect(currentMarker).toBeVisible();
		});

		test("shows Translate buttons for missing locales", async ({ admin }) => {
			await admin.goToContent("posts");
			await admin.waitForLoading();

			await admin.page.locator("table tbody tr a").first().click();
			await admin.waitForLoading();

			// FR and ES should have "Translate" buttons since no translations exist yet
			expect(await admin.hasTranslateButton("fr")).toBe(true);
			expect(await admin.hasTranslateButton("es")).toBe(true);
		});

		test("does not show translations sidebar for new content", async ({ admin }) => {
			await admin.goToNewContent("posts");
			await admin.waitForLoading();

			// The translations sidebar should NOT be visible for unsaved content
			const translationsHeading = admin.page.locator("h3", {
				hasText: "Translations",
			});
			await expect(translationsHeading).not.toBeVisible();
		});
	});

	test.describe("Translation Flow", () => {
		test("creates a translation and navigates to it", async ({ admin }) => {
			// Create a fresh post so we have a clean translation group
			await admin.goToNewContent("posts");
			await admin.waitForLoading();

			const postTitle = `i18n Test Post ${Date.now()}`;
			await admin.fillField("title", postTitle);
			await admin.clickSave();

			// Wait for redirect to edit page
			await expect(admin.page).toHaveURL(CONTENT_EDIT_URL_PATTERN, {
				timeout: 10000,
			});
			await admin.waitForLoading();

			// Capture the original post URL
			const originalUrl = admin.page.url();

			// Should see Translate buttons for FR and ES
			expect(await admin.hasTranslateButton("fr")).toBe(true);

			// Click "Translate" for FR — wait for URL to change (SPA navigation)
			await admin.clickTranslate("fr");
			await admin.page.waitForURL(
				(url) => CONTENT_EDIT_URL_PATTERN.test(url.pathname) && url.href !== originalUrl,
				{ timeout: 15000 },
			);
			await admin.waitForLoading();

			// The title should be pre-filled from the original
			await expect(admin.page.locator("#field-title")).toHaveValue(postTitle);

			// The slug should be the same as the original (no locale suffix)
			const slug = await admin.page.getByLabel("Slug").inputValue();
			expect(slug).not.toContain("-fr");
			expect(slug).not.toContain("-en");
		});

		test("shows Edit link for existing translations", async ({ admin }) => {
			// Create a post and its FR translation
			await admin.goToNewContent("posts");
			await admin.waitForLoading();

			const postTitle = `Translation Edit Test ${Date.now()}`;
			await admin.fillField("title", postTitle);
			await admin.clickSave();

			await expect(admin.page).toHaveURL(CONTENT_EDIT_URL_PATTERN, {
				timeout: 10000,
			});
			await admin.waitForLoading();

			const originalUrl = admin.page.url();

			// Create FR translation and wait for navigation
			await admin.clickTranslate("fr");
			await admin.page.waitForURL(
				(url) => CONTENT_EDIT_URL_PATTERN.test(url.pathname) && url.href !== originalUrl,
				{ timeout: 15000 },
			);
			await admin.waitForLoading();

			// Now on the FR translation — EN should show "Edit" link, not "Translate"
			expect(await admin.hasEditTranslationLink("en")).toBe(true);
			// ES should still show "Translate"
			expect(await admin.hasTranslateButton("es")).toBe(true);
		});

		test("can navigate between translations via Edit links", async ({ admin }) => {
			// Create a post and FR translation
			await admin.goToNewContent("posts");
			await admin.waitForLoading();

			const postTitle = `Navigation Test ${Date.now()}`;
			await admin.fillField("title", postTitle);
			await admin.clickSave();

			await expect(admin.page).toHaveURL(CONTENT_EDIT_URL_PATTERN, {
				timeout: 10000,
			});
			await admin.waitForLoading();

			const originalUrl = admin.page.url();

			// Create FR translation and wait for navigation
			await admin.clickTranslate("fr");
			await admin.page.waitForURL(
				(url) => CONTENT_EDIT_URL_PATTERN.test(url.pathname) && url.href !== originalUrl,
				{ timeout: 15000 },
			);
			await admin.waitForLoading();

			const frUrl = admin.page.url();

			// Navigate back to EN via Edit link
			await admin.clickEditTranslation("en");
			await admin.page.waitForURL(
				(url) => CONTENT_EDIT_URL_PATTERN.test(url.pathname) && url.href !== frUrl,
				{ timeout: 15000 },
			);
			await admin.waitForLoading();

			// Should be back on the original post
			await expect(admin.page).toHaveURL(originalUrl);
			await expect(admin.page.locator("#field-title")).toHaveValue(postTitle);
		});

		test("creating multiple translations does not accumulate locale suffixes in slugs", async ({
			admin,
		}) => {
			// This is the regression test for the slug accumulation bug:
			// old code: slug = rawItem.slug + "-" + locale
			// Each translate would append more suffixes: post-fr-en-fr-en...

			await admin.goToNewContent("posts");
			await admin.waitForLoading();

			const postTitle = `Slug Accumulation Test ${Date.now()}`;
			await admin.fillField("title", postTitle);
			await admin.clickSave();

			await expect(admin.page).toHaveURL(CONTENT_EDIT_URL_PATTERN, {
				timeout: 10000,
			});
			await admin.waitForLoading();

			const originalUrl = admin.page.url();
			const originalSlug = await admin.page.getByLabel("Slug").inputValue();
			expect(originalSlug).toBeTruthy();

			// Create FR translation and wait for navigation
			await admin.clickTranslate("fr");
			await admin.page.waitForURL(
				(url) => CONTENT_EDIT_URL_PATTERN.test(url.pathname) && url.href !== originalUrl,
				{ timeout: 15000 },
			);
			await admin.waitForLoading();

			// FR slug should be the same as original (UNIQUE(slug, locale) allows this)
			const frSlug = await admin.page.getByLabel("Slug").inputValue();
			expect(frSlug).toBe(originalSlug);

			const frUrl = admin.page.url();

			// Navigate back to EN
			await admin.clickEditTranslation("en");
			await admin.page.waitForURL(
				(url) => CONTENT_EDIT_URL_PATTERN.test(url.pathname) && url.href !== frUrl,
				{ timeout: 15000 },
			);
			await admin.waitForLoading();

			const enUrl = admin.page.url();

			// Create ES translation from EN
			await admin.clickTranslate("es");
			await admin.page.waitForURL(
				(url) => CONTENT_EDIT_URL_PATTERN.test(url.pathname) && url.href !== enUrl,
				{ timeout: 15000 },
			);
			await admin.waitForLoading();

			// ES slug should also be the same — no accumulation
			const esSlug = await admin.page.getByLabel("Slug").inputValue();
			expect(esSlug).toBe(originalSlug);
		});
	});
});
