/**
 * Plugins Manager E2E Tests
 *
 * Tests the plugins manager admin page at /plugins-manager.
 * Verifies that the page renders, displays plugin info, and
 * supports enable/disable toggling.
 *
 * This test exists because the plugins page previously crashed due to
 * incorrect API response envelope unwrapping (fetchPlugins returned
 * { items: [...] } instead of [...]) -- a bug that component tests
 * never caught because they mock fetchPlugins at the module level.
 *
 * The e2e fixture configures a color plugin (id: "color", version: "0.0.1").
 */

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

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

	test.describe("Page rendering", () => {
		test("displays the plugins page with at least one plugin", async ({ admin, page }) => {
			await admin.goto("/plugins-manager");
			await admin.waitForShell();
			await admin.waitForLoading();

			// Page title
			await admin.expectPageTitle("Plugins");

			// Should show the plugin count
			await expect(page.locator("text=/\\d+ plugin/")).toBeVisible({ timeout: 10000 });

			// Should have at least one plugin card (the color plugin from the fixture)
			const pluginCards = page.locator(".rounded-lg.border.bg-kumo-base");
			await expect(pluginCards.first()).toBeVisible({ timeout: 10000 });
		});

		test("does not show a crash or error state", async ({ admin, page }) => {
			await admin.goto("/plugins-manager");
			await admin.waitForShell();
			await admin.waitForLoading();

			// The bug that prompted this test caused the page to show an error.
			// Verify no error state is visible.
			await expect(page.locator("text=Failed to load plugins")).not.toBeVisible();
		});
	});

	test.describe("Plugin card info", () => {
		test("shows plugin name, version, and toggle", async ({ admin, page }) => {
			await admin.goto("/plugins-manager");
			await admin.waitForShell();
			await admin.waitForLoading();

			// Find the color plugin card
			const colorCard = page
				.locator(".rounded-lg.border.bg-kumo-base", { hasText: "color" })
				.first();
			await expect(colorCard).toBeVisible({ timeout: 10000 });

			// Plugin name
			await expect(colorCard.locator("h3")).toContainText("color");

			// Version badge
			await expect(colorCard.locator("text=v0.0.1")).toBeVisible();

			// Enable/disable switch
			const toggle = colorCard.locator("button[role='switch']");
			await expect(toggle).toBeVisible();
		});
	});

	test.describe("Enable / disable toggle", () => {
		test.skip("can disable a plugin and see the Disabled badge", async ({ admin, page }) => {
			// TODO: Enable/disable only works for marketplace plugins, not config plugins.
			await admin.goto("/plugins-manager");
			await admin.waitForShell();
			await admin.waitForLoading();

			const colorCard = page
				.locator(".rounded-lg.border.bg-kumo-base", { hasText: "color" })
				.first();
			await expect(colorCard).toBeVisible({ timeout: 10000 });

			const toggle = colorCard.locator("button[role='switch']");
			await expect(toggle).toBeVisible({ timeout: 5000 });

			// If the plugin is currently disabled, enable it first
			const isChecked = await toggle.getAttribute("aria-checked");
			if (isChecked !== "true") {
				await toggle.click();
				await page.waitForTimeout(2000);
				await admin.waitForLoading();
			}

			// Now disable the plugin
			await toggle.click();
			await page.waitForTimeout(2000);
			await admin.waitForLoading();

			// The "Disabled" badge should appear on the card
			await expect(colorCard.getByText("Disabled")).toBeVisible({ timeout: 10000 });

			// The toggle should now be unchecked
			await expect(toggle).toHaveAttribute("aria-checked", "false");
		});

		test.skip("can re-enable a disabled plugin", async ({ admin, page }) => {
			// TODO: Enable/disable only works for marketplace plugins, not config plugins.
			await admin.goto("/plugins-manager");
			await admin.waitForShell();
			await admin.waitForLoading();

			const colorCard = page
				.locator(".rounded-lg.border.bg-kumo-base", { hasText: "color" })
				.first();
			await expect(colorCard).toBeVisible({ timeout: 10000 });

			const toggle = colorCard.locator("button[role='switch']");
			await expect(toggle).toBeVisible({ timeout: 5000 });

			// Ensure the plugin is disabled first
			const isChecked = await toggle.getAttribute("aria-checked");
			if (isChecked === "true") {
				await toggle.click();
				await page.waitForTimeout(2000);
				await admin.waitForLoading();
			}

			// Verify it shows "Disabled"
			await expect(colorCard.getByText("Disabled")).toBeVisible({ timeout: 10000 });

			// Re-enable it
			await toggle.click();
			await page.waitForTimeout(2000);
			await admin.waitForLoading();

			// The "Disabled" badge should be gone
			await expect(colorCard.getByText("Disabled")).not.toBeVisible({ timeout: 10000 });

			// Toggle should be checked again
			await expect(toggle).toHaveAttribute("aria-checked", "true");
		});
	});

	test.describe("Expand details", () => {
		test("expand button reveals details section", async ({ admin, page }) => {
			await admin.goto("/plugins-manager");
			await admin.waitForShell();
			await admin.waitForLoading();

			const colorCard = page
				.locator(".rounded-lg.border.bg-kumo-base", { hasText: "color" })
				.first();
			await expect(colorCard).toBeVisible({ timeout: 10000 });

			// Find and click the expand button
			const expandBtn = colorCard.locator("button[aria-label='Expand details']");
			await expect(expandBtn).toBeVisible();
			await expandBtn.click();

			// The details section should now be visible (it has a border-t class)
			const detailsSection = colorCard.locator(".border-t.px-4");
			await expect(detailsSection).toBeVisible({ timeout: 5000 });

			// Collapse button should now be present
			await expect(colorCard.locator("button[aria-label='Collapse details']")).toBeVisible();
		});

		test("collapse button hides the details section", async ({ admin, page }) => {
			await admin.goto("/plugins-manager");
			await admin.waitForShell();
			await admin.waitForLoading();

			const colorCard = page
				.locator(".rounded-lg.border.bg-kumo-base", { hasText: "color" })
				.first();
			await expect(colorCard).toBeVisible({ timeout: 10000 });

			// Expand first
			await colorCard.locator("button[aria-label='Expand details']").click();
			const detailsSection = colorCard.locator(".border-t.px-4");
			await expect(detailsSection).toBeVisible({ timeout: 5000 });

			// Now collapse
			await colorCard.locator("button[aria-label='Collapse details']").click();

			// Details should be hidden
			await expect(detailsSection).not.toBeVisible({ timeout: 5000 });

			// Expand button should be back
			await expect(colorCard.locator("button[aria-label='Expand details']")).toBeVisible();
		});
	});

	test.describe("API integration", () => {
		test("plugins API returns the correct envelope shape", async ({ page, serverInfo }) => {
			// Directly verify the API response shape that caused the original bug.
			// fetchPlugins expected { data: { items: [...] } } but was getting
			// the items at a different nesting level.
			const res = await page.request.get("/_emdash/api/admin/plugins", {
				headers: {
					"X-EmDash-Request": "1",
					Authorization: `Bearer ${serverInfo.token}`,
				},
			});

			expect(res.ok()).toBe(true);
			const body = await res.json();

			// The response should have { data: { items: [...] } }
			expect(body.data).toBeDefined();
			expect(body.data.items).toBeDefined();
			expect(Array.isArray(body.data.items)).toBe(true);
			expect(body.data.items.length).toBeGreaterThan(0);

			// Each plugin should have the expected shape
			const plugin = body.data.items[0];
			expect(plugin.id).toBeDefined();
			expect(plugin.name).toBeDefined();
			expect(plugin.version).toBeDefined();
			expect(typeof plugin.enabled).toBe("boolean");
			expect(Array.isArray(plugin.capabilities)).toBe(true);
		});
	});
});
