/**
 * Baseline manager for config-audit.
 * Stores and retrieves scanner envelopes as named baselines.
 * Zero external dependencies.
 */

import { readFile, writeFile, readdir, unlink, mkdir, stat } from 'node:fs/promises';
import { join } from 'node:path';
import { homedir } from 'node:os';

const BASELINES_DIR = join(homedir(), '.config-audit', 'baselines');

/**
 * Get the baselines directory path.
 * @returns {string}
 */
export function getBaselinesDir() {
  return BASELINES_DIR;
}

/**
 * Save a scanner envelope as a named baseline.
 * @param {object} envelope - Full envelope from scan-orchestrator
 * @param {string} [name='default'] - Baseline name
 * @returns {Promise<{ path: string, name: string }>}
 */
export async function saveBaseline(envelope, name = 'default') {
  await mkdir(BASELINES_DIR, { recursive: true });

  const enriched = {
    ...envelope,
    _baseline: {
      saved_at: new Date().toISOString(),
      target_path: envelope.meta?.target || '',
      finding_count: envelope.aggregate?.total_findings || 0,
      score: avgScore(envelope),
    },
  };

  const filePath = join(BASELINES_DIR, `${name}.json`);
  await writeFile(filePath, JSON.stringify(enriched, null, 2), 'utf-8');

  return { path: filePath, name };
}

/**
 * Load a named baseline.
 * @param {string} [name='default'] - Baseline name
 * @returns {Promise<object|null>} Envelope or null if not found
 */
export async function loadBaseline(name = 'default') {
  const filePath = join(BASELINES_DIR, `${name}.json`);
  try {
    const content = await readFile(filePath, 'utf-8');
    return JSON.parse(content);
  } catch {
    return null;
  }
}

/**
 * List all saved baselines.
 * @returns {Promise<{ baselines: Array<{ name: string, savedAt: string, targetPath: string, findingCount: number, score: number }> }>}
 */
export async function listBaselines() {
  try {
    await stat(BASELINES_DIR);
  } catch {
    return { baselines: [] };
  }

  const entries = await readdir(BASELINES_DIR);
  const baselines = [];

  for (const entry of entries) {
    if (!entry.endsWith('.json')) continue;
    const name = entry.replace(/\.json$/, '');
    const filePath = join(BASELINES_DIR, entry);

    try {
      const content = await readFile(filePath, 'utf-8');
      const data = JSON.parse(content);
      const meta = data._baseline || {};
      baselines.push({
        name,
        savedAt: meta.saved_at || '',
        targetPath: meta.target_path || '',
        findingCount: meta.finding_count || 0,
        score: meta.score || 0,
      });
    } catch {
      // Skip corrupt baselines
      baselines.push({ name, savedAt: '', targetPath: '', findingCount: 0, score: 0 });
    }
  }

  return { baselines };
}

/**
 * Delete a named baseline.
 * @param {string} name - Baseline name
 * @returns {Promise<{ deleted: boolean }>}
 */
export async function deleteBaseline(name) {
  const filePath = join(BASELINES_DIR, `${name}.json`);
  try {
    await unlink(filePath);
    return { deleted: true };
  } catch {
    return { deleted: false };
  }
}

// --- Internal helpers ---

function avgScore(envelope) {
  const scanners = envelope.scanners || [];
  if (scanners.length === 0) return 0;
  // Simple: count findings as proxy for score
  const total = envelope.aggregate?.total_findings || 0;
  // Lower findings = higher score. Cap at 100.
  return Math.max(0, 100 - total * 3);
}
