"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 (mod) {
    if (mod && mod.__esModule) return mod;
    var result = {};
    if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
    __setModuleDefault(result, mod);
    return result;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.saveDroidRawSettings = exports.getDroidRawSettings = exports.getDroidDashboardDiagnostics = exports.summarizeDroidCustomModels = exports.resolveDroidConfigPaths = exports.maskApiKeyPreview = exports.DroidRawSettingsValidationError = exports.DroidRawSettingsConflictError = void 0;
const os = __importStar(require("os"));
const path = __importStar(require("path"));
const child_process_1 = require("child_process");
const droid_detector_1 = require("../../targets/droid-detector");
const compatible_cli_json_file_service_1 = require("./compatible-cli-json-file-service");
Object.defineProperty(exports, "DroidRawSettingsConflictError", { enumerable: true, get: function () { return compatible_cli_json_file_service_1.JsonFileConflictError; } });
Object.defineProperty(exports, "DroidRawSettingsValidationError", { enumerable: true, get: function () { return compatible_cli_json_file_service_1.JsonFileValidationError; } });
const compatible_cli_docs_registry_1 = require("./compatible-cli-docs-registry");
function isObject(value) {
    return typeof value === 'object' && value !== null && !Array.isArray(value);
}
function asObject(value) {
    return isObject(value) ? value : null;
}
function asString(value) {
    return typeof value === 'string' && value.trim().length > 0 ? value.trim() : null;
}
function asNumber(value) {
    return typeof value === 'number' && Number.isFinite(value) ? value : null;
}
function parseHost(value) {
    try {
        return new URL(value).host || null;
    }
    catch {
        return null;
    }
}
function maskApiKeyPreview(value) {
    if (!value)
        return '';
    const suffix = value.slice(-4);
    return `***${suffix}`;
}
exports.maskApiKeyPreview = maskApiKeyPreview;
function isCcsManagedDisplayName(displayName) {
    return displayName.startsWith('CCS ') || displayName.startsWith('ccs-');
}
function resolveDroidConfigPaths(options = {}) {
    const env = options.env ?? process.env;
    const homeDir = options.homeDir ?? os.homedir();
    const byokBase = env.CCS_HOME || homeDir;
    const settingsPath = path.join(byokBase, '.factory', 'settings.json');
    const legacyConfigPath = path.join(byokBase, '.factory', 'config.json');
    return {
        settingsPath,
        settingsDisplayPath: '~/.factory/settings.json',
        legacyConfigPath,
        legacyConfigDisplayPath: '~/.factory/config.json',
    };
}
exports.resolveDroidConfigPaths = resolveDroidConfigPaths;
function getBinaryVersion(binaryPath) {
    try {
        return (0, child_process_1.execFileSync)(binaryPath, ['--version'], {
            encoding: 'utf8',
            stdio: ['ignore', 'pipe', 'ignore'],
            timeout: 5000,
        })
            .trim()
            .split('\n')[0]
            .trim();
    }
    catch {
        return null;
    }
}
function summarizeDroidCustomModels(customModelsValue) {
    const rows = [];
    const providerBreakdown = {};
    let invalidModelEntryCount = 0;
    const source = Array.isArray(customModelsValue)
        ? customModelsValue
        : isObject(customModelsValue)
            ? Object.values(customModelsValue)
            : [];
    for (const item of source) {
        if (!isObject(item)) {
            invalidModelEntryCount += 1;
            continue;
        }
        const displayName = asString(item.displayName) ?? asString(item.model_display_name);
        const model = asString(item.model);
        const baseUrl = asString(item.baseUrl) ?? asString(item.base_url);
        const providerRaw = asString(item.provider);
        const apiKey = asString(item.apiKey) ?? asString(item.api_key);
        if (!displayName || !model || !baseUrl || !providerRaw) {
            invalidModelEntryCount += 1;
            continue;
        }
        const provider = providerRaw.toLowerCase();
        providerBreakdown[provider] = (providerBreakdown[provider] ?? 0) + 1;
        rows.push({
            displayName,
            model,
            provider,
            baseUrl,
            host: parseHost(baseUrl),
            maxOutputTokens: asNumber(item.maxOutputTokens) ?? asNumber(item.max_tokens),
            isCcsManaged: isCcsManagedDisplayName(displayName),
            apiKeyState: apiKey ? 'set' : 'missing',
            apiKeyPreview: apiKey ? maskApiKeyPreview(apiKey) : null,
        });
    }
    const ccsManagedCount = rows.filter((row) => row.isCcsManaged).length;
    return {
        activeModelSelector: null,
        customModelCount: rows.length,
        ccsManagedCount,
        userManagedCount: rows.length - ccsManagedCount,
        invalidModelEntryCount,
        providerBreakdown,
        customModels: rows,
    };
}
exports.summarizeDroidCustomModels = summarizeDroidCustomModels;
function resolveCustomModelsValue(settings) {
    if (!settings)
        return undefined;
    const modern = settings.customModels;
    if (Array.isArray(modern) || isObject(modern))
        return modern;
    const legacy = settings.custom_models;
    if (Array.isArray(legacy) || isObject(legacy))
        return legacy;
    return undefined;
}
function usesLegacyCustomModelsKey(settings) {
    if (!settings)
        return false;
    const modern = settings.customModels;
    if (Array.isArray(modern) || isObject(modern))
        return false;
    const legacy = settings.custom_models;
    return Array.isArray(legacy) || isObject(legacy);
}
async function getDroidDashboardDiagnostics() {
    const paths = resolveDroidConfigPaths();
    const binaryPath = (0, droid_detector_1.detectDroidCli)();
    const docsReference = (0, compatible_cli_docs_registry_1.getCompatibleCliDocsReference)('droid');
    const source = process.env.CCS_DROID_PATH ? 'CCS_DROID_PATH' : binaryPath ? 'PATH' : 'missing';
    const settingsProbe = await (0, compatible_cli_json_file_service_1.probeJsonObjectFile)(paths.settingsPath, 'BYOK settings', paths.settingsDisplayPath);
    const legacyConfigProbe = await (0, compatible_cli_json_file_service_1.probeJsonObjectFile)(paths.legacyConfigPath, 'Legacy config', paths.legacyConfigDisplayPath);
    const settingsJson = asObject(settingsProbe.json);
    const legacyJson = asObject(legacyConfigProbe.json);
    const settingsCustomModels = resolveCustomModelsValue(settingsJson);
    const legacyCustomModels = resolveCustomModelsValue(legacyJson);
    const byok = summarizeDroidCustomModels(settingsCustomModels ?? legacyCustomModels);
    byok.activeModelSelector = asString(settingsProbe.json?.model);
    const warnings = [];
    if (!binaryPath)
        warnings.push('Droid binary is not detected in PATH or CCS_DROID_PATH.');
    if (settingsProbe.diagnostics.parseError) {
        warnings.push('~/.factory/settings.json contains invalid JSON.');
    }
    if (byok.invalidModelEntryCount > 0) {
        warnings.push(`${byok.invalidModelEntryCount} customModels entries are malformed.`);
    }
    if (legacyConfigProbe.diagnostics.parseError) {
        warnings.push('Legacy Droid config (~/.factory/config.json) JSON is invalid.');
    }
    if (usesLegacyCustomModelsKey(settingsJson)) {
        warnings.push('settings.json uses legacy "custom_models" key; prefer "customModels" for forward compatibility.');
    }
    return {
        binary: {
            installed: !!binaryPath,
            path: binaryPath,
            installDir: binaryPath ? path.dirname(binaryPath) : null,
            source,
            version: binaryPath ? getBinaryVersion(binaryPath) : null,
            overridePath: process.env.CCS_DROID_PATH || null,
        },
        files: {
            settings: settingsProbe.diagnostics,
            legacyConfig: legacyConfigProbe.diagnostics,
        },
        byok,
        warnings,
        docsReference,
    };
}
exports.getDroidDashboardDiagnostics = getDroidDashboardDiagnostics;
async function getDroidRawSettings() {
    const paths = resolveDroidConfigPaths();
    const settingsProbe = await (0, compatible_cli_json_file_service_1.probeJsonObjectFile)(paths.settingsPath, 'BYOK settings', paths.settingsDisplayPath);
    return {
        path: paths.settingsDisplayPath,
        resolvedPath: paths.settingsPath,
        exists: settingsProbe.diagnostics.exists,
        mtime: settingsProbe.diagnostics.mtimeMs ?? Date.now(),
        rawText: settingsProbe.rawText,
        settings: settingsProbe.json,
        parseError: settingsProbe.diagnostics.parseError,
    };
}
exports.getDroidRawSettings = getDroidRawSettings;
async function saveDroidRawSettings(input) {
    const paths = resolveDroidConfigPaths();
    if (typeof input.rawText !== 'string') {
        throw new compatible_cli_json_file_service_1.JsonFileValidationError('rawText must be a string.');
    }
    const saved = await (0, compatible_cli_json_file_service_1.writeJsonObjectFileAtomic)({
        filePath: paths.settingsPath,
        rawText: input.rawText,
        expectedMtime: input.expectedMtime,
        fileLabel: 'settings.json',
    });
    return { success: true, mtime: saved.mtime };
}
exports.saveDroidRawSettings = saveDroidRawSettings;
//# sourceMappingURL=droid-dashboard-service.js.map