import { loadSync } from "jsr:@std/dotenv";
// Sandbox provisioning loads its OWN .env.sandbox; prod config stays in .env (main.ts).
loadSync({ envPath: ".env.sandbox", export: true });
import { chromium } from "playwright";
import path from "node:path";
import login from "./scripts/login.ts";
import moduleSetup from "./scripts/admin/moduleSetup.ts";
import userSetup from "./scripts/admin/userSetup.ts";

/*
  provisionSandbox.ts — separate entrypoint (does NOT touch main.ts).

  Provisions the erp-sandbox Dolibarr so the AI agent can write to it:
    1. enable the REST API / Web services module,
    2. create a write-scoped `ai_agent_sandbox` user (non-admin),
    3. grant it the write rights it needs,
    4. have Dolibarr generate its API key and emit it safely to
       test/.ai_agent_sandbox.key (gitignored).

  Run:
    cd test && deno run --allow-all provisionSandbox.ts

  CANNOT be run end-to-end yet: the sandbox Dolibarr is not installed/provisioned
  (empty DB, fresh install wizard). Selector correctness in moduleSetup.ts /
  userSetup.ts is therefore best-effort and must be verified on the first real
  run, AFTER the install wizard has been completed against the sandbox.

  NEXT STEP (not implemented here): load the generated key into the dolibarr
  skill's sandbox config / Vault at kvv2/erp-sandbox/ai_agent. We intentionally
  do NOT write to Vault from this POC.
*/

/*
  Write rights to grant `ai_agent_sandbox` (stable Dolibarr rights ids, verified
  against prod Dolibarr 22.0.4). Each module's read (lire) + create (creer):
    facture:           lire=11,   creer=12
    societe:           lire=121,  creer=122, client voir (see-all)=262
    societe contact:   lire=281,  creer=282
    fournisseur:       lire=1181, facture lire=1231, facture creer=1232
    produit:           lire=31,   creer=32
    banque:            lire=111
    user:              lire=251
*/
const WRITE_IDS = [
  11, // facture lire
  12, // facture creer
  121, // societe lire
  122, // societe creer
  262, // societe client "voir" (see-all) — REQUIRED for the /thirdparties LIST
  //      endpoint; without it the list 404s (the voir_tous ACL trap, cf. the
  //      dolibarr skill SKILL.md). Other modules' lists work with plain `lire`.
  281, // societe contact lire
  282, // societe contact creer
  1181, // fournisseur lire
  1231, // fournisseur facture lire
  1232, // fournisseur facture creer
  31, // produit lire
  32, // produit creer
  111, // banque lire — list bank accounts (GET /bankaccounts) to pick account_id
  251, // user lire — requis par le probe armé GET /users/info (checkpoint status/relink)
  //      Sans lui l'endpoint répond 403 alors que la clé authentifie, et le
  //      checkpoint affiche NOT armed sur un agent pourtant fonctionnel.
];

const KEY_FILE = ".ai_agent_sandbox.key";

/*
  Initialisation — mirrors main.ts but targeted at the sandbox. The default
  address points at the sandbox; admin creds come from env (the same
  DOLI_ADMIN_LOGIN / DOLI_ADMIN_PASSWORD vars main.ts uses, populated from the
  erp-sandbox namespace secrets — see test/README.md "Provision the sandbox").
*/
const dolibarrAddress = Deno.env.get("DOLIBARR_ADDRESS") ||
  "https://erp-sandbox.arcodange.lab";
const debug = true;
const DBpassword = Deno.env.get("DOLI_DB_PASSWORD") || "undefined";
const adminCredentials = {
  username: Deno.env.get("DOLI_ADMIN_LOGIN") || "admin",
  password: Deno.env.get("DOLI_ADMIN_PASSWORD") || "undefined",
};

// The new user's login is fixed; its password comes from env or is generated.
const AI_AGENT_LOGIN = "ai_agent_sandbox";
const aiAgentPassword = Deno.env.get("AI_AGENT_SANDBOX_PASSWORD") ||
  generatePassword();

const rootFolderPath = Deno.env.get("ROOT_FOLDER") ||
  path.join(Deno.cwd(), "..");
const imgFolderPath = Deno.env.get("IMG_FOLDER") ||
  path.join(rootFolderPath, "static/img");
const configFolderPath = Deno.env.get("CONFIG_FOLDER") ||
  path.join(rootFolderPath, "static/config");

/* Generate a reasonably strong random password (used only if none provided). */
function generatePassword(): string {
  const bytes = new Uint8Array(18);
  crypto.getRandomValues(bytes);
  // URL-safe base64 → no shell-hostile characters.
  return btoa(String.fromCharCode(...bytes))
    .replace(/\+/g, "-")
    .replace(/\//g, "_")
    .replace(/=+$/, "");
}

const browser = await chromium.launch({
  headless: false,
  logger: {
    isEnabled: (_name, _severity) => debug,
    log: (name, severity, message, args) =>
      console.warn(`${severity}| ${name} :: ${message} __ ${args}`),
  },
});
const context = await browser.newContext({ locale: "fr-FR" });
const page = await context.newPage();

const globalCtx = {
  dolibarrAddress,
  DBpassword,
  adminCredentials,

  debug,
  rootFolderPath,
  imgFolderPath,
  configFolderPath,

  browser,
  page,
  context,
};

try {
  await login.doAdminLogin(globalCtx);
  console.log(`connected as ${await login.whoAmI(globalCtx)}`);

  await moduleSetup.enableApiModule(globalCtx);
  console.log("REST API module enabled");

  const userId = await userSetup.createUser(globalCtx, {
    login: AI_AGENT_LOGIN,
    password: aiAgentPassword,
    lastname: "AI Agent (sandbox)",
    admin: false,
  });
  console.log(`created user '${AI_AGENT_LOGIN}' (id=${userId})`);

  await userSetup.assignRights(globalCtx, userId, WRITE_IDS);
  console.log(`granted ${WRITE_IDS.length} write rights to id=${userId}`);

  const apiKey = await userSetup.generateApiKey(globalCtx, userId);

  // Emit the key safely: write it to a gitignored file rather than printing it.
  await Deno.writeTextFile(KEY_FILE, apiKey + "\n");
  console.log(`AI_AGENT_SANDBOX API KEY WRITTEN TO test/${KEY_FILE}`);
} catch (error) {
  console.error(error);
} finally {
  await browser.close();
}
