"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.loadAuthProfiles = loadAuthProfiles;
exports.writeAuthProfiles = writeAuthProfiles;
exports.loadAuthProfileStateFile = loadAuthProfileStateFile;
exports.writeAuthProfileStateFile = writeAuthProfileStateFile;
exports.registerAuthProfile = registerAuthProfile;
exports.removeAuthProfile = removeAuthProfile;
exports.clearAllAuthProfiles = clearAllAuthProfiles;
exports.upsertAuthProfileState = upsertAuthProfileState;
exports.ensureAuthProfileResources = ensureAuthProfileResources;
exports.setAuthProfileProviderOrder = setAuthProfileProviderOrder;
const promises_1 = require("node:fs/promises");
const node_path_1 = __importDefault(require("node:path"));
const file_readers_1 = require("../core/file-readers");
const paths_1 = require("../core/paths");
const kind_1 = require("./kind");
const credential_store_1 = require("./credential-store");
const model_1 = require("./model");
const storage_helpers_1 = require("./storage-helpers");
const PRIVATE_DIRECTORY_MODE = 0o700;
async function loadAuthProfiles(homeDirectory) {
    const filePath = (0, paths_1.getAuthProfilesPath)(homeDirectory);
    const profiles = await (0, file_readers_1.readJsonFileIfExists)(filePath, model_1.authProfilesFileSchema);
    return profiles ?? (0, storage_helpers_1.createEmptyAuthProfilesFile)();
}
async function writeAuthProfiles(profiles, homeDirectory) {
    const filePath = (0, paths_1.getAuthProfilesPath)(homeDirectory);
    return writeJsonFile(filePath, model_1.authProfilesFileSchema, (0, storage_helpers_1.normalizeAuthProfilesFile)(profiles));
}
async function loadAuthProfileStateFile(homeDirectory) {
    const filePath = (0, paths_1.getAuthProfileStatePath)(homeDirectory);
    const state = await (0, file_readers_1.readJsonFileIfExists)(filePath, model_1.authProfileStateFileSchema);
    return state ?? (0, storage_helpers_1.createEmptyAuthProfileStateFile)();
}
async function writeAuthProfileStateFile(state, homeDirectory) {
    const filePath = (0, paths_1.getAuthProfileStatePath)(homeDirectory);
    return writeJsonFile(filePath, model_1.authProfileStateFileSchema, state);
}
async function registerAuthProfile(input, homeDirectory) {
    const profiles = await loadAuthProfiles(homeDirectory);
    const provider = (0, kind_1.getAuthProfileProvider)(input);
    const order = (0, storage_helpers_1.nextAuthProfileOrder)(profiles.profiles, provider);
    const profile = (0, storage_helpers_1.createAuthProfile)({
        ...input,
        order,
        createdAt: new Date().toISOString(),
    }, homeDirectory);
    const existing = profiles.profiles.find((candidate) => candidate.id === profile.id);
    if (existing) {
        if ((0, storage_helpers_1.hasSameAuthProfileDefinition)(existing, profile)) {
            await ensureAuthProfileResources(existing);
            await upsertAuthProfileState(existing.id, undefined, homeDirectory);
            return { kind: "noop", profile: existing };
        }
        return { kind: "conflict", existing };
    }
    await writeAuthProfiles((0, storage_helpers_1.appendAuthProfile)(profiles, profile), homeDirectory);
    await ensureAuthProfileResources(profile);
    await upsertAuthProfileState(profile.id, undefined, homeDirectory);
    return { kind: "added", profile };
}
async function removeAuthProfile(profileId, homeDirectory, credentialStore) {
    const profiles = await loadAuthProfiles(homeDirectory);
    const profile = profiles.profiles.find((candidate) => candidate.id === profileId);
    if (!profile) {
        return { kind: "missing" };
    }
    await writeAuthProfiles((0, storage_helpers_1.removeAuthProfileById)(profiles, profileId), homeDirectory);
    await updateAuthProfileStateFile(homeDirectory, (state) => ({
        nextState: (0, storage_helpers_1.removeAuthProfileStateById)(state, profileId),
        result: undefined,
    }));
    const managedPath = (0, kind_1.getManagedAuthProfilePath)(profile);
    if (managedPath) {
        await (0, promises_1.rm)((0, paths_1.getAuthProfileDirectory)(profile.id, homeDirectory), {
            recursive: true,
            force: true,
        });
    }
    const credentialDeleteFailure = tryDeleteAuthProfileCredential(profile, credentialStore);
    return {
        kind: "removed",
        profile,
        ...(credentialDeleteFailure ? { credentialDeleteFailure } : {}),
    };
}
async function clearAllAuthProfiles(homeDirectory, credentialStore) {
    const profiles = await loadAuthProfiles(homeDirectory).catch(() => null);
    await Promise.all([
        (0, promises_1.rm)((0, paths_1.getAuthProfilesPath)(homeDirectory), { force: true }),
        (0, promises_1.rm)((0, paths_1.getAuthProfileStatePath)(homeDirectory), { force: true }),
        (0, promises_1.rm)((0, paths_1.getAuthProfileDirectoriesRootPath)(homeDirectory), {
            recursive: true,
            force: true,
        }),
    ]);
    return (profiles?.profiles ?? [])
        .map((profile) => tryDeleteAuthProfileCredential(profile, credentialStore))
        .filter((failure) => Boolean(failure));
}
function tryDeleteAuthProfileCredential(profile, credentialStore) {
    if (profile.kind !== "claude-api-key") {
        return null;
    }
    try {
        (0, credential_store_1.deleteStoredCredential)(profile, credentialStore);
        return null;
    }
    catch (error) {
        return { profile, error };
    }
}
async function upsertAuthProfileState(profileId, overrides, homeDirectory) {
    return updateAuthProfileStateFile(homeDirectory, (state) => {
        const current = state.states.find((candidate) => candidate.profileId === profileId);
        const next = (0, storage_helpers_1.buildAuthProfileState)(profileId, current, overrides);
        return {
            nextState: (0, storage_helpers_1.replaceAuthProfileState)(state, next),
            result: next,
        };
    });
}
async function ensureAuthProfileResources(profile) {
    const managedPath = (0, kind_1.getManagedAuthProfilePath)(profile);
    if (!managedPath) {
        return;
    }
    await ensurePrivateDirectory(node_path_1.default.dirname(managedPath));
    await ensurePrivateDirectory(managedPath);
}
async function setAuthProfileProviderOrder(provider, orderedProfileIds, homeDirectory) {
    const profiles = await loadAuthProfiles(homeDirectory);
    const nextProfiles = (0, storage_helpers_1.replaceAuthProfiles)(profiles, (0, storage_helpers_1.applyProviderProfileOrder)(profiles.profiles, provider, orderedProfileIds));
    await writeAuthProfiles(nextProfiles, homeDirectory);
    return nextProfiles.profiles.filter((profile) => (0, kind_1.getAuthProfileProvider)(profile) === provider);
}
async function ensurePrivateDirectory(directory) {
    await (0, promises_1.mkdir)(directory, {
        recursive: true,
        mode: PRIVATE_DIRECTORY_MODE,
    });
    await (0, promises_1.chmod)(directory, PRIVATE_DIRECTORY_MODE);
}
async function writeJsonFile(filePath, schema, value) {
    const normalized = schema.parse(value);
    await ensurePrivateDirectory(node_path_1.default.dirname(filePath));
    await (0, promises_1.writeFile)(filePath, `${JSON.stringify(normalized, null, 2)}\n`, "utf8");
    return filePath;
}
async function updateAuthProfileStateFile(homeDirectory, update) {
    const state = await loadAuthProfileStateFile(homeDirectory);
    const next = update(state);
    await writeAuthProfileStateFile(next.nextState, homeDirectory);
    return next.result;
}
