"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.inventoryPlanning = inventoryPlanning;
exports.discoverPlanningWorkCandidates = discoverPlanningWorkCandidates;
exports.gapReportPlanning = gapReportPlanning;
const errors_1 = require("../../errors");
const paths_1 = require("../../paths");
const workspace_discovery_1 = require("../../workspace-discovery");
const legacy_compatibility_projection_1 = require("../legacy-compatibility-projection");
const work_discovery_1 = require("../work-discovery");
const artifact_discovery_1 = require("./artifact-discovery");
const document_support_1 = require("./document-support");
const gap_analysis_1 = require("./gap-analysis");
const rendering_1 = require("./rendering");
const work_candidates_1 = require("./work-candidates");
function inventoryPlanning(options) {
    const scope = (0, artifact_discovery_1.resolveScope)(options.repositoryRoot, options.rootPath ?? ".day-shift/planning", true);
    const discovery = (0, workspace_discovery_1.discoverWorkspacePaths)({
        workspaceRoot: options.repositoryRoot,
        budgets: { files: 25_000, directories: 10_000, evidenceEntries: 50_000 },
        include: (entry) => entry.kind === "file" && (0, document_support_1.isRecognizedArtifactFilename)(entry.path) && (scope.kind !== "planning-root" || entry.path === scope.path || entry.path.startsWith(`${scope.path}/`))
    });
    const artifacts = scope.kind === "planning-root"
        ? [...discovery.paths].sort((left, right) => left.localeCompare(right)).map((artifactPath) => (0, artifact_discovery_1.readArtifactRecord)(options.repositoryRoot, artifactPath))
        : (0, artifact_discovery_1.collectArtifactsForScope)(options.repositoryRoot, scope);
    const findings = [];
    const grouped = (0, work_candidates_1.groupArtifacts)(artifacts);
    const taskByPath = new Map(grouped.taskDefinitionPaths.map((record) => [record.path, record]));
    for (const taskRecord of grouped.taskDefinitionPaths) {
        const expectedSummaryPath = (0, document_support_1.pairedImplementationSummaryPath)(taskRecord.path);
        const summaryRecord = grouped.implementationSummaryPaths.find((record) => record.path === expectedSummaryPath) ?? null;
        if (!(0, document_support_1.isClosedTaskDefinition)(taskRecord)) {
            continue;
        }
        if (summaryRecord === null) {
            findings.push(`Task definition '${taskRecord.path}' is missing paired implementation summary '${expectedSummaryPath}'.`);
            continue;
        }
        if (!(0, document_support_1.isCompletedImplementationSummary)(summaryRecord)) {
            findings.push(`Paired implementation summary '${summaryRecord.path}' is still incomplete for task '${taskRecord.path}'.`);
        }
        if ((0, document_support_1.isCompletedImplementationSummary)(summaryRecord)
            && taskRecord.status !== "completed") {
            findings.push(`Task definition '${taskRecord.path}' still carries stale lifecycle metadata after completed implementation evidence.`);
        }
    }
    for (const milestoneRecord of grouped.milestoneOverviewPaths) {
        const expectedReconciliationPath = (0, document_support_1.pairedReconciliationPath)(milestoneRecord.path);
        const reconciliationRecord = grouped.reconciliationPaths.find((record) => record.path === expectedReconciliationPath) ?? null;
        const allTaskSummariesComplete = (0, gap_analysis_1.areAllKnownTaskImplementationSummariesCompleteForMilestone)(grouped.taskDefinitionPaths, grouped.implementationSummaryPaths, milestoneRecord.path);
        if (!allTaskSummariesComplete) {
            continue;
        }
        if (reconciliationRecord === null) {
            findings.push(`Milestone overview '${milestoneRecord.path}' is missing paired reconciliation '${expectedReconciliationPath}'.`);
            continue;
        }
        if (!(0, document_support_1.isCompletedReconciliation)(reconciliationRecord)) {
            findings.push(`Paired reconciliation '${reconciliationRecord.path}' is still incomplete for milestone '${milestoneRecord.path}'.`);
            continue;
        }
        if (milestoneRecord.status !== "completed") {
            findings.push(`Milestone overview '${milestoneRecord.path}' still carries stale status metadata after completed reconciliation evidence.`);
        }
    }
    for (const summaryRecord of grouped.implementationSummaryPaths) {
        if (summaryRecord.upstreamTaskDefinitionPath !== null
            && !taskByPath.has(summaryRecord.upstreamTaskDefinitionPath)) {
            findings.push(`Implementation summary '${summaryRecord.path}' points to missing task definition '${summaryRecord.upstreamTaskDefinitionPath}'.`);
        }
    }
    const planningRootScope = scope.kind === "planning-root";
    return {
        scopePath: scope.path,
        scopeKind: scope.kind,
        workOverviewPaths: grouped.workOverviewPaths.map((record) => record.path),
        sliceOverviewPaths: grouped.sliceOverviewPaths.map((record) => record.path),
        phaseOverviewPaths: grouped.phaseOverviewPaths.map((record) => record.path),
        milestoneOverviewPaths: grouped.milestoneOverviewPaths.map((record) => record.path),
        taskDefinitionPaths: grouped.taskDefinitionPaths.map((record) => record.path),
        implementationSummaryPaths: grouped.implementationSummaryPaths.map((record) => record.path),
        reconciliationPaths: grouped.reconciliationPaths.map((record) => record.path),
        findings,
        discovery: discovery.evidence,
        workDiscovery: planningRootScope
            ? (0, work_discovery_1.discoverCanonicalWork)({
                repositoryRoot: options.repositoryRoot,
                planningRootPath: scope.path,
                projectContext: options.projectContext
            })
            : null,
        legacyCompatibility: planningRootScope
            ? (0, rendering_1.summarizeLegacyPlanningCompatibility)((0, legacy_compatibility_projection_1.projectLegacyPlanningCompatibility)({
                repositoryRoot: options.repositoryRoot,
                planningRootPath: scope.path
            }))
            : null
    };
}
function discoverPlanningWorkCandidates(options) {
    const defaultLimit = 10;
    const requestedLimit = options.limit ?? defaultLimit;
    if (!Number.isInteger(requestedLimit) || requestedLimit <= 0) {
        throw (0, errors_1.createUsageError)("Planning work candidate limit must be a positive integer.", [
            `Received: ${String(requestedLimit)}`
        ]);
    }
    const scope = (0, artifact_discovery_1.resolveScope)(options.repositoryRoot, options.rootPath ?? ".day-shift/planning", true);
    if (scope.kind !== "planning-root") {
        throw (0, errors_1.createUsageError)("Planning work candidates require a directory scope.", [
            "Pass a planning root or planning subdirectory with --root."
        ]);
    }
    const planningRootPath = (0, paths_1.parseRepositoryRelativePath)(options.planningRootPath ?? ".day-shift/planning").normalizedPath;
    const workDiscovery = (0, work_discovery_1.discoverCanonicalWork)({
        repositoryRoot: options.repositoryRoot,
        planningRootPath: scope.path,
        projectContext: options.projectContext
    });
    const legacyCompatibility = (0, rendering_1.summarizeLegacyPlanningCompatibility)((0, legacy_compatibility_projection_1.projectLegacyPlanningCompatibility)({
        repositoryRoot: options.repositoryRoot,
        planningRootPath: scope.path
    }));
    const workEvidenceByPath = new Map(workDiscovery.candidates.map((candidate) => [candidate.artifactPath, candidate]));
    const artifacts = (0, artifact_discovery_1.collectArtifactsForScope)(options.repositoryRoot, scope);
    const selectableRecords = artifacts.filter(work_candidates_1.isSelectablePlanningRecord);
    const incompleteRecords = selectableRecords.filter((record) => !(0, work_candidates_1.isPlanningRecordCompleted)(options.repositoryRoot, record));
    const frontierRecords = incompleteRecords.filter((record) => !incompleteRecords.some((candidate) => candidate.path !== record.path && (0, work_candidates_1.isPlanningDescendant)(candidate.path, record.path)));
    const candidates = frontierRecords.map((record) => (0, work_candidates_1.buildPlanningWorkCandidate)(options.repositoryRoot, record, selectableRecords, workEvidenceByPath.get(record.path) ?? null, planningRootPath));
    const returnedCandidates = candidates.slice(0, requestedLimit);
    return {
        scopePath: scope.path,
        scopeKind: scope.kind,
        defaultLimit,
        requestedLimit,
        totalCandidateCount: candidates.length,
        returnedCandidateCount: returnedCandidates.length,
        omittedCandidateCount: candidates.length - returnedCandidates.length,
        candidates: returnedCandidates,
        workDiscovery,
        legacyCompatibility,
        advisory: true,
        readOnly: true
    };
}
function gapReportPlanning(options) {
    const scope = (0, artifact_discovery_1.resolveScope)(options.repositoryRoot, options.scopePath ?? ".day-shift/planning", true);
    const gapMap = new Map();
    if (scope.kind === "planning-root") {
        const artifacts = (0, artifact_discovery_1.collectArtifactsForScope)(options.repositoryRoot, scope);
        const roots = (0, work_candidates_1.pickGapAnalysisRoots)(artifacts);
        for (const record of roots) {
            (0, gap_analysis_1.collectArtifactGaps)(options.repositoryRoot, record, gapMap);
        }
    }
    else if (scope.kind === "task_definition" || scope.kind === "implementation_summary") {
        const pairRecords = (0, artifact_discovery_1.collectArtifactsForScope)(options.repositoryRoot, scope);
        for (const record of (0, work_candidates_1.pickGapAnalysisRoots)(pairRecords)) {
            (0, gap_analysis_1.collectArtifactGaps)(options.repositoryRoot, record, gapMap);
        }
    }
    else {
        (0, gap_analysis_1.collectArtifactGaps)(options.repositoryRoot, (0, artifact_discovery_1.readArtifactRecord)(options.repositoryRoot, scope.path), gapMap);
    }
    return {
        scopePath: scope.path,
        scopeKind: scope.kind,
        gaps: [...gapMap.values()].sort((left, right) => (left.path.localeCompare(right.path)
            || left.code.localeCompare(right.code)
            || left.message.localeCompare(right.message))),
        workEvidence: scope.kind === "task_definition"
            ? (0, work_discovery_1.projectCanonicalWorkCandidate)({ repositoryRoot: options.repositoryRoot, artifactPath: scope.path })
            : null
    };
}
