/**
 * Pure model for Deploy pipeline stages — parse deploy.yml, map holds, assemble.
 * @module cli/ui-deploy-pipeline-model
 */
import { isJsonObject } from "../sync/json-path.js";
import { loadYaml } from "../utils/yaml.js";
/** Stable probe id consumed by the Deploy section hydration. */
export const DEPLOY_PIPELINE_PROBE_ID = "deploy-pipeline-stages";
const NOT_AUTHENTICATED_REASON = "not-authenticated";
const ENVIRONMENT_NOT_FOUND_REASON = "environment-not-found";
/**
 * Extract ordered job stages from a deploy.yml document.
 * @param contents - Raw YAML text
 * @returns Workflow job stages in document order
 */
export function parseDeployWorkflowStages(contents) {
    try {
        const loaded = loadYaml(contents);
        if (!isJsonObject(loaded)) {
            return [];
        }
        const jobs = loaded.jobs;
        if (!isJsonObject(jobs)) {
            return [];
        }
        return Object.entries(jobs).map(([id, job]) => {
            const name = isJsonObject(job) && typeof job.name === "string" && job.name.length > 0
                ? job.name
                : id;
            return {
                id: `job:${id}`,
                name,
                description: `Workflow job \`${id}\` from deploy.yml`,
                environment: "",
                active: true,
                reason: "",
            };
        });
    }
    catch {
        return [];
    }
}
/**
 * Map one configured environment onto a hold stage using live GH evidence.
 * @param environment - Configured environment name
 * @param lookup - Live environments API result
 * @returns Approval-hold stage that never false-greens
 */
export function mapEnvironmentHoldStage(environment, lookup) {
    const base = {
        id: `hold:${environment}`,
        name: `Release approval — ${environment}`,
        description: `Pauses at the release_approval job until a configured reviewer approves the GitHub environment \`${environment}\``,
        environment,
    };
    if (lookup.status === "not-authenticated") {
        return {
            ...base,
            active: "unknown",
            reason: `${NOT_AUTHENTICATED_REASON}: ${lookup.message}`,
        };
    }
    if (lookup.status === "error") {
        return {
            ...base,
            active: "unknown",
            reason: `environments-api-error: ${lookup.message}`,
        };
    }
    const match = lookup.environments.find(entry => entry.name === environment);
    if (match === undefined) {
        return {
            ...base,
            active: "unknown",
            reason: `${ENVIRONMENT_NOT_FOUND_REASON}: GitHub environment '${environment}' is named in github.environments but was not found on the repository`,
        };
    }
    if (match.hasRequiredReviewers) {
        return { ...base, active: true, reason: "" };
    }
    return {
        ...base,
        active: false,
        reason: `No required reviewers on GitHub environment '${environment}'`,
    };
}
/**
 * Interleave approval holds before the first release job (or append).
 * @param jobStages - Stages parsed from deploy.yml
 * @param holdStages - Per-environment approval hold stages
 * @returns Ordered pipeline stages for the console table
 */
export function assembleDeployPipelineStages(jobStages, holdStages) {
    if (holdStages.length === 0) {
        return jobStages;
    }
    if (jobStages.length === 0) {
        return holdStages;
    }
    const releaseIndex = jobStages.findIndex(stage => /release/iu.test(stage.id) || /release/iu.test(stage.name));
    if (releaseIndex === -1) {
        return [...jobStages, ...holdStages];
    }
    return [
        ...jobStages.slice(0, releaseIndex),
        ...holdStages,
        ...jobStages.slice(releaseIndex),
    ];
}
/**
 * Build the tri-state probe result from filesystem + live environment inputs.
 * @param workflow - deploy.yml contents, or null when absent
 * @param configuredEnvironments - Keys from github.environments
 * @param lookup - Live GitHub environments lookup
 * @returns Probe result — value, not-applicable, or unknown
 */
export function buildDeployPipelineResult(workflow, configuredEnvironments, lookup) {
    const jobStages = workflow === null ? [] : parseDeployWorkflowStages(workflow);
    const holdStages = configuredEnvironments.map(name => mapEnvironmentHoldStage(name, lookup));
    const stages = assembleDeployPipelineStages(jobStages, holdStages);
    if (stages.length === 0) {
        return { state: "not-applicable" };
    }
    return { state: "value", value: { stages: [...stages] } };
}
//# sourceMappingURL=ui-deploy-pipeline-model.js.map