/**
 * CLI Settings File Manager
 * Manages Claude CLI settings files for endpoint configuration
 *
 * Storage: ~/.ccw/cli-settings/{endpoint-id}.json
 */
import { existsSync, readFileSync, writeFileSync, unlinkSync } from 'fs';
import { join } from 'path';
import * as os from 'os';
import { getCCWHome, ensureStorageDir } from './storage-paths.js';
import { validateSettings, createDefaultSettings } from '../types/cli-settings.js';
import { addClaudeCustomEndpoint, removeClaudeCustomEndpoint } from '../tools/claude-cli-tools.js';
/**
 * Get CLI settings directory path
 */
export function getCliSettingsDir() {
    return join(getCCWHome(), 'cli-settings');
}
/**
 * Get settings file path for an endpoint
 */
export function getSettingsFilePath(endpointId) {
    return join(getCliSettingsDir(), `${endpointId}.json`);
}
/**
 * Get index file path (stores endpoint metadata)
 */
function getIndexFilePath() {
    return join(getCliSettingsDir(), '_index.json');
}
/**
 * Ensure settings directory exists
 */
export function ensureSettingsDir() {
    ensureStorageDir(getCliSettingsDir());
}
/**
 * Load endpoint index (metadata only, not settings content)
 */
function loadIndex() {
    const indexPath = getIndexFilePath();
    if (!existsSync(indexPath)) {
        return new Map();
    }
    try {
        const data = JSON.parse(readFileSync(indexPath, 'utf-8'));
        return new Map(Object.entries(data));
    }
    catch {
        return new Map();
    }
}
/**
 * Save endpoint index
 */
function saveIndex(index) {
    ensureSettingsDir();
    const indexPath = getIndexFilePath();
    const data = Object.fromEntries(index);
    writeFileSync(indexPath, JSON.stringify(data, null, 2), 'utf-8');
}
/**
 * Generate unique endpoint ID
 */
function generateEndpointId() {
    const timestamp = Date.now().toString(36);
    const random = Math.random().toString(36).substring(2, 8);
    return `ep-${timestamp}-${random}`;
}
/**
 * Save endpoint settings to file
 */
export function saveEndpointSettings(request) {
    try {
        ensureSettingsDir();
        const now = new Date().toISOString();
        const index = loadIndex();
        // Determine endpoint ID
        const endpointId = request.id || generateEndpointId();
        // Check if updating existing or creating new
        const existing = index.get(endpointId);
        // Create endpoint metadata
        const metadata = {
            id: endpointId,
            name: request.name,
            description: request.description,
            enabled: request.enabled ?? true,
            createdAt: existing?.createdAt || now,
            updatedAt: now
        };
        // Save settings file
        const settingsPath = getSettingsFilePath(endpointId);
        writeFileSync(settingsPath, JSON.stringify(request.settings, null, 2), 'utf-8');
        // Update index
        index.set(endpointId, metadata);
        saveIndex(index);
        // Sync with cli-tools.json for ccw cli --tool integration
        // CLI Settings endpoints are added as tools with type: 'cli-wrapper'
        // Usage: ccw cli -p "..." --tool <name> --mode analysis
        try {
            const projectDir = os.homedir(); // Use home dir as base for global config
            addClaudeCustomEndpoint(projectDir, {
                id: endpointId,
                name: request.name,
                enabled: request.enabled ?? true,
                tags: ['cli-wrapper'] // cli-wrapper tag -> registers as type: 'cli-wrapper'
            });
            console.log(`[CliSettings] Synced endpoint ${endpointId} to cli-tools.json tools (cli-wrapper)`);
        }
        catch (syncError) {
            console.warn(`[CliSettings] Failed to sync with cli-tools.json: ${syncError}`);
            // Non-fatal: continue even if sync fails
        }
        // Return full endpoint settings
        const endpoint = {
            ...metadata,
            settings: request.settings
        };
        return {
            success: true,
            message: existing ? 'Endpoint updated' : 'Endpoint created',
            endpoint,
            filePath: settingsPath
        };
    }
    catch (error) {
        return {
            success: false,
            message: `Failed to save endpoint settings: ${error instanceof Error ? error.message : String(error)}`
        };
    }
}
/**
 * Load endpoint settings from file
 */
export function loadEndpointSettings(endpointId) {
    try {
        const index = loadIndex();
        const metadata = index.get(endpointId);
        if (!metadata) {
            return null;
        }
        const settingsPath = getSettingsFilePath(endpointId);
        if (!existsSync(settingsPath)) {
            return null;
        }
        const settings = JSON.parse(readFileSync(settingsPath, 'utf-8'));
        if (!validateSettings(settings)) {
            console.error(`[CliSettings] Invalid settings format for ${endpointId}`);
            return null;
        }
        return {
            ...metadata,
            settings
        };
    }
    catch (e) {
        console.error(`[CliSettings] Failed to load settings for ${endpointId}:`, e);
        return null;
    }
}
/**
 * Delete endpoint settings
 */
export function deleteEndpointSettings(endpointId) {
    const index = loadIndex();
    if (!index.has(endpointId)) {
        return {
            success: false,
            message: 'Endpoint not found'
        };
    }
    const settingsPath = getSettingsFilePath(endpointId);
    try {
        // Step 1: Delete file first
        if (existsSync(settingsPath)) {
            unlinkSync(settingsPath);
        }
        // Step 2: Only update index after successful file deletion
        index.delete(endpointId);
        saveIndex(index);
        // Step 3: Remove from cli-tools.json tools (api-endpoint type)
        try {
            const projectDir = os.homedir();
            removeClaudeCustomEndpoint(projectDir, endpointId);
            console.log(`[CliSettings] Removed endpoint ${endpointId} from cli-tools.json tools`);
        }
        catch (syncError) {
            console.warn(`[CliSettings] Failed to remove from cli-tools.json: ${syncError}`);
            // Non-fatal: continue even if sync fails
        }
        return {
            success: true,
            message: 'Endpoint deleted'
        };
    }
    catch (error) {
        // If deletion fails, index remains unchanged for consistency
        return {
            success: false,
            message: `Failed to delete endpoint file: ${error instanceof Error ? error.message : String(error)}`
        };
    }
}
/**
 * List all endpoint settings
 */
export function listAllSettings() {
    try {
        const index = loadIndex();
        const endpoints = [];
        for (const [endpointId, metadata] of index) {
            const settingsPath = getSettingsFilePath(endpointId);
            if (!existsSync(settingsPath)) {
                continue;
            }
            try {
                const settings = JSON.parse(readFileSync(settingsPath, 'utf-8'));
                if (validateSettings(settings)) {
                    endpoints.push({
                        ...metadata,
                        settings
                    });
                }
            }
            catch (e) {
                // Skip invalid settings files, but log the error for debugging
                console.error(`[CliSettings] Failed to load or parse settings for ${endpointId}:`, e);
            }
        }
        return {
            endpoints,
            total: endpoints.length
        };
    }
    catch (e) {
        console.error('[CliSettings] Failed to list settings:', e);
        return {
            endpoints: [],
            total: 0
        };
    }
}
/**
 * Toggle endpoint enabled status
 */
export function toggleEndpointEnabled(endpointId, enabled) {
    try {
        const index = loadIndex();
        const metadata = index.get(endpointId);
        if (!metadata) {
            return {
                success: false,
                message: 'Endpoint not found'
            };
        }
        metadata.enabled = enabled;
        metadata.updatedAt = new Date().toISOString();
        index.set(endpointId, metadata);
        saveIndex(index);
        // Sync enabled status with cli-tools.json tools (cli-wrapper type)
        try {
            const projectDir = os.homedir();
            addClaudeCustomEndpoint(projectDir, {
                id: endpointId,
                name: metadata.name,
                enabled: enabled,
                tags: ['cli-wrapper'] // cli-wrapper tag -> registers as type: 'cli-wrapper'
            });
            console.log(`[CliSettings] Synced endpoint ${endpointId} enabled=${enabled} to cli-tools.json tools`);
        }
        catch (syncError) {
            console.warn(`[CliSettings] Failed to sync enabled status to cli-tools.json: ${syncError}`);
        }
        // Load full settings for response
        const endpoint = loadEndpointSettings(endpointId);
        return {
            success: true,
            message: enabled ? 'Endpoint enabled' : 'Endpoint disabled',
            endpoint: endpoint || undefined
        };
    }
    catch (error) {
        return {
            success: false,
            message: `Failed to toggle endpoint: ${error instanceof Error ? error.message : String(error)}`
        };
    }
}
/**
 * Get settings file path for CLI execution
 * Returns null if endpoint not found or disabled
 */
export function getExecutableSettingsPath(endpointId) {
    const endpoint = loadEndpointSettings(endpointId);
    if (!endpoint || !endpoint.enabled) {
        return null;
    }
    const settingsPath = getSettingsFilePath(endpointId);
    return existsSync(settingsPath) ? settingsPath : null;
}
/**
 * Create settings from LiteLLM provider configuration
 */
export function createSettingsFromProvider(provider, options) {
    const settings = createDefaultSettings();
    // Map provider credentials to env
    if (provider.apiKey) {
        settings.env.ANTHROPIC_AUTH_TOKEN = provider.apiKey;
    }
    if (provider.apiBase) {
        settings.env.ANTHROPIC_BASE_URL = provider.apiBase;
    }
    // Apply options
    if (options?.model) {
        settings.model = options.model;
    }
    if (options?.includeCoAuthoredBy !== undefined) {
        settings.includeCoAuthoredBy = options.includeCoAuthoredBy;
    }
    return settings;
}
/**
 * Validate and sanitize endpoint ID
 */
export function sanitizeEndpointId(id) {
    // Remove special characters, keep alphanumeric and hyphens
    return id.toLowerCase().replace(/[^a-z0-9-]/g, '-').replace(/-+/g, '-').replace(/^-|-$/g, '');
}
/**
 * Check if endpoint ID exists
 */
export function endpointExists(endpointId) {
    const index = loadIndex();
    return index.has(endpointId);
}
/**
 * Get enabled endpoints only
 */
export function getEnabledEndpoints() {
    const { endpoints } = listAllSettings();
    return endpoints.filter(ep => ep.enabled);
}
/**
 * Find endpoint by name (case-insensitive)
 * Useful for CLI where user types --tool doubao instead of --tool ep-xxx
 */
export function findEndpointByName(name) {
    const { endpoints } = listAllSettings();
    const lowerName = name.toLowerCase();
    return endpoints.find(ep => ep.name.toLowerCase() === lowerName) || null;
}
/**
 * Find endpoint by ID or name
 * First tries exact ID match, then falls back to name match
 */
export function findEndpoint(idOrName) {
    // Try by ID first
    const byId = loadEndpointSettings(idOrName);
    if (byId)
        return byId;
    // Try by name
    return findEndpointByName(idOrName);
}
/**
 * Validate endpoint name for CLI compatibility
 * Name must be: lowercase, alphanumeric, hyphens allowed, no spaces or special chars
 */
export function validateEndpointName(name) {
    if (!name || name.trim().length === 0) {
        return { valid: false, error: 'Name is required' };
    }
    // Check for valid characters: a-z, 0-9, hyphen, underscore
    const validPattern = /^[a-z][a-z0-9_-]*$/;
    if (!validPattern.test(name.toLowerCase())) {
        return {
            valid: false,
            error: 'Name must start with a letter and contain only letters, numbers, hyphens, and underscores'
        };
    }
    // Check length
    if (name.length > 32) {
        return { valid: false, error: 'Name must be 32 characters or less' };
    }
    // Check if name conflicts with built-in tools
    const builtinTools = ['gemini', 'qwen', 'codex', 'claude', 'opencode', 'litellm'];
    if (builtinTools.includes(name.toLowerCase())) {
        return { valid: false, error: `Name "${name}" conflicts with a built-in tool` };
    }
    return { valid: true };
}
//# sourceMappingURL=cli-settings-manager.js.map