import path from "node:path";
import { patchtrailAppDataDir } from "../config/appDataPath.js";
import { EncryptedFallbackSecureStore, parseFallbackKey, } from "./EncryptedFallbackSecureStore.js";
import { FallbackSecureStore } from "./FallbackSecureStore.js";
import { OsKeyringSecureStore } from "./OsKeyringSecureStore.js";
import { PlaintextDevSecureStore } from "./PlaintextDevSecureStore.js";
import { InMemorySecureStore } from "./SecureStore.js";
export const CREDENTIAL_STORE_FAILURE_REASONS = {
    encryptedFallbackKeyMissing: "credential-store-encrypted-fallback-key-missing",
    plaintextProductionBlocked: "credential-store-plaintext-production-blocked",
    inMemoryProductionBlocked: "credential-store-in-memory-production-blocked",
    unsupportedStore: "credential-store-unsupported",
};
export function createSecureStore(options) {
    const env = options.env ?? process.env;
    const storeMode = parseStoreMode(env.PATCHTRAIL_CREDENTIAL_STORE);
    const encryptedFallback = createEncryptedFallbackIfConfigured(env);
    switch (storeMode) {
        case "auto": {
            const primary = new OsKeyringSecureStore();
            return encryptedFallback
                ? new FallbackSecureStore(primary, encryptedFallback)
                : primary;
        }
        case "os":
            return new OsKeyringSecureStore();
        case "encrypted":
            if (!encryptedFallback) {
                throw new Error(CREDENTIAL_STORE_FAILURE_REASONS.encryptedFallbackKeyMissing);
            }
            return encryptedFallback;
        case "plaintext-dev":
            if (options.mode === "production") {
                throw new Error(CREDENTIAL_STORE_FAILURE_REASONS.plaintextProductionBlocked);
            }
            return new PlaintextDevSecureStore(plaintextStorePath(env), options.mode);
        case "in-memory":
            if (options.mode === "production") {
                throw new Error(CREDENTIAL_STORE_FAILURE_REASONS.inMemoryProductionBlocked);
            }
            return new InMemorySecureStore();
    }
}
function createEncryptedFallbackIfConfigured(env) {
    const key = parseFallbackKey(env.PATCHTRAIL_CREDENTIAL_FALLBACK_KEY);
    if (!key)
        return undefined;
    return new EncryptedFallbackSecureStore(encryptedStorePath(env), key);
}
function parseStoreMode(value) {
    if (!value)
        return "auto";
    if (value === "auto" ||
        value === "os" ||
        value === "encrypted" ||
        value === "plaintext-dev" ||
        value === "in-memory") {
        return value;
    }
    throw new Error(CREDENTIAL_STORE_FAILURE_REASONS.unsupportedStore);
}
function encryptedStorePath(env) {
    return (env.PATCHTRAIL_CREDENTIAL_FALLBACK_FILE ??
        path.join(patchtrailAppDataDir(env), "credentials.enc.json"));
}
function plaintextStorePath(env) {
    return (env.PATCHTRAIL_CREDENTIAL_PLAINTEXT_FILE ??
        path.join(patchtrailAppDataDir(env), "credentials.dev.json"));
}
