"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.groupArtifacts = groupArtifacts;
exports.isSelectablePlanningRecord = isSelectablePlanningRecord;
exports.isPlanningRecordCompleted = isPlanningRecordCompleted;
exports.isPlanningDescendant = isPlanningDescendant;
exports.buildPlanningWorkCandidate = buildPlanningWorkCandidate;
exports.collectPriorSiblingBlockers = collectPriorSiblingBlockers;
exports.collectDependencyBlockers = collectDependencyBlockers;
exports.extractRepositoryRelativeDependencyPaths = extractRepositoryRelativeDependencyPaths;
exports.isCompletionEvidencePath = isCompletionEvidencePath;
exports.isPathInsidePlanningRoot = isPathInsidePlanningRoot;
exports.planningCandidateObservedState = planningCandidateObservedState;
exports.planningCandidateReason = planningCandidateReason;
exports.pickGapAnalysisRoots = pickGapAnalysisRoots;
const node_fs_1 = __importDefault(require("node:fs"));
const node_path_1 = __importDefault(require("node:path"));
const paths_1 = require("../../paths");
const planning_document_utils_1 = require("../planning-document-utils");
const artifact_discovery_1 = require("./artifact-discovery");
const document_support_1 = require("./document-support");
const gap_analysis_1 = require("./gap-analysis");
function groupArtifacts(records) {
    return {
        workOverviewPaths: records.filter((record) => record.artifactType === "work_overview"),
        sliceOverviewPaths: records.filter((record) => record.artifactType === "slice_overview"),
        phaseOverviewPaths: records.filter((record) => record.artifactType === "phase_overview"),
        milestoneOverviewPaths: records.filter((record) => record.artifactType === "milestone_overview"),
        taskDefinitionPaths: records.filter((record) => record.artifactType === "task_definition"),
        implementationSummaryPaths: records.filter((record) => record.artifactType === "implementation_summary"),
        reconciliationPaths: records.filter((record) => record.artifactType === "reconciliation")
    };
}
function isSelectablePlanningRecord(record) {
    return record.artifactType === "slice_overview"
        || record.artifactType === "phase_overview"
        || record.artifactType === "milestone_overview"
        || record.artifactType === "task_definition";
}
function isPlanningRecordCompleted(repositoryRoot, record) {
    switch (record.artifactType) {
        case "work_overview":
            return true;
        case "task_definition": {
            const summary = (0, artifact_discovery_1.readArtifactIfExists)(repositoryRoot, (0, document_support_1.pairedImplementationSummaryPath)(record.path));
            return summary !== null && (0, document_support_1.isCompletedImplementationSummary)(summary);
        }
        case "milestone_overview": {
            const reconciliation = (0, artifact_discovery_1.readArtifactIfExists)(repositoryRoot, (0, document_support_1.pairedReconciliationPath)(record.path));
            return reconciliation !== null && (0, document_support_1.isCompletedReconciliation)(reconciliation);
        }
        case "phase_overview":
            return (0, gap_analysis_1.areAllDeclaredMilestonesReconciled)(repositoryRoot, record);
        case "slice_overview":
            return record.status === "completed";
        default:
            return false;
    }
}
function isPlanningDescendant(candidatePath, ancestorPath) {
    return candidatePath.startsWith(`${node_path_1.default.posix.dirname(ancestorPath)}/`);
}
function buildPlanningWorkCandidate(repositoryRoot, record, selectableRecords, workEvidence, planningRootPath) {
    const blockers = [
        ...collectPriorSiblingBlockers(repositoryRoot, record, selectableRecords),
        ...collectDependencyBlockers(repositoryRoot, record, planningRootPath),
        ...(workEvidence?.blockers.map((blocker) => ({
            code: blocker.code.toUpperCase().replace(/-/g, "_"),
            path: blocker.path,
            message: blocker.message
        })) ?? [])
    ];
    const actionable = blockers.length === 0;
    return {
        artifactPath: record.path,
        artifactType: record.artifactType,
        observedState: planningCandidateObservedState(repositoryRoot, record),
        status: actionable ? "actionable" : "blocked",
        reasons: [planningCandidateReason(record.artifactType, actionable)],
        blockers,
        selectionArgv: ["day-shift", "work", "select", "--artifact", record.path],
        selectionCommandState: "callable",
        workEvidence
    };
}
function collectPriorSiblingBlockers(repositoryRoot, record, selectableRecords) {
    const siblingRoot = node_path_1.default.posix.dirname(node_path_1.default.posix.dirname(record.path));
    const priorIncompleteSibling = selectableRecords.find((candidate) => candidate.artifactType === record.artifactType
        && node_path_1.default.posix.dirname(node_path_1.default.posix.dirname(candidate.path)) === siblingRoot
        && candidate.path.localeCompare(record.path) < 0
        && !isPlanningRecordCompleted(repositoryRoot, candidate));
    return priorIncompleteSibling === undefined
        ? []
        : [{
                code: "PRIOR_SIBLING_INCOMPLETE",
                path: priorIncompleteSibling.path,
                message: `Earlier declared ${record.artifactType} work is incomplete.`
            }];
}
function collectDependencyBlockers(repositoryRoot, record, planningRootPath) {
    const dependencySection = record.document.sections.get("Dependencies") ?? "";
    const dependencyPaths = extractRepositoryRelativeDependencyPaths(dependencySection);
    const blockers = [];
    for (const dependencyPath of dependencyPaths) {
        const absolutePath = (0, paths_1.resolveRepositoryRelativePath)(repositoryRoot, (0, paths_1.parseRepositoryRelativePath)(dependencyPath));
        if (!node_fs_1.default.existsSync(absolutePath)) {
            blockers.push({
                code: "DEPENDENCY_MISSING",
                path: dependencyPath,
                message: "Declared dependency does not exist."
            });
            continue;
        }
        if (!isCompletionEvidencePath(dependencyPath)
            || !isPathInsidePlanningRoot(dependencyPath, planningRootPath)) {
            continue;
        }
        const dependencyRecord = (0, artifact_discovery_1.readArtifactRecord)(repositoryRoot, dependencyPath);
        const completed = dependencyRecord.artifactType === "implementation_summary"
            ? (0, document_support_1.isCompletedImplementationSummary)(dependencyRecord)
            : dependencyRecord.artifactType === "reconciliation"
                ? (0, document_support_1.isCompletedReconciliation)(dependencyRecord)
                : (0, document_support_1.isClosedTaskDefinition)(dependencyRecord);
        if (!completed) {
            blockers.push({
                code: "DEPENDENCY_INCOMPLETE",
                path: dependencyPath,
                message: "Declared lifecycle dependency is present but incomplete."
            });
        }
    }
    return blockers;
}
function extractRepositoryRelativeDependencyPaths(sectionText) {
    const paths = new Set();
    for (const line of sectionText.split(/\r?\n/)) {
        const match = line.match(/(?:^|[\s`(])((?:\.day-shift|src|tests_v2|schemas|scripts|apps)\/[^\s`)]+)/);
        if (match !== null) {
            paths.add(match[1].replace(/[.,;:]$/, ""));
        }
    }
    return [...paths];
}
function isCompletionEvidencePath(dependencyPath) {
    return dependencyPath.endsWith("/implementation-summary.md")
        || dependencyPath.endsWith("/reconciliation.md")
        || dependencyPath.endsWith("/task-definition.md");
}
function isPathInsidePlanningRoot(dependencyPath, planningRootPath) {
    return dependencyPath === planningRootPath
        || dependencyPath.startsWith(`${planningRootPath}/`);
}
function planningCandidateObservedState(repositoryRoot, record) {
    switch (record.artifactType) {
        case "work_overview":
            return "non-actionable-parent";
        case "task_definition":
            return record.readiness ?? record.status ?? "unknown";
        case "milestone_overview":
            return (0, gap_analysis_1.areAllTaskImplementationSummariesComplete)(repositoryRoot, record.path)
                ? "ready-for-reconciliation"
                : "tasks-pending";
        case "phase_overview":
            return "milestones-pending";
        case "slice_overview":
            return "phases-pending";
        default:
            return "unknown";
    }
}
function planningCandidateReason(artifactType, actionable) {
    if (!actionable) {
        return "Canonical planning work is incomplete but cannot advance until the reported blockers are resolved.";
    }
    switch (artifactType) {
        case "task_definition":
            return "Task is the next incomplete declared implementation unit in its milestone.";
        case "milestone_overview":
            return "Milestone is the next incomplete declared checkpoint in its phase.";
        case "phase_overview":
            return "Phase is the next incomplete declared work group in its slice.";
        case "slice_overview":
            return "Slice contains incomplete declared planning work.";
    }
}
function pickGapAnalysisRoots(records) {
    const grouped = groupArtifacts(records);
    const structuredRoots = grouped.workOverviewPaths.filter((record) => (0, planning_document_utils_1.readTopLevelField)(record.document.frontMatterLines, "workflow_level") === "structured");
    const governedRoots = grouped.sliceOverviewPaths.filter(document_support_1.isCanonicalGovernedSliceRoot);
    if (structuredRoots.length > 0 || governedRoots.length > 0) {
        return [...structuredRoots, ...governedRoots]
            .sort((left, right) => left.path.localeCompare(right.path));
    }
    // Historical shapes remain inspectable until compatibility classification,
    // but they are not preferred over canonical Structured or Governed owners.
    if (grouped.sliceOverviewPaths.length > 0) {
        return grouped.sliceOverviewPaths;
    }
    if (grouped.workOverviewPaths.length > 0) {
        return grouped.workOverviewPaths;
    }
    if (grouped.phaseOverviewPaths.length > 0) {
        return grouped.phaseOverviewPaths;
    }
    if (grouped.milestoneOverviewPaths.length > 0) {
        return grouped.milestoneOverviewPaths;
    }
    if (grouped.taskDefinitionPaths.length > 0) {
        return grouped.taskDefinitionPaths;
    }
    if (grouped.implementationSummaryPaths.length > 0) {
        return grouped.implementationSummaryPaths;
    }
    return grouped.reconciliationPaths;
}
