import { existsSync, readFileSync } from 'node:fs';
import { HeddleEventType } from '../../../../core/event-types.js';
import { ReviewDiffParser } from '../../../../core/review/index.js';
import { normalizeCommandText, readBoolean, readNumber, readObject, readString, } from '../../../../server/helpers/control-plane-read-values.js';
export class ControlPlaneChatTurnReviewPresenter {
    static load(traceFile) {
        if (!traceFile || !existsSync(traceFile)) {
            return undefined;
        }
        try {
            const parsed = JSON.parse(readFileSync(traceFile, 'utf8'));
            if (!Array.isArray(parsed)) {
                return undefined;
            }
            const reviewCommands = [];
            const verificationCommands = [];
            const mutationCommands = [];
            const approvals = [];
            const files = new Map();
            let diffExcerpt;
            let finalSummary;
            for (const entry of parsed) {
                const event = readObject(entry);
                const type = readString(event?.type);
                if (!event || !type) {
                    continue;
                }
                if (type === HeddleEventType.toolCompleted) {
                    const call = readObject(event.call);
                    const tool = readString(call?.tool) ?? 'unknown';
                    const result = readObject(event.result);
                    if (tool === 'edit_file' && readBoolean(result?.ok) === true) {
                        const output = readObject(result?.output);
                        const file = ControlPlaneChatTurnReviewPresenter.projectEditFileReview(output);
                        if (file) {
                            ControlPlaneChatTurnReviewPresenter.addChangedFile(files, file);
                        }
                    }
                    const output = readObject(result?.output);
                    const evidence = output ? ControlPlaneChatTurnReviewPresenter.projectCommandEvidence(tool, output) : undefined;
                    if (!evidence) {
                        continue;
                    }
                    if (ControlPlaneChatTurnReviewPresenter.isReviewCommand(evidence.command)) {
                        reviewCommands.push(evidence);
                        if (!diffExcerpt && /^git diff(?:\s|$)/.test(evidence.command) && evidence.stdout) {
                            diffExcerpt = evidence.stdout;
                        }
                        if (/^git diff(?:\s|$)/.test(evidence.command) && evidence.stdout) {
                            for (const file of ControlPlaneChatTurnReviewPresenter.parseGitDiffFiles(evidence.stdout)) {
                                ControlPlaneChatTurnReviewPresenter.addChangedFile(files, file);
                            }
                        }
                        continue;
                    }
                    if (ControlPlaneChatTurnReviewPresenter.isVerificationCommand(evidence.command)) {
                        verificationCommands.push(evidence);
                        continue;
                    }
                    if (tool === 'run_shell_mutate') {
                        mutationCommands.push(evidence);
                    }
                    continue;
                }
                if (type === HeddleEventType.toolCalling) {
                    const call = readObject(event.call);
                    const tool = readString(call?.tool);
                    if (tool !== 'edit_file') {
                        continue;
                    }
                    const input = readObject(call?.input);
                    const path = readString(input?.path);
                    mutationCommands.push({
                        tool,
                        command: path ? `edit_file ${path}` : 'edit_file',
                    });
                    continue;
                }
                if (type === HeddleEventType.toolApprovalResolved) {
                    const call = readObject(event.call);
                    const tool = readString(call?.tool);
                    if (!tool) {
                        continue;
                    }
                    const input = readObject(call?.input);
                    approvals.push({
                        tool,
                        command: readString(input?.command) ?? readString(input?.path),
                        approved: readBoolean(event.approved) ?? false,
                        reason: readString(event.reason),
                        timestamp: readString(event.timestamp),
                    });
                    continue;
                }
                if (type === HeddleEventType.runFinished) {
                    finalSummary = readString(event.summary) ?? finalSummary;
                }
            }
            return {
                traceFile,
                diffExcerpt,
                finalSummary,
                files: [...files.values()],
                reviewCommands: ControlPlaneChatTurnReviewPresenter.dedupeEvidence(reviewCommands),
                verificationCommands: ControlPlaneChatTurnReviewPresenter.dedupeEvidence(verificationCommands),
                mutationCommands: ControlPlaneChatTurnReviewPresenter.dedupeEvidence(mutationCommands),
                approvals,
            };
        }
        catch {
            return undefined;
        }
    }
    static projectCommandEvidence(tool, output) {
        const command = readString(output.command);
        if (!command) {
            return undefined;
        }
        return {
            tool,
            command,
            exitCode: readNumber(output.exitCode),
            stdout: normalizeCommandText(readString(output.stdout)),
            stderr: normalizeCommandText(readString(output.stderr)),
        };
    }
    static dedupeEvidence(evidence) {
        const seen = new Set();
        return evidence.filter((entry) => {
            const key = `${entry.tool}:${entry.command}`;
            if (seen.has(key)) {
                return false;
            }
            seen.add(key);
            return true;
        });
    }
    static isReviewCommand(command) {
        return /^git (?:status\b|diff\b|show\b|branch\b|remote\b)/.test(command);
    }
    static isVerificationCommand(command) {
        return /^(?:yarn|npm|pnpm|bun|vitest|jest|tsx|tsc|go test|cargo test|pytest|ruff|eslint)\b/.test(command);
    }
    static projectEditFileReview(output) {
        if (!output) {
            return undefined;
        }
        const path = readString(output.path);
        const diff = readObject(output.diff);
        const patch = normalizeCommandText(readString(diff?.diff));
        if (!path) {
            return undefined;
        }
        return {
            path,
            status: ControlPlaneChatTurnReviewPresenter.statusFromEditAction(readString(output.action)),
            source: 'edit_file',
            patch,
            diff: patch ? ReviewDiffParser.parseUnifiedDiffFiles(patch).find((file) => file.path === path || file.oldPath === path) : undefined,
            truncated: readBoolean(diff?.truncated),
        };
    }
    static statusFromEditAction(action) {
        switch (action) {
            case 'created':
                return 'added';
            case 'overwritten':
            case 'replaced':
                return 'modified';
            default:
                return 'unknown';
        }
    }
    static parseGitDiffFiles(diff) {
        return ReviewDiffParser.parseUnifiedDiffFiles(diff).map((file) => ({
            path: file.path,
            status: file.status === 'copied' ? 'modified' : file.status,
            source: 'git_diff',
            patch: normalizeCommandText(file.patch),
            diff: file,
            truncated: file.binary === true,
        }));
    }
    static addChangedFile(files, file) {
        const existing = files.get(file.path);
        if (!existing) {
            files.set(file.path, file);
            return;
        }
        if (existing.source === 'edit_file') {
            return;
        }
        if (file.source === 'edit_file' || (!existing.patch && file.patch)) {
            files.set(file.path, file);
        }
    }
}
//# sourceMappingURL=chat-turn-review-presenter.js.map