"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.removeApiProfile = exports.updateApiProfileTarget = exports.createCliproxyBridgeProfile = exports.createApiProfile = void 0;
/**
 * API Profile Writer Service - Create/remove operations for API profiles.
 * Supports both unified YAML config and legacy JSON config.
 */
const fs = __importStar(require("fs"));
const path = __importStar(require("path"));
const config_manager_1 = require("../../utils/config-manager");
const helpers_1 = require("../../utils/helpers");
const validation_service_1 = require("./validation-service");
const websearch_manager_1 = require("../../utils/websearch-manager");
const image_analysis_1 = require("../../utils/image-analysis");
const droid_provider_1 = require("../../targets/droid-provider");
const reserved_names_1 = require("../../config/reserved-names");
const provider_capabilities_1 = require("../../cliproxy/provider-capabilities");
const model_id_normalizer_1 = require("../../cliproxy/ai-providers/model-id-normalizer");
const profile_reader_1 = require("./profile-reader");
const cliproxy_profile_bridge_1 = require("./cliproxy-profile-bridge");
const config_loader_facade_1 = require("../../config/config-loader-facade");
/** Check if URL is an OpenRouter endpoint */
function isOpenRouterUrl(baseUrl) {
    return baseUrl.toLowerCase().includes('openrouter.ai');
}
/** Detect Anthropic direct API profile (native auth, no proxy) */
function isAnthropicDirect(baseUrl, apiKey) {
    return apiKey.startsWith('sk-ant-') || baseUrl.includes('api.anthropic.com');
}
function resolveProviderFromBaseUrl(baseUrl) {
    if (baseUrl.trim().length === 0) {
        return null;
    }
    try {
        const parsed = new URL(baseUrl);
        const extracted = (0, model_id_normalizer_1.extractProviderFromPathname)(parsed.pathname);
        return extracted ? (0, provider_capabilities_1.mapExternalProviderName)(extracted) : null;
    }
    catch {
        const extracted = (0, model_id_normalizer_1.extractProviderFromPathname)(baseUrl);
        return extracted ? (0, provider_capabilities_1.mapExternalProviderName)(extracted) : null;
    }
}
function getDeniedModelReason(baseUrl, models) {
    const provider = resolveProviderFromBaseUrl(baseUrl);
    if (!provider)
        return null;
    for (const modelId of [models.default, models.opus, models.sonnet, models.haiku]) {
        if (modelId.trim().length === 0)
            continue;
        const deniedReason = (0, model_id_normalizer_1.getDeniedModelIdReasonForProvider)(modelId, provider);
        if (deniedReason)
            return deniedReason;
    }
    return null;
}
function rollbackSettingsFile(filePath, previousContent, existedBefore) {
    if (existedBefore && previousContent !== null) {
        fs.writeFileSync(filePath, previousContent, 'utf8');
        return;
    }
    if (fs.existsSync(filePath)) {
        fs.unlinkSync(filePath);
    }
}
/** Create settings.json file for API profile (legacy format) */
function createSettingsFile(name, baseUrl, apiKey, models, provider, extraModels) {
    const ccsDir = (0, config_loader_facade_1.getCcsDir)();
    const settingsPath = path.join(ccsDir, `${name}.settings.json`);
    const droidProvider = (0, droid_provider_1.resolveDroidProvider)({
        provider,
        baseUrl,
        model: models.default,
    });
    const isNative = isAnthropicDirect(baseUrl, apiKey);
    const settings = {
        env: {
            // Native mode: ANTHROPIC_API_KEY only, no BASE_URL/AUTH_TOKEN
            // Proxy mode: ANTHROPIC_BASE_URL + AUTH_TOKEN (existing behavior)
            ...(isNative
                ? { ANTHROPIC_API_KEY: apiKey }
                : {
                    ANTHROPIC_BASE_URL: baseUrl,
                    ANTHROPIC_AUTH_TOKEN: apiKey,
                    ...(isOpenRouterUrl(baseUrl) && { ANTHROPIC_API_KEY: '' }),
                }),
            ANTHROPIC_MODEL: models.default,
            ANTHROPIC_DEFAULT_OPUS_MODEL: models.opus,
            ANTHROPIC_DEFAULT_SONNET_MODEL: models.sonnet,
            ANTHROPIC_DEFAULT_HAIKU_MODEL: models.haiku,
            ...(extraModels && extraModels.length > 0
                ? { ANTHROPIC_EXTRA_MODELS: extraModels.join(',') }
                : {}),
            CCS_DROID_PROVIDER: droidProvider,
        },
    };
    const settingsExisted = fs.existsSync(settingsPath);
    const previousSettingsContent = settingsExisted ? fs.readFileSync(settingsPath, 'utf8') : null;
    fs.mkdirSync(ccsDir, { recursive: true });
    fs.writeFileSync(settingsPath, JSON.stringify(settings, null, 2) + '\n', 'utf8');
    try {
        (0, websearch_manager_1.ensureWebSearchMcpOrThrow)();
        (0, image_analysis_1.ensureImageAnalysisMcpOrThrow)();
    }
    catch (error) {
        rollbackSettingsFile(settingsPath, previousSettingsContent, settingsExisted);
        throw error;
    }
    return settingsPath;
}
/** Update config.json with new API profile (legacy format) */
function updateLegacyConfig(name, target = 'claude') {
    const configPath = (0, config_manager_1.getConfigPath)();
    const ccsDir = (0, config_loader_facade_1.getCcsDir)();
    let config;
    try {
        config = JSON.parse(fs.readFileSync(configPath, 'utf8'));
    }
    catch {
        config = { profiles: {} };
    }
    const relativePath = `~/.ccs/${name}.settings.json`;
    config.profiles[name] = relativePath;
    config.profile_targets = config.profile_targets || {};
    if (target === 'claude') {
        delete config.profile_targets[name];
    }
    else {
        config.profile_targets[name] = target;
    }
    if (!fs.existsSync(ccsDir)) {
        fs.mkdirSync(ccsDir, { recursive: true });
    }
    // Write config atomically
    const tempPath = configPath + '.tmp';
    fs.writeFileSync(tempPath, JSON.stringify(config, null, 2) + '\n', 'utf8');
    fs.renameSync(tempPath, configPath);
}
/** Create API profile in unified config */
function createApiProfileUnified(name, baseUrl, apiKey, models, target = 'claude', provider, extraModels) {
    const ccsDir = (0, config_loader_facade_1.getCcsDir)();
    const settingsFile = `${name}.settings.json`;
    const settingsPath = path.join(ccsDir, settingsFile);
    const droidProvider = (0, droid_provider_1.resolveDroidProvider)({
        provider,
        baseUrl,
        model: models.default,
    });
    const isNative = isAnthropicDirect(baseUrl, apiKey);
    const settings = {
        env: {
            ...(isNative
                ? { ANTHROPIC_API_KEY: apiKey }
                : {
                    ANTHROPIC_BASE_URL: baseUrl,
                    ANTHROPIC_AUTH_TOKEN: apiKey,
                    ...(isOpenRouterUrl(baseUrl) && { ANTHROPIC_API_KEY: '' }),
                }),
            ANTHROPIC_MODEL: models.default,
            ANTHROPIC_DEFAULT_OPUS_MODEL: models.opus,
            ANTHROPIC_DEFAULT_SONNET_MODEL: models.sonnet,
            ANTHROPIC_DEFAULT_HAIKU_MODEL: models.haiku,
            ...(extraModels && extraModels.length > 0
                ? { ANTHROPIC_EXTRA_MODELS: extraModels.join(',') }
                : {}),
            CCS_DROID_PROVIDER: droidProvider,
        },
    };
    if (!fs.existsSync(ccsDir)) {
        fs.mkdirSync(ccsDir, { recursive: true });
    }
    const settingsExisted = fs.existsSync(settingsPath);
    const previousSettingsContent = settingsExisted ? fs.readFileSync(settingsPath, 'utf8') : null;
    fs.writeFileSync(settingsPath, JSON.stringify(settings, null, 2) + '\n', 'utf8');
    try {
        (0, websearch_manager_1.ensureWebSearchMcpOrThrow)();
        (0, image_analysis_1.ensureImageAnalysisMcpOrThrow)();
    }
    catch (error) {
        rollbackSettingsFile(settingsPath, previousSettingsContent, settingsExisted);
        throw error;
    }
    (0, config_loader_facade_1.mutateConfig)((config) => {
        config.profiles[name] = {
            type: 'api',
            settings: `~/.ccs/${settingsFile}`,
            ...(target !== 'claude' && { target }),
        };
    });
}
/** Create a new API profile */
function createApiProfile(name, baseUrl, apiKey, models, target = 'claude', provider, extraModels) {
    try {
        const deniedReason = getDeniedModelReason(baseUrl, models);
        if (deniedReason) {
            return { success: false, settingsFile: '', error: deniedReason };
        }
        const settingsFile = `~/.ccs/${name}.settings.json`;
        if ((0, config_loader_facade_1.isUnifiedMode)()) {
            createApiProfileUnified(name, baseUrl, apiKey, models, target, provider, extraModels);
        }
        else {
            createSettingsFile(name, baseUrl, apiKey, models, provider, extraModels);
            updateLegacyConfig(name, target);
        }
        return { success: true, settingsFile };
    }
    catch (error) {
        return {
            success: false,
            settingsFile: '',
            error: error.message,
        };
    }
}
exports.createApiProfile = createApiProfile;
function createCliproxyBridgeProfile(provider, options = {}) {
    const providedName = options.name?.trim();
    if (providedName) {
        const nameError = (0, validation_service_1.validateApiName)(providedName);
        if (nameError) {
            return { success: false, settingsFile: '', error: nameError };
        }
        if ((0, reserved_names_1.isReservedName)(providedName)) {
            return {
                success: false,
                settingsFile: '',
                error: `Profile name '${providedName}' is reserved`,
            };
        }
    }
    const resolved = (0, cliproxy_profile_bridge_1.resolveCliproxyBridgeProfile)(provider, options);
    const settingsPath = path.join((0, config_loader_facade_1.getCcsDir)(), `${resolved.name}.settings.json`);
    if (!options.force && ((0, profile_reader_1.apiProfileExists)(resolved.name) || fs.existsSync(settingsPath))) {
        return {
            success: false,
            settingsFile: '',
            error: `Profile already exists: ${resolved.name}`,
        };
    }
    const result = createApiProfile(resolved.name, resolved.baseUrl, resolved.apiKey, resolved.models, resolved.target, provider);
    return {
        ...result,
        name: resolved.name,
        provider,
        target: resolved.target,
        cliproxyBridge: (0, cliproxy_profile_bridge_1.resolveCliproxyBridgeMetadata)({
            env: {
                ANTHROPIC_BASE_URL: resolved.baseUrl,
                ANTHROPIC_AUTH_TOKEN: resolved.apiKey,
            },
        }) ?? null,
    };
}
exports.createCliproxyBridgeProfile = createCliproxyBridgeProfile;
/**
 * Update API profile target (claude/droid).
 * Persists to config.yaml in unified mode and config.json profile_targets in legacy mode.
 */
function updateApiProfileTarget(name, target) {
    try {
        if ((0, config_loader_facade_1.isUnifiedMode)()) {
            (0, config_loader_facade_1.mutateConfig)((config) => {
                if (!config.profiles[name]) {
                    throw new Error(`API profile not found: ${name}`);
                }
                if (target === 'claude') {
                    delete config.profiles[name].target;
                }
                else {
                    config.profiles[name].target = target;
                }
            });
            return { success: true, target };
        }
        const configPath = (0, config_manager_1.getConfigPath)();
        let config;
        try {
            config = JSON.parse(fs.readFileSync(configPath, 'utf8'));
        }
        catch {
            config = { profiles: {} };
        }
        if (!config.profiles[name]) {
            return { success: false, error: `API profile not found: ${name}` };
        }
        config.profile_targets = config.profile_targets || {};
        if (target === 'claude') {
            delete config.profile_targets[name];
        }
        else {
            config.profile_targets[name] = target;
        }
        const tempPath = configPath + '.tmp';
        fs.writeFileSync(tempPath, JSON.stringify(config, null, 2) + '\n', 'utf8');
        fs.renameSync(tempPath, configPath);
        return { success: true, target };
    }
    catch (error) {
        return { success: false, error: error.message };
    }
}
exports.updateApiProfileTarget = updateApiProfileTarget;
/** Remove API profile from unified config */
function removeApiProfileUnified(name) {
    (0, config_loader_facade_1.mutateConfig)((config) => {
        const profile = config.profiles[name];
        if (!profile) {
            throw new Error(`API profile not found: ${name}`);
        }
        if (profile.settings) {
            const settingsPath = (0, helpers_1.expandPath)(profile.settings);
            if (fs.existsSync(settingsPath)) {
                fs.unlinkSync(settingsPath);
            }
        }
        delete config.profiles[name];
        if (config.default === name) {
            config.default = undefined;
        }
    });
}
/** Remove API profile from legacy config */
function removeApiProfileLegacy(name) {
    const config = (0, config_loader_facade_1.loadConfigSafe)();
    delete config.profiles[name];
    if (config.profile_targets) {
        delete config.profile_targets[name];
        if (Object.keys(config.profile_targets).length === 0) {
            delete config.profile_targets;
        }
    }
    const configPath = (0, config_manager_1.getConfigPath)();
    const tempPath = configPath + '.tmp';
    fs.writeFileSync(tempPath, JSON.stringify(config, null, 2) + '\n', 'utf8');
    fs.renameSync(tempPath, configPath);
    // Remove settings file if it exists
    const expandedPath = path.join((0, config_loader_facade_1.getCcsDir)(), `${name}.settings.json`);
    if (fs.existsSync(expandedPath)) {
        fs.unlinkSync(expandedPath);
    }
}
/** Remove an API profile */
function removeApiProfile(name) {
    try {
        if ((0, config_loader_facade_1.isUnifiedMode)()) {
            removeApiProfileUnified(name);
        }
        else {
            removeApiProfileLegacy(name);
        }
        return { success: true };
    }
    catch (error) {
        return { success: false, error: error.message };
    }
}
exports.removeApiProfile = removeApiProfile;
//# sourceMappingURL=profile-writer.js.map