/**
 * Watch mode for audit — re-runs audit at interval, shows only changes.
 * Bridge to future guard command.
 */
import { runAudit } from "./index.js";
import { saveAuditHistory } from "./history.js";
import { extractReason } from "../../utils/errors.js";
/** Default interval in seconds (5 minutes) */
const DEFAULT_INTERVAL = 300;
/**
 * Watch mode: run audit periodically, show full output on first run,
 * then only score deltas on subsequent runs.
 */
export async function watchAudit(ip, serverName, platform, options) {
    const interval = (options.interval ?? DEFAULT_INTERVAL) * 1000;
    const log = options.output ?? console.log;
    let previousScore;
    let previousFailedIds = new Set();
    let timer;
    const runOnce = async () => {
        const result = await runAudit(ip, serverName, platform);
        if (!result.success || !result.data) {
            const timestamp = new Date().toLocaleTimeString("en-GB");
            log(`[${timestamp}] Audit failed: ${result.error ?? "Unknown error"}`);
            return;
        }
        const auditResult = result.data;
        // Save to history
        await saveAuditHistory(auditResult);
        if (previousScore === undefined) {
            // First run: full output + populate previousFailedIds for correct delta on next run
            log(options.formatter(auditResult));
            for (const cat of auditResult.categories) {
                for (const check of cat.checks) {
                    if (!check.passed) {
                        previousFailedIds.add(check.id);
                    }
                }
            }
        }
        else {
            // Subsequent runs: delta only
            const diff = auditResult.overallScore - previousScore;
            const diffStr = diff > 0 ? `+${diff}` : diff < 0 ? `${diff}` : "unchanged";
            const timestamp = new Date().toLocaleTimeString("en-GB");
            // Find new failures
            const currentFailedIds = new Set();
            for (const cat of auditResult.categories) {
                for (const check of cat.checks) {
                    if (!check.passed) {
                        currentFailedIds.add(check.id);
                    }
                }
            }
            const newFailures = [];
            for (const id of currentFailedIds) {
                if (!previousFailedIds.has(id)) {
                    // Find severity
                    let severity = "";
                    for (const cat of auditResult.categories) {
                        const check = cat.checks.find((c) => c.id === id);
                        if (check) {
                            severity = ` (${check.severity})`;
                            break;
                        }
                    }
                    newFailures.push(`${id}${severity}`);
                }
            }
            const issueStr = newFailures.length > 0
                ? `New issues: ${newFailures.join(", ")}`
                : "New issues: 0";
            log(`[${timestamp}] Score: ${auditResult.overallScore}/100 (${diffStr}) | ${issueStr}`);
            previousFailedIds = currentFailedIds;
        }
        previousScore = auditResult.overallScore;
    };
    return new Promise((resolve) => {
        const cleanup = () => {
            if (timer !== undefined) {
                clearInterval(timer);
                timer = undefined;
            }
            process.removeListener("SIGINT", onSigint);
            resolve();
        };
        const onSigint = () => {
            log("\nWatch mode stopped.");
            cleanup();
        };
        process.on("SIGINT", onSigint);
        // Run immediately
        let consecutiveFailures = 0;
        const MAX_CONSECUTIVE_FAILURES = 3;
        runOnce().then(() => {
            timer = setInterval(() => {
                runOnce()
                    .then(() => {
                    consecutiveFailures = 0;
                })
                    .catch((err) => {
                    consecutiveFailures++;
                    log(`[Error] Watch audit failed: ${extractReason(err)}`);
                    if (consecutiveFailures >= MAX_CONSECUTIVE_FAILURES) {
                        log(`[Error] ${MAX_CONSECUTIVE_FAILURES} consecutive failures — stopping watch mode.`);
                        cleanup();
                    }
                });
            }, interval);
        }).catch((err) => {
            log(`[Error] Initial audit failed: ${extractReason(err)}`);
            cleanup();
        });
    });
}
//# sourceMappingURL=watch.js.map