import assert from "node:assert/strict";
import { execFileSync } from "node:child_process";

const webUrl = process.env.AWP_WEB_URL;
const databaseUrl = process.env.AWP_TEST_POSTGRES_URL;
const playwrightModule = process.env.AWP_PLAYWRIGHT_MODULE;
if (!webUrl) throw new Error("AWP_WEB_URL is required");
if (!databaseUrl) throw new Error("AWP_TEST_POSTGRES_URL is required");
if (!playwrightModule) throw new Error("AWP_PLAYWRIGHT_MODULE is required");

const { chromium } = await import(playwrightModule);
const browser = await chromium.launch({ headless: true });
const projectName = `AWP browser acceptance ${Date.now()}`;
const repositoryUrl = "https://github.com/alexcodeplace/awp.git";
const vision = "Deliver one trustworthy Project-to-Merge journey.";
const goalTitle = "Launch the first complete journey";
const criterion = "Project, execution, review, and trusted merge are proven.";
const taskTitles = [
  "Prepare browser fixture",
  "Implement browser fixture",
  "Verify browser fixture",
];

function psql(query: string): string {
  return execFileSync("psql", [databaseUrl!, "-At", "-c", query], { encoding: "utf8" }).trim();
}

try {
  const page = await browser.newPage();
  await page.goto(webUrl, { waitUntil: "networkidle" });
  await page.getByLabel("Name").fill(projectName);
  await page.getByLabel("Repository URL").fill(repositoryUrl);
  await page.getByRole("button", { name: "Create Project" }).click();
  await page.waitForURL(/\/projects\//);
  const projectId = decodeURIComponent(new URL(page.url()).pathname.split("/").pop()!);
  await page.getByRole("heading", { name: projectName }).waitFor();

  await page.getByLabel("Vision").fill(vision);
  await page.getByRole("button", { name: "Save ProjectVision" }).click();
  await page.getByText(vision).waitFor();

  await page.getByLabel("Goal title").fill(goalTitle);
  await page.getByLabel("Launch criteria").fill(criterion);
  await page.getByRole("button", { name: "Create Goal" }).click();
  await page.getByText(goalTitle).waitFor();
  await page.getByText(criterion).waitFor();

  await page.getByLabel("Plan title").fill("Browser acceptance plan");
  await page.getByLabel("Tasks (one per line, at least three)").fill(taskTitles.join("\n"));
  await page.getByRole("button", { name: "Create Plan" }).click();
  for (const title of taskTitles) {
    await page.locator("[data-task-id] strong", { hasText: title }).waitFor();
  }

  const taskRows = page.locator("[data-task-id]");
  const firstId = await taskRows.nth(0).getAttribute("data-task-id");
  const secondId = await taskRows.nth(1).getAttribute("data-task-id");
  assert.ok(firstId);
  assert.ok(secondId);

  await taskRows.nth(1).getByLabel("Add prerequisite").selectOption(firstId);
  await taskRows.nth(1).getByRole("button", { name: "Add dependency" }).click();
  await page
    .locator(`[data-task-id="${secondId}"]`)
    .getByText("blocked", { exact: true })
    .waitFor();

  const dependencyCount = Number(psql("select count(*) from task_dependencies"));
  await taskRows.nth(0).getByLabel("Add prerequisite").selectOption(secondId);
  await taskRows.nth(0).getByRole("button", { name: "Add dependency" }).click();
  const cycleError = taskRows.nth(0).locator("[data-form-error]");
  await cycleError.getByText(/cycle/i).waitFor();
  const cycleText = await cycleError.textContent();
  assert.match(cycleText ?? "", new RegExp(firstId));
  assert.match(cycleText ?? "", new RegExp(secondId));
  assert.equal(Number(psql("select count(*) from task_dependencies")), dependencyCount);

  await page.getByRole("button", { name: "Approve Plan" }).click();
  await page.getByText("approved", { exact: true }).waitFor();
  await page
    .locator(`[data-task-id="${firstId}"]`)
    .getByText("dispatched", { exact: true })
    .waitFor();
  assert.equal(
    psql(`select count(*) from factory_runs where task_id = '${firstId.replaceAll("'", "''")}'`),
    "1",
  );
  await page.reload({ waitUntil: "networkidle" });
  await page.getByText("approved", { exact: true }).waitFor();

  const escapedProjectId = projectId.replaceAll("'", "''");
  assert.equal(
    psql(`select repository_url from projects where id = '${escapedProjectId}'`),
    repositoryUrl,
  );
  assert.equal(
    psql(`select summary from project_vision_versions where project_id = '${escapedProjectId}'`),
    vision,
  );
  assert.equal(
    psql(`select status from plans where project_id = '${escapedProjectId}'`),
    "approved",
  );

  await page.goto(webUrl, { waitUntil: "networkidle" });
  await page.getByRole("link", { name: projectName }).waitFor();
  process.stdout.write(
    "AC-04..AC-11 PASS: owner lifecycle and automatic first dispatch persisted through live UI and PostgreSQL\n",
  );
} finally {
  await browser.close();
}
