"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    var desc = Object.getOwnPropertyDescriptor(m, k);
    if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
      desc = { enumerable: true, get: function() { return m[k]; } };
    }
    Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
    Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
    o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
    var ownKeys = function(o) {
        ownKeys = Object.getOwnPropertyNames || function (o) {
            var ar = [];
            for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
            return ar;
        };
        return ownKeys(o);
    };
    return function (mod) {
        if (mod && mod.__esModule) return mod;
        var result = {};
        if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
        __setModuleDefault(result, mod);
        return result;
    };
})();
Object.defineProperty(exports, "__esModule", { value: true });
exports.renderArchitecturePrCommentMarkdown = renderArchitecturePrCommentMarkdown;
exports.writeArchitecturePrCommentMarkdown = writeArchitecturePrCommentMarkdown;
const path = __importStar(require("node:path"));
const node_fs_1 = require("node:fs");
const architectureHealthHistoryReporter_1 = require("./architectureHealthHistoryReporter");
const architectureReviewReporter_1 = require("./architectureReviewReporter");
const architectureValidation_1 = require("../architectureValidation");
function sortUniqueLines(values) {
    return [...new Set(values)].sort((left, right) => left.localeCompare(right));
}
function formatRuleLine(ruleId) {
    const metadata = (0, architectureValidation_1.getValidationRuleMetadataById)(ruleId);
    return `${ruleId} ${metadata.title}`;
}
function formatFindingLine(finding) {
    return `${formatRuleLine(finding.id)} | ${finding.message}`;
}
function parseFindingKind(value) {
    return value === 'violation' || value === 'setup-gap' || value === 'guidance'
        ? value
        : undefined;
}
function readFindingKind(value) {
    if (!value || typeof value !== 'object') {
        return undefined;
    }
    const typed = value;
    return (parseFindingKind(typed.kind) ??
        parseFindingKind(typed.classification) ??
        parseFindingKind(typed.type));
}
function renderArchitecturePrCommentMarkdown(input) {
    const lines = [];
    const findingKindByRuleAndMessage = new Map();
    const findingKindByRule = new Map();
    for (const finding of input.summary.findings) {
        const kind = readFindingKind(finding);
        if (!kind) {
            continue;
        }
        const byRule = findingKindByRule.get(finding.id) ?? new Set();
        byRule.add(kind);
        findingKindByRule.set(finding.id, byRule);
        findingKindByRuleAndMessage.set(`${finding.id}::${finding.message}`, kind);
    }
    const resolveKind = (entry) => {
        const explicit = readFindingKind(entry);
        if (explicit) {
            return explicit;
        }
        if (entry.message) {
            const matched = findingKindByRuleAndMessage.get(`${entry.ruleId}::${entry.message}`);
            if (matched) {
                return matched;
            }
        }
        const byRule = findingKindByRule.get(entry.ruleId);
        if (byRule && byRule.size === 1) {
            return [...byRule][0];
        }
        return 'violation';
    };
    const newQualityViolationLines = sortUniqueLines((input.driftComparison?.newViolations ?? [])
        .filter((entry) => resolveKind(entry) === 'violation')
        .map((entry) => formatRuleLine(entry.ruleId)));
    const newSetupGapLines = sortUniqueLines((input.driftComparison?.newViolations ?? [])
        .filter((entry) => resolveKind(entry) === 'setup-gap')
        .map((entry) => formatRuleLine(entry.ruleId)));
    const newGuidanceLines = sortUniqueLines((input.driftComparison?.newViolations ?? [])
        .filter((entry) => resolveKind(entry) === 'guidance')
        .map((entry) => formatRuleLine(entry.ruleId)));
    const resolvedViolationLines = sortUniqueLines((input.driftComparison?.resolvedViolations ?? [])
        .filter((entry) => resolveKind(entry) === 'violation')
        .map((entry) => formatRuleLine(entry.ruleId)));
    const resolvedSetupGapLines = sortUniqueLines((input.driftComparison?.resolvedViolations ?? [])
        .filter((entry) => resolveKind(entry) === 'setup-gap')
        .map((entry) => formatRuleLine(entry.ruleId)));
    const activeQualityViolationLines = sortUniqueLines(input.summary.findings
        .filter((entry) => resolveKind({ ruleId: entry.id, message: entry.message }) === 'violation')
        .map((entry) => formatFindingLine(entry)));
    const activeSetupGapLines = sortUniqueLines(input.summary.findings
        .filter((entry) => resolveKind({ ruleId: entry.id, message: entry.message }) === 'setup-gap')
        .map((entry) => formatFindingLine(entry)));
    const activeGuidanceLines = sortUniqueLines(input.summary.findings
        .filter((entry) => resolveKind({ ruleId: entry.id, message: entry.message }) === 'guidance')
        .map((entry) => formatFindingLine(entry)));
    const activeQualityViolationCount = activeQualityViolationLines.length;
    const activeSetupGapCount = activeSetupGapLines.length;
    const activeGuidanceCount = activeGuidanceLines.length;
    const summaryWithReadiness = input.summary;
    const trendLine = input.healthTrend
        ? (0, architectureHealthHistoryReporter_1.formatArchitectureHealthTrendLine)(input.healthTrend)
        : 'Trend: no previous history';
    const scoreDelta = input.driftComparison?.scoreDelta ?? 0;
    const isScoreDrop = !!input.driftComparison?.hasPreviousSnapshot && scoreDelta < 0;
    const hasViolations = activeQualityViolationCount > 0;
    const hasSetupGaps = activeSetupGapCount > 0;
    const hasGuidance = activeGuidanceCount > 0;
    const elevatedChangeRisk = input.summary.changeRisk.riskLevel !== 'low';
    const useDetailed = hasViolations || hasSetupGaps || hasGuidance || elevatedChangeRisk || isScoreDrop;
    const changedModulesCount = input.summary.changeRisk.signals.changedModulesCount;
    const affectedDependentsCount = input.summary.changeRisk.signals.affectedDependentsCount;
    const changeRiskSummary = changedModulesCount !== undefined || affectedDependentsCount !== undefined
        ? `${input.summary.changeRisk.riskLevel.toUpperCase()} (modules: ${changedModulesCount ?? 0}, dependents: ${affectedDependentsCount ?? 0})`
        : input.summary.changeRisk.riskLevel.toUpperCase();
    if (!useDetailed) {
        lines.push(`\u2705 ArchPilot: Score ${input.summary.healthScore}/100 · Risk ${input.summary.changeRisk.riskLevel.toUpperCase()} · No violations`);
        lines.push('');
        lines.push('<details>');
        lines.push('<summary>Architecture details</summary>');
        lines.push('');
        lines.push(`Architecture Health Score: ${input.summary.healthScore}`);
        lines.push(`Setup Readiness: ${summaryWithReadiness.readinessScore ?? 100}`);
        lines.push(`Change Risk: ${input.summary.changeRisk.riskLevel.toUpperCase()}`);
        lines.push('Findings: 0 violations, 0 setup gaps');
        lines.push(trendLine);
        lines.push('</details>');
        lines.push('');
        return `${lines.join('\n')}\n`;
    }
    lines.push('ArchPilot Review');
    lines.push(`Score: ${input.summary.healthScore} / 100`);
    lines.push(`Change Risk: ${input.summary.changeRisk.riskLevel.toUpperCase()}`);
    lines.push(`Violations: ${activeQualityViolationCount}`);
    lines.push(`Setup Gaps: ${activeSetupGapCount}`);
    lines.push('');
    lines.push(`Change Risk (Diff-Aware PR Impact): ${changeRiskSummary}`);
    lines.push(`Change Risk Summary: ${input.summary.changeRisk.summary}`);
    for (const reason of input.summary.changeRisk.reasons) {
        lines.push(`- ${reason}`);
    }
    if (input.summary.changeRisk.changedModules.length > 0) {
        lines.push(`- Changed modules: ${input.summary.changeRisk.changedModules.join(', ')}`);
    }
    if (input.summary.changeRisk.directlyAffectedModules.length > 0) {
        lines.push(`- Directly affected modules: ${input.summary.changeRisk.directlyAffectedModules.join(', ')}`);
    }
    if (input.summary.changeRisk.transitivelyAffectedModules.length > 0) {
        lines.push(`- Transitively affected modules: ${input.summary.changeRisk.transitivelyAffectedModules.join(', ')}`);
    }
    lines.push('');
    lines.push(`Architecture Review Level: ${input.summary.risk.level.toUpperCase()}`);
    for (const reason of input.summary.risk.reasons) {
        lines.push(`- ${reason}`);
    }
    lines.push('');
    lines.push(`Enforcement (Policy Outcome): ${input.summary.enforcement.action.toUpperCase()}`);
    if (input.summary.enforcement.policyLevel) {
        lines.push(`- Policy level: ${input.summary.enforcement.policyLevel.toUpperCase()}`);
    }
    if (input.summary.enforcement.enforcementDecision) {
        lines.push(`- Enforcement decision: ${input.summary.enforcement.enforcementDecision}`);
    }
    if (input.summary.enforcement.matchedThreshold) {
        lines.push(`- Matched threshold: ${input.summary.enforcement.matchedThreshold.id ?? '(unknown)'} (configured=${input.summary.enforcement.matchedThreshold.configuredValue ?? 'n/a'}, matched=${input.summary.enforcement.matchedThreshold.matchedValue ?? 'n/a'}, source=${input.summary.enforcement.matchedThreshold.source ?? input.summary.enforcement.thresholdSource ?? 'n/a'})`);
    }
    if (input.summary.enforcement.baselineContribution) {
        lines.push(`- Baseline contribution: ${input.summary.enforcement.baselineContribution.elevated
            ? 'ELEVATED'
            : 'NOT_ELEVATED'} (${input.summary.enforcement.baselineContribution.reason ?? 'n/a'})`);
    }
    if (input.summary.enforcement.ciExitBehavior) {
        lines.push(`- CI exit behavior: exitCode=${input.summary.enforcement.ciExitBehavior.exitCode}, blocking=${input.summary.enforcement.ciExitBehavior.blocking ? 'yes' : 'no'}`);
    }
    for (const reason of input.summary.enforcement.reasons) {
        lines.push(`- ${reason}`);
    }
    if ((input.summary.enforcement.requiredActions?.length ?? 0) > 0) {
        lines.push('Required actions:');
        for (const action of input.summary.enforcement.requiredActions ?? []) {
            lines.push(`- ${action}`);
        }
    }
    lines.push('');
    lines.push('ADR Requirement');
    const adrDisplay = (0, architectureReviewReporter_1.resolveAdrRequirementDisplay)({
        enforcementAction: input.summary.enforcement.action,
        adrRequirement: input.summary.adrRequirement,
        findings: input.summary.findings,
    });
    lines.push(`- Required: ${adrDisplay.requiredLabel}`);
    lines.push(`- Satisfied: ${adrDisplay.satisfiedLabel}`);
    lines.push('- Reasons:');
    lines.push(adrDisplay.reasons.length === 0
        ? '  - (none)'
        : adrDisplay.reasons.map((reason) => `  - ${reason}`).join('\n'));
    if (adrDisplay.state === 'required' && input.summary.adrRequirement.suggestedCommand) {
        lines.push('- Suggested command:');
        lines.push(`  - ${input.summary.adrRequirement.suggestedCommand}`);
    }
    if (adrDisplay.state === 'required' &&
        input.summary.adrRequirement.suggestedFilenameHint) {
        lines.push('- Suggested filename hint:');
        lines.push(`  - ${input.summary.adrRequirement.suggestedFilenameHint}`);
    }
    if (input.summary.safetyControls?.triggered &&
        (input.summary.safetyControls.findings.length ?? 0) > 0) {
        lines.push('');
        lines.push('Recommended Deployment Safety Controls');
        lines.push(`- ${input.summary.safetyControls.summary}`);
        for (const finding of input.summary.safetyControls.findings) {
            lines.push(`- [${finding.ruleId}] ${finding.message}${finding.evidencePath ? ` (${finding.evidencePath})` : ''}`);
        }
    }
    lines.push('');
    lines.push(`Architecture Score: ${input.summary.healthScore} / 100`);
    if (typeof summaryWithReadiness.readinessScore === 'number') {
        lines.push(`Setup Readiness: ${summaryWithReadiness.readinessScore} / 100`);
    }
    if (typeof summaryWithReadiness.setupGaps === 'number') {
        lines.push(`Setup gaps: ${activeSetupGapCount}`);
    }
    lines.push(trendLine);
    if (input.driftComparison?.hasPreviousSnapshot) {
        lines.push(`Previous score: ${input.driftComparison.previousScore ?? 'n/a'}${input.driftComparison.scoreDelta !== undefined ? ` (${input.driftComparison.scoreDelta >= 0 ? '+' : ''}${input.driftComparison.scoreDelta})` : ''}`);
    }
    lines.push('');
    lines.push(`New quality violations: ${newQualityViolationLines.length}`);
    lines.push(`New setup gaps: ${newSetupGapLines.length}`);
    lines.push(`New guidance findings: ${newGuidanceLines.length}`);
    lines.push(`Resolved violations: ${resolvedViolationLines.length}`);
    if (resolvedSetupGapLines.length > 0) {
        lines.push(`Resolved setup gaps: ${resolvedSetupGapLines.length}`);
    }
    lines.push('');
    lines.push('<details>');
    lines.push(`<summary>Change Risk Factors (${input.summary.changeRisk.factors.length})</summary>`);
    lines.push('');
    lines.push(input.summary.changeRisk.factors.length === 0
        ? '- (none)'
        : input.summary.changeRisk.factors
            .map((factor) => `- ${factor.id} ${factor.label} (${factor.category}, weight=${factor.weight}) | ${factor.evidence}`)
            .join('\n'));
    lines.push('</details>');
    lines.push('');
    lines.push('<details>');
    lines.push(`<summary>Violations (${activeQualityViolationCount})</summary>`);
    lines.push('');
    lines.push(activeQualityViolationLines.length === 0
        ? '- (none)'
        : activeQualityViolationLines.map((line) => `- ${line}`).join('\n'));
    lines.push('</details>');
    lines.push('');
    lines.push('<details>');
    lines.push(`<summary>Setup Gaps (${activeSetupGapCount})</summary>`);
    lines.push('');
    lines.push(activeSetupGapLines.length === 0
        ? '- (none)'
        : activeSetupGapLines.map((line) => `- ${line}`).join('\n'));
    lines.push('</details>');
    lines.push('');
    lines.push('<details>');
    lines.push(`<summary>Guidance (${activeGuidanceCount})</summary>`);
    lines.push('');
    lines.push(activeGuidanceLines.length === 0
        ? '- (none)'
        : activeGuidanceLines.map((line) => `- ${line}`).join('\n'));
    lines.push('</details>');
    lines.push('');
    lines.push('<details>');
    lines.push('<summary>Resolved Findings</summary>');
    lines.push('');
    lines.push('Resolved violations:');
    lines.push(resolvedViolationLines.length === 0
        ? '- (none)'
        : resolvedViolationLines.map((line) => `- ${line}`).join('\n'));
    lines.push('Resolved setup gaps:');
    lines.push(resolvedSetupGapLines.length === 0
        ? '- (none)'
        : resolvedSetupGapLines.map((line) => `- ${line}`).join('\n'));
    lines.push('</details>');
    lines.push('');
    lines.push('<details>');
    lines.push('<summary>Report Artifacts</summary>');
    lines.push('');
    lines.push('- `.archpilot/reports/architecture-review.md`');
    lines.push('- `.archpilot/reports/architecture-review-compact.md`');
    lines.push('- `.archpilot/reports/pr-architecture-review.md`');
    lines.push('</details>');
    return `${lines.join('\n')}\n`;
}
async function writeArchitecturePrCommentMarkdown(workspaceRoot, markdown) {
    const reportsDir = path.join(workspaceRoot, '.archpilot', 'reports');
    const outputPath = path.join(reportsDir, 'pr-architecture-review.md');
    await node_fs_1.promises.mkdir(reportsDir, { recursive: true });
    await node_fs_1.promises.writeFile(outputPath, markdown, { encoding: 'utf8' });
    return outputPath;
}
//# sourceMappingURL=architecturePrCommentReporter.js.map