const path = require("path");
const { spawnSync } = require("child_process");

const fastapiDir = path.join(__dirname, "..", "servers", "fastapi");
const uvCmd = process.platform === "win32" ? "uv.exe" : "uv";
const requiredModel = process.env.MEM0_SPACY_MODEL || "en_core_web_sm";
const strictMode =
  (process.env.MEM0_SPACY_STRICT || "").trim().toLowerCase() === "true";
const venvDir = path.join(fastapiDir, ".venv");

function runUv(args, description) {
  const result = spawnSync(uvCmd, args, {
    cwd: fastapiDir,
    stdio: "inherit",
    env: process.env,
  });

  if (result.error) {
    throw new Error(`${description} failed: ${result.error.message}`);
  }
  return result.status === 0;
}

function runUvPython(args, description) {
  return runUv(["run", "python", ...args], description);
}

function ensureVenv() {
  if (require("fs").existsSync(venvDir)) {
    return true;
  }
  console.log(`[spacy-setup] Creating uv venv at ${venvDir}`);
  return runUv(["venv"], "uv venv");
}

function hasModelInstalled() {
  return runUvPython(
    ["-c", `import spacy; spacy.load("${requiredModel}")`],
    `spaCy model check (${requiredModel})`,
  );
}

function installModel() {
  return runUvPython(
    ["-m", "spacy", "download", requiredModel],
    `spaCy model install (${requiredModel})`,
  );
}

function main() {
  if (!ensureVenv()) {
    throw new Error("Failed to create uv virtual environment");
  }
  console.log(`[spacy-setup] Checking spaCy model: ${requiredModel}`);
  if (hasModelInstalled()) {
    console.log(
      `[spacy-setup] spaCy model already available: ${requiredModel}`,
    );
    return;
  }

  console.log(`[spacy-setup] Installing spaCy model: ${requiredModel}`);
  const installed = installModel();
  if (installed && hasModelInstalled()) {
    console.log(`[spacy-setup] spaCy model installed: ${requiredModel}`);
    return;
  }

  const message =
    `[spacy-setup] Could not install spaCy model (${requiredModel}). ` +
    "Mem0 will self-disable at runtime if this dependency is unavailable.";

  if (strictMode) {
    throw new Error(message);
  }
  console.warn(message);
}

try {
  main();
} catch (error) {
  console.error(`[spacy-setup] ${error.message}`);
  process.exit(1);
}