"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.createPhaseFullSetWorkspaces = createPhaseFullSetWorkspaces;
exports.createMilestoneFullSetWorkspaces = createMilestoneFullSetWorkspaces;
exports.createTaskFullSetWorkspaces = createTaskFullSetWorkspaces;
const node_fs_1 = __importDefault(require("node:fs"));
const node_path_1 = __importDefault(require("node:path"));
const errors_1 = require("../errors");
const command_write_summary_1 = require("../license/command-write-summary");
const paths_1 = require("../paths");
const front_matter_utils_1 = require("./front-matter-utils");
const milestone_generation_1 = require("./milestone-generation");
const phase_generation_1 = require("./phase-generation");
const planning_document_utils_1 = require("./planning-document-utils");
const scaffold_application_1 = require("./scaffold-application");
const task_generation_1 = require("./task-generation");
function createPhaseFullSetWorkspaces(repositoryRoot, options) {
    const sliceOverviewPath = resolveParentOverviewPath(repositoryRoot, options.sliceOverviewPath, "--slice-overview");
    const workflowCliCommand = `day-shift phase new --slice-overview ${sliceOverviewPath.relative} --full-set`;
    const declaredPhaseSlugs = parseDeclaredChildSlugs(sliceOverviewPath.absolute, "slice_overview", "Phases", "phase");
    if (declaredPhaseSlugs.length === 0) {
        throw (0, errors_1.createUsageError)(`Parent overview '${sliceOverviewPath.relative}' does not declare any phases in its ## Phases section.`, ["Add declared phase slugs to the parent overview before requesting full-set expansion."]);
    }
    const plannedWorkspaces = declaredPhaseSlugs.map((phaseSlug) => {
        return (0, phase_generation_1.createPhaseWorkspace)(repositoryRoot, {
            sliceOverviewPath: sliceOverviewPath.relative,
            phaseSlug,
            workflowCliCommand,
            validateOnly: true
        });
    });
    const application = (0, scaffold_application_1.applyPlanningScaffoldSync)(repositoryRoot, plannedWorkspaces.flatMap((workspace) => [...workspace.plannedWrites]), {
        parentPaths: [sliceOverviewPath.relative],
        transaction: options.transaction
    });
    (0, scaffold_application_1.assertPlanningScaffoldApplied)(application);
    const phaseWorkspaces = plannedWorkspaces.map((workspace) => ({
        ...workspace,
        application
    }));
    const pendingRefinementPaths = phaseWorkspaces
        .filter((workspace) => workspace.requiresRefinement)
        .map((workspace) => (0, front_matter_utils_1.toRepositoryLikePath)(node_path_1.default.relative(repositoryRoot, workspace.overviewPath)));
    return {
        repositoryRoot,
        sliceOverviewPath: sliceOverviewPath.relative,
        declaredPhaseSlugs,
        phaseWorkspaces,
        createdCount: phaseWorkspaces.filter((result) => result.overviewAction === "created").length,
        keptCount: phaseWorkspaces.filter((result) => result.overviewAction === "kept").length,
        workflowCliCommand,
        application,
        requiresRefinement: pendingRefinementPaths.length > 0,
        pendingRefinementPaths,
        commandWriteSummary: normalizeFullSetCommandWriteSummary("phase_generation", phaseWorkspaces.map((workspace) => workspace.commandWriteSummary))
    };
}
function createMilestoneFullSetWorkspaces(repositoryRoot, options) {
    const phaseOverviewPath = resolveParentOverviewPath(repositoryRoot, options.phaseOverviewPath, "--phase-overview");
    const workflowCliCommand = [
        `day-shift milestone new --phase-overview ${phaseOverviewPath.relative} --full-set`,
        options.recoverScaffold === true ? "--recover-scaffold" : ""
    ].filter((value) => value !== "").join(" ");
    const declaredMilestones = parseDeclaredChildren(phaseOverviewPath.absolute, "phase_overview", "Milestones", "milestone");
    const declaredMilestoneSlugs = declaredMilestones.map((milestone) => milestone.slug);
    if (declaredMilestoneSlugs.length === 0) {
        throw (0, errors_1.createUsageError)(`Parent overview '${phaseOverviewPath.relative}' does not declare any milestones in its ## Milestones section.`, ["Add declared milestone slugs to the parent overview before requesting full-set expansion."]);
    }
    const plannedWorkspaces = declaredMilestones.map((milestone) => {
        return (0, milestone_generation_1.createMilestoneWorkspace)(repositoryRoot, {
            phaseOverviewPath: phaseOverviewPath.relative,
            milestoneSlug: milestone.slug,
            milestoneDescription: milestone.description,
            workflowCliCommand,
            validateOnly: true,
            recoverScaffold: options.recoverScaffold
        });
    });
    const parentExpectedRevisions = uniqueValues(plannedWorkspaces.map((workspace) => workspace.parentExpectedRevision));
    if (parentExpectedRevisions.length !== 1) {
        throw new Error(`Milestone full-set planning observed ${parentExpectedRevisions.length} parent phase revisions; no write was attempted.`);
    }
    const application = (0, scaffold_application_1.applyPlanningScaffoldSync)(repositoryRoot, plannedWorkspaces.flatMap((workspace) => [...workspace.plannedWrites]), {
        parentPaths: [{
                path: phaseOverviewPath.relative,
                expectedRevision: parentExpectedRevisions[0]
            }],
        transaction: options.transaction
    });
    (0, scaffold_application_1.assertPlanningScaffoldApplied)(application);
    const milestoneWorkspaces = plannedWorkspaces.map((workspace) => ({
        ...workspace,
        application
    }));
    return {
        repositoryRoot,
        phaseOverviewPath: phaseOverviewPath.relative,
        declaredMilestoneSlugs,
        milestoneWorkspaces,
        createdCount: milestoneWorkspaces.filter((result) => result.overviewAction === "created").length,
        keptCount: milestoneWorkspaces.filter((result) => result.overviewAction === "kept").length,
        refreshedCount: milestoneWorkspaces.filter((result) => result.overviewAction === "refreshed").length,
        workflowCliCommand,
        application,
        requiresRefinement: milestoneWorkspaces.some((workspace) => workspace.requiresRefinement),
        commandWriteSummary: normalizeFullSetCommandWriteSummary("milestone_generation", milestoneWorkspaces.map((workspace) => workspace.commandWriteSummary))
    };
}
function createTaskFullSetWorkspaces(repositoryRoot, options) {
    const milestoneOverviewPath = resolveParentOverviewPath(repositoryRoot, options.milestoneOverviewPath, "--milestone-overview");
    const workflowCliCommand = [
        `day-shift task new --milestone-overview ${milestoneOverviewPath.relative} --full-set`,
        options.recoverScaffold === true ? "--recover-scaffold" : ""
    ].filter((value) => value !== "").join(" ");
    const declaredTasks = parseDeclaredChildren(milestoneOverviewPath.absolute, "milestone_overview", "Tasks", "task");
    const declaredTaskSlugs = declaredTasks.map((task) => task.slug);
    if (declaredTaskSlugs.length === 0) {
        throw (0, errors_1.createUsageError)(`Parent overview '${milestoneOverviewPath.relative}' does not declare any tasks in its ## Tasks section.`, ["Add declared task slugs to the parent overview before requesting full-set expansion."]);
    }
    const plannedWorkspaces = declaredTasks.map((task) => {
        return (0, task_generation_1.createTaskWorkspace)(repositoryRoot, {
            milestoneOverviewPath: milestoneOverviewPath.relative,
            taskSlug: task.slug,
            taskDescription: task.description,
            workflowCliCommand,
            validateOnly: true,
            recoverScaffold: options.recoverScaffold
        });
    });
    const parentExpectedRevisions = uniqueValues(plannedWorkspaces.map((workspace) => workspace.parentExpectedRevision));
    if (parentExpectedRevisions.length !== 1) {
        throw new Error(`Task full-set planning observed ${parentExpectedRevisions.length} parent milestone revisions; no write was attempted.`);
    }
    const application = (0, scaffold_application_1.applyPlanningScaffoldSync)(repositoryRoot, plannedWorkspaces.flatMap((workspace) => [...workspace.plannedWrites]), {
        parentPaths: [{
                path: milestoneOverviewPath.relative,
                expectedRevision: parentExpectedRevisions[0]
            }],
        transaction: options.transaction
    });
    (0, scaffold_application_1.assertPlanningScaffoldApplied)(application);
    const taskWorkspaces = plannedWorkspaces.map((workspace) => ({
        ...workspace,
        application
    }));
    return {
        repositoryRoot,
        milestoneOverviewPath: milestoneOverviewPath.relative,
        declaredTaskSlugs,
        taskWorkspaces,
        createdCount: taskWorkspaces.filter((result) => result.taskDefinitionAction === "created").length,
        keptCount: taskWorkspaces.filter((result) => result.taskDefinitionAction === "kept").length,
        refreshedCount: taskWorkspaces.filter((result) => result.taskDefinitionAction === "refreshed").length,
        workflowCliCommand,
        application,
        requiresRefinement: taskWorkspaces.some((workspace) => workspace.requiresRefinement),
        commandWriteSummary: normalizeFullSetCommandWriteSummary("task_generation", taskWorkspaces.map((workspace) => workspace.commandWriteSummary))
    };
}
function normalizeFullSetCommandWriteSummary(commandFamily, summaries) {
    return (0, command_write_summary_1.normalizeCommandWriteSummary)({
        commandFamily,
        primaryOutputArtifacts: summaries.flatMap((summary) => [...summary.primaryOutputArtifacts]),
        updatedArtifacts: summaries.flatMap((summary) => [...summary.updatedArtifacts])
    });
}
function resolveParentOverviewPath(repositoryRoot, inputPath, optionName) {
    try {
        if (optionName === "--slice-overview") {
            return (0, paths_1.resolvePlanningOverviewInputPath)(repositoryRoot, {
                layer: "slice",
                inputPath
            });
        }
        if (optionName === "--phase-overview") {
            return (0, paths_1.resolvePlanningOverviewInputPath)(repositoryRoot, {
                layer: "phase",
                inputPath
            });
        }
        if (optionName === "--milestone-overview") {
            return (0, paths_1.resolvePlanningOverviewInputPath)(repositoryRoot, {
                layer: "milestone",
                inputPath
            });
        }
        const parsed = (0, paths_1.parseRepositoryRelativePath)(inputPath);
        return {
            relative: parsed.normalizedPath,
            absolute: node_path_1.default.join(repositoryRoot, parsed.normalizedPath)
        };
    }
    catch (error) {
        throw (0, errors_1.createUsageError)(`Invalid ${optionName} path '${inputPath}'.`, [error instanceof Error ? error.message : String(error)]);
    }
}
function parseDeclaredChildSlugs(parentOverviewPath, expectedArtifactType, sectionName, childKind) {
    return parseDeclaredChildren(parentOverviewPath, expectedArtifactType, sectionName, childKind).map((child) => child.slug);
}
function parseDeclaredChildren(parentOverviewPath, expectedArtifactType, sectionName, childKind) {
    if (!node_fs_1.default.existsSync(parentOverviewPath)) {
        throw (0, errors_1.createUsageError)(`Parent overview not found at '${(0, front_matter_utils_1.toRepositoryLikePath)(parentOverviewPath)}'.`);
    }
    const fileText = node_fs_1.default.readFileSync(parentOverviewPath, "utf8");
    const lines = fileText.split(/\r?\n/);
    const artifactType = readTopLevelField(lines, "artifact_type");
    if (artifactType !== expectedArtifactType) {
        throw (0, errors_1.createUsageError)(`Parent overview '${(0, front_matter_utils_1.toRepositoryLikePath)(parentOverviewPath)}' must use artifact_type: ${expectedArtifactType}.`);
    }
    const sectionHeader = `## ${sectionName}`;
    const sectionIndex = lines.findIndex((line) => line.trim() === sectionHeader);
    if (sectionIndex === -1) {
        throw (0, errors_1.createUsageError)(`Parent overview '${(0, front_matter_utils_1.toRepositoryLikePath)(parentOverviewPath)}' is missing its ${sectionHeader} section.`, ["Declare the child slugs in that section before requesting full-set expansion."]);
    }
    const children = [];
    const seenChildSlugs = new Set();
    const sectionLines = [];
    for (let index = sectionIndex + 1; index < lines.length; index += 1) {
        if (lines[index].trim().startsWith("## ")) {
            break;
        }
        sectionLines.push(lines[index]);
    }
    const descriptions = new Map((0, planning_document_utils_1.parseDeclaredChildSlugBullets)(sectionLines).map((declaration) => [
        declaration.slug,
        declaration.description
    ]));
    for (const line of sectionLines) {
        const trimmed = line.trim();
        if (!trimmed.startsWith("- ")) {
            continue;
        }
        const declaredChild = parseDeclaredChild(trimmed.slice(2), parentOverviewPath, sectionName, childKind);
        if (declaredChild === undefined) {
            continue;
        }
        const declaredSlug = declaredChild.slug;
        if (seenChildSlugs.has(declaredSlug)) {
            throw (0, errors_1.createUsageError)(`Parent overview '${(0, front_matter_utils_1.toRepositoryLikePath)(parentOverviewPath)}' declares '${declaredSlug}' more than once in its ${sectionHeader} section.`);
        }
        seenChildSlugs.add(declaredSlug);
        children.push({
            ...declaredChild,
            description: descriptions.get(declaredSlug) ?? declaredChild.description
        });
    }
    return children;
}
function parseDeclaredChild(rawListItem, parentOverviewPath, sectionName, childKind) {
    const declaration = (0, planning_document_utils_1.parseDeclaredChildSlugBullet)(`- ${rawListItem}`);
    if (declaration !== null) {
        const slug = declaration.slug;
        if (!isCanonicalChildSlug(slug)) {
            throw (0, errors_1.createUsageError)(`Parent overview '${(0, front_matter_utils_1.toRepositoryLikePath)(parentOverviewPath)}' declares an invalid ${childKind} slug '${slug}' in its ## ${sectionName} section.`);
        }
        return {
            slug,
            description: declaration.description
        };
    }
    const plainMatch = rawListItem.match(/^([A-Za-z0-9]+(?:-[A-Za-z0-9]+)*)\b/);
    if (plainMatch !== null) {
        const slug = plainMatch[1].trim();
        if (isCanonicalChildSlug(slug) || /^[a-z0-9]+(?:-[a-z0-9]+)*$/u.test(slug)) {
            throw (0, errors_1.createUsageError)(`Parent overview '${(0, front_matter_utils_1.toRepositoryLikePath)(parentOverviewPath)}' declares ${childKind} slug '${slug}' without the required backticks in its ## ${sectionName} section.`);
        }
    }
    return undefined;
}
function readTopLevelField(lines, key) {
    for (const line of lines) {
        if (/^\s/.test(line)) {
            continue;
        }
        const match = line.match(/^([A-Za-z0-9_]+):\s*(.*)$/);
        if (match === null) {
            continue;
        }
        if (match[1] === key) {
            return (0, front_matter_utils_1.parseScalar)(match[2]);
        }
    }
    return undefined;
}
function isCanonicalChildSlug(value) {
    return /^\d{2}-[a-z0-9]+(?:-[a-z0-9]+)*$/u.test(value);
}
function uniqueValues(values) {
    return [...new Set(values)];
}
