"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.copyRepositoryNoticeFiles = copyRepositoryNoticeFiles;
exports.copyDirectoryFiltered = copyDirectoryFiltered;
exports.copyRepositorySharedAuthoringDirectories = copyRepositorySharedAuthoringDirectories;
exports.resolveReleaseAgentEntrypointSourcePath = resolveReleaseAgentEntrypointSourcePath;
exports.removePublicCliExcludedPrivateRuntimeFiles = removePublicCliExcludedPrivateRuntimeFiles;
exports.validateReleasePayloadContent = validateReleasePayloadContent;
exports.classifyForbiddenReleasePayloadFile = classifyForbiddenReleasePayloadFile;
exports.isPackageManagerCachePath = isPackageManagerCachePath;
exports.isLocalLicenseStatePath = isLocalLicenseStatePath;
exports.isReminderStatePath = isReminderStatePath;
exports.isConfigOverridePath = isConfigOverridePath;
exports.classifyPrivateLicenseOperationPath = classifyPrivateLicenseOperationPath;
exports.isPrivateSigningKeyPath = isPrivateSigningKeyPath;
exports.isPrivateSupportRecordPath = isPrivateSupportRecordPath;
exports.isRuntimeRequiredTypeScriptPath = isRuntimeRequiredTypeScriptPath;
exports.createForbiddenPayloadFile = createForbiddenPayloadFile;
exports.normalizePayloadPath = normalizePayloadPath;
exports.collectFiles = collectFiles;
exports.normalizeStringRecord = normalizeStringRecord;
exports.readOptionalString = readOptionalString;
exports.toRepositoryRelativePath = toRepositoryRelativePath;
// Mechanically extracted from output-lifecycle.ts to keep release responsibilities bounded.
const node_fs_1 = __importDefault(require("node:fs"));
const node_path_1 = __importDefault(require("node:path"));
const errors_1 = require("../../../lib/errors");
const default_assets_1 = require("../../../lib/workspace-init/default-assets");
const output_lifecycle_output_state_1 = require("./output-lifecycle-output-state");
const output_lifecycle_staging_1 = require("./output-lifecycle-staging");
function copyRepositoryNoticeFiles(options) {
    const noticeFiles = node_fs_1.default
        .readdirSync(options.repositoryRoot, { withFileTypes: true })
        .filter((entry) => entry.isFile())
        .map((entry) => entry.name)
        .filter((name) => /^(?:LICENSE|NOTICE|THIRD_PARTY_NOTICES)(?:\..*)?$/i.test(name))
        .sort();
    for (const noticeFile of noticeFiles) {
        node_fs_1.default.copyFileSync(node_path_1.default.join(options.repositoryRoot, noticeFile), node_path_1.default.join(options.stagingDirectory, noticeFile));
    }
    return noticeFiles;
}
function copyDirectoryFiltered(options) {
    if (!node_fs_1.default.existsSync(options.sourceDirectory) || !node_fs_1.default.statSync(options.sourceDirectory).isDirectory()) {
        return;
    }
    for (const entry of node_fs_1.default.readdirSync(options.sourceDirectory, { withFileTypes: true })) {
        const sourcePath = node_path_1.default.join(options.sourceDirectory, entry.name);
        const destinationPath = node_path_1.default.join(options.destinationDirectory, entry.name);
        const payloadRelativePath = toRepositoryRelativePath(options.payloadRoot, destinationPath);
        const forbidden = classifyForbiddenReleasePayloadFile(payloadRelativePath);
        if (forbidden !== null) {
            continue;
        }
        if (entry.isDirectory()) {
            copyDirectoryFiltered({
                sourceDirectory: sourcePath,
                destinationDirectory: destinationPath,
                payloadRoot: options.payloadRoot,
            });
        }
        else if (entry.isFile()) {
            node_fs_1.default.mkdirSync(node_path_1.default.dirname(destinationPath), { recursive: true });
            node_fs_1.default.copyFileSync(sourcePath, destinationPath);
        }
        else if (entry.isSymbolicLink()) {
            node_fs_1.default.mkdirSync(node_path_1.default.dirname(destinationPath), { recursive: true });
            node_fs_1.default.symlinkSync(node_fs_1.default.readlinkSync(sourcePath), destinationPath);
        }
    }
}
function copyRepositorySharedAuthoringDirectories(options) {
    for (const filePlan of [
        {
            sourcePath: resolveReleaseAgentEntrypointSourcePath(options.repositoryRoot),
            destinationRelativePath: '.day-shift/agents.md',
        },
        {
            sourcePath: node_path_1.default.join(options.repositoryRoot, '.day-shift', '.markdownlint.json'),
            destinationRelativePath: '.day-shift/.markdownlint.json',
        },
    ]) {
        const sourcePath = filePlan.sourcePath;
        const relativeFile = filePlan.destinationRelativePath;
        const destinationPath = node_path_1.default.join(options.stagingDirectory, ...relativeFile.split('/'));
        if (!node_fs_1.default.existsSync(sourcePath) || !node_fs_1.default.statSync(sourcePath).isFile()) {
            continue;
        }
        const forbidden = classifyForbiddenReleasePayloadFile(toRepositoryRelativePath(options.stagingDirectory, destinationPath));
        if (forbidden !== null) {
            continue;
        }
        node_fs_1.default.mkdirSync(node_path_1.default.dirname(destinationPath), { recursive: true });
        node_fs_1.default.copyFileSync(sourcePath, destinationPath);
    }
    for (const relativeDirectory of default_assets_1.SHARED_AUTHORING_SOURCE_ROOTS) {
        copyDirectoryFiltered({
            sourceDirectory: node_path_1.default.join(options.repositoryRoot, ...relativeDirectory.split('/')),
            destinationDirectory: node_path_1.default.join(options.stagingDirectory, ...relativeDirectory.split('/')),
            payloadRoot: options.stagingDirectory,
        });
    }
}
function resolveReleaseAgentEntrypointSourcePath(repositoryRoot) {
    const scaffoldEntrypointPath = node_path_1.default.join(repositoryRoot, '.day-shift', 'scaffolds', 'agents.init.md');
    if (node_fs_1.default.existsSync(scaffoldEntrypointPath) && node_fs_1.default.statSync(scaffoldEntrypointPath).isFile()) {
        return scaffoldEntrypointPath;
    }
    return node_path_1.default.join(repositoryRoot, '.day-shift', 'agents.md');
}
function removePublicCliExcludedPrivateRuntimeFiles(stagingDirectory) {
    for (const relativePath of output_lifecycle_output_state_1.PUBLIC_CLI_EXCLUDED_PRIVATE_RUNTIME_FILES) {
        (0, output_lifecycle_staging_1.removeIfExists)(node_path_1.default.join(stagingDirectory, ...relativePath.split('/')));
    }
}
function validateReleasePayloadContent(options) {
    const fileSet = new Set(options.files);
    const missingRequiredFiles = options.requiredFiles.filter((requiredFile) => !fileSet.has(requiredFile));
    const forbiddenFiles = options.files
        .map((filePath) => classifyForbiddenReleasePayloadFile(filePath))
        .filter((finding) => finding !== null);
    if (missingRequiredFiles.length > 0 || forbiddenFiles.length > 0) {
        throw (0, errors_1.createUsageError)(`Release ${options.payload} payload content validation failed.`, [
            'Reason: forbidden-or-missing-release-payload-content',
            `Missing required files: ${missingRequiredFiles.length === 0 ? '(none)' : missingRequiredFiles.join(', ')}`,
            `Forbidden files: ${forbiddenFiles.length === 0 ? '(none)' : forbiddenFiles.map((finding) => `${finding.path} [${finding.group}] ${finding.reason}`).join('; ')}`,
            'Recovery: fix release staging/archive payload rules so required runtime files remain and forbidden local or development files are excluded.',
            'Exit behavior: exits before successful-release state is recorded.',
        ]);
    }
    return {
        status: 'passed',
        payload: options.payload,
        requiredFiles: [...options.requiredFiles],
        forbiddenFiles: [],
    };
}
function classifyForbiddenReleasePayloadFile(filePath) {
    const normalizedPath = normalizePayloadPath(filePath);
    const segments = normalizedPath.split('/');
    const basename = segments[segments.length - 1] ?? normalizedPath;
    if (normalizedPath.startsWith('.day-shift/specs/')) {
        return createForbiddenPayloadFile(normalizedPath, 'planning-specs', 'planning specification artifacts are not runtime payload files');
    }
    if (normalizedPath.startsWith('.day-shift/planning/')) {
        return createForbiddenPayloadFile(normalizedPath, 'planning-artifacts', 'planning artifacts are not runtime payload files');
    }
    if (normalizedPath.startsWith('.day-shift/state/') ||
        normalizedPath.startsWith('.day-shift/local/') ||
        normalizedPath.startsWith('.day-shift/runs/') ||
        normalizedPath.startsWith('.day-shift/rehearsals/') ||
        normalizedPath.startsWith('.day-shift/checkpoints/')) {
        return createForbiddenPayloadFile(normalizedPath, 'local-day-shift-state', 'local Day Shift state must not be released');
    }
    if (segments.includes('test') || segments.includes('tests') || /\.test\.[cm]?[jt]s$/.test(basename)) {
        return createForbiddenPayloadFile(normalizedPath, 'tests', 'tests are development-only');
    }
    if (segments.includes('fixture') || segments.includes('fixtures')) {
        return createForbiddenPayloadFile(normalizedPath, 'fixtures', 'fixtures are development-only');
    }
    if (isPackageManagerCachePath(normalizedPath, segments)) {
        return createForbiddenPayloadFile(normalizedPath, 'package-manager-cache', 'package-manager caches are local generated state');
    }
    if (isLocalLicenseStatePath(normalizedPath, basename)) {
        return createForbiddenPayloadFile(normalizedPath, 'local-license-state', 'local license state is user-specific and must not be released');
    }
    if (isReminderStatePath(normalizedPath, basename)) {
        return createForbiddenPayloadFile(normalizedPath, 'reminder-state', 'reminder state and generated reminder artifacts are user-specific');
    }
    if (isConfigOverridePath(normalizedPath, basename)) {
        return createForbiddenPayloadFile(normalizedPath, 'config-overrides', 'local configuration overrides are user-specific');
    }
    const privateLicenseOperation = classifyPrivateLicenseOperationPath(normalizedPath, segments, basename);
    if (privateLicenseOperation !== null) {
        return privateLicenseOperation;
    }
    if (/\.(?:ts|tsx)$/.test(basename) && !isRuntimeRequiredTypeScriptPath(normalizedPath)) {
        return createForbiddenPayloadFile(normalizedPath, 'source-typescript', 'source TypeScript files are excluded unless explicitly runtime-required');
    }
    return null;
}
function isPackageManagerCachePath(normalizedPath, segments) {
    return (normalizedPath === '.pnpm-store' ||
        normalizedPath.startsWith('.pnpm-store/') ||
        normalizedPath === '.npm' ||
        normalizedPath.startsWith('.npm/') ||
        normalizedPath === '.yarn/cache' ||
        normalizedPath.startsWith('.yarn/cache/') ||
        segments.includes('.cache') ||
        segments.includes('.pnpm-store') ||
        segments.includes('.npm') ||
        segments.includes('.turbo'));
}
function isLocalLicenseStatePath(normalizedPath, basename) {
    return (normalizedPath.startsWith('.day-shift/licenses/') ||
        normalizedPath.startsWith('.day-shift/license/') ||
        /^\.?day-shift-license(?:[._-].*)?$/i.test(basename) ||
        /^license(?:[._-]state|[._-]local)\./i.test(basename));
}
function isReminderStatePath(normalizedPath, basename) {
    return (normalizedPath.startsWith('.day-shift/reminders/') ||
        normalizedPath.startsWith('.day-shift/managed-reminders/') ||
        /^\.?day-shift-reminder/i.test(basename) ||
        /^managed-reminder/i.test(basename) ||
        /^reminder(?:[._-]state|[._-]local)\.(?:json|ya?ml|toml|txt|log)$/i.test(basename));
}
function isConfigOverridePath(normalizedPath, basename) {
    return (normalizedPath.startsWith('.day-shift/config.local') ||
        normalizedPath.startsWith('.day-shift/config/') ||
        /^day-shift\.config\.local\./i.test(basename) ||
        /^\.env(?:\.|$)/.test(basename));
}
function classifyPrivateLicenseOperationPath(normalizedPath, segments, basename) {
    if (segments.includes('local-license-ops')) {
        return createForbiddenPayloadFile(normalizedPath, 'private-license-ops', 'local license-issuer operator files must not be released');
    }
    if (/^issue-local-license\.(?:js|cjs|mjs)$/i.test(basename)) {
        return createForbiddenPayloadFile(normalizedPath, 'private-license-issuer-script', 'local issuer scripts must not be released');
    }
    if (/^license-issuer\.(?:js|cjs|mjs|map|d\.ts)$/i.test(basename)) {
        return createForbiddenPayloadFile(normalizedPath, 'private-license-issuer-runtime', 'compiled issuer helpers must not be released');
    }
    if (/^recipients\.(?:csv|json)$/i.test(basename)) {
        return createForbiddenPayloadFile(normalizedPath, 'private-license-recipient-input', 'recipient input is private license-operation data');
    }
    if (segments.includes('licenses-out')) {
        return createForbiddenPayloadFile(normalizedPath, 'private-generated-license-output', 'generated license batches must not be released');
    }
    if (/^(?:beta|vip)[\w.-]*licenses?[\w.-]*\.(?:json|zip|tgz|tar\.gz)$/i.test(basename)) {
        return createForbiddenPayloadFile(normalizedPath, 'private-generated-license-batch', 'generated beta/VIP license batches must not be released');
    }
    if (/^issuance-report\.json$/i.test(basename)) {
        return createForbiddenPayloadFile(normalizedPath, 'private-license-issuance-report', 'license issuance reports are private operator records');
    }
    if (isPrivateSigningKeyPath(basename)) {
        return createForbiddenPayloadFile(normalizedPath, 'private-license-signing-key', 'private signing keys must not be released');
    }
    if (isPrivateSupportRecordPath(normalizedPath, segments, basename)) {
        return createForbiddenPayloadFile(normalizedPath, 'private-support-record', 'private support records and archives must not be released');
    }
    return null;
}
function isPrivateSigningKeyPath(basename) {
    return (/(?:private|signing|license|root)[\w.-]*(?:key|ed25519)[\w.-]*\.(?:pem|key|json)$/i.test(basename) ||
        /(?:key|ed25519)[\w.-]*(?:private|signing|license|root)[\w.-]*\.(?:pem|key|json)$/i.test(basename));
}
function isPrivateSupportRecordPath(normalizedPath, segments, basename) {
    return (segments.includes('support-records') ||
        /\bsupport-records?\b/i.test(normalizedPath) ||
        /^support-archive\.(?:zip|tgz|tar\.gz|enc|json)$/i.test(basename) ||
        /^encrypted-support(?:-archive|-records?)?\.(?:zip|tgz|tar\.gz|enc|json)$/i.test(basename));
}
function isRuntimeRequiredTypeScriptPath(_normalizedPath) {
    return false;
}
function createForbiddenPayloadFile(pathValue, group, reason) {
    return {
        path: pathValue,
        group,
        reason,
    };
}
function normalizePayloadPath(filePath) {
    return filePath
        .split(node_path_1.default.sep)
        .join('/')
        .replace(/^\.\/+/, '');
}
function collectFiles(directoryPath) {
    const files = [];
    for (const entry of node_fs_1.default.readdirSync(directoryPath, { withFileTypes: true })) {
        const entryPath = node_path_1.default.join(directoryPath, entry.name);
        if (entry.isDirectory()) {
            files.push(...collectFiles(entryPath));
        }
        else if (entry.isFile()) {
            files.push(entryPath);
        }
    }
    return files;
}
function normalizeStringRecord(value) {
    if (typeof value !== 'object' || value === null || Array.isArray(value)) {
        return {};
    }
    return Object.fromEntries(Object.entries(value).filter((entry) => typeof entry[1] === 'string'));
}
function readOptionalString(value) {
    return typeof value === 'string' ? value : null;
}
function toRepositoryRelativePath(repositoryRoot, value) {
    const relative = node_path_1.default.relative(repositoryRoot, value);
    return relative.split(node_path_1.default.sep).join('/');
}
