"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.createTemplatesListCommand = createTemplatesListCommand;
const node_fs_1 = __importDefault(require("node:fs"));
const errors_1 = require("../../../lib/errors");
const output_1 = require("../../../lib/output");
const paths_1 = require("../../../lib/paths");
const runtime_contract_1 = require("../../../lib/runtime/runtime-contract");
const path_resolution_1 = require("../../../lib/templates/path-resolution");
const global_format_1 = require("../global-format");
const PACKAGED_DEFAULT_ARTIFACT_PATHS = new Set([
    ".day-shift/templates/specification.md",
    ".day-shift/templates/slice-overview.md",
    ".day-shift/templates/phase-overview.md",
    ".day-shift/templates/milestone-overview.md",
    ".day-shift/templates/task-definition.md",
    ".day-shift/templates/implementation-summary.md",
    ".day-shift/templates/reconciliation.md",
    ".day-shift/templates/milestone-reconciliation.md"
]);
async function createTemplatesListCommand() {
    const { Command } = await import("commander");
    const command = new Command("list");
    command
        .description("List manifest-backed template inventory without writing template files or metadata.")
        .action((_, commandInstance) => {
        const format = (0, output_1.resolveOutputFormat)((0, global_format_1.getGlobalFormat)(commandInstance));
        if (format === null) {
            throw (0, errors_1.createUsageError)("Output format must be one of: text, json.", [`Received: ${String((0, global_format_1.getGlobalFormat)(commandInstance))}`]);
        }
        const repositoryContext = (0, runtime_contract_1.createRepositoryContext)((0, runtime_contract_1.detectRepositoryRoot)(), false);
        const { document, findings } = loadTemplateManifest(repositoryContext.root);
        const entries = document.templates.map((entry) => classifyTemplateEntry(repositoryContext.root, entry));
        const driftFindings = collectTemplateWorkspaceFindings(entries);
        const result = {
            repositoryRoot: repositoryContext.root,
            manifestPath: path_resolution_1.TEMPLATE_MANIFEST_PATH,
            manifestSource: "workspace",
            templateManifestVersion: readNumber(document.template_manifest_version),
            templateVersion: readNumber(document.template_version),
            familyVersionAvailable: typeof document.template_version === "number",
            entryCount: entries.length,
            entries
        };
        const allFindings = [...findings, ...driftFindings];
        (0, output_1.emitSuccess)({
            command: "templates list",
            format,
            text: renderTemplatesListText(result, allFindings),
            data: result,
            findings: allFindings
        });
    });
    return command;
}
function loadTemplateManifest(repositoryRoot) {
    const manifestAbsolutePath = (0, path_resolution_1.resolveWorkspaceTemplateAbsolutePath)({
        repositoryRoot,
        templatePath: path_resolution_1.TEMPLATE_MANIFEST_PATH
    });
    if (!node_fs_1.default.existsSync(manifestAbsolutePath)) {
        throw blockedTemplateListError({
            message: "Template inventory could not be listed.",
            detail: `Template manifest '${path_resolution_1.TEMPLATE_MANIFEST_PATH}' does not exist in the repository workspace.`,
            findingPath: path_resolution_1.TEMPLATE_MANIFEST_PATH
        });
    }
    try {
        const parsed = JSON.parse(node_fs_1.default.readFileSync(manifestAbsolutePath, "utf8"));
        if (!Array.isArray(parsed.templates)) {
            throw new TypeError(`Template manifest '${path_resolution_1.TEMPLATE_MANIFEST_PATH}' is missing a templates[] collection.`);
        }
        const document = {
            template_manifest_version: parsed.template_manifest_version,
            template_version: parsed.template_version,
            templates: parsed.templates
        };
        return {
            document,
            findings: collectTemplateManifestFindings(document)
        };
    }
    catch (error) {
        const detail = error instanceof Error
            ? error.message
            : `Template manifest '${path_resolution_1.TEMPLATE_MANIFEST_PATH}' could not be read.`;
        throw blockedTemplateListError({
            message: "Template inventory could not be listed.",
            detail,
            findingPath: path_resolution_1.TEMPLATE_MANIFEST_PATH
        });
    }
}
function collectTemplateManifestFindings(document) {
    const findings = [];
    if (typeof document.template_version !== "number") {
        findings.push(createTemplateFinding({
            code: "TEMPLATE_FAMILY_VERSION_MISSING",
            message: "Template manifest does not declare a numeric top-level template_version.",
            path: path_resolution_1.TEMPLATE_MANIFEST_PATH,
            evidenceSource: "manifest:template_version",
            reason: "missing-template-family-version",
            recommendedCommand: "template update"
        }));
    }
    document.templates.forEach((entry, index) => {
        const entryPath = typeof entry.path === "string"
            ? entry.path
            : `${path_resolution_1.TEMPLATE_MANIFEST_PATH}#templates[${index}]`;
        if (typeof entry.version !== "number") {
            findings.push(createTemplateFinding({
                code: "TEMPLATE_ENTRY_VERSION_MISSING",
                message: `Template manifest entry '${entryPath}' does not declare a numeric version.`,
                path: entryPath,
                evidenceSource: "manifest:templates[].version",
                reason: "missing-template-entry-version",
                recommendedCommand: "template update"
            }));
        }
        if (typeof entry.path !== "string" || typeof entry.kind !== "string" || typeof entry.artifact_type !== "string") {
            findings.push(createTemplateFinding({
                code: "TEMPLATE_ENTRY_IDENTITY_INCOMPLETE",
                message: `Template manifest entry '${entryPath}' is missing path, kind, or artifact_type identity fields.`,
                path: entryPath,
                evidenceSource: "manifest:templates[]",
                reason: "incomplete-template-entry-identity",
                recommendedCommand: "manifest update"
            }));
        }
    });
    return findings;
}
function classifyTemplateEntry(repositoryRoot, entry) {
    const entryPath = typeof entry.path === "string" ? entry.path : "";
    const kind = typeof entry.kind === "string" ? entry.kind : null;
    const artifactType = typeof entry.artifact_type === "string" ? entry.artifact_type : null;
    const destination = typeof entry.destination === "string" ? entry.destination : null;
    const usage = typeof entry.usage === "string" ? entry.usage : null;
    const version = readNumber(entry.version);
    const sourceExists = entryPath !== "" && repositoryPathExists(repositoryRoot, entryPath);
    const destinationExists = destination === null
        ? null
        : repositoryPathExists(repositoryRoot, destination);
    return {
        path: entryPath,
        role: classifyTemplateRole({
            path: entryPath,
            kind,
            artifactType,
            destination
        }),
        kind,
        artifactType,
        sourceTemplateIdentity: isSourceTemplateIdentity({ kind, destination }),
        generatedDestinationPolicy: describeGeneratedDestinationPolicy({
            entryPath,
            role: classifyTemplateRole({
                path: entryPath,
                kind,
                artifactType,
                destination
            })
        }),
        version,
        versionAvailable: version !== null,
        usage,
        destination,
        destinationEligibility: classifyDestinationEligibility({ kind, destination }),
        sourceExists,
        destinationExists
    };
}
function repositoryPathExists(repositoryRoot, repositoryPath) {
    try {
        return node_fs_1.default.existsSync((0, paths_1.resolveRepositoryRelativePath)(repositoryRoot, repositoryPath));
    }
    catch {
        return false;
    }
}
function collectTemplateWorkspaceFindings(entries) {
    const findings = [];
    for (const entry of entries) {
        if (entry.path !== "" && !entry.sourceExists) {
            findings.push(createTemplateFinding({
                code: "TEMPLATE_SOURCE_MISSING",
                message: `Template manifest entry '${entry.path}' does not exist in the local template workspace.`,
                path: entry.path,
                evidenceSource: "workspace-template-source",
                reason: "missing-template-source",
                recommendedCommand: "template materialize"
            }));
        }
        if (entry.destinationEligibility === "declared"
            && entry.destination !== null
            && entry.destinationExists === false) {
            findings.push(createTemplateFinding({
                code: "TEMPLATE_DESTINATION_MISSING",
                message: `Template manifest entry '${entry.path}' declares destination '${entry.destination}', but that destination does not exist in the local workspace.`,
                path: entry.destination,
                evidenceSource: "workspace-template-destination",
                reason: "missing-template-destination",
                recommendedCommand: "template materialize"
            }));
        }
        if (entry.destinationEligibility === "not-applicable" && entry.destination !== null) {
            findings.push(createTemplateFinding({
                code: "TEMPLATE_DESTINATION_NOT_ALLOWED",
                message: `Template manifest entry '${entry.path}' declares destination '${entry.destination}', but destination routing is allowed only for scaffold entries.`,
                path: entry.path,
                evidenceSource: "manifest:templates[].destination",
                reason: "invalid-template-destination-routing",
                recommendedCommand: "manifest update"
            }));
        }
    }
    return findings;
}
function createTemplateFinding(options) {
    return (0, output_1.createValidationFinding)({
        code: options.code,
        message: options.message,
        severity: "warning",
        path: options.path,
        ruleFamily: "template-manifest",
        artifactPath: options.path,
        evidenceSource: options.evidenceSource,
        reason: options.reason,
        recommendedCommand: options.recommendedCommand,
        affectedPaths: [
            {
                role: "finding-location",
                path: options.path,
                description: "Template manifest or workspace finding location."
            }
        ],
        evidence: {
            category: "template",
            details: {
                ruleFamily: "template-manifest",
                evidenceSource: options.evidenceSource,
                reason: options.reason,
                recommendedCommand: options.recommendedCommand,
                noWriteBoundary: "Templates list is read-only; it reports template-family evidence and does not materialize, update, or repair template assets."
            }
        }
    });
}
function classifyTemplateRole(options) {
    if (options.kind === "artifact" && options.path.includes("/lightweight-")) {
        return "lightweight-artifact-variant";
    }
    if (options.kind === "artifact" && PACKAGED_DEFAULT_ARTIFACT_PATHS.has(options.path)) {
        return "packaged-default-artifact-template";
    }
    if (options.kind === "artifact") {
        return "repository-local-exception";
    }
    if (options.kind === "scaffold" && options.destination !== null) {
        return "destination-bearing-scaffold-asset";
    }
    if (options.kind === "scaffold") {
        return "usage-only-scaffold-asset";
    }
    return "unclassified";
}
function isSourceTemplateIdentity(options) {
    return options.kind === "artifact" && options.destination === null;
}
function describeGeneratedDestinationPolicy(options) {
    if (options.role !== "packaged-default-artifact-template") {
        return null;
    }
    if (options.entryPath === ".day-shift/templates/slice-overview.md") {
        return "source-template identity; slice scaffold destination is slice-overview.md";
    }
    if (options.entryPath === ".day-shift/templates/phase-overview.md") {
        return "source-template identity; phase scaffold destination is phase-overview.md";
    }
    if (options.entryPath === ".day-shift/templates/milestone-overview.md") {
        return "source-template identity; milestone scaffold destination is milestone-overview.md";
    }
    return "source-template identity; generated destination is selected by the owning scaffold or build command";
}
function classifyDestinationEligibility(options) {
    if (options.kind === "scaffold" && options.destination !== null) {
        return "declared";
    }
    if (options.kind === "scaffold") {
        return "usage-only";
    }
    if (options.kind === "artifact") {
        return "not-applicable";
    }
    return "invalid";
}
function readNumber(value) {
    return typeof value === "number" && Number.isFinite(value) ? value : null;
}
function renderTemplatesListText(result, findings) {
    const lines = [
        (0, output_1.renderTerminalHeading)("Template Inventory", "title"),
        (0, output_1.renderTerminalSection)({
            heading: "Summary",
            fields: [
                { label: "Entries", value: result.entryCount },
                { label: "Findings", value: findings.length },
                { label: "Family version available", value: result.familyVersionAvailable ? "yes" : "no" }
            ]
        }),
        "",
        (0, output_1.renderTerminalSection)({
            heading: "Provenance",
            fields: [
                { label: "Source", value: result.manifestSource },
                { label: "Manifest path", value: result.manifestPath },
                { label: "Template manifest version", value: result.templateManifestVersion ?? "missing" },
                { label: "Family template version", value: result.templateVersion ?? "missing" }
            ]
        }),
        "",
        (0, output_1.renderTerminalCompactList)({
            heading: "Entries",
            entrySpacing: "loose",
            entries: result.entries.map((entry) => ({
                label: entry.path === "" ? "(missing path)" : entry.path,
                fields: [
                    { label: "Role", value: entry.role },
                    { label: "Kind", value: entry.kind ?? "missing" },
                    { label: "Artifact type", value: entry.artifactType ?? "missing" },
                    { label: "Source template identity", value: entry.sourceTemplateIdentity ? "yes" : "no" },
                    { label: "Generated destination policy", value: entry.generatedDestinationPolicy ?? "not-applicable" },
                    { label: "Entry version", value: entry.version ?? "missing" },
                    { label: "Entry version available", value: entry.versionAvailable ? "yes" : "no" },
                    { label: "Source exists", value: entry.sourceExists ? "yes" : "no" },
                    { label: "Destination eligibility", value: entry.destinationEligibility },
                    { label: "Destination", value: entry.destination ?? "none" },
                    {
                        label: "Destination exists",
                        value: entry.destinationExists === null ? "not-applicable" : entry.destinationExists ? "yes" : "no"
                    },
                    ...(entry.usage === null ? [] : [{ label: "Usage", value: entry.usage }])
                ]
            })),
            emptyMessage: "No template entries were found in the manifest."
        }),
        "",
        (0, output_1.renderValidationFindingsText)(findings, "Findings"),
        "",
        (0, output_1.renderTerminalSection)({
            heading: "Write Boundary",
            lines: [(0, output_1.renderTerminalBoundary)({ kind: "read-only" })]
        })
    ];
    return lines.join("\n");
}
function blockedTemplateListError(options) {
    const finding = (0, output_1.createValidationFinding)({
        code: "TEMPLATE_LIST_BLOCKED",
        message: options.detail,
        severity: "error",
        path: options.findingPath,
        ruleFamily: "template-manifest",
        artifactPath: options.findingPath,
        evidenceSource: "manifest-read",
        reason: "template-list-blocked",
        noWriteBoundary: "Templates list is read-only; blocked reads must not create fallback manifests or rewrite malformed JSON.",
        recommendedCommand: "template update"
    });
    return (0, errors_1.createInvalidConfigError)(options.message, [options.detail], [finding]);
}
