/*
  Grant a Dolibarr permission to the sandbox write agent, through the admin UI.

  The REST API cannot do this (the write agent is non-admin by design), and the
  permission set it ships with is deliberately narrow: invoices, thirdparties,
  payments. Anything beyond that is an explicit, auditable grant — which is what
  this script performs, one right at a time, on the sandbox only.

  Run:
    DOLIBARR_ADDRESS=https://erp-sandbox.arcodange.lab \
      deno run -A test/grantAgentRight.ts --user-id 4 --match "proposition"
*/
import "load_dotenv";
import { chromium } from "playwright";
import login from "./scripts/login.ts";
import { assertSandbox } from "./scripts/guard.ts";

const argv = Deno.args;
const pick = (f: string, d: string) =>
  argv.includes(f) ? argv[argv.indexOf(f) + 1] : d;
const userId = pick("--user-id", "4");
const match = pick("--match", "");
const dryRun = argv.includes("--dry-run");
const revoke = argv.includes("--revoke");
const shotDir = Deno.env.get("SHOT_DIR") ?? "/tmp";

if (!match) {
  console.error("--match <substring of the permission label> is required");
  Deno.exit(2);
}

const dolibarrAddress = assertSandbox();
console.log(`target: ${dolibarrAddress} (guard passed)`);

const browser = await chromium.launch({ headless: true });
const context = await browser.newContext({ locale: "fr-FR" });
const page = await context.newPage();

try {
  await login.doAdminLogin({
    page,
    dolibarrAddress,
    adminCredentials: {
      username: Deno.env.get("DOLI_ADMIN_LOGIN") || "undefined",
      password: Deno.env.get("DOLI_ADMIN_PASSWORD") || "undefined",
    },
  });

  await page.goto(`${dolibarrAddress}/user/perms.php?id=${userId}`);
  const who = await page.locator("h1, .titre, .nowrap").first()
    .textContent({ timeout: 5000 }).catch(() => "(title not found)");
  console.log(`permissions page for: ${who?.trim()}`);
  console.log(`url: ${page.url()}`);

  // Rows whose label matches, that are not already granted (a granted row shows
  // the "remove" link instead of the "add" one).
  const rows = page.locator("tr", {
    has: page.locator("td", { hasText: new RegExp(match, "i") }),
  });
  const total = await rows.count();
  console.log(`rows matching /${match}/i: ${total}`);

  let granted = 0;
  for (let i = 0; i < total; i++) {
    const row = rows.nth(i);
    const label = (await row.textContent())?.replace(/\s+/g, " ").trim().slice(0, 90);
    const action = revoke ? "delrights" : "addrights";
    const addLink = row.locator(`a[href*="action=${action}"]`);
    if (await addLink.count() === 0) {
      console.log(`  [skip, already ${revoke ? "revoked" : "granted"} or not actionable] ${label}`);
      continue;
    }
    if (dryRun) {
      console.log(`  [dry-run would ${revoke ? "revoke" : "grant"}] ${label}`);
      continue;
    }
    await addLink.first().click();
    await page.waitForLoadState("networkidle");
    granted++;
    console.log(`  [${revoke ? "revoked" : "granted"}] ${label}`);
    // The DOM is rebuilt after each grant — re-resolve on the next iteration.
    await page.goto(`${dolibarrAddress}/user/perms.php?id=${userId}`);
  }
  console.log(`${revoke ? "revoked" : "granted"} ${granted} right(s)`);
  await page.screenshot({ path: `${shotDir}/perms.png`, fullPage: true });
} finally {
  await context.close();
  await browser.close();
}
