/**
 * Content Types / Schema Editor E2E Tests
 *
 * Tests listing, viewing, creating, editing fields, and deleting content types.
 * Runs against an isolated fixture with seeded posts and pages collections.
 *
 * Seed data (from fixture/.emdash/seed.json):
 *   - posts: title (string, required), body (portableText), excerpt (text), theme_color (string)
 *   - pages: title (string, required), body (portableText)
 */

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

// Regex patterns (module scope per lint rules)
const CONTENT_TYPES_SLUG_PATTERN = /\/content-types\/posts$/;

// Fixed test slug -- sequential tests (workers: 1) share state.
// Use a fixed value so cross-test dependencies work reliably.
const TEST_SLUG = "e2e_test_articles";
const TEST_LABEL_SINGULAR = "Article";
const TEST_LABEL_PLURAL = `${TEST_LABEL_SINGULAR}s`;

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

	test.describe("Content Types List", () => {
		test("displays seeded collections in a table", async ({ admin }) => {
			await admin.goto("/content-types");
			await admin.waitForLoading();

			// Page title
			await admin.expectPageTitle("Content Types");

			// Should show the table
			await expect(admin.page.locator("table")).toBeVisible();

			// Seeded collections should appear as links in the table (scope to table to avoid sidebar)
			const table = admin.page.locator("table");
			await expect(table.getByRole("link", { name: "Posts", exact: true })).toBeVisible();
			await expect(table.getByRole("link", { name: "Pages", exact: true })).toBeVisible();
		});

		test("shows slug column for each collection", async ({ admin }) => {
			await admin.goto("/content-types");
			await admin.waitForLoading();

			// Slug values rendered as <code> elements inside the table
			await expect(admin.page.locator("table code", { hasText: "posts" })).toBeVisible();
			await expect(admin.page.locator("table code", { hasText: "pages" })).toBeVisible();
		});

		test("has a New Content Type button", async ({ admin }) => {
			await admin.goto("/content-types");
			await admin.waitForLoading();

			await expect(admin.page.getByRole("link", { name: "New Content Type" })).toBeVisible();
		});
	});

	test.describe("View Content Type", () => {
		test("clicking a collection shows its field list", async ({ admin }) => {
			await admin.goto("/content-types");
			await admin.waitForLoading();

			// Click into the posts collection (scope to table to avoid sidebar link)
			await admin.page.locator("table").getByRole("link", { name: "Posts", exact: true }).click();

			// Should navigate to the editor page
			await expect(admin.page).toHaveURL(CONTENT_TYPES_SLUG_PATTERN, {
				timeout: 10000,
			});

			// Page heading should show the collection label
			await admin.expectPageTitle("Posts");

			// Should show system fields section
			await expect(admin.page.getByText("System Fields")).toBeVisible();

			// Should show custom fields section
			await expect(admin.page.getByText("Custom Fields", { exact: true })).toBeVisible();
		});

		test("shows expected custom fields for posts", async ({ admin }) => {
			await admin.goto("/content-types/posts");
			await admin.waitForShell();
			await admin.waitForLoading();

			// Custom field labels
			await expect(admin.page.getByText("Title").first()).toBeVisible();
			await expect(admin.page.getByText("Body").first()).toBeVisible();
			await expect(admin.page.getByText("Excerpt").first()).toBeVisible();

			// Field slugs rendered as <code> elements
			await expect(admin.page.locator("code", { hasText: "title" }).first()).toBeVisible();
			await expect(admin.page.locator("code", { hasText: "body" }).first()).toBeVisible();
			await expect(admin.page.locator("code", { hasText: "excerpt" }).first()).toBeVisible();
		});

		test("shows system fields for a collection", async ({ admin }) => {
			await admin.goto("/content-types/posts");
			await admin.waitForShell();
			await admin.waitForLoading();

			// System field slugs
			for (const slug of ["id", "slug", "status", "created_at", "updated_at", "published_at"]) {
				await expect(admin.page.locator("code", { hasText: slug }).first()).toBeVisible();
			}
		});
	});

	test.describe("Create Content Type", () => {
		test("creates a new content type and redirects to editor", async ({ admin }) => {
			await admin.goto("/content-types/new");
			await admin.waitForShell();
			await admin.waitForLoading();

			// Page heading
			await admin.expectPageTitle("New Content Type");

			// Fill in the singular label -- this auto-generates plural label and slug
			const singularInput = admin.page.getByLabel("Label (Singular)");
			await singularInput.fill(TEST_LABEL_SINGULAR);

			// Verify auto-generated plural label
			const pluralInput = admin.page.getByLabel("Label (Plural)");
			await expect(pluralInput).toHaveValue(TEST_LABEL_PLURAL);

			// Override slug with our unique test slug
			const slugInput = admin.page.getByLabel("Slug");
			await slugInput.fill(TEST_SLUG);

			// Submit
			await admin.page.getByRole("button", { name: "Create Content Type" }).click();

			// Should redirect to the new collection's editor page
			await expect(admin.page).toHaveURL(new RegExp(`/content-types/${TEST_SLUG}$`), {
				timeout: 15000,
			});

			// Heading should show the plural label
			await admin.expectPageTitle(TEST_LABEL_PLURAL);
		});

		test("new collection appears in the content types list", async ({ admin }) => {
			await admin.goto("/content-types");
			await admin.waitForLoading();

			// The collection we created in the previous test should appear (scope to table)
			await expect(
				admin.page.locator("table").getByRole("link", { name: TEST_LABEL_PLURAL, exact: true }),
			).toBeVisible({ timeout: 10000 });

			await expect(admin.page.locator("table code", { hasText: TEST_SLUG })).toBeVisible();
		});
	});

	test.describe("Add Field to Content Type", () => {
		test("adds a text field to the test collection", async ({ admin }) => {
			await admin.goto(`/content-types/${TEST_SLUG}`);
			await admin.waitForShell();
			await admin.waitForLoading();

			// Wait for the collection editor to fully load
			await admin.expectPageTitle(TEST_LABEL_PLURAL);

			// Click "Add Field" button
			await admin.page.getByRole("button", { name: "Add Field" }).first().click();

			// The field editor dialog should open -- first step is type selection
			const dialog = admin.page.locator('[role="dialog"]');
			await expect(dialog).toBeVisible({ timeout: 5000 });

			// Select "Short Text" field type
			await dialog.getByText("Short Text").click();

			// Now on the config step -- fill in label (slug auto-generates)
			await dialog.getByLabel("Label").fill("Summary");

			// Verify slug was auto-generated
			await expect(dialog.getByLabel("Slug")).toHaveValue("summary");

			// Click save
			await dialog.getByRole("button", { name: "Add Field" }).click();

			// Dialog should close
			await expect(dialog).not.toBeVisible({ timeout: 10000 });

			// The new field should appear in the field list
			await admin.waitForLoading();
			await expect(admin.page.getByText("Summary", { exact: true })).toBeVisible({
				timeout: 10000,
			});
			await expect(admin.page.locator("code", { hasText: "summary" })).toBeVisible();
		});
	});

	test.describe("Delete Content Type", () => {
		test("deletes the test-created collection", async ({ admin }) => {
			await admin.goto("/content-types");
			await admin.waitForLoading();

			// Verify the test collection exists before deletion
			await expect(admin.page.locator("table code", { hasText: TEST_SLUG })).toBeVisible({
				timeout: 10000,
			});

			// Find the row for the test collection and click its delete button
			const row = admin.page.locator("tr").filter({ hasText: TEST_LABEL_PLURAL });
			await row.getByRole("button", { name: `Delete ${TEST_LABEL_PLURAL}` }).click();

			// Confirm deletion in the dialog
			const dialog = admin.page.locator('[role="dialog"]');
			await expect(dialog).toBeVisible({ timeout: 5000 });
			await dialog.getByRole("button", { name: "Delete" }).click();

			// Collection should disappear from the list
			await admin.waitForLoading();
			await expect(admin.page.locator("table code", { hasText: TEST_SLUG })).not.toBeVisible({
				timeout: 10000,
			});
		});
	});
});
