"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    var desc = Object.getOwnPropertyDescriptor(m, k);
    if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
      desc = { enumerable: true, get: function() { return m[k]; } };
    }
    Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
    Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
    o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
    var ownKeys = function(o) {
        ownKeys = Object.getOwnPropertyNames || function (o) {
            var ar = [];
            for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
            return ar;
        };
        return ownKeys(o);
    };
    return function (mod) {
        if (mod && mod.__esModule) return mod;
        var result = {};
        if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
        __setModuleDefault(result, mod);
        return result;
    };
})();
Object.defineProperty(exports, "__esModule", { value: true });
exports.detectOS = detectOS;
exports.deriveMachineKey = deriveMachineKey;
exports.getKeyProvider = getKeyProvider;
exports.getCanonicalProvider = getCanonicalProvider;
exports.resetCanonicalProvider = resetCanonicalProvider;
exports.getCanonicalProviderInfo = getCanonicalProviderInfo;
exports.getKey = getKey;
exports.setKey = setKey;
exports.deleteKey = deleteKey;
exports.getOrCreateKey = getOrCreateKey;
exports.getKeyProviderInfo = getKeyProviderInfo;
exports.getProviderHealthCheck = getProviderHealthCheck;
exports.getKeyProviderConfidence = getKeyProviderConfidence;
const crypto = __importStar(require("crypto"));
const os = __importStar(require("os"));
function detectOS() {
    switch (process.platform) {
        case 'win32': return 'windows';
        case 'darwin': return 'macos';
        case 'linux': return 'linux';
        default: return 'unknown';
    }
}
// ============================================================
// Machine-bound key derivation (for file fallback)
// Derives a key from hostname + username + salt
// so the encrypted file is only readable on this machine
// ============================================================
const MACHINE_SALT = 'fivocell-v2-salt-2026';
function deriveMachineKey() {
    const hostname = os.hostname();
    const username = os.userInfo().username;
    return crypto.scryptSync(`${hostname}:${username}:${MACHINE_SALT}`, 'fivocell-key-derivation', 32);
}
// ============================================================
// Provider chain — tries providers in order
// ============================================================
let providers = null;
function getProviders() {
    if (providers)
        return providers;
    providers = [];
    // Import lazily to avoid circular deps
    try {
        const { OSKeyProvider } = require('./key-provider-os');
        providers.push(new OSKeyProvider());
    }
    catch { /* not available */ }
    try {
        const { FileKeyProvider } = require('./key-provider-file');
        providers.push(new FileKeyProvider());
    }
    catch { /* not available */ }
    return providers;
}
function getKeyProvider() {
    const available = getProviders().filter(p => p.isAvailable());
    if (available.length > 0)
        return available[0];
    // Should never happen — file provider is always available
    throw new Error('No key provider available');
}
// ============================================================
// Canonical provider — deterministic, unified
// ============================================================
let canonicalProvider = null;
/**
 * Get the canonical key provider for this machine.
 * Result is cached — same call always returns same provider.
 * Priority: OS-native > File-encrypted > Legacy
 */
function getCanonicalProvider() {
    if (canonicalProvider)
        return canonicalProvider;
    const available = getProviders().filter(p => p.isAvailable());
    if (available.length > 0) {
        canonicalProvider = available[0];
        return canonicalProvider;
    }
    // Should never happen — file provider is always available
    throw new Error('No key provider available');
}
/**
 * Force re-selection of key provider (for testing or after OS changes)
 */
function resetCanonicalProvider() {
    canonicalProvider = null;
    providers = null;
}
/**
 * Get provider selection info (deterministic, cached)
 */
function getCanonicalProviderInfo() {
    const osType = detectOS();
    try {
        const provider = getCanonicalProvider();
        let confidence = 'high';
        let reason = `Using ${provider.name} provider`;
        if (provider.name === 'file-encrypted') {
            confidence = 'medium';
            reason = 'OS-native provider not available. Using file-based encryption (weaker).';
            if (osType === 'windows') {
                reason = 'Windows DPAPI not available (PowerShell may be blocked). Using file-based encryption.';
            }
        }
        return { provider: provider.name, os: osType, confidence, reason };
    }
    catch {
        return { provider: 'none', os: osType, confidence: 'low', reason: 'No key provider available' };
    }
}
// ============================================================
// Public API
// ============================================================
function getKey(id) {
    return getKeyProvider().getKey(id);
}
function setKey(id, key) {
    return getKeyProvider().setKey(id, key);
}
function deleteKey(id) {
    return getKeyProvider().deleteKey(id);
}
function getOrCreateKey(id, keyLength = 32) {
    const existing = getKey(id);
    if (existing && existing.length === keyLength)
        return existing;
    const newKey = crypto.randomBytes(keyLength);
    setKey(id, newKey);
    return newKey;
}
function getKeyProviderInfo() {
    const osType = detectOS();
    try {
        const provider = getKeyProvider();
        return { name: provider.name, os: osType, available: true };
    }
    catch {
        return { name: 'none', os: osType, available: false };
    }
}
function getProviderHealthCheck() {
    const osType = detectOS();
    try {
        const provider = getKeyProvider();
        const health = provider.healthCheck ? provider.healthCheck() : undefined;
        return { name: provider.name, os: osType, available: true, health };
    }
    catch {
        return { name: 'none', os: osType, available: false };
    }
}
/**
 * Get key provider confidence level
 * High: OS-native provider available and working
 * Medium: File-based provider (weaker encryption)
 * Low: No provider available
 */
function getKeyProviderConfidence() {
    const osType = detectOS();
    try {
        const provider = getKeyProvider();
        if (provider.name === 'os-native') {
            return { level: 'high', reason: `OS-native provider active (${osType})` };
        }
        if (provider.name === 'file-encrypted') {
            let reason = 'Using file-based encryption (weaker than OS-native)';
            if (osType === 'windows') {
                reason = 'Windows DPAPI not available (PowerShell may be blocked). Using file-based encryption.';
            }
            return { level: 'medium', reason };
        }
        return { level: 'low', reason: 'Unknown provider' };
    }
    catch {
        return { level: 'low', reason: 'No key provider available' };
    }
}
//# sourceMappingURL=key-provider.js.map