"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.installLicenseFile = installLicenseFile;
exports.deriveInstalledLicenseFilename = deriveInstalledLicenseFilename;
const node_fs_1 = __importDefault(require("node:fs"));
const node_path_1 = __importDefault(require("node:path"));
const license_resolution_1 = require("./license-resolution");
const license_file_1 = require("./license-file");
const license_guidance_1 = require("./license-guidance");
const SAFE_LICENSE_ID_PATTERN = /^[A-Za-z0-9][A-Za-z0-9._-]*$/;
function installLicenseFile(options) {
    const discovery = (0, license_resolution_1.discoverLicenseSources)(options);
    const sourcePath = options.sourcePath;
    const licenseDirectory = discovery.userLicenseDirectory;
    const hostLicensePath = discovery.hostLicensePath;
    const automationHostGuidance = (0, license_guidance_1.renderAutomationHostGuidanceLine)(hostLicensePath);
    if (!node_fs_1.default.existsSync(sourcePath)) {
        return installFailure({
            sourcePath,
            licenseDirectory,
            hostLicensePath,
            automationHostGuidance,
            reason: "source_missing",
            message: "License source file does not exist."
        });
    }
    const sourceStat = safeStatFile(sourcePath);
    if (sourceStat === null) {
        return installFailure({
            sourcePath,
            licenseDirectory,
            hostLicensePath,
            automationHostGuidance,
            reason: "source_unreadable",
            message: "License source path is not a readable file."
        });
    }
    let parseResult;
    try {
        parseResult = (0, license_file_1.parseLicenseFile)(sourcePath);
    }
    catch {
        return installFailure({
            sourcePath,
            licenseDirectory,
            hostLicensePath,
            automationHostGuidance,
            reason: "source_unreadable",
            message: "License source file could not be read."
        });
    }
    if (!parseResult.ok) {
        return installFailure({
            sourcePath,
            licenseDirectory,
            hostLicensePath,
            automationHostGuidance,
            reason: parseResult.reason,
            message: malformedInstallMessage(parseResult.reason)
        });
    }
    const verification = (0, license_file_1.verifyLicenseFileSignature)(parseResult.parsed);
    if (!verification.ok) {
        return installFailure({
            sourcePath,
            licenseDirectory,
            hostLicensePath,
            automationHostGuidance,
            reason: verification.reason,
            message: signatureInstallMessage(verification.reason)
        });
    }
    const installedFilename = deriveInstalledLicenseFilename(parseResult.parsed.safePayload.licenseId);
    if (installedFilename === null) {
        return installFailure({
            sourcePath,
            licenseDirectory,
            hostLicensePath,
            automationHostGuidance,
            reason: "unsafe_license_id",
            message: "License payload license_id cannot be used as a safe installed filename."
        });
    }
    const installedPath = resolveInstalledLicensePath(licenseDirectory, installedFilename);
    if (installedPath === null) {
        return installFailure({
            sourcePath,
            licenseDirectory,
            hostLicensePath,
            automationHostGuidance,
            reason: "destination_escape",
            message: "Installed license destination would escape the license directory."
        });
    }
    try {
        node_fs_1.default.mkdirSync(licenseDirectory, { recursive: true });
        const replacedExisting = node_fs_1.default.existsSync(installedPath);
        copyFileAtomically(sourcePath, installedPath);
        return {
            ok: true,
            installed: true,
            sourcePath,
            licenseDirectory,
            installedPath,
            installedFilename,
            replacedExisting,
            hostLicensePath,
            automationHostGuidance
        };
    }
    catch {
        return installFailure({
            sourcePath,
            licenseDirectory,
            hostLicensePath,
            automationHostGuidance,
            reason: "copy_failed",
            message: "License file could not be copied to the user-local license directory."
        });
    }
}
function deriveInstalledLicenseFilename(licenseId) {
    if (licenseId === undefined) {
        return null;
    }
    const trimmed = licenseId.trim();
    if (trimmed.length === 0 ||
        trimmed === "." ||
        trimmed === ".." ||
        trimmed.includes("/") ||
        trimmed.includes("\\") ||
        trimmed.includes("..") ||
        !SAFE_LICENSE_ID_PATTERN.test(trimmed)) {
        return null;
    }
    return `${trimmed}.json`;
}
function resolveInstalledLicensePath(licenseDirectory, installedFilename) {
    const resolvedDirectory = node_path_1.default.resolve(licenseDirectory);
    const resolvedDestination = node_path_1.default.resolve(resolvedDirectory, installedFilename);
    return node_path_1.default.dirname(resolvedDestination) === resolvedDirectory
        ? resolvedDestination
        : null;
}
function safeStatFile(filePath) {
    try {
        const stat = node_fs_1.default.statSync(filePath);
        return stat.isFile() ? stat : null;
    }
    catch {
        return null;
    }
}
function copyFileAtomically(sourcePath, installedPath) {
    const tempPath = node_path_1.default.join(node_path_1.default.dirname(installedPath), `.${node_path_1.default.basename(installedPath)}.${process.pid}.${Date.now()}.tmp`);
    try {
        node_fs_1.default.copyFileSync(sourcePath, tempPath);
        node_fs_1.default.renameSync(tempPath, installedPath);
    }
    catch (error) {
        try {
            node_fs_1.default.rmSync(tempPath, { force: true });
        }
        catch {
            // Best-effort cleanup after a failed install; the reported failure remains copy_failed.
        }
        throw error;
    }
}
function installFailure(options) {
    return {
        ok: false,
        installed: false,
        sourcePath: options.sourcePath,
        licenseDirectory: options.licenseDirectory,
        installedPath: null,
        installedFilename: null,
        replacedExisting: false,
        hostLicensePath: options.hostLicensePath,
        automationHostGuidance: options.automationHostGuidance,
        reason: options.reason,
        message: options.message
    };
}
function malformedInstallMessage(reason) {
    switch (reason) {
        case "malformed_json":
            return "License source file is not valid JSON.";
        case "malformed_envelope":
            return "License source file does not contain a valid Day Shift license envelope.";
        case "unsupported_schema_version":
            return "License source file uses an unsupported schema version.";
        case "malformed_payload":
            return "License source file does not contain a valid payload.";
        case "malformed_signature":
            return "License source file does not contain a valid signature block.";
    }
}
function signatureInstallMessage(reason) {
    switch (reason) {
        case "unsupported_algorithm":
            return "License source file uses an unsupported signature algorithm.";
        case "unsupported_key_id":
            return "License source file uses an unsupported signing key.";
        case "malformed_signature":
            return "License source file contains a malformed signature value.";
        case "signature_mismatch":
            return "License source file signature does not match the signed payload.";
        case "canonical_payload_not_encodable":
            return "License source file payload cannot be canonicalized for signature verification.";
    }
}
