/**
 * Form Data Loss Prevention E2E Tests
 *
 * Verifies fixes from PR #133 — background refetches, false save states,
 * and stale taxonomy selections no longer cause silent data loss.
 *
 * Seed data:
 *   - posts: "First Post" (published), with categories taxonomy
 *   - categories taxonomy: "News", "Tutorials", "Opinion"
 *   - sections: "Hero Section" (slug: hero)
 */

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

test.describe("Form Data Loss Prevention", () => {
	test.beforeEach(async ({ admin }) => {
		await admin.devBypassAuth();
	});

	test("settings edits survive window blur/focus", async ({ admin, page }) => {
		await admin.goto("/settings/general");
		await admin.waitForShell();
		await admin.waitForLoading();

		// Edit the tagline field
		const taglineInput = page.getByLabel("Tagline");
		await taglineInput.fill("My edited tagline");

		// Simulate window blur + focus (triggers React Query refetches for stale queries)
		await page.evaluate(() => {
			window.dispatchEvent(new Event("blur"));
			window.dispatchEvent(new Event("focus"));
		});

		// Wait for any potential refetch to complete
		await page.waitForTimeout(1000);

		// The edit should persist (staleTime: Infinity prevents refetch from overwriting)
		await expect(taglineInput).toHaveValue("My edited tagline");
	});

	test("section editor edits survive window blur/focus", async ({ admin, page }) => {
		await admin.goto("/sections/hero");
		await admin.waitForShell();
		await admin.waitForLoading();

		// Edit the title field
		const titleInput = page.getByLabel("Title");
		const originalTitle = await titleInput.inputValue();
		const editedTitle = `Edited ${Date.now()}`;
		await titleInput.fill(editedTitle);

		// Simulate window blur + focus (triggers React Query refetches without staleTime)
		await page.evaluate(() => {
			window.dispatchEvent(new Event("blur"));
			window.dispatchEvent(new Event("focus"));
		});

		// Small wait for any potential refetch to complete
		await page.waitForTimeout(1000);

		// Edits should still be there (staleTime: Infinity prevents overwrite)
		await expect(titleInput).toHaveValue(editedTitle);

		// Save button should show "Save" (dirty), not "Saved" (clean)
		await expect(page.getByRole("button", { name: "Save" })).toBeEnabled();

		// Restore original value to avoid side effects on other tests
		await titleInput.fill(originalTitle);
	});

	test("section editor save failure keeps form dirty", async ({ admin, page }) => {
		await admin.goto("/sections/hero");
		await admin.waitForShell();
		await admin.waitForLoading();

		// Edit the title field so the form is dirty
		const titleInput = page.getByLabel("Title");
		const originalTitle = await titleInput.inputValue();
		await titleInput.fill(`Error test ${Date.now()}`);

		// Intercept the section update API call and force a failure
		await page.route("**/api/sections/hero", (route) => {
			if (route.request().method() === "PUT" || route.request().method() === "PATCH") {
				return route.fulfill({
					status: 500,
					contentType: "application/json",
					body: JSON.stringify({ error: { code: "SERVER_ERROR", message: "Simulated failure" } }),
				});
			}
			return route.continue();
		});

		// Click save
		const saveButton = page.getByRole("button", { name: "Save" });
		await saveButton.click();

		// Wait for the error to be processed
		await page.waitForTimeout(1000);

		// The Save button should still be enabled (form is still dirty)
		// It should NOT show "Saved" — the mutation failed
		await expect(page.getByRole("button", { name: "Save" })).toBeEnabled();

		// Remove the route intercept and restore title
		await page.unroute("**/api/sections/hero");
		await titleInput.fill(originalTitle);
	});

	test("taxonomy checkboxes clear when all terms are removed", async ({
		admin,
		page,
		serverInfo,
	}) => {
		// Navigate to a published post that we can assign terms to
		const postId = serverInfo.contentIds["posts"]?.[0];
		if (!postId) {
			test.skip();
			return;
		}

		await admin.goToEditContent("posts", postId);
		await admin.waitForLoading();

		// Wait for the taxonomy sidebar to load
		const taxonomyHeading = page.locator("h3", { hasText: "Taxonomies" });
		await expect(taxonomyHeading).toBeVisible({ timeout: 10000 });

		// Find the category checkboxes
		const newsCheckbox = page.getByRole("checkbox", { name: "News" });
		const tutorialsCheckbox = page.getByRole("checkbox", { name: "Tutorials" });

		// Check two categories
		await newsCheckbox.check();
		await page.waitForTimeout(500); // Wait for auto-save
		await tutorialsCheckbox.check();
		await page.waitForTimeout(500); // Wait for auto-save

		// Verify both are checked
		await expect(newsCheckbox).toBeChecked();
		await expect(tutorialsCheckbox).toBeChecked();

		// Now uncheck both — this is the bug scenario from PR #133
		await newsCheckbox.uncheck();
		await page.waitForTimeout(500);
		await tutorialsCheckbox.uncheck();
		await page.waitForTimeout(500);

		// All checkboxes should be unchecked (the old bug would leave stale checks)
		await expect(newsCheckbox).not.toBeChecked();
		await expect(tutorialsCheckbox).not.toBeChecked();
		await expect(page.getByRole("checkbox", { name: "Opinion" })).not.toBeChecked();

		// Reload to verify server state matches
		await page.reload();
		await admin.waitForShell();
		await admin.waitForLoading();

		// After reload, all should still be unchecked
		await expect(taxonomyHeading).toBeVisible({ timeout: 10000 });
		await expect(page.getByRole("checkbox", { name: "News" })).not.toBeChecked();
		await expect(page.getByRole("checkbox", { name: "Tutorials" })).not.toBeChecked();
		await expect(page.getByRole("checkbox", { name: "Opinion" })).not.toBeChecked();
	});
});
