import { expect, test, type Page } from "@playwright/test";

async function signIn(page: Page) {
  await page.goto("/auth/signin");
  await page.fill('input[type="email"]', "admin@nexus.dev");
  await page.fill('input[type="password"]', "admin123");
  await page.click('button[type="submit"]');
  await expect(page).toHaveURL(/\/(dashboard|resources)/);
}

/**
 * Navigate to the projects list and return the href of the first project row.
 * Returns null if the list is empty (seed data may not be present).
 */
async function getFirstProjectHref(page: Page): Promise<string | null> {
  await page.goto("/projects");
  await page.waitForLoadState("networkidle");

  // Try to find a link inside the projects table that points to /projects/<id>
  const projectLink = page
    .locator("table a[href*='/projects/']")
    .or(page.locator("a[href*='/projects/']").filter({ hasNot: page.locator("nav") }))
    .first();

  if ((await projectLink.count()) === 0) {
    return null;
  }
  return projectLink.getAttribute("href");
}

test.describe("Project Detail Page", () => {
  test.beforeEach(async ({ page }) => {
    await signIn(page);
  });

  test("project detail page loads from list link", async ({ page }) => {
    const href = await getFirstProjectHref(page);
    if (!href) {
      test.skip(true, "No seeded projects available to navigate to");
      return;
    }

    await page.goto(href);
    await page.waitForLoadState("networkidle");

    // Project detail renders an h1 with the project name
    await expect(page.locator("h1").first()).toBeVisible({ timeout: 10000 });
  });

  test("project detail shows assignments and demands sections", async ({ page }) => {
    const href = await getFirstProjectHref(page);
    if (!href) {
      test.skip(true, "No seeded projects available to navigate to");
      return;
    }

    await page.goto(href);
    await page.waitForLoadState("networkidle");

    // The detail page should contain stat labels for assignments and open demands
    await expect(
      page.locator("text=Assignments").or(page.locator("text=Open Demands")).first(),
    ).toBeVisible({ timeout: 10000 });
  });

  test("project detail shows budget status card", async ({ page }) => {
    const href = await getFirstProjectHref(page);
    if (!href) {
      test.skip(true, "No seeded projects available to navigate to");
      return;
    }

    await page.goto(href);
    await page.waitForLoadState("networkidle");

    // BudgetStatusCard renders budget-related content
    await expect(page.locator("text=Budget").or(page.locator("text=budget")).first()).toBeVisible({
      timeout: 10000,
    });
  });

  test("unknown project id shows not-found state", async ({ page }) => {
    await page.goto("/projects/does-not-exist-abc123");
    await page.waitForLoadState("networkidle");

    // Server-side notFound() triggers the Next.js 404 page
    await expect(
      page
        .locator("text=404")
        .or(page.locator("text=Not Found"))
        .or(page.locator("text=not found"))
        .first(),
    ).toBeVisible({ timeout: 10000 });
  });

  test("no console errors when viewing first project", async ({ page }) => {
    const consoleErrors: string[] = [];
    page.on("console", (msg) => {
      if (msg.type() === "error") {
        consoleErrors.push(msg.text());
      }
    });

    const href = await getFirstProjectHref(page);
    if (!href) {
      test.skip(true, "No seeded projects available to navigate to");
      return;
    }

    await page.goto(href);
    await page.waitForLoadState("networkidle");

    const appErrors = consoleErrors.filter(
      (e) => !e.includes("extension") && !e.includes("favicon"),
    );
    expect(appErrors, `Unexpected console errors: ${appErrors.join("\n")}`).toHaveLength(0);
  });
});
