import path from 'node:path';
import fs from 'node:fs';
import os from 'node:os';
import { fileURLToPath } from 'node:url';

const here = path.dirname(fileURLToPath(import.meta.url));
export const ROOT = path.resolve(here, '..');

// Runtime package root. ROOT is derived from import.meta.url, which Next.js
// bakes at BUILD time — for any lib module pulled into the standalone web
// bundle that resolves to the CI builder's path (/home/runner/work/...),
// which does not exist on the user's machine. Using it as a spawn `cwd` (or to
// locate a sibling script) fails with `spawn <cmd> ENOENT`. The `madarx` CLI
// knows the real install dir and exports it as MADARX_PKG_ROOT when it spawns
// the web server — prefer that. Fall back to the baked ROOT, which is correct
// in dev (`next dev` bakes the local path) and for non-bundled callers.
export const PKG_ROOT = process.env.MADARX_PKG_ROOT
  ? path.resolve(process.env.MADARX_PKG_ROOT)
  : ROOT;

// First candidate that exists and is a directory, else process.cwd(). Use to
// pick a spawn `cwd` that is guaranteed to exist at runtime.
export function pickExistingDir(...candidates) {
  for (const dir of candidates) {
    try { if (dir && fs.statSync(dir).isDirectory()) return dir; } catch { /* next */ }
  }
  return process.cwd();
}

// ---------------------------------------------------------------------------
// Data + workspace location resolution.
//
// Precedence (first match wins):
//   1. MADARX_DATA_DIR / MADARX_WORKSPACE      — explicit override (tests,
//      power users, one-shot scripts).
//   2. VILLA515_DATA_DIR / VILLA515_WORKSPACE  — DEPRECATED alias. This was the
//      original (client) env prefix; it still works so existing .env files and
//      the test harness keep running, and emits a one-time warning for real
//      (non-temp) data dirs. Remove in a future major.
//   3. $MADARX_HOME/data , $MADARX_HOME/workspace — set by the `madarx` CLI
//      so a global install keeps its data OUTSIDE the package dir (which is
//      wiped and rewritten on every `npm i -g …@latest` upgrade).
//   4. ROOT/data , ROOT/workspace — repo-relative default (git-clone dev mode).
// ---------------------------------------------------------------------------

let _warnedVilla = false;
function warnVillaDeprecation(varName, resolvedPath) {
  if (_warnedVilla) return;
  // Don't nag inside test isolation — the suite points the legacy var at an OS
  // temp dir. Only warn for real, persistent data locations.
  if (resolvedPath.startsWith(os.tmpdir())) return;
  _warnedVilla = true;
  const canonical = varName.replace('VILLA515_', 'MADARX_');
  console.warn(
    `[paths] ${varName} is deprecated — rename it to ${canonical}. ` +
    'The old name still works for now but will be removed in a future release.'
  );
}

function homeDir() {
  return process.env.MADARX_HOME ? path.resolve(process.env.MADARX_HOME) : null;
}

function resolveDir(canonicalEnv, legacyEnv, subdir) {
  if (process.env[canonicalEnv]) return path.resolve(process.env[canonicalEnv]);
  if (process.env[legacyEnv]) {
    const resolved = path.resolve(process.env[legacyEnv]);
    warnVillaDeprecation(legacyEnv, resolved);
    return resolved;
  }
  const home = homeDir();
  if (home) return path.join(home, subdir);
  return path.join(ROOT, subdir);
}

export const DATA_DIR = resolveDir('MADARX_DATA_DIR', 'VILLA515_DATA_DIR', 'data');
export const WORKSPACE = resolveDir('MADARX_WORKSPACE', 'VILLA515_WORKSPACE', 'workspace');

/**
 * True when an explicit data-dir override is set (MADARX_DATA_DIR or the legacy
 * VILLA515_DATA_DIR). The test harness sets one of these to isolate its DB from
 * the real data dir, so several runtime guards use it as the "running under test
 * isolation" signal.
 *
 * NOTE: $MADARX_HOME does NOT count. A real CLI install sets MADARX_HOME and
 * MUST keep its cron/heartbeat daemons and disk-encryption health check running.
 * Only the explicit dir override means "isolated / one-shot".
 */
export function hasExplicitDataDirOverride() {
  return Boolean(process.env.MADARX_DATA_DIR || process.env.VILLA515_DATA_DIR);
}

export const AGENTS_DIR = path.join(WORKSPACE, 'agents');
export const REPORTS_DIR = path.join(WORKSPACE, 'reports');
export const ARTIFACTS_DIR = path.join(WORKSPACE, 'artifacts');
export const BRAND_DIR = path.join(WORKSPACE, 'brand');

export const DB_FILE = path.join(DATA_DIR, 'madarx.sqlite');

export const WHATSAPP_DIR = path.join(DATA_DIR, 'whatsapp');
export const WHATSAPP_SESSION_DIR = path.join(WHATSAPP_DIR, 'session');
export const WHATSAPP_BRIDGE_DIR = path.join(ROOT, 'scripts', 'whatsapp-bridge');

export function ensureDirs() {
  for (const dir of [DATA_DIR, WORKSPACE, AGENTS_DIR, REPORTS_DIR, ARTIFACTS_DIR, BRAND_DIR]) {
    fs.mkdirSync(dir, { recursive: true });
  }
}

export function relToRoot(absPath) {
  return path.relative(ROOT, absPath);
}

/**
 * Resolve a stored artifact/run `path` (produced by relToRoot) back to an
 * absolute path on THIS machine.
 *
 * relToRoot = path.relative(ROOT, abs). ROOT comes from import.meta.url, which
 * Next.js bakes at BUILD time — so in the standalone web bundle ROOT is the CI
 * builder's path (/home/runner/work/...). On a global install the file lives
 * under WORKSPACE ($MADARX_HOME/workspace), OUTSIDE that baked ROOT, so the
 * stored relative path becomes a `../../..` traversal carrying the absolute
 * tail (e.g. `../../../../../Users/x/.madarx/workspace/projects/p/artifacts/f.html`)
 * that resolves to nothing locally. The read side compounded this by resolving
 * against process.cwd() instead of ROOT, doubling the path.
 *
 * Strategy:
 *   1. Absolute → use as-is.
 *   2. Resolve against the runtime ROOT (correct in dev where ROOT == repo).
 *   3. Re-anchor the `workspace/…` or `data/…` tail on the runtime WORKSPACE /
 *      DATA_DIR — recovers rows written with a build-baked ROOT.
 * Returns the best-effort absolute path (caller checks existence).
 */
export function resolveStoredPath(storedPath) {
  if (!storedPath) return null;
  if (path.isAbsolute(storedPath)) return storedPath;
  const viaRoot = path.resolve(ROOT, storedPath);
  if (fs.existsSync(viaRoot)) return viaRoot;
  const norm = storedPath.replace(/\\/g, '/');
  for (const base of [WORKSPACE, DATA_DIR]) {
    const marker = `${path.basename(base)}/`;
    const idx = norm.lastIndexOf(marker);
    if (idx !== -1) {
      const candidate = path.join(base, norm.slice(idx + marker.length));
      if (fs.existsSync(candidate)) return candidate;
    }
  }
  return viaRoot;
}
