import { parseArgs } from 'node:util';
import { join } from 'node:path';
import { homedir } from 'node:os';
import { chmodSync, mkdirSync } from 'node:fs';

export interface Config {
  port: number;
  bind: string;
  dbPath: string;
  dataDir: string;
  /** origins supplémentaires autorisées (ex. https://machine.tailnet.ts.net) */
  allowedOrigins: string[];
  printToken: boolean;
  /** ~/.claude/projects (transcripts JSONL) — surchargeable via --claude-home (tests). */
  claudeProjectsDir: string;
  /** ~/.claude/sessions (registre des sessions CLI vivantes). */
  claudeSessionsDir: string;
  /** sujet VAPID des notifications Web Push (mailto: ou URL). */
  vapidContact: string;
  /** découverte auto des repos au démarrage + périodique (désactivable via --no-discover). */
  autoDiscover: boolean;
}

export function loadConfig(argv = process.argv.slice(2)): Config {
  const { values } = parseArgs({
    args: argv,
    options: {
      port: { type: 'string', default: '7317' },
      bind: { type: 'string', default: '127.0.0.1' },
      db: { type: 'string' },
      'allow-origin': { type: 'string', multiple: true },
      'print-token': { type: 'boolean', default: false },
      'i-know-this-exposes-a-terminal': { type: 'boolean', default: false },
      // racine de l'install Claude (~/.claude par défaut) — surchargée par les tests d'acceptation.
      'claude-home': { type: 'string' },
      // sujet VAPID des notifications push (contact requis par la spec Web Push).
      'vapid-contact': { type: 'string' },
      // désactive la découverte auto des repos (boot + périodique) — utilisé par les tests d'acceptation.
      'no-discover': { type: 'boolean', default: false },
    },
    strict: true,
  });

  const bind = values.bind ?? '127.0.0.1';
  const loopback = bind === '127.0.0.1' || bind === '::1' || bind === 'localhost';
  if (!loopback && !values['i-know-this-exposes-a-terminal']) {
    throw new Error(
      `Refusing to bind to ${bind}: an Arboretum server is remote code execution by design.\n` +
        `Use Tailscale Serve against the default 127.0.0.1 bind (recommended), or pass\n` +
        `--i-know-this-exposes-a-terminal if you really know what you are doing.`,
    );
  }

  const dataDir = join(process.env.XDG_DATA_HOME ?? join(homedir(), '.local', 'share'), 'arboretum');
  mkdirSync(dataDir, { recursive: true });
  // La DB contient des secrets (server_secret, clé privée VAPID, hashs de tokens) : le dossier de
  // données ne doit jamais être lisible par d'autres utilisateurs du système. chmod best-effort
  // (peut échouer sur certains FS Windows/montés ; le démarrage avertit alors sans bloquer).
  try {
    chmodSync(dataDir, 0o700);
  } catch {
    /* FS sans permissions POSIX : ignoré, cf. avertissement dans db.openDb */
  }
  const claudeHome = values['claude-home'] ?? join(homedir(), '.claude');
  return {
    port: Number(values.port),
    bind,
    dbPath: values.db ?? join(dataDir, 'arboretum.db'),
    dataDir,
    allowedOrigins: values['allow-origin'] ?? [],
    printToken: values['print-token'] ?? false,
    claudeProjectsDir: join(claudeHome, 'projects'),
    claudeSessionsDir: join(claudeHome, 'sessions'),
    vapidContact: values['vapid-contact'] ?? 'mailto:arboretum@localhost',
    autoDiscover: !(values['no-discover'] ?? false),
  };
}
