/**
 * Local config env-file manager.
 *
 * Handles NON-CREDENTIAL local configuration only — tool behavior settings,
 * daemon tuning, file-access limits, etc.
 *
 * Integration credentials (Supabase keys, Vercel tokens, Firecrawl / Brave API
 * keys) are stored in the encrypted secrets vault (lib/secrets.js). Use the
 * secrets vault API (/api/secrets) or the migration script
 * (scripts/migrate-env-to-secrets.mjs) to manage those.
 */

import fs from 'node:fs';
import path from 'node:path';

export const ENV_DEFINITIONS = [
  // --- Web tool provider config ---
  // Note: FIRECRAWL_API_KEY, FIRECRAWL_API_URL, SEARXNG_URL, and
  // BRAVE_SEARCH_API_KEY are integration credentials — they now live in the
  // secrets vault, not here.
  { name: 'MADARX_WEB_PROVIDER', label: 'Web Provider Override', group: 'Web', description: 'Force a specific search provider: firecrawl, searxng, brave, or fetch.' },

  // --- File tool config ---
  { name: 'MADARX_ALLOWED_ROOTS', label: 'Allowed File Roots', group: 'Local Tools', description: 'Colon-separated absolute paths the file adapter may read/write.' },
  { name: 'MADARX_FILE_READ_MAX_BYTES', label: 'Max File Read Bytes', group: 'Local Tools', description: 'Maximum bytes returned by a single file_read call (default: 1MB).' },

  // --- Daemon / heartbeat tuning ---
  { name: 'CRON_DAEMON_INTERVAL_MS', label: 'Cron Daemon Interval (ms)', group: 'Daemons', description: 'How often the cron daemon checks for due schedules (default: 30000).' },
  { name: 'HEARTBEAT_WORKER_ONCE', label: 'Heartbeat One-Shot Mode', group: 'Daemons', description: 'Set to 1 to run one heartbeat worker pass then exit (for testing).' },
  { name: 'CLAUDE_CODE_TICK_TIMEOUT_MS', label: 'Claude Code Tick Timeout (ms)', group: 'Daemons', description: 'Max ms for a single claude-code agent tick (default: 600000).' },
  { name: 'CLAUDE_CODE_MAX_TURNS', label: 'Claude Code Max Turns', group: 'Daemons', description: 'Max conversation turns for a claude-code agent run (default: 30).' },
];

const ALLOWED_ENV = new Set(ENV_DEFINITIONS.map(item => item.name));

function envFilePath() {
  return process.env.MADARX_ENV_FILE || path.join(process.cwd(), '.env.local');
}

function readEnvFile(file = envFilePath()) {
  try {
    return fs.readFileSync(file, 'utf8');
  } catch (err) {
    if (err.code === 'ENOENT') return '';
    throw err;
  }
}

function parseEnvContent(content) {
  const values = {};
  for (const line of String(content || '').split(/\r?\n/)) {
    const match = line.match(/^\s*([A-Za-z_][A-Za-z0-9_]*)\s*=\s*(.*)\s*$/);
    if (!match) continue;
    let value = match[2] || '';
    if ((value.startsWith('"') && value.endsWith('"')) || (value.startsWith("'") && value.endsWith("'"))) {
      value = value.slice(1, -1);
    }
    values[match[1]] = value;
  }
  return values;
}

function formatEnvValue(value) {
  const text = String(value || '');
  if (/^[A-Za-z0-9_./:@+\-]*$/.test(text)) return text;
  return JSON.stringify(text);
}

export function getEnvStatus() {
  const fileValues = parseEnvContent(readEnvFile());
  return ENV_DEFINITIONS.map(def => ({
    ...def,
    configured: Boolean(process.env[def.name] || fileValues[def.name]),
  }));
}

export function upsertEnvValues(values = {}) {
  const updates = Object.entries(values)
    .filter(([name, value]) => ALLOWED_ENV.has(name) && String(value || '').trim());
  if (!updates.length) return getEnvStatus();

  const file = envFilePath();
  const existing = readEnvFile(file);
  const lines = existing ? existing.split(/\r?\n/) : [];
  const seen = new Set();
  const next = lines.map(line => {
    const match = line.match(/^(\s*)([A-Za-z_][A-Za-z0-9_]*)(\s*=).*/);
    if (!match) return line;
    const name = match[2];
    const update = updates.find(([key]) => key === name);
    if (!update) return line;
    seen.add(name);
    return `${name}=${formatEnvValue(update[1])}`;
  });

  for (const [name, value] of updates) {
    if (!seen.has(name)) next.push(`${name}=${formatEnvValue(value)}`);
    process.env[name] = String(value);
  }

  fs.mkdirSync(path.dirname(file), { recursive: true });
  fs.writeFileSync(file, `${next.filter((line, idx) => line || idx < next.length - 1).join('\n')}\n`, { mode: 0o600 });
  try { fs.chmodSync(file, 0o600); } catch {}
  return getEnvStatus();
}
