import fs from 'fs';
import path from 'path';
import { resolveSynapsePaths } from '../db/client.js';
function walk(dir) {
    if (!fs.existsSync(dir))
        return [];
    const entries = fs.readdirSync(dir, { withFileTypes: true });
    const files = [];
    for (const entry of entries) {
        const next = path.join(dir, entry.name);
        if (entry.isDirectory()) {
            files.push(...walk(next));
        }
        else if (entry.isFile() && next.endsWith('.md')) {
            files.push(next);
        }
    }
    return files;
}
function resolveCheckpointPath(root) {
    return path.join(resolveSynapsePaths(root).ledgerDir, '.restore-checkpoint.json');
}
function loadCheckpoint(root) {
    const checkpointPath = resolveCheckpointPath(root);
    if (!fs.existsSync(checkpointPath))
        return null;
    try {
        const parsed = JSON.parse(fs.readFileSync(checkpointPath, 'utf8'));
        if (parsed.version !== 1 || !parsed.files || typeof parsed.files !== 'object')
            return null;
        return {
            version: 1,
            updatedAt: typeof parsed.updatedAt === 'number' ? parsed.updatedAt : 0,
            files: parsed.files,
        };
    }
    catch {
        return null;
    }
}
function writeCheckpoint(root, checkpoint) {
    const checkpointPath = resolveCheckpointPath(root);
    fs.mkdirSync(path.dirname(checkpointPath), { recursive: true });
    fs.writeFileSync(checkpointPath, JSON.stringify(checkpoint, null, 2), 'utf8');
}
export function parseLedgerMarkdown(content) {
    const firstLine = content.split('\n', 1)[0] ?? '';
    const match = firstLine.match(/^<!-- synapse-field-report:(.+) -->$/);
    if (!match)
        return null;
    try {
        return JSON.parse(match[1]);
    }
    catch {
        return null;
    }
}
export function fieldReportExists(db, fieldReportId) {
    return Boolean(db.prepare('SELECT id FROM synapse_field_reports WHERE id=?').get(fieldReportId));
}
export function insertFieldReport(db, report) {
    db.prepare(`
    INSERT INTO synapse_field_reports (
      id, sortie_id, operative_id, strike_team_id, mission_title, findings, files_changed,
      blockers_encountered, next_recommended_action, tokens_used, cost_usd, ledger_path,
      status, completed_at
    ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
  `).run(report.id, report.sortieId, report.operativeId, report.strikeTeamId ?? null, report.missionTitle, report.findings, JSON.stringify(report.filesChanged ?? []), report.blockersEncountered ?? '', report.nextRecommendedAction ?? '', report.tokensUsed ?? 0, report.costUsd ?? 0, report.ledgerPath ?? null, report.status, report.completedAt);
}
export function restoreSynapseFromLedger(db, root) {
    const ledgerDir = resolveSynapsePaths(root).ledgerDir;
    const checkpoint = loadCheckpoint(root);
    const dbCount = db.prepare('SELECT COUNT(*) AS count FROM synapse_field_reports').get();
    const forceFull = (dbCount?.count ?? 0) === 0;
    const files = walk(ledgerDir);
    let restored = 0;
    const nextCheckpoint = {
        version: 1,
        updatedAt: Date.now(),
        files: {},
    };
    for (const filePath of files) {
        const stat = fs.statSync(filePath);
        nextCheckpoint.files[filePath] = { mtimeMs: stat.mtimeMs, size: stat.size };
        if (!forceFull && checkpoint?.files[filePath] && checkpoint.files[filePath].mtimeMs === stat.mtimeMs && checkpoint.files[filePath].size === stat.size) {
            continue;
        }
        const parsed = parseLedgerMarkdown(fs.readFileSync(filePath, 'utf8'));
        if (!parsed || fieldReportExists(db, parsed.id))
            continue;
        insertFieldReport(db, parsed);
        restored += 1;
    }
    if (files.length > 0) {
        writeCheckpoint(root, nextCheckpoint);
    }
    return restored;
}
