"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.loadUserEventHooks = loadUserEventHooks;
exports.loadUserEventHookEntries = loadUserEventHookEntries;
exports.writeUserEventHooks = writeUserEventHooks;
exports.getUserEventHooksPath = getUserEventHooksPath;
exports.getUserEventHooksLedgerPath = getUserEventHooksLedgerPath;
exports.getUserEventHookDirectory = getUserEventHookDirectory;
exports.requireUserEventHookDirectory = requireUserEventHookDirectory;
exports.resolveUserEventHookFilePath = resolveUserEventHookFilePath;
exports.normalizeUserEventHookFilePath = normalizeUserEventHookFilePath;
const node_crypto_1 = require("node:crypto");
const promises_1 = require("node:fs/promises");
const node_path_1 = __importDefault(require("node:path"));
const paths_1 = require("../core/paths");
const control_plane_home_1 = require("../core/control-plane-home");
const global_settings_1 = require("../core/global-settings");
const provider_resolution_1 = require("../platform/provider-resolution");
const config_1 = require("./config");
async function loadUserEventHooks(input) {
    const filePath = getUserEventHooksPath(input);
    let text;
    try {
        text = await (0, promises_1.readFile)(filePath, "utf8");
    }
    catch (error) {
        if (isFileNotFoundError(error)) {
            return [];
        }
        throw error;
    }
    return [...(0, config_1.parseUserEventHookConfigFile)(JSON.parse(text)).eventHooks];
}
async function loadUserEventHookEntries(input) {
    const globalTarget = { scope: "global" };
    const projectTarget = { scope: "project", config: input.config };
    const [globalHooks, projectHooks] = await Promise.all([
        loadUserEventHooks({
            target: globalTarget,
            ...optionalHomeDirectory(input.homeDirectory),
        }),
        loadUserEventHooks({
            target: projectTarget,
            ...optionalHomeDirectory(input.homeDirectory),
        }),
    ]);
    if (globalHooks.length === 0 && projectHooks.length === 0) {
        return [];
    }
    const userDirectory = requireUserEventHookDirectory(input.homeDirectory);
    return [
        ...globalHooks.map((hook) => ({
            hook,
            source: "user:all",
            baseDirectory: userDirectory,
        })),
        ...projectHooks.map((hook) => ({
            hook,
            source: "user:project",
            baseDirectory: userDirectory,
        })),
    ];
}
async function writeUserEventHooks(input) {
    const filePath = getUserEventHooksPath(input);
    const file = {
        eventHooks: (0, config_1.validateUserEventHooks)(input.eventHooks),
    };
    const directory = node_path_1.default.dirname(filePath);
    const tempPath = node_path_1.default.join(directory, `.hooks.${(0, node_crypto_1.randomUUID)()}.tmp`);
    await (0, promises_1.mkdir)(directory, { recursive: true });
    try {
        await (0, promises_1.writeFile)(tempPath, `${JSON.stringify(file, null, 2)}\n`, "utf8");
        await (0, promises_1.rename)(tempPath, filePath);
    }
    catch (error) {
        await (0, promises_1.rm)(tempPath, { force: true });
        throw error;
    }
    return filePath;
}
function getUserEventHooksPath(input) {
    return input.target.scope === "global"
        ? (0, paths_1.getEventHooksGlobalConfigPath)(input.homeDirectory)
        : (0, paths_1.getEventHooksProjectConfigPath)((0, provider_resolution_1.getEventHookProjectStorageSegments)(input.target.config), input.homeDirectory);
}
function getUserEventHooksLedgerPath(input) {
    return input.target.scope === "global"
        ? (0, paths_1.getEventHooksGlobalLedgerPath)(input.homeDirectory)
        : (0, paths_1.getEventHooksProjectLedgerPath)((0, provider_resolution_1.getEventHookProjectStorageSegments)(input.target.config), input.homeDirectory);
}
function getUserEventHookDirectory(homeDirectory) {
    return ((0, global_settings_1.loadControlPlaneGlobalSettings)(homeDirectory).eventHooks?.userDirectory ??
        null);
}
function requireUserEventHookDirectory(homeDirectory) {
    const directory = getUserEventHookDirectory(homeDirectory);
    if (directory === null) {
        throw new Error("User event hook directory is not configured. Run alpaca event-hook config set --user-dir <directory> first.");
    }
    return directory;
}
function resolveUserEventHookFilePath(input) {
    return normalizeUserEventHookFilePath({
        hookPath: input.hookPath,
        ...optionalHomeDirectory(input.homeDirectory),
    });
}
function normalizeUserEventHookFilePath(input) {
    const resolved = (0, config_1.normalizeEventHookConfigPath)({
        hookPath: input.hookPath,
        baseDir: input.baseDirectory ?? requireUserEventHookDirectory(input.homeDirectory),
        allowAbsolutePath: false,
    });
    assertOutsideHiddenEventHookStorage(resolved.absolutePath, input.homeDirectory);
    return resolved;
}
function isFileNotFoundError(error) {
    return (typeof error === "object" &&
        error !== null &&
        "code" in error &&
        error.code === "ENOENT");
}
function optionalHomeDirectory(homeDirectory) {
    return homeDirectory === undefined ? {} : { homeDirectory };
}
function assertOutsideHiddenEventHookStorage(absolutePath, homeDirectory) {
    const eventHooksRoot = node_path_1.default.join((0, control_plane_home_1.getControlPlaneHomePath)(homeDirectory), "event-hooks");
    const relativePath = node_path_1.default.relative(eventHooksRoot, absolutePath);
    if (relativePath === "" ||
        (!relativePath.startsWith("..") && !node_path_1.default.isAbsolute(relativePath))) {
        throw new Error("User event hook files must not be inside ~/.alpaca/event-hooks.");
    }
}
