"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.createPhaseWorkspace = createPhaseWorkspace;
const node_fs_1 = __importDefault(require("node:fs"));
const node_path_1 = __importDefault(require("node:path"));
const errors_1 = require("../errors");
const authoring_policy_1 = require("./authoring-policy");
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 upstream_specs_1 = require("./upstream-specs");
const workflow_provenance_1 = require("./workflow-provenance");
const runtime_acceptance_1 = require("./runtime-acceptance");
const ALLOWED_PLANNING_DEPTH_VALUES = new Set(["standard", "strict"]);
function createPhaseWorkspace(repositoryRoot, options) {
    const sliceOverviewPath = resolveSliceOverviewPath(repositoryRoot, options.sliceOverviewPath);
    if (!node_fs_1.default.existsSync(sliceOverviewPath.absolute)) {
        throw (0, errors_1.createUsageError)(`Parent slice overview not found at '${sliceOverviewPath.relative}'.`, ["Run day-shift slice new first or pass the correct --slice-overview path."]);
    }
    const parsedSliceOverview = parseSliceOverview(sliceOverviewPath.absolute);
    const sliceOverviewText = node_fs_1.default.readFileSync(sliceOverviewPath.absolute, "utf8");
    const declaredPhaseSlugs = (0, authoring_policy_1.declaredPlanningChildSlugs)(sliceOverviewText, "Phases");
    const decompositionIssues = (0, authoring_policy_1.auditParentDecomposition)({
        artifactPath: sliceOverviewPath.relative,
        markdownText: sliceOverviewText,
        childKind: "phase",
        declaredChildSlugs: declaredPhaseSlugs
    });
    if (decompositionIssues.length > 0) {
        throw (0, errors_1.createUsageError)(`Planning decomposition contract rejected '${sliceOverviewPath.relative}' before phase writes.`, (0, authoring_policy_1.formatParentDecompositionIssues)(decompositionIssues));
    }
    const upstreamSpecs = (0, upstream_specs_1.normalizeUpstreamSpecsToLocalSpecPaths)(repositoryRoot, parsedSliceOverview.upstreamSpecs);
    const phaseSlug = resolvePhaseSlug(options.phaseSlug);
    if (!declaredPhaseSlugs.includes(phaseSlug)) {
        throw (0, errors_1.createUsageError)(`Phase '${phaseSlug}' is not declared by '${sliceOverviewPath.relative}'.`, ["Declare the phase and update the authored target count and decomposition rationale before scaffolding."]);
    }
    const phaseTitle = resolvePhaseTitle(phaseSlug, options.phaseTitle);
    const sliceDirectoryPath = node_path_1.default.dirname(sliceOverviewPath.absolute);
    const phasesDirectoryPath = node_path_1.default.join(sliceDirectoryPath, "phases");
    const phaseDirectoryPath = node_path_1.default.join(phasesDirectoryPath, phaseSlug);
    const phaseDirectoryRelative = (0, front_matter_utils_1.toRepositoryLikePath)(node_path_1.default.relative(repositoryRoot, phaseDirectoryPath));
    const overviewRelativePath = node_path_1.default.basename(sliceOverviewPath.relative) === "overview.md"
        ? (0, paths_1.composeLegacyPlanningOverviewPath)(phaseDirectoryRelative)
        : (0, paths_1.composeCanonicalPlanningOverviewPath)("phase", phaseDirectoryRelative);
    const overviewPath = node_path_1.default.join(repositoryRoot, overviewRelativePath);
    const renderedOverview = node_fs_1.default.existsSync(overviewPath)
        ? null
        : renderPhaseOverviewMarkdown({
            phaseTitle,
            slice: parsedSliceOverview.slice,
            phaseSlug,
            planningDepth: parsedSliceOverview.planningDepth,
            sliceOverviewPath: sliceOverviewPath.relative,
            upstreamSpecs,
            runtimeAcceptance: parsedSliceOverview.runtimeAcceptance === null
                ? null
                : (0, runtime_acceptance_1.childRuntimeAcceptanceMetadata)(parsedSliceOverview.runtimeAcceptance),
            workflowCliCommand: options.workflowCliCommand
        });
    const overviewExists = node_fs_1.default.existsSync(overviewPath);
    const phasesDirectoryAction = node_fs_1.default.existsSync(phasesDirectoryPath) ? "kept" : "created";
    if (options.validateOnly !== true) {
        ensureDirectory(phasesDirectoryPath);
        node_fs_1.default.mkdirSync(phaseDirectoryPath, { recursive: true });
        if (!overviewExists && renderedOverview !== null) {
            node_fs_1.default.writeFileSync(overviewPath, renderedOverview, "utf8");
        }
    }
    return {
        repositoryRoot,
        slice: parsedSliceOverview.slice,
        planningDepth: parsedSliceOverview.planningDepth,
        sliceOverviewPath: sliceOverviewPath.relative,
        phasesDirectoryPath,
        phaseDirectoryPath,
        overviewPath,
        phaseSlug,
        phaseTitle,
        phasesDirectoryAction,
        overviewAction: overviewExists ? "kept" : "created",
        contributingSpecIds: upstreamSpecs.map((entry) => entry.id),
        commandWriteSummary: (0, command_write_summary_1.normalizeCommandWriteSummary)({
            commandFamily: "phase_generation",
            primaryOutputArtifacts: [(0, front_matter_utils_1.toRepositoryLikePath)(node_path_1.default.relative(repositoryRoot, overviewPath))],
            updatedArtifacts: [
                {
                    path: (0, front_matter_utils_1.toRepositoryLikePath)(node_path_1.default.relative(repositoryRoot, overviewPath)),
                    action: overviewExists ? "kept" : "created",
                    reason: overviewExists ? "no_write" : "accepted_create"
                }
            ]
        })
    };
}
function resolveSliceOverviewPath(repositoryRoot, inputPath) {
    try {
        return (0, paths_1.resolvePlanningOverviewInputPath)(repositoryRoot, {
            layer: "slice",
            inputPath
        });
    }
    catch (error) {
        throw (0, errors_1.createUsageError)(`Invalid --slice-overview path '${inputPath}'.`, [error instanceof Error ? error.message : String(error)]);
    }
}
function resolvePhaseSlug(rawPhaseSlug) {
    if ((0, paths_1.isCanonicalSlug)(rawPhaseSlug)) {
        return rawPhaseSlug;
    }
    const normalized = (0, paths_1.normalizeCanonicalSlug)(rawPhaseSlug);
    if (normalized.kind === "canonical-slug") {
        return normalized.normalizedSlug;
    }
    throw (0, errors_1.createUsageError)(`Invalid phase slug '${rawPhaseSlug}'.`, [normalized.reason.message]);
}
function resolvePhaseTitle(phaseSlug, requestedTitle) {
    const trimmed = requestedTitle?.trim();
    if (trimmed !== undefined && trimmed !== "") {
        return trimmed;
    }
    return (0, front_matter_utils_1.toTitleCase)(phaseSlug);
}
function ensureDirectory(directoryPath) {
    if (node_fs_1.default.existsSync(directoryPath)) {
        return "kept";
    }
    node_fs_1.default.mkdirSync(directoryPath, { recursive: true });
    return "created";
}
function parseSliceOverview(sliceOverviewPath) {
    const fileText = node_fs_1.default.readFileSync(sliceOverviewPath, "utf8");
    const frontMatter = extractFrontMatter(sliceOverviewPath, fileText);
    const artifactType = readTopLevelField(frontMatter.lines, "artifact_type");
    if (artifactType !== "slice_overview") {
        throw (0, errors_1.createUsageError)(`Parent overview '${(0, front_matter_utils_1.toRepositoryLikePath)(sliceOverviewPath)}' must use artifact_type: slice_overview.`);
    }
    const slice = readTopLevelField(frontMatter.lines, "slice");
    if (slice === undefined || slice.trim() === "") {
        throw (0, errors_1.createUsageError)(`Parent overview '${(0, front_matter_utils_1.toRepositoryLikePath)(sliceOverviewPath)}' is missing required top-level field 'slice'.`);
    }
    const planningDepth = readTopLevelField(frontMatter.lines, "planning_depth")?.trim() || "standard";
    const upstreamSpecs = parseUpstreamSpecs(frontMatter.lines, sliceOverviewPath);
    const runtimeAcceptance = (0, runtime_acceptance_1.assertRuntimeAcceptanceInspection)((0, runtime_acceptance_1.inspectRuntimeAcceptance)({
        artifactPath: sliceOverviewPath,
        artifactKind: "slice",
        frontMatterLines: frontMatter.lines,
        markdownText: fileText
    }));
    if (upstreamSpecs.length === 0) {
        throw (0, errors_1.createUsageError)(`Parent overview '${(0, front_matter_utils_1.toRepositoryLikePath)(sliceOverviewPath)}' must include at least one upstream spec entry under upstream.specs.`);
    }
    return {
        slice: slice.trim(),
        planningDepth,
        upstreamSpecs,
        runtimeAcceptance
    };
}
function extractFrontMatter(filePath, text) {
    const lines = text.split(/\r?\n/);
    if (lines[0] !== "---") {
        throw (0, errors_1.createUsageError)(`Parent overview '${(0, front_matter_utils_1.toRepositoryLikePath)(filePath)}' is missing YAML front matter.`);
    }
    let closingIndex = -1;
    for (let index = 1; index < lines.length; index += 1) {
        if (lines[index] === "---") {
            closingIndex = index;
            break;
        }
    }
    if (closingIndex === -1) {
        throw (0, errors_1.createUsageError)(`Parent overview '${(0, front_matter_utils_1.toRepositoryLikePath)(filePath)}' has malformed YAML front matter.`);
    }
    return {
        lines: lines.slice(1, closingIndex)
    };
}
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 parseUpstreamSpecs(lines, filePath) {
    const entries = [];
    for (let index = 0; index < lines.length; index += 1) {
        const idMatch = lines[index].match(/^\s*-\s+id:\s*(.+)$/);
        if (idMatch === null) {
            continue;
        }
        const depthLine = lines[index + 1];
        const refLine = lines[index + 2];
        const sourceTypeLine = lines[index + 3];
        const depthMatch = depthLine?.match(/^\s+depth:\s*(.+)$/);
        const refMatch = refLine?.match(/^\s+ref:\s*(.+)$/);
        const sourceTypeMatch = sourceTypeLine?.match(/^\s+source_type:\s*(.+)$/);
        if (depthMatch === null || refMatch === null || sourceTypeMatch === null) {
            throw (0, errors_1.createUsageError)(`Parent overview '${(0, front_matter_utils_1.toRepositoryLikePath)(filePath)}' has malformed upstream.specs metadata near '${lines[index].trim()}'.`);
        }
        entries.push({
            id: (0, front_matter_utils_1.parseScalar)(idMatch[1]),
            depth: (0, front_matter_utils_1.parseScalar)(depthMatch[1]),
            ref: (0, front_matter_utils_1.parseScalar)(refMatch[1]),
            sourceType: (0, front_matter_utils_1.parseScalar)(sourceTypeMatch[1])
        });
        index += 3;
    }
    return entries;
}
function renderPhaseOverviewMarkdown(options) {
    const workflowProvenance = (0, workflow_provenance_1.buildCliWorkflowProvenance)(options.workflowCliCommand
        ?? `day-shift phase new --slice-overview ${options.sliceOverviewPath} --phase-slug ${options.phaseSlug}`);
    const upstreamSpecs = options.upstreamSpecs
        .map((entry) => {
        return [
            `    - id: ${entry.id}`,
            `      depth: ${entry.depth}`,
            `      ref: ${JSON.stringify(entry.ref)}`,
            `      source_type: ${JSON.stringify(entry.sourceType)}`
        ].join("\n");
    })
        .join("\n");
    const text = (0, runtime_acceptance_1.injectRuntimeAcceptanceFrontMatter)([
        "---",
        "artifact_schema_version: 1",
        "artifact_type: phase_overview",
        `slice: ${options.slice}`,
        `phase: ${options.phaseSlug}`,
        `planning_depth: ${options.planningDepth}`,
        `workflow_provenance: ${workflowProvenance.workflowProvenance}`,
        `workflow_cli_command: ${JSON.stringify(workflowProvenance.workflowCliCommand)}`,
        "status: draft",
        "upstream:",
        "  specs:",
        upstreamSpecs,
        `  slice_overview: ${options.sliceOverviewPath}`,
        "---",
        "",
        `# ${options.phaseTitle}`,
        "",
        "## Purpose",
        "",
        `Document the ${options.phaseSlug} phase checkpoint from the selected slice context so milestone planning can proceed with deterministic traceability.`,
        "",
        "## Scope",
        "",
        "- Preserve deterministic phase-level planning paths beneath the selected slice overview.",
        "- Keep parent and source traceability explicit in phase metadata.",
        "- Keep phase content focused on outcome scope rather than task implementation detail.",
        "",
        "## Navigation",
        "",
        `- ${options.sliceOverviewPath}`,
        "",
        "## Milestones",
        "",
        "- Replace with `01-some-ordered-slug`: short milestone description before creating milestone artifacts.",
        "",
        "## Acceptance Criteria",
        "",
        "- The phase documents clear milestone checkpoints for this planning slice.",
        "- Phase-level scope remains aligned with parent slice intent.",
        "",
        "## Dependencies",
        "",
        "- Parent slice overview and upstream spec context.",
        "",
        "## Risks",
        "",
        "- Follow-on updates should keep phase-generation guidance and executable behavior aligned.",
        "",
        "## Validation Focus",
        "",
        "- Validate parent traceability and phase path consistency.",
        "",
        "## Open Questions",
        "",
        "- None currently.",
        ""
    ].join("\n"), options.runtimeAcceptance);
    assertPlanningAuthoringCompliance("phase_overview", text);
    try {
        if (!ALLOWED_PLANNING_DEPTH_VALUES.has(options.planningDepth)) {
            throw new TypeError(`Unsupported planning_depth token '${options.planningDepth}' for field 'planning_depth'.`);
        }
        return (0, front_matter_utils_1.applyStatusAndPlanningFieldTransition)(text, {
            slice: options.slice,
            phase: options.phaseSlug,
            planning_depth: options.planningDepth,
            status: "draft"
        });
    }
    catch (error) {
        if (error instanceof TypeError) {
            throw (0, errors_1.createInvalidConfigError)("Phase overview metadata updates were rejected.", [error.message], [{
                    code: "PHASE_METADATA_UPDATE_BLOCKED",
                    message: error.message,
                    severity: "error"
                }]);
        }
        throw error;
    }
}
function assertPlanningAuthoringCompliance(artifactType, markdownText) {
    const issues = (0, authoring_policy_1.auditPlanningArtifactAuthoring)({
        artifactPath: "generated phase overview",
        artifactType,
        markdownText
    });
    if (issues.length > 0) {
        throw (0, errors_1.createUsageError)(`Planning authoring policy rejected generated ${artifactType} scaffold text.`, (0, authoring_policy_1.formatPlanningAuthoringIssues)(issues));
    }
}
