import { test, expect } from "./fixtures.js";
import type { GrackleClient } from "./rpc-client.js";

/**
 * Helper: set onboarding_completed via direct RPC.
 */
async function setOnboardingCompleted(
  client: GrackleClient,
  value: "true" | "false",
): Promise<void> {
  await client.core.setSetting({ key: "onboarding_completed", value });
}

// Run tests serially — they share server state (onboarding_completed setting).
test.describe.configure({ mode: "serial" });

test.describe("Setup Wizard (FRE)", { tag: ["@settings"] }, () => {
  // Always restore onboarding state after each test so that failures
  // cannot cascade to other tests sharing this worker.
  test.afterEach(async ({ grackle: { client } }) => {
    await setOnboardingCompleted(client, "true");
  });

  test("redirects to /setup when onboarding is incomplete", async ({ page, grackle: { client } }) => {
    await setOnboardingCompleted(client, "false");

    await page.goto("/");
    await page.waitForURL("**/setup", { timeout: 10_000 });
    await expect(page.getByTestId("setup-wizard")).toBeVisible();
    await expect(page.getByText("Welcome to Grackle")).toBeVisible();
  });

  test("back buttons navigate between steps", async ({ page, grackle: { client } }) => {
    await setOnboardingCompleted(client, "false");
    await page.goto("/");
    await page.waitForURL("**/setup", { timeout: 10_000 });

    // Welcome → About
    await page.getByTestId("setup-get-started").click();
    await expect(page.getByTestId("setup-about")).toBeVisible();

    // About → back to Welcome
    await page.getByRole("button", { name: "Back" }).click();
    await expect(page.getByTestId("setup-welcome")).toBeVisible();

    // Welcome → About → Runtime
    await page.getByTestId("setup-get-started").click();
    await page.getByTestId("setup-about-next").click();
    await expect(page.getByTestId("setup-runtime")).toBeVisible();

    // Runtime → Notifications
    await page.getByTestId("setup-runtime-next").click();
    await expect(page.getByTestId("setup-notifications")).toBeVisible();

    // Notifications → back to Runtime
    await page.getByRole("button", { name: "Back" }).click();
    await expect(page.getByTestId("setup-runtime")).toBeVisible();

    // Runtime → back to About
    await page.getByRole("button", { name: "Back" }).click();
    await expect(page.getByTestId("setup-about")).toBeVisible();
  });

  test("walks through all four steps and completes", async ({ page, grackle: { client } }) => {
    await setOnboardingCompleted(client, "false");
    await page.goto("/");
    await page.waitForURL("**/setup", { timeout: 10_000 });

    // Step 0: Welcome
    await expect(page.getByTestId("setup-welcome")).toBeVisible();
    await page.getByTestId("setup-get-started").click();

    // Step 1: About
    await expect(page.getByTestId("setup-about")).toBeVisible();
    await page.getByTestId("setup-about-next").click();

    // Step 2: Runtime — claude-code should be pre-selected
    await expect(page.getByTestId("setup-runtime")).toBeVisible();
    await expect(page.getByTestId("runtime-card-claude-code")).toHaveAttribute("aria-pressed", "true");
    await expect(page.getByTestId("runtime-card-copilot")).toHaveAttribute("aria-pressed", "false");

    // Select a different runtime
    await page.getByTestId("runtime-card-copilot").click();
    await expect(page.getByTestId("runtime-card-copilot")).toHaveAttribute("aria-pressed", "true");

    // Advance to notification step
    await page.getByTestId("setup-runtime-next").click();

    // Step 3: Notifications — skip or finish
    await expect(page.getByTestId("setup-notifications")).toBeVisible();
    // Click whichever button is available (Skip if permission is "default", Finish otherwise)
    const skipButton = page.getByTestId("setup-notifications-skip");
    const finishButton = page.getByTestId("setup-finish");
    if (await skipButton.isVisible().catch(() => false)) {
      await skipButton.click();
    } else {
      await finishButton.click();
    }

    await page.waitForFunction(
      () => document.body.innerText.includes("Connected"),
      { timeout: 10_000 },
    );
  });

  test("does not show wizard after onboarding is complete", async ({ page }) => {
    // Onboarding was just completed by the previous test
    await page.goto("/");
    await page.waitForFunction(
      () => document.body.innerText.includes("Connected"),
      { timeout: 10_000 },
    );
    await expect(page.getByTestId("setup-wizard")).not.toBeVisible();
  });

  test("/setup redirects to / when onboarding is already complete", async ({ page }) => {
    // Onboarding is still complete
    await page.goto("/setup");
    await page.waitForFunction(
      () => document.body.innerText.includes("Connected"),
      { timeout: 10_000 },
    );
    await expect(page.getByTestId("setup-wizard")).not.toBeVisible();
  });

});
