import { expect, test, type Route } from "@playwright/test";
import { gotoDashboardRoute } from "./helpers/dashboardAuth";

const NAVIGATION_TIMEOUT_MS = 300_000;

type AgentSkill = {
  id: string;
  name: string;
  description: string;
  category: "api" | "cli";
  area: string;
  icon: string;
  endpoints?: string[];
  cliCommands?: string[];
  rawUrl: string;
  githubUrl: string;
};

type SkillCoverage = {
  api: { have: number; total: number };
  cli: { have: number; total: number };
  totalSkills: number;
  generatedAt: string;
};

function makeAgentSkills(): AgentSkill[] {
  const skills: AgentSkill[] = [];
  for (let i = 0; i < 22; i++) {
    skills.push({
      id: `omni-skill-${i}`,
      name: `API Skill ${i}`,
      description: `API skill description ${i}`,
      category: "api",
      area: `area-${i}`,
      icon: "api",
      endpoints: [`GET /api/skill-${i}`],
      rawUrl: `https://raw.githubusercontent.com/example/OmniRoute/main/skills/omni-skill-${i}/SKILL.md`,
      githubUrl: `https://github.com/example/OmniRoute/blob/main/skills/omni-skill-${i}/SKILL.md`,
    });
  }
  for (let i = 0; i < 20; i++) {
    skills.push({
      id: `cli-skill-${i}`,
      name: `CLI Skill ${i}`,
      description: `CLI skill description ${i}`,
      category: "cli",
      area: `cli-area-${i}`,
      icon: "terminal",
      cliCommands: [`skill${i} run`],
      rawUrl: `https://raw.githubusercontent.com/example/OmniRoute/main/skills/cli-skill-${i}/SKILL.md`,
      githubUrl: `https://github.com/example/OmniRoute/blob/main/skills/cli-skill-${i}/SKILL.md`,
    });
  }
  return skills;
}

const FULL_COVERAGE: SkillCoverage = {
  api: { have: 22, total: 22 },
  cli: { have: 20, total: 20 },
  totalSkills: 42,
  generatedAt: new Date().toISOString(),
};

async function fulfillJson(route: Route, body: unknown, status = 200) {
  await route.fulfill({
    status,
    contentType: "application/json",
    body: JSON.stringify(body),
  });
}

async function fulfillText(route: Route, body: string, status = 200) {
  await route.fulfill({
    status,
    contentType: "text/markdown; charset=utf-8",
    body,
  });
}

test.describe("Agent Skills page", () => {
  test.setTimeout(600_000);

  test("renders SkillsConceptCard with data-testid skills-concept-card-agent", async ({
    page,
  }) => {
    const skills = makeAgentSkills();

    await page.route(/\/api\/agent-skills(?:\?.*)?$/, async (route) => {
      if (route.request().method() === "GET") {
        await fulfillJson(route, { skills, coverage: FULL_COVERAGE });
      } else {
        await route.continue();
      }
    });

    await gotoDashboardRoute(page, "/dashboard/agent-skills", {
      timeoutMs: NAVIGATION_TIMEOUT_MS,
    });

    const conceptCard = page.locator("[data-testid='skills-concept-card-agent']");
    await expect(conceptCard).toBeVisible({ timeout: 15_000 });
  });

  test("grid shows 42 skill cards when filter is 'all'", async ({ page }) => {
    const skills = makeAgentSkills();

    await page.route(/\/api\/agent-skills(?:\?.*)?$/, async (route) => {
      if (route.request().method() === "GET") {
        await fulfillJson(route, { skills, coverage: FULL_COVERAGE });
      } else {
        await route.continue();
      }
    });

    await gotoDashboardRoute(page, "/dashboard/agent-skills", {
      timeoutMs: NAVIGATION_TIMEOUT_MS,
    });

    // Wait for cards to render
    await expect(page.locator("[data-testid^='skill-card-']").first()).toBeVisible({
      timeout: 15_000,
    });

    const cards = page.locator("[data-testid^='skill-card-']");
    await expect(cards).toHaveCount(42, { timeout: 15_000 });
  });

  test("clicking omni-skill-0 card renders markdown in preview pane", async ({
    page,
  }) => {
    const skills = makeAgentSkills();
    const mockMarkdown = "# API Skill 0\n\nThis skill manages connections.";

    await page.route(/\/api\/agent-skills(?:\?.*)?$/, async (route) => {
      if (route.request().method() === "GET") {
        await fulfillJson(route, { skills, coverage: FULL_COVERAGE });
      } else {
        await route.continue();
      }
    });

    await page.route(/\/api\/agent-skills\/omni-skill-0\/raw/, async (route) => {
      await fulfillText(route, mockMarkdown);
    });

    await gotoDashboardRoute(page, "/dashboard/agent-skills", {
      timeoutMs: NAVIGATION_TIMEOUT_MS,
    });

    // Wait for cards to render and click first card
    const firstCard = page.locator("[data-testid='skill-card-omni-skill-0']");
    await expect(firstCard).toBeVisible({ timeout: 15_000 });
    await firstCard.click();

    // Preview pane should show non-empty content
    const previewPane = page.locator("[data-testid='skill-preview-pane']");
    await expect(previewPane).toBeVisible({ timeout: 15_000 });
    const previewText = await previewPane.textContent();
    expect(previewText?.trim().length).toBeGreaterThan(0);
  });

  test("cross-link 'Understand the difference' navigates to /dashboard/omni-skills", async ({
    page,
  }) => {
    const skills = makeAgentSkills();

    await page.route(/\/api\/agent-skills(?:\?.*)?$/, async (route) => {
      if (route.request().method() === "GET") {
        await fulfillJson(route, { skills, coverage: FULL_COVERAGE });
      } else {
        await route.continue();
      }
    });

    await gotoDashboardRoute(page, "/dashboard/agent-skills", {
      timeoutMs: NAVIGATION_TIMEOUT_MS,
    });

    const conceptCard = page.locator("[data-testid='skills-concept-card-agent']");
    await expect(conceptCard).toBeVisible({ timeout: 15_000 });

    // Find the cross-link inside the concept card
    const crossLink = conceptCard.locator("a");
    await expect(crossLink).toBeVisible({ timeout: 5_000 });

    await crossLink.click();
    await page.waitForURL(/\/dashboard\/omni-skills/, { timeout: 15_000 });
    expect(page.url()).toContain("/dashboard/omni-skills");
  });

  test("/dashboard/skills redirects to /dashboard/omni-skills", async ({ page }) => {
    await page.goto("/dashboard/skills", { waitUntil: "commit", timeout: NAVIGATION_TIMEOUT_MS });
    // Next.js redirects /dashboard/skills → /dashboard/omni-skills (next.config.mjs).
    // If auth is required the app then client-redirects to /login (bare path, no /dashboard/ prefix).
    await page.waitForURL(/\/(login|onboarding|dashboard\/(omni-skills|onboarding))/, {
      timeout: 15_000,
    });
    const finalUrl = page.url();
    expect(
      finalUrl.includes("/dashboard/omni-skills") ||
        finalUrl.includes("/login") ||
        finalUrl.includes("/onboarding"),
    ).toBe(true);
  });
});
