/*
  Fait produire à Dolibarr le PDF d'une facture client, puis l'enregistre.

  POURQUOI CE CHEMIN EXISTE. Valider une facture par l'API **ne génère aucun
  PDF** : le fichier n'existe sur le disque que lorsque quelqu'un a demandé sa
  production. `PUT /documents/builddoc` le ferait, mais ce droit n'est accordé à
  aucun scope agent (voir test/scopes.ts) et répond 403. Le seul chemin ouvert
  est donc l'interface — celui que l'opérateur emprunterait lui-même.

  Deux pièges :
    - le PDF n'est PAS servi par la page : on demande sa production par l'UI,
      puis on le relit par l'API `/documents/download`, qui prouve du même coup
      qu'il est bien déposé et lisible par un tiers ;
    - `action=builddoc` exige le jeton CSRF de session. On ne le devine pas : on
      le relit sur un lien de la fiche.

  Usage :
    deno run -A test/buildInvoicePdf.ts --ref FAC009-CL0001009 --out dossier/
*/
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 = "") => (argv.includes(f) ? argv[argv.indexOf(f) + 1] : d);

const ref = pick("--ref");
const out = pick("--out", ".");
const model = pick("--model", "sponge");
const dryRun = argv.includes("--dry-run");

if (!ref) {
  console.error("--ref est requis (ex. FAC009-CL0001009)");
  Deno.exit(2);
}

const dolibarrAddress = assertSandbox();
console.log(`cible  : ${dolibarrAddress}`);
console.log(`facture: ${ref}`);
console.log(`modèle : ${model}`);
if (dryRun) {
  console.log("\n--dry-run : rien n'est produit.");
  Deno.exit(0);
}

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",
    },
  });

  const card = `${dolibarrAddress}/compta/facture/card.php?ref=${encodeURIComponent(ref)}`;
  await page.goto(card);
  const body = await page.locator("body").innerText();
  if (!body.includes(ref)) {
    console.error(`facture introuvable : ${card}`);
    Deno.exit(1);
  }

  // Identifiant réel de la facture, tel que l'URL le porte après résolution du ref.
  const idMatch = (await page.locator('a[href*="facid="]').first().getAttribute("href")
    .catch(() => null))?.match(/facid=(\d+)/);
  const anyToken = (await page.locator('a[href*="token="]').first().getAttribute("href")
    .catch(() => null))?.match(/token=([a-zA-Z0-9]+)/);
  if (!anyToken) {
    console.error("aucun jeton de session lisible sur la fiche — droits insuffisants ?");
    Deno.exit(1);
  }
  const token = anyToken[1];
  const id = idMatch?.[1];

  const buildUrl = `${dolibarrAddress}/compta/facture/card.php` +
    `?${id ? `facid=${id}` : `ref=${encodeURIComponent(ref)}`}` +
    `&action=builddoc&token=${token}&model=${model}`;
  await page.goto(buildUrl);

  // On ne croit pas la page de retour : on relit le fichier par l'API.
  const apiUrl = Deno.env.get("DOLIBARR_URL") || dolibarrAddress;
  const apiKey = Deno.env.get("DOLIBARR_API_KEY") || "";
  const res = await fetch(
    `${apiUrl}/api/index.php/documents/download` +
      `?modulepart=facture&original_file=${encodeURIComponent(`${ref}/${ref}.pdf`)}`,
    { headers: { DOLAPIKEY: apiKey, Accept: "application/json" } },
  );
  const payload = await res.json();
  if (!res.ok || !payload.content) {
    console.error(`le PDF n'est pas déposé : HTTP ${res.status} ${JSON.stringify(payload).slice(0, 200)}`);
    Deno.exit(1);
  }

  const bytes = Uint8Array.from(atob(payload.content), (c) => c.charCodeAt(0));
  const dest = out.endsWith(".pdf") ? out : `${out.replace(/\/$/, "")}/${ref}.pdf`;
  await Deno.writeFile(dest, bytes);
  console.log(`ok — ${dest} (${bytes.length} octets)`);
} finally {
  await browser.close();
}
