import { existsSync, readFileSync, writeFileSync } from 'node:fs';
import { execSync } from 'node:child_process';
import { ENV_FILE, getDaemonPid, readMeta, META_FILE, ensureDirs } from './daemon.js';

// Keys that should be masked in output
const SECRET_KEYS = new Set([
  'BETTER_AUTH_SECRET',
  'ANTHROPIC_API_KEY',
  'OPENAI_API_KEY',
  'ZAI_API_KEY',
  'OPENROUTER_API_KEY',
  'DISCORD_BOT_TOKEN',
  'TELEGRAM_BOT_TOKEN',
]);

function maskValue(key: string, value: string): string {
  if (SECRET_KEYS.has(key) && value.length > 8) {
    return value.slice(0, 4) + '…' + value.slice(-4);
  }
  return value;
}

function parseEnvFile(): Map<string, string> {
  const map = new Map<string, string>();
  if (!existsSync(ENV_FILE)) return map;

  const lines = readFileSync(ENV_FILE, 'utf-8').split('\n');
  for (const line of lines) {
    const trimmed = line.trim();
    if (!trimmed || trimmed.startsWith('#')) continue;
    const eqIdx = trimmed.indexOf('=');
    if (eqIdx === -1) continue;
    map.set(trimmed.slice(0, eqIdx), trimmed.slice(eqIdx + 1));
  }
  return map;
}

function writeEnvFile(entries: Map<string, string>): void {
  ensureDirs();
  const lines: string[] = [];
  for (const [key, value] of entries) {
    lines.push(`${key}=${value}`);
  }
  writeFileSync(ENV_FILE, lines.join('\n') + '\n', { mode: 0o600 });
}

interface ConfigOpts {
  set?: string;
  unset?: string;
  edit?: boolean;
}

export async function runConfig(opts: ConfigOpts): Promise<void> {
  // Set a value
  if (opts.set) {
    const eqIdx = opts.set.indexOf('=');
    if (eqIdx === -1) {
      console.error('Usage: mosaic gateway config --set KEY=VALUE');
      process.exit(1);
    }
    const key = opts.set.slice(0, eqIdx);
    const value = opts.set.slice(eqIdx + 1);
    const entries = parseEnvFile();
    entries.set(key, value);
    writeEnvFile(entries);
    console.log(`Set ${key}=${maskValue(key, value)}`);
    promptRestart();
    return;
  }

  // Unset a value
  if (opts.unset) {
    const entries = parseEnvFile();
    if (!entries.has(opts.unset)) {
      console.error(`Key not found: ${opts.unset}`);
      process.exit(1);
    }
    entries.delete(opts.unset);
    writeEnvFile(entries);
    console.log(`Removed ${opts.unset}`);
    promptRestart();
    return;
  }

  // Open in editor
  if (opts.edit) {
    if (!existsSync(ENV_FILE)) {
      console.error(`No config file found at ${ENV_FILE}`);
      console.error('Run `mosaic gateway install` first.');
      process.exit(1);
    }
    const editor = process.env['EDITOR'] ?? process.env['VISUAL'] ?? 'vi';
    try {
      execSync(`${editor} "${ENV_FILE}"`, { stdio: 'inherit' });
      promptRestart();
    } catch {
      console.error('Editor exited with error.');
    }
    return;
  }

  // Default: show current config
  showConfig();
}

function showConfig(): void {
  if (!existsSync(ENV_FILE)) {
    console.log('No gateway configuration found.');
    console.log('Run `mosaic gateway install` to set up.');
    return;
  }

  const entries = parseEnvFile();
  const meta = readMeta();

  console.log('Mosaic Gateway Configuration');
  console.log('────────────────────────────');
  console.log(`  Config file: ${ENV_FILE}`);
  console.log(`  Meta file:   ${META_FILE}`);
  console.log();

  if (entries.size === 0) {
    console.log('  (empty)');
    return;
  }

  const maxKeyLen = Math.max(...[...entries.keys()].map((k) => k.length));
  for (const [key, value] of entries) {
    const padding = ' '.repeat(maxKeyLen - key.length);
    console.log(`  ${key}${padding}  ${maskValue(key, value)}`);
  }

  if (meta?.adminToken) {
    console.log();
    console.log(`  Admin token: ${maskValue('token', meta.adminToken)}`);
  }
}

function promptRestart(): void {
  if (getDaemonPid() !== null) {
    console.log('\nGateway is running — restart to apply changes: mosaic gateway restart');
  }
}
