// API Settings View
// Manages LiteLLM API providers, custom endpoints, and cache settings

// ========== State Management ==========
let apiSettingsData = null;
const providerModels = {};
let currentModal = null;

// New state for split layout
let selectedProviderId = null;
let providerSearchQuery = '';
let activeModelTab = 'llm';
let expandedModelGroups = new Set();
let activeSidebarTab = 'providers'; // 'providers' | 'endpoints' | 'cache' | 'embedding-pool'

// Embedding Pool state
let embeddingPoolConfig = null;
let embeddingPoolAvailableModels = [];
let embeddingPoolDiscoveredProviders = [];

// Cache for ccw-litellm status (frontend cache with TTL)
let ccwLitellmStatusCache = null;
let ccwLitellmStatusCacheTime = 0;
const CCW_LITELLM_STATUS_CACHE_TTL = 60000; // 60 seconds

// Track if this is the first render (force refresh on first load)
let isFirstApiSettingsRender = true;

// ========== Data Loading ==========

/**
 * Load API configuration
 * @param {boolean} forceRefresh - Force refresh from server, bypass cache
 */
async function loadApiSettings(forceRefresh = false) {
  // If not forcing refresh and data already exists, return cached data
  if (!forceRefresh && apiSettingsData && apiSettingsData.providers) {
    console.log('[API Settings] Using cached API settings data');
    return apiSettingsData;
  }

  try {
    console.log('[API Settings] Fetching API settings from server...');
    const response = await fetch('/api/litellm-api/config');
    if (!response.ok) throw new Error('Failed to load API settings');
    apiSettingsData = await response.json();
    return apiSettingsData;
  } catch (err) {
    console.error('Failed to load API settings:', err);
    showRefreshToast(t('common.error') + ': ' + err.message, 'error');
    return null;
  }
}

/**
 * Load available models for a provider type
 */
async function loadProviderModels(providerType) {
  try {
    const response = await fetch('/api/litellm-api/models/' + providerType);
    if (!response.ok) throw new Error('Failed to load models');
    const data = await response.json();
    providerModels[providerType] = data.models || [];
    return data.models;
  } catch (err) {
    console.error('Failed to load provider models:', err);
    return [];
  }
}

/**
 * Load cache statistics
 */
async function loadCacheStats() {
  try {
    const response = await fetch('/api/litellm-api/cache/stats');
    if (!response.ok) throw new Error('Failed to load cache stats');
    return await response.json();
  } catch (err) {
    console.error('Failed to load cache stats:', err);
    return { enabled: false, totalSize: 0, maxSize: 104857600, entries: 0 };
  }
}

/**
 * Load embedding pool configuration and available models
 */
async function loadEmbeddingPoolConfig() {
  try {
    const response = await fetch('/api/litellm-api/embedding-pool');
    if (!response.ok) throw new Error('Failed to load embedding pool config');
    const data = await response.json();
    embeddingPoolConfig = data.poolConfig;
    embeddingPoolAvailableModels = data.availableModels || [];

    // If pool is enabled and has a target model, discover providers
    if (embeddingPoolConfig && embeddingPoolConfig.enabled && embeddingPoolConfig.targetModel) {
      await discoverProvidersForTargetModel(embeddingPoolConfig.targetModel);
    }

    return data;
  } catch (err) {
    console.error('Failed to load embedding pool config:', err);
    showRefreshToast(t('common.error') + ': ' + err.message, 'error');
    return null;
  }
}

/**
 * Discover providers for a specific target model
 */
async function discoverProvidersForTargetModel(targetModel) {
  try {
    const response = await fetch('/api/litellm-api/embedding-pool/discover/' + encodeURIComponent(targetModel));
    if (!response.ok) throw new Error('Failed to discover providers');
    const data = await response.json();
    embeddingPoolDiscoveredProviders = data.discovered || [];
    return data;
  } catch (err) {
    console.error('Failed to discover providers:', err);
    embeddingPoolDiscoveredProviders = [];
    return null;
  }
}

/**
 * Save embedding pool configuration
 */
async function saveEmbeddingPoolConfig() {
  try {
    const enabled = document.getElementById('embedding-pool-enabled')?.checked || false;
    const targetModel = document.getElementById('embedding-pool-target-model')?.value || '';
    const strategy = document.getElementById('embedding-pool-strategy')?.value || 'round_robin';
    const defaultCooldown = parseInt(document.getElementById('embedding-pool-cooldown')?.value || '60');
    const defaultMaxConcurrentPerKey = parseInt(document.getElementById('embedding-pool-concurrent')?.value || '4');

    const poolConfig = enabled ? {
      enabled: true,
      targetModel: targetModel,
      strategy: strategy,
      autoDiscover: true,
      excludedProviderIds: embeddingPoolConfig?.excludedProviderIds || [],
      defaultCooldown: defaultCooldown,
      defaultMaxConcurrentPerKey: defaultMaxConcurrentPerKey
    } : null;

    const response = await fetch('/api/litellm-api/embedding-pool', {
      method: 'PUT',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify(poolConfig)
    });

    if (!response.ok) throw new Error('Failed to save embedding pool config');

    const result = await response.json();
    embeddingPoolConfig = result.poolConfig;

    const syncCount = result.syncResult?.syncedEndpoints?.length || 0;
    showRefreshToast(t('apiSettings.poolSaved') + (syncCount > 0 ? ' (' + syncCount + ' endpoints synced)' : ''), 'success');

    // Invalidate API settings cache since endpoints may have been synced
    apiSettingsData = null;

    // Reload the embedding pool section
    await renderEmbeddingPoolMainPanel();
    
    // Update sidebar summary
    const sidebarContainer = document.querySelector('.api-settings-sidebar');
    if (sidebarContainer) {
      const contentArea = sidebarContainer.querySelector('.provider-list, .endpoints-list, .embedding-pool-sidebar-info, .embedding-pool-sidebar-summary, .cache-sidebar-info');
      if (contentArea && contentArea.parentElement) {
        contentArea.parentElement.innerHTML = renderEmbeddingPoolSidebar();
        if (window.lucide) lucide.createIcons();
      }
    }

  } catch (err) {
    console.error('Failed to save embedding pool config:', err);
    showRefreshToast(t('common.error') + ': ' + err.message, 'error');
  }
}

/**
 * Toggle provider exclusion in embedding pool
 */
async function toggleProviderExclusion(providerId) {
  if (!embeddingPoolConfig) return;

  const excludedIds = embeddingPoolConfig.excludedProviderIds || [];
  const index = excludedIds.indexOf(providerId);

  if (index > -1) {
    excludedIds.splice(index, 1);
  } else {
    excludedIds.push(providerId);
  }

  embeddingPoolConfig.excludedProviderIds = excludedIds;

  // Re-render the discovered providers section
  renderDiscoveredProviders();
  
  // Update sidebar summary
  const sidebarContainer = document.querySelector('.api-settings-sidebar .embedding-pool-sidebar-summary');
  if (sidebarContainer && sidebarContainer.parentElement) {
    sidebarContainer.parentElement.innerHTML = renderEmbeddingPoolSidebar();
    if (window.lucide) lucide.createIcons();
  }
}

// ========== Provider Management ==========

/**
 * Show add provider modal
 */
async function showAddProviderModal() {
  const modalHtml = '<div class="generic-modal-overlay active" id="providerModal">' +
    '<div class="generic-modal">' +
    '<div class="generic-modal-header">' +
    '<h3 class="generic-modal-title">' + t('apiSettings.addProvider') + '</h3>' +
    '<button class="generic-modal-close" onclick="closeProviderModal()">&times;</button>' +
    '</div>' +
    '<div class="generic-modal-body">' +
    '<form id="providerForm" class="api-settings-form">' +
    '<div class="form-group">' +
    '<label for="provider-type">' + t('apiSettings.apiFormat') + '</label>' +
    '<select id="provider-type" class="cli-input" onchange="updateProviderSpecificFields()" required>' +
    '<option value="openai">OpenAI ' + t('apiSettings.compatible') + '</option>' +
    '<option value="anthropic">Anthropic</option>' +
    '<option value="custom">' + t('apiSettings.customFormat') + '</option>' +
    '</select>' +
    '<small class="form-hint">' + t('apiSettings.apiFormatHint') + '</small>' +
    '</div>' +
    '<div class="form-group">' +
    '<label for="provider-name">' + t('apiSettings.displayName') + '</label>' +
    '<input type="text" id="provider-name" class="cli-input" placeholder="My OpenAI" required />' +
    '</div>' +
    '<div class="form-group">' +
    '<label for="provider-apikey">' + t('apiSettings.apiKey') + '</label>' +
    '<div class="api-key-input-group">' +
    '<input type="password" id="provider-apikey" class="cli-input" placeholder="sk-..." required />' +
    '<button type="button" class="btn-icon" onclick="toggleApiKeyVisibility(\'provider-apikey\')" title="' + t('apiSettings.toggleVisibility') + '">' +
    '<i data-lucide="eye"></i>' +
    '</button>' +
    '</div>' +
    '<label class="checkbox-label">' +
    '<input type="checkbox" id="use-env-var" onchange="toggleEnvVarInput()" /> ' +
    t('apiSettings.useEnvVar') +
    '</label>' +
    '<input type="text" id="env-var-name" class="cli-input" placeholder="OPENAI_API_KEY" style="display:none; margin-top: 0.5rem;" />' +
    '</div>' +
    '<div class="form-group">' +
    '<label for="provider-apibase">' + t('apiSettings.apiBaseUrl') + ' <span class="text-muted">(' + t('common.optional') + ')</span></label>' +
    '<input type="text" id="provider-apibase" class="cli-input" placeholder="https://api.openai.com/v1" />' +
    '</div>' +
    '<div class="form-group">' +
    '<label class="checkbox-label">' +
    '<input type="checkbox" id="provider-enabled" checked /> ' +
    t('apiSettings.enableProvider') +
    '</label>' +
    '</div>' +
    // Advanced Settings Collapsible Panel
    '<fieldset class="advanced-settings-fieldset">' +
    '<legend class="advanced-settings-legend" onclick="toggleAdvancedSettings()">' +
    '<i data-lucide="chevron-right" class="advanced-toggle-icon"></i> ' +
    t('apiSettings.advancedSettings') +
    '</legend>' +
    '<div id="advanced-settings-content" class="advanced-settings-content collapsed">' +
    // Timeout
    '<div class="form-group">' +
    '<label for="provider-timeout">' + t('apiSettings.timeout') + ' <span class="text-muted">(' + t('common.optional') + ')</span></label>' +
    '<input type="number" id="provider-timeout" class="cli-input" placeholder="300" min="1" max="3600" />' +
    '<small class="form-hint">' + t('apiSettings.timeoutHint') + '</small>' +
    '</div>' +
    // Max Retries
    '<div class="form-group">' +
    '<label for="provider-max-retries">' + t('apiSettings.maxRetries') + ' <span class="text-muted">(' + t('common.optional') + ')</span></label>' +
    '<input type="number" id="provider-max-retries" class="cli-input" placeholder="3" min="0" max="10" />' +
    '</div>' +
    // Organization (OpenAI only)
    '<div class="form-group provider-specific openai-only" style="display:none;">' +
    '<label for="provider-organization">' + t('apiSettings.organization') + ' <span class="text-muted">(' + t('common.optional') + ')</span></label>' +
    '<input type="text" id="provider-organization" class="cli-input" placeholder="org-..." />' +
    '<small class="form-hint">' + t('apiSettings.organizationHint') + '</small>' +
    '</div>' +
    // API Version (Azure only)
    '<div class="form-group provider-specific azure-only" style="display:none;">' +
    '<label for="provider-api-version">' + t('apiSettings.apiVersion') + ' <span class="text-muted">(' + t('common.optional') + ')</span></label>' +
    '<input type="text" id="provider-api-version" class="cli-input" placeholder="2024-02-01" />' +
    '<small class="form-hint">' + t('apiSettings.apiVersionHint') + '</small>' +
    '</div>' +
    // Rate Limiting (side by side)
    '<div class="form-row">' +
    '<div class="form-group form-group-half">' +
    '<label for="provider-rpm">' + t('apiSettings.rpm') + ' <span class="text-muted">(' + t('common.optional') + ')</span></label>' +
    '<input type="number" id="provider-rpm" class="cli-input" placeholder="' + t('apiSettings.unlimited') + '" min="0" />' +
    '</div>' +
    '<div class="form-group form-group-half">' +
    '<label for="provider-tpm">' + t('apiSettings.tpm') + ' <span class="text-muted">(' + t('common.optional') + ')</span></label>' +
    '<input type="number" id="provider-tpm" class="cli-input" placeholder="' + t('apiSettings.unlimited') + '" min="0" />' +
    '</div>' +
    '</div>' +
    // Proxy
    '<div class="form-group">' +
    '<label for="provider-proxy">' + t('apiSettings.proxy') + ' <span class="text-muted">(' + t('common.optional') + ')</span></label>' +
    '<input type="text" id="provider-proxy" class="cli-input" placeholder="http://proxy.example.com:8080" />' +
    '</div>' +
    // Custom Headers
    '<div class="form-group">' +
    '<label for="provider-custom-headers">' + t('apiSettings.customHeaders') + ' <span class="text-muted">(' + t('common.optional') + ')</span></label>' +
    '<textarea id="provider-custom-headers" class="cli-input cli-textarea" rows="3" placeholder=\'{"X-Custom-Header": "value"}\'></textarea>' +
    '<small class="form-hint">' + t('apiSettings.customHeadersHint') + '</small>' +
    '</div>' +
    '</div>' +
    '</fieldset>' +
    '<div class="modal-actions">' +
    '<button type="button" class="btn btn-secondary" onclick="testProviderConnection()">' +
    '<i data-lucide="wifi"></i> ' + t('apiSettings.testConnection') +
    '</button>' +
    '<button type="button" class="btn btn-secondary" onclick="closeProviderModal()">' + t('common.cancel') + '</button>' +
    '<button type="submit" class="btn btn-primary">' +
    '<i data-lucide="save"></i> ' + t('common.save') +
    '</button>' +
    '</div>' +
    '</form>' +
    '</div>' +
    '</div>' +
    '</div>';

  document.body.insertAdjacentHTML('beforeend', modalHtml);

  document.getElementById('providerForm').addEventListener('submit', async function(e) {
    e.preventDefault();
    await saveProvider();
  });

  if (window.lucide) lucide.createIcons();
}

/**
 * Show edit provider modal
 */
async function showEditProviderModal(providerId) {
  if (!apiSettingsData) return;

  const provider = apiSettingsData.providers?.find(function(p) { return p.id === providerId; });
  if (!provider) return;

  await showAddProviderModal();

  // Update modal title
  document.querySelector('#providerModal .generic-modal-title').textContent = t('apiSettings.editProvider');

  // Populate form
  document.getElementById('provider-type').value = provider.type;
  document.getElementById('provider-name').value = provider.name;
  document.getElementById('provider-apikey').value = provider.apiKey;
  if (provider.apiBase) {
    document.getElementById('provider-apibase').value = provider.apiBase;
  }
  document.getElementById('provider-enabled').checked = provider.enabled !== false;

  // Populate advanced settings if they exist
  if (provider.advancedSettings) {
    var settings = provider.advancedSettings;

    if (settings.timeout) {
      document.getElementById('provider-timeout').value = settings.timeout;
    }
    if (settings.maxRetries !== undefined) {
      document.getElementById('provider-max-retries').value = settings.maxRetries;
    }
    if (settings.organization) {
      document.getElementById('provider-organization').value = settings.organization;
    }
    if (settings.apiVersion) {
      document.getElementById('provider-api-version').value = settings.apiVersion;
    }
    if (settings.rpm) {
      document.getElementById('provider-rpm').value = settings.rpm;
    }
    if (settings.tpm) {
      document.getElementById('provider-tpm').value = settings.tpm;
    }
    if (settings.proxy) {
      document.getElementById('provider-proxy').value = settings.proxy;
    }
    if (settings.customHeaders) {
      document.getElementById('provider-custom-headers').value =
        JSON.stringify(settings.customHeaders, null, 2);
    }

    // Expand advanced settings if any values exist
    if (Object.keys(settings).length > 0) {
      toggleAdvancedSettings();
    }
  }

  // Update provider-specific field visibility
  updateProviderSpecificFields();

  // Store provider ID for update
  document.getElementById('providerForm').dataset.providerId = providerId;
}

/**
 * Save provider (create or update)
 */
async function saveProvider() {
  const form = document.getElementById('providerForm');
  const providerId = form.dataset.providerId;

  const useEnvVar = document.getElementById('use-env-var').checked;
  const apiKey = useEnvVar
    ? '${' + document.getElementById('env-var-name').value + '}'
    : document.getElementById('provider-apikey').value;

  // Collect advanced settings
  var advancedSettings = {};

  var timeout = document.getElementById('provider-timeout').value;
  if (timeout) advancedSettings.timeout = parseInt(timeout);

  var maxRetries = document.getElementById('provider-max-retries').value;
  if (maxRetries) advancedSettings.maxRetries = parseInt(maxRetries);

  var organization = document.getElementById('provider-organization').value;
  if (organization) advancedSettings.organization = organization;

  var apiVersion = document.getElementById('provider-api-version').value;
  if (apiVersion) advancedSettings.apiVersion = apiVersion;

  var rpm = document.getElementById('provider-rpm').value;
  if (rpm) advancedSettings.rpm = parseInt(rpm);

  var tpm = document.getElementById('provider-tpm').value;
  if (tpm) advancedSettings.tpm = parseInt(tpm);

  var proxy = document.getElementById('provider-proxy').value;
  if (proxy) advancedSettings.proxy = proxy;

  var customHeadersJson = document.getElementById('provider-custom-headers').value;
  if (customHeadersJson) {
    try {
      advancedSettings.customHeaders = JSON.parse(customHeadersJson);
    } catch (e) {
      showRefreshToast(t('apiSettings.invalidJsonHeaders'), 'error');
      return;
    }
  }

  const providerData = {
    type: document.getElementById('provider-type').value,
    name: document.getElementById('provider-name').value,
    apiKey: apiKey,
    apiBase: document.getElementById('provider-apibase').value || undefined,
    enabled: document.getElementById('provider-enabled').checked,
    advancedSettings: Object.keys(advancedSettings).length > 0 ? advancedSettings : undefined
  };

  try {
    const url = providerId
      ? '/api/litellm-api/providers/' + providerId
      : '/api/litellm-api/providers';
    const method = providerId ? 'PUT' : 'POST';

    const response = await fetch(url, {
      method: method,
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify(providerData)
    });

    if (!response.ok) throw new Error('Failed to save provider');

    const result = await response.json();
    showRefreshToast(t('apiSettings.providerSaved'), 'success');

    closeProviderModal();
    // Force refresh data after saving
    apiSettingsData = null;
    await renderApiSettings();
  } catch (err) {
    console.error('Failed to save provider:', err);
    showRefreshToast(t('common.error') + ': ' + err.message, 'error');
  }
}

/**
 * Delete provider
 */
async function deleteProvider(providerId) {
  if (!confirm(t('apiSettings.confirmDeleteProvider'))) return;

  try {
    const response = await fetch('/api/litellm-api/providers/' + providerId, {
      method: 'DELETE'
    });

    if (!response.ok) throw new Error('Failed to delete provider');

    showRefreshToast(t('apiSettings.providerDeleted'), 'success');
    // Force refresh data after deleting
    apiSettingsData = null;
    await renderApiSettings();
  } catch (err) {
    console.error('Failed to delete provider:', err);
    showRefreshToast(t('common.error') + ': ' + err.message, 'error');
  }
}

/**
 * Test provider connection
 * @param {string} [providerIdParam] - Optional provider ID. If not provided, uses form context or selectedProviderId
 */
async function testProviderConnection(providerIdParam) {
  var providerId = providerIdParam;

  // Try to get providerId from different sources
  if (!providerId) {
    var form = document.getElementById('providerForm');
    if (form && form.dataset.providerId) {
      providerId = form.dataset.providerId;
    } else if (selectedProviderId) {
      providerId = selectedProviderId;
    }
  }

  if (!providerId) {
    showRefreshToast(t('apiSettings.saveProviderFirst'), 'warning');
    return;
  }

  try {
    const response = await fetch('/api/litellm-api/providers/' + providerId + '/test', {
      method: 'POST'
    });

    if (!response.ok) throw new Error('Failed to test provider');

    const result = await response.json();

    if (result.success) {
      showRefreshToast(t('apiSettings.connectionSuccess'), 'success');
    } else {
      showRefreshToast(t('apiSettings.connectionFailed') + ': ' + (result.error || 'Unknown error'), 'error');
    }
  } catch (err) {
    console.error('Failed to test provider:', err);
    showRefreshToast(t('common.error') + ': ' + err.message, 'error');
  }
}

/**
 * Close provider modal
 */
function closeProviderModal() {
  const modal = document.getElementById('providerModal');
  if (modal) modal.remove();
}

/**
 * Toggle API key visibility
 */
function toggleApiKeyVisibility(inputId) {
  const input = document.getElementById(inputId);
  const icon = event.target.closest('button').querySelector('i');

  if (input.type === 'password') {
    input.type = 'text';
    icon.setAttribute('data-lucide', 'eye-off');
  } else {
    input.type = 'password';
    icon.setAttribute('data-lucide', 'eye');
  }

  if (window.lucide) lucide.createIcons();
}

/**
 * Toggle environment variable input
 */
function toggleEnvVarInput() {
  const useEnvVar = document.getElementById('use-env-var').checked;
  const apiKeyInput = document.getElementById('provider-apikey');
  const envVarInput = document.getElementById('env-var-name');

  if (useEnvVar) {
    apiKeyInput.style.display = 'none';
    apiKeyInput.required = false;
    envVarInput.style.display = 'block';
    envVarInput.required = true;
  } else {
    apiKeyInput.style.display = 'block';
    apiKeyInput.required = true;
    envVarInput.style.display = 'none';
    envVarInput.required = false;
  }
}

/**
 * Toggle advanced settings visibility
 */
function toggleAdvancedSettings() {
  var content = document.getElementById('advanced-settings-content');
  var legend = document.querySelector('.advanced-settings-legend');
  var isCollapsed = content.classList.contains('collapsed');

  content.classList.toggle('collapsed');
  legend.classList.toggle('expanded');

  // Update icon
  var icon = legend.querySelector('.advanced-toggle-icon');
  if (icon) {
    icon.setAttribute('data-lucide', isCollapsed ? 'chevron-down' : 'chevron-right');
    if (window.lucide) lucide.createIcons();
  }
}

/**
 * Update provider-specific fields visibility based on provider type
 */
function updateProviderSpecificFields() {
  var providerType = document.getElementById('provider-type').value;

  // Hide all provider-specific fields first
  var specificFields = document.querySelectorAll('.provider-specific');
  specificFields.forEach(function(el) {
    el.style.display = 'none';
  });

  // Show OpenAI-specific fields
  if (providerType === 'openai') {
    var openaiFields = document.querySelectorAll('.openai-only');
    openaiFields.forEach(function(el) {
      el.style.display = 'block';
    });
  }

  // Show Azure-specific fields
  if (providerType === 'azure') {
    var azureFields = document.querySelectorAll('.azure-only');
    azureFields.forEach(function(el) {
      el.style.display = 'block';
    });
  }
}

// ========== Endpoint Management ==========

/**
 * Show add endpoint modal
 */
async function showAddEndpointModal() {
  if (!apiSettingsData || !apiSettingsData.providers || apiSettingsData.providers.length === 0) {
    showRefreshToast(t('apiSettings.addProviderFirst'), 'warning');
    return;
  }

  const providerOptions = apiSettingsData.providers
    .filter(function(p) { return p.enabled !== false; })
    .map(function(p) {
      return '<option value="' + p.id + '">' + p.name + ' (' + p.type + ')</option>';
    })
    .join('');

  const modalHtml = '<div class="generic-modal-overlay active" id="endpointModal">' +
    '<div class="generic-modal">' +
    '<div class="generic-modal-header">' +
    '<h3 class="generic-modal-title">' + t('apiSettings.addEndpoint') + '</h3>' +
    '<button class="generic-modal-close" onclick="closeEndpointModal()">&times;</button>' +
    '</div>' +
    '<div class="generic-modal-body">' +
    '<form id="endpointForm" class="api-settings-form">' +
    '<div class="form-group">' +
    '<label for="endpoint-id">' + t('apiSettings.endpointId') + '</label>' +
    '<input type="text" id="endpoint-id" class="cli-input" placeholder="my-gpt4o" required />' +
    '<small class="form-hint">' + t('apiSettings.endpointIdHint') + '</small>' +
    '</div>' +
    '<div class="form-group">' +
    '<label for="endpoint-name">' + t('apiSettings.displayName') + '</label>' +
    '<input type="text" id="endpoint-name" class="cli-input" placeholder="GPT-4o for Code Review" required />' +
    '</div>' +
    '<div class="form-group">' +
    '<label for="endpoint-provider">' + t('apiSettings.provider') + '</label>' +
    '<select id="endpoint-provider" class="cli-input" onchange="loadModelsForProvider()" required>' +
    providerOptions +
    '</select>' +
    '</div>' +
    '<div class="form-group">' +
    '<label for="endpoint-model">' + t('apiSettings.model') + '</label>' +
    '<select id="endpoint-model" class="cli-input" required>' +
    '<option value="">' + t('apiSettings.selectModel') + '</option>' +
    '</select>' +
    '</div>' +
    '<fieldset class="form-fieldset">' +
    '<legend>' + t('apiSettings.cacheStrategy') + '</legend>' +
    '<label class="checkbox-label">' +
    '<input type="checkbox" id="cache-enabled" onchange="toggleCacheSettings()" /> ' +
    t('apiSettings.enableContextCaching') +
    '</label>' +
    '<div id="cache-settings" style="display:none;">' +
    '<div class="form-group">' +
    '<label for="cache-ttl">' + t('apiSettings.cacheTTL') + '</label>' +
    '<input type="number" id="cache-ttl" class="cli-input" value="60" min="1" />' +
    '</div>' +
    '<div class="form-group">' +
    '<label for="cache-maxsize">' + t('apiSettings.cacheMaxSize') + '</label>' +
    '<input type="number" id="cache-maxsize" class="cli-input" value="512" min="1" />' +
    '</div>' +
    '<div class="form-group">' +
    '<label for="cache-patterns">' + t('apiSettings.autoCachePatterns') + '</label>' +
    '<input type="text" id="cache-patterns" class="cli-input" placeholder="*.ts, *.md, CLAUDE.md" />' +
    '</div>' +
    '</div>' +
    '</fieldset>' +
    '<div class="modal-actions">' +
    '<button type="button" class="btn btn-secondary" onclick="closeEndpointModal()"><i data-lucide="x"></i> ' + t('common.cancel') + '</button>' +
    '<button type="submit" class="btn btn-primary">' +
    '<i data-lucide="check"></i> ' + t('common.save') +
    '</button>' +
    '</div>' +
    '</form>' +
    '</div>' +
    '</div>' +
    '</div>';

  document.body.insertAdjacentHTML('beforeend', modalHtml);

  document.getElementById('endpointForm').addEventListener('submit', async function(e) {
    e.preventDefault();
    await saveEndpoint();
  });

  // Load models for first provider
  await loadModelsForProvider();

  if (window.lucide) lucide.createIcons();
}

/**
 * Show edit endpoint modal
 */
async function showEditEndpointModal(endpointId) {
  if (!apiSettingsData) return;

  const endpoint = apiSettingsData.endpoints?.find(function(e) { return e.id === endpointId; });
  if (!endpoint) return;

  await showAddEndpointModal();

  // Update modal title
  document.querySelector('#endpointModal .generic-modal-title').textContent = t('apiSettings.editEndpoint');

  // Populate form
  document.getElementById('endpoint-id').value = endpoint.id;
  document.getElementById('endpoint-id').disabled = true;
  document.getElementById('endpoint-name').value = endpoint.name;
  document.getElementById('endpoint-provider').value = endpoint.providerId;

  await loadModelsForProvider();
  document.getElementById('endpoint-model').value = endpoint.model;

  if (endpoint.cacheStrategy) {
    document.getElementById('cache-enabled').checked = endpoint.cacheStrategy.enabled;
    if (endpoint.cacheStrategy.enabled) {
      toggleCacheSettings();
      document.getElementById('cache-ttl').value = endpoint.cacheStrategy.ttlMinutes || 60;
      document.getElementById('cache-maxsize').value = endpoint.cacheStrategy.maxSizeKB || 512;
      document.getElementById('cache-patterns').value = endpoint.cacheStrategy.autoCachePatterns?.join(', ') || '';
    }
  }

  // Store endpoint ID for update
  document.getElementById('endpointForm').dataset.endpointId = endpointId;
}

/**
 * Save endpoint (create or update)
 */
async function saveEndpoint() {
  const form = document.getElementById('endpointForm');
  const endpointId = form.dataset.endpointId || document.getElementById('endpoint-id').value;

  const cacheEnabled = document.getElementById('cache-enabled').checked;
  const cacheStrategy = cacheEnabled ? {
    enabled: true,
    ttlMinutes: parseInt(document.getElementById('cache-ttl').value) || 60,
    maxSizeKB: parseInt(document.getElementById('cache-maxsize').value) || 512,
    autoCachePatterns: document.getElementById('cache-patterns').value
      .split(',')
      .map(function(p) { return p.trim(); })
      .filter(function(p) { return p; })
  } : { enabled: false };

  const endpointData = {
    id: endpointId,
    name: document.getElementById('endpoint-name').value,
    providerId: document.getElementById('endpoint-provider').value,
    model: document.getElementById('endpoint-model').value,
    cacheStrategy: cacheStrategy
  };

  try {
    const url = form.dataset.endpointId
      ? '/api/litellm-api/endpoints/' + form.dataset.endpointId
      : '/api/litellm-api/endpoints';
    const method = form.dataset.endpointId ? 'PUT' : 'POST';

    const response = await fetch(url, {
      method: method,
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify(endpointData)
    });

    if (!response.ok) throw new Error('Failed to save endpoint');

    const result = await response.json();
    showRefreshToast(t('apiSettings.endpointSaved'), 'success');

    closeEndpointModal();
    // Force refresh data after saving
    apiSettingsData = null;
    await renderApiSettings();
  } catch (err) {
    console.error('Failed to save endpoint:', err);
    showRefreshToast(t('common.error') + ': ' + err.message, 'error');
  }
}

/**
 * Delete endpoint
 */
async function deleteEndpoint(endpointId) {
  if (!confirm(t('apiSettings.confirmDeleteEndpoint'))) return;

  try {
    const response = await fetch('/api/litellm-api/endpoints/' + endpointId, {
      method: 'DELETE'
    });

    if (!response.ok) throw new Error('Failed to delete endpoint');

    showRefreshToast(t('apiSettings.endpointDeleted'), 'success');
    // Force refresh data after deleting
    apiSettingsData = null;
    await renderApiSettings();
  } catch (err) {
    console.error('Failed to delete endpoint:', err);
    showRefreshToast(t('common.error') + ': ' + err.message, 'error');
  }
}

/**
 * Close endpoint modal
 */
function closeEndpointModal() {
  const modal = document.getElementById('endpointModal');
  if (modal) modal.remove();
}

/**
 * Load models for selected provider
 */
async function loadModelsForProvider() {
  const providerSelect = document.getElementById('endpoint-provider');
  const modelSelect = document.getElementById('endpoint-model');

  if (!providerSelect || !modelSelect) return;

  const providerId = providerSelect.value;
  const provider = apiSettingsData.providers.find(function(p) { return p.id === providerId; });

  if (!provider) return;

  // Use LLM models configured for this provider (not static presets)
  const models = provider.llmModels || [];

  if (models.length === 0) {
    modelSelect.innerHTML = '<option value="">' + t('apiSettings.noModelsConfigured') + '</option>';
    return;
  }

  modelSelect.innerHTML = '<option value="">' + t('apiSettings.selectModel') + '</option>' +
    models.filter(function(m) { return m.enabled; }).map(function(m) {
      const contextInfo = m.capabilities && m.capabilities.contextWindow 
        ? ' (' + Math.round(m.capabilities.contextWindow / 1000) + 'K)' 
        : '';
      return '<option value="' + m.id + '">' + m.name + contextInfo + '</option>';
    }).join('');
}

/**
 * Toggle cache settings visibility
 */
function toggleCacheSettings() {
  const enabled = document.getElementById('cache-enabled').checked;
  const settings = document.getElementById('cache-settings');
  settings.style.display = enabled ? 'block' : 'none';
}

// ========== Cache Management ==========

/**
 * Clear cache
 */
async function clearCache() {
  if (!confirm(t('apiSettings.confirmClearCache'))) return;

  try {
    const response = await fetch('/api/litellm-api/cache/clear', {
      method: 'POST'
    });

    if (!response.ok) throw new Error('Failed to clear cache');

    const result = await response.json();
    showRefreshToast(t('apiSettings.cacheCleared') + ' (' + result.removed + ' entries)', 'success');

    // Cache stats might have changed, but apiSettingsData doesn't need refresh
    await renderApiSettings();
  } catch (err) {
    console.error('Failed to clear cache:', err);
    showRefreshToast(t('common.error') + ': ' + err.message, 'error');
  }
}

/**
 * Toggle global cache
 */
async function toggleGlobalCache() {
  const enabled = document.getElementById('global-cache-enabled').checked;

  try {
    const response = await fetch('/api/litellm-api/config/cache', {
      method: 'PUT',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ enabled: enabled })
    });

    if (!response.ok) throw new Error('Failed to update cache settings');

    showRefreshToast(t('apiSettings.cacheSettingsUpdated'), 'success');
  } catch (err) {
    console.error('Failed to update cache settings:', err);
    showRefreshToast(t('common.error') + ': ' + err.message, 'error');
    // Revert checkbox
    document.getElementById('global-cache-enabled').checked = !enabled;
  }
}

// ========== Rendering ==========

/**
 * Render API Settings page - Split Layout
 */
async function renderApiSettings() {
  var container = document.getElementById('mainContent');
  if (!container) return;

  // Hide stats grid and search
  var statsGrid = document.getElementById('statsGrid');
  var searchInput = document.getElementById('searchInput');
  if (statsGrid) statsGrid.style.display = 'none';
  if (searchInput) searchInput.parentElement.style.display = 'none';

  // Load data (use cache by default, forceRefresh=false)
  await loadApiSettings(false);

  if (!apiSettingsData) {
    container.innerHTML = '<div class="api-settings-container">' +
      '<div class="error-message">' + t('apiSettings.failedToLoad') + '</div>' +
      '</div>';
    return;
  }

  // Build sidebar tabs HTML
  var sidebarTabsHtml = '<div class="sidebar-tabs">' +
    '<button class="sidebar-tab' + (activeSidebarTab === 'providers' ? ' active' : '') + '" onclick="switchSidebarTab(\'providers\')">' +
    '<i data-lucide="server"></i> ' + t('apiSettings.providers') +
    '</button>' +
    '<button class="sidebar-tab' + (activeSidebarTab === 'endpoints' ? ' active' : '') + '" onclick="switchSidebarTab(\'endpoints\')">' +
    '<i data-lucide="link"></i> ' + t('apiSettings.endpoints') +
    '</button>' +
    '<button class="sidebar-tab' + (activeSidebarTab === 'embedding-pool' ? ' active' : '') + '" onclick="switchSidebarTab(\'embedding-pool\')">' +
    '<i data-lucide="repeat"></i> ' + t('apiSettings.embeddingPool') +
    '</button>' +
    '<button class="sidebar-tab' + (activeSidebarTab === 'cache' ? ' active' : '') + '" onclick="switchSidebarTab(\'cache\')">' +
    '<i data-lucide="database"></i> ' + t('apiSettings.cache') +
    '</button>' +
    '</div>';

  // Build sidebar content based on active tab
  var sidebarContentHtml = '';
  var addButtonHtml = '';

  if (activeSidebarTab === 'providers') {
    sidebarContentHtml = '<div class="provider-search">' +
      '<i data-lucide="search" class="search-icon"></i>' +
      '<input type="text" class="cli-input" id="provider-search-input" placeholder="' + t('apiSettings.searchProviders') + '" oninput="filterProviders(this.value)" />' +
      '</div>' +
      '<div class="provider-list" id="provider-list"></div>';
    addButtonHtml = '<button class="btn btn-primary btn-full" onclick="showAddProviderModal()">' +
      '<i data-lucide="plus"></i> ' + t('apiSettings.addProvider') +
      '</button>';
  } else if (activeSidebarTab === 'endpoints') {
    sidebarContentHtml = '<div class="endpoints-list" id="endpoints-list"></div>';
    addButtonHtml = '<button class="btn btn-primary btn-full" onclick="showAddEndpointModal()">' +
      '<i data-lucide="plus"></i> ' + t('apiSettings.addEndpoint') +
      '</button>';
  } else if (activeSidebarTab === 'embedding-pool') {
    // Load embedding pool config first if not already loaded
    if (!embeddingPoolConfig) {
      await loadEmbeddingPoolConfig();
    }
    sidebarContentHtml = renderEmbeddingPoolSidebar();
  } else if (activeSidebarTab === 'cache') {
    sidebarContentHtml = '<div class="cache-sidebar-info" style="padding: 1rem; color: var(--text-secondary); font-size: 0.875rem;">' +
      '<p>' + t('apiSettings.cacheTabHint') + '</p>' +
      '</div>';
  }

  // Build split layout
  container.innerHTML =
    // CCW-LiteLLM Status Container
    '<div id="ccwLitellmStatusContainer" class="mb-4"></div>' +
    '<div class="api-settings-container api-settings-split">' +
    // Left Sidebar
    '<aside class="api-settings-sidebar">' +
    sidebarTabsHtml +
    sidebarContentHtml +
    '<div class="provider-list-footer">' +
    addButtonHtml +
    '</div>' +
    '</aside>' +
    // Right Main Panel
    '<main class="api-settings-main" id="provider-detail-panel"></main>' +
    '</div>' +
    // Cache Panel Overlay
    '<div class="cache-panel-overlay" id="cache-panel-overlay" onclick="closeCachePanelOverlay(event)"></div>';

  // Render content based on active tab
  if (activeSidebarTab === 'providers') {
    renderProviderList();
    // Auto-select first provider if exists
    if (!selectedProviderId && apiSettingsData.providers && apiSettingsData.providers.length > 0) {
      selectProvider(apiSettingsData.providers[0].id);
    } else if (selectedProviderId) {
      renderProviderDetail(selectedProviderId);
    } else {
      renderProviderEmptyState();
    }
  } else if (activeSidebarTab === 'endpoints') {
    renderEndpointsList();
    renderEndpointsMainPanel();
  } else if (activeSidebarTab === 'embedding-pool') {
    renderEmbeddingPoolMainPanel();
  } else if (activeSidebarTab === 'cache') {
    renderCacheMainPanel();
  }

  // Check and render ccw-litellm status
  // Force refresh on first load, use cache on subsequent renders
  const forceStatusRefresh = isFirstApiSettingsRender;
  if (isFirstApiSettingsRender) {
    isFirstApiSettingsRender = false;
  }
  checkCcwLitellmStatus(forceStatusRefresh).then(renderCcwLitellmStatusCard);

  if (window.lucide) lucide.createIcons();
}

/**
 * Render provider list in sidebar
 */
function renderProviderList() {
  var container = document.getElementById('provider-list');
  if (!container) return;

  var providers = apiSettingsData.providers || [];
  var query = providerSearchQuery.toLowerCase();

  // Filter providers
  if (query) {
    providers = providers.filter(function(p) {
      return p.name.toLowerCase().includes(query) || p.type.toLowerCase().includes(query);
    });
  }

  if (providers.length === 0) {
    container.innerHTML = '<div class="provider-list-empty">' +
      '<p>' + (query ? t('apiSettings.noProvidersFound') : t('apiSettings.noProviders')) + '</p>' +
      '</div>';
    return;
  }

  var html = '';
  providers.forEach(function(provider) {
    var isSelected = provider.id === selectedProviderId;
    var iconClass = getProviderIconClass(provider.type);
    var iconLetter = provider.type.charAt(0).toUpperCase();

    html += '<div class="provider-list-item' + (isSelected ? ' selected' : '') + '" ' +
      'data-provider-id="' + provider.id + '" onclick="selectProvider(\'' + provider.id + '\')">' +
      '<div class="provider-item-icon ' + iconClass + '">' + iconLetter + '</div>' +
      '<div class="provider-item-info">' +
      '<span class="provider-item-name">' + escapeHtml(provider.name) + '</span>' +
      '<span class="provider-item-type">' + provider.type + '</span>' +
      '</div>' +
      '<span class="status-badge ' + (provider.enabled ? 'status-enabled' : 'status-disabled') + '">' +
      (provider.enabled ? 'ON' : 'OFF') +
      '</span>' +
      '</div>';
  });

  container.innerHTML = html;
}

/**
 * Filter providers by search query
 */
function filterProviders(query) {
  providerSearchQuery = query;
  renderProviderList();
}

/**
 * Switch sidebar tab
 */
function switchSidebarTab(tab) {
  activeSidebarTab = tab;
  renderApiSettings();
}

/**
 * Select a provider
 */
function selectProvider(providerId) {
  selectedProviderId = providerId;
  renderProviderList();
  renderProviderDetail(providerId);
}

/**
 * Render provider detail panel
 */
function renderProviderDetail(providerId) {
  var container = document.getElementById('provider-detail-panel');
  if (!container) return;

  var provider = apiSettingsData.providers.find(function(p) { return p.id === providerId; });
  if (!provider) {
    renderProviderEmptyState();
    return;
  }

  var maskedKey = provider.apiKey ? '••••••••••••••••' + provider.apiKey.slice(-4) : '••••••••';
  var currentApiBase = provider.apiBase || getDefaultApiBase(provider.type);
  // Show full endpoint URL preview based on active model tab
  var endpointPath = activeModelTab === 'embedding' ? '/embeddings' : '/chat/completions';
  var apiBasePreview = currentApiBase + endpointPath;

  var html = '<div class="provider-detail-header">' +
    '<div class="provider-detail-title">' +
    '<div class="provider-item-icon ' + getProviderIconClass(provider.type) + '">' +
    provider.type.charAt(0).toUpperCase() +
    '</div>' +
    '<h2>' + escapeHtml(provider.name) + '</h2>' +
    '<button class="btn-icon-sm" onclick="showEditProviderModal(\'' + providerId + '\')" title="' + t('common.settings') + '">' +
    '<i data-lucide="settings"></i>' +
    '</button>' +
    '<button class="btn-icon-sm text-destructive" onclick="deleteProviderWithConfirm(\'' + providerId + '\')" title="' + t('apiSettings.deleteProvider') + '">' +
    '<i data-lucide="trash-2"></i>' +
    '</button>' +
    '</div>' +
    '<div class="provider-detail-actions">' +
    '<label class="toggle-switch">' +
    '<input type="checkbox" ' + (provider.enabled ? 'checked' : '') + ' onchange="toggleProviderEnabled(\'' + providerId + '\', this.checked)" />' +
    '<span class="toggle-track"><span class="toggle-thumb"></span></span>' +
    '</label>' +
    '</div>' +
    '</div>' +
    '<div class="provider-detail-content">' +
    // API Key field
    '<div class="field-group">' +
    '<div class="field-label">' +
    '<span>' + t('apiSettings.apiKey') + '</span>' +
    '<div class="field-label-actions">' +
    '<button class="btn-icon-sm" onclick="copyProviderApiKey(\'' + providerId + '\')" title="' + t('common.copy') + '">' +
    '<i data-lucide="copy"></i>' +
    '</button>' +
    '</div>' +
    '</div>' +
    '<div class="field-input-group">' +
    '<input type="password" class="cli-input" id="provider-detail-apikey" value="' + escapeHtml(provider.apiKey) + '" readonly />' +
    '<button class="btn-icon" onclick="toggleApiKeyVisibility(\'provider-detail-apikey\')">' +
    '<i data-lucide="eye"></i>' +
    '</button>' +
    '<button class="btn btn-secondary" onclick="testProviderConnection()">' + t('apiSettings.testConnection') + '</button>' +
    '</div>' +
    '</div>' +
    // API Base URL field - editable
    '<div class="field-group">' +
    '<div class="field-label">' +
    '<span>' + t('apiSettings.apiBaseUrl') + '</span>' +
    '</div>' +
    '<div class="field-input-group">' +
    '<input type="text" class="cli-input" id="provider-detail-apibase" value="' + escapeHtml(currentApiBase) + '" placeholder="https://api.openai.com/v1" oninput="updateApiBasePreview(this.value)" />' +
    '<button class="btn btn-secondary" onclick="saveProviderApiBase(\'' + providerId + '\')">' +
    '<i data-lucide="save"></i> ' + t('common.save') +
    '</button>' +
    '</div>' +
    '<span class="field-hint" id="api-base-preview">' + t('apiSettings.preview') + ': ' + escapeHtml(apiBasePreview) + '</span>' +
    '</div>' +
    // Model Section
    '<div class="model-section">' +
    '<div class="model-section-header">' +
    '<div class="model-tabs">' +
    '<button class="model-tab' + (activeModelTab === 'llm' ? ' active' : '') + '" onclick="switchModelTab(\'llm\')">' +
    t('apiSettings.llmModels') +
    '</button>' +
    '<button class="model-tab' + (activeModelTab === 'embedding' ? ' active' : '') + '" onclick="switchModelTab(\'embedding\')">' +
    t('apiSettings.embeddingModels') +
    '</button>' +
    '</div>' +
    '<div class="model-section-actions">' +
    '<button class="btn btn-secondary" onclick="showManageModelsModal(\'' + providerId + '\')">' +
    '<i data-lucide="list"></i> ' + t('apiSettings.manageModels') +
    '</button>' +
    '<button class="btn btn-primary" onclick="showAddModelModal(\'' + providerId + '\')">' +
    '<i data-lucide="plus"></i> ' + t('apiSettings.addModel') +
    '</button>' +
    '</div>' +
    '</div>' +
    '<div class="model-tree" id="model-tree"></div>' +
    '</div>' +
    // Multi-key and sync buttons
    '<div class="multi-key-trigger">' +
    '<button class="btn btn-secondary multi-key-btn" onclick="showMultiKeyModal(\'' + providerId + '\')">' +
    '<i data-lucide="key-round"></i> ' + t('apiSettings.multiKeySettings') +
    '</button>' +
    '<button class="btn btn-secondary" onclick="syncConfigToCodexLens()">' +
    '<i data-lucide="refresh-cw"></i> ' + t('apiSettings.syncToCodexLens') +
    '</button>' +
    '</div>' +
    '</div>';

  container.innerHTML = html;
  renderModelTree(provider);

  if (window.lucide) lucide.createIcons();
}

/**
 * Render provider empty state
 */
function renderProviderEmptyState() {
  var container = document.getElementById('provider-detail-panel');
  if (!container) return;

  container.innerHTML = '<div class="provider-empty-state">' +
    '<i data-lucide="database" class="provider-empty-state-icon"></i>' +
    '<h3>' + t('apiSettings.selectProvider') + '</h3>' +
    '<p>' + t('apiSettings.selectProviderHint') + '</p>' +
    '</div>';

  if (window.lucide) lucide.createIcons();
}

/**
 * Render model tree
 */
function renderModelTree(provider) {
  var container = document.getElementById('model-tree');
  if (!container) return;

  var models = activeModelTab === 'llm'
    ? (provider.llmModels || [])
    : (provider.embeddingModels || []);

  if (models.length === 0) {
    container.innerHTML = '<div class="model-tree-empty">' +
      '<i data-lucide="package" class="model-tree-empty-icon"></i>' +
      '<p>' + t('apiSettings.noModels') + '</p>' +
      '</div>';
    if (window.lucide) lucide.createIcons();
    return;
  }

  // Group models by series
  var groups = groupModelsBySeries(models);

  var html = '';
  groups.forEach(function(group) {
    var isExpanded = expandedModelGroups.has(group.series);

    html += '<div class="model-group' + (isExpanded ? ' expanded' : '') + '" data-series="' + escapeHtml(group.series) + '">' +
      '<div class="model-group-header" onclick="toggleModelGroup(\'' + escapeHtml(group.series) + '\')">' +
      '<i data-lucide="chevron-right" class="model-group-toggle"></i>' +
      '<span class="model-group-name">' + escapeHtml(group.series) + '</span>' +
      '<span class="model-group-count">' + group.models.length + '</span>' +
      '</div>' +
      '<div class="model-group-children">';

    group.models.forEach(function(model) {
      var badge = model.capabilities && model.capabilities.contextWindow
        ? formatContextWindow(model.capabilities.contextWindow)
        : '';

      // Badge for embedding models shows dimension instead of context window
      var embeddingBadge = model.capabilities && model.capabilities.embeddingDimension
        ? model.capabilities.embeddingDimension + 'd'
        : '';
      var displayBadge = activeModelTab === 'llm' ? badge : embeddingBadge;

      html += '<div class="model-item" data-model-id="' + model.id + '">' +
        '<i data-lucide="' + (activeModelTab === 'llm' ? 'sparkles' : 'box') + '" class="model-item-icon"></i>' +
        '<span class="model-item-name">' + escapeHtml(model.name) + '</span>' +
        (displayBadge ? '<span class="model-item-badge">' + displayBadge + '</span>' : '') +
        '<div class="model-item-actions">' +
        '<button class="btn-icon-sm" onclick="showModelSettingsModal(\'' + selectedProviderId + '\', \'' + model.id + '\', \'' + activeModelTab + '\')" title="' + t('apiSettings.modelSettings') + '">' +
        '<i data-lucide="settings"></i>' +
        '</button>' +
        '<button class="btn-icon-sm text-destructive" onclick="deleteModel(\'' + selectedProviderId + '\', \'' + model.id + '\', \'' + activeModelTab + '\')" title="' + t('apiSettings.deleteModel') + '">' +
        '<i data-lucide="trash-2"></i>' +
        '</button>' +
        '</div>' +
        '</div>';
    });

    html += '</div></div>';
  });

  container.innerHTML = html;
  if (window.lucide) lucide.createIcons();
}

/**
 * Group models by series
 */
function groupModelsBySeries(models) {
  var seriesMap = {};

  models.forEach(function(model) {
    var series = model.series || 'Other';
    if (!seriesMap[series]) {
      seriesMap[series] = [];
    }
    seriesMap[series].push(model);
  });

  return Object.keys(seriesMap).map(function(series) {
    return { series: series, models: seriesMap[series] };
  }).sort(function(a, b) {
    return a.series.localeCompare(b.series);
  });
}

/**
 * Toggle model group expand/collapse
 */
function toggleModelGroup(series) {
  if (expandedModelGroups.has(series)) {
    expandedModelGroups.delete(series);
  } else {
    expandedModelGroups.add(series);
  }

  var provider = apiSettingsData.providers.find(function(p) { return p.id === selectedProviderId; });
  if (provider) {
    renderModelTree(provider);
  }
}

/**
 * Switch model tab (LLM / Embedding)
 */
function switchModelTab(tab) {
  activeModelTab = tab;
  expandedModelGroups.clear();

  var provider = apiSettingsData.providers.find(function(p) { return p.id === selectedProviderId; });
  if (provider) {
    renderProviderDetail(selectedProviderId);
  }
}

/**
 * Format context window for display
 */
function formatContextWindow(tokens) {
  if (tokens >= 1000000) return Math.round(tokens / 1000000) + 'M';
  if (tokens >= 1000) return Math.round(tokens / 1000) + 'K';
  return tokens.toString();
}

/**
 * Get default API base URL for provider type
 */
function getDefaultApiBase(type) {
  var defaults = {
    'openai': 'https://api.openai.com/v1',
    'anthropic': 'https://api.anthropic.com/v1'
  };
  return defaults[type] || 'https://api.example.com/v1';
}

/**
 * Toggle provider enabled status
 */
async function toggleProviderEnabled(providerId, enabled) {
  try {
    var response = await fetch('/api/litellm-api/providers/' + providerId, {
      method: 'PUT',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ enabled: enabled })
    });
    if (!response.ok) throw new Error('Failed to update provider');

    // Update local data (for instant UI feedback)
    var provider = apiSettingsData.providers.find(function(p) { return p.id === providerId; });
    if (provider) provider.enabled = enabled;

    renderProviderList();
    showRefreshToast(t('apiSettings.providerUpdated'), 'success');

    // Invalidate cache for next render
    setTimeout(function() {
      apiSettingsData = null;
    }, 100);
  } catch (err) {
    console.error('Failed to toggle provider:', err);
    showRefreshToast(t('common.error') + ': ' + err.message, 'error');
  }
}

/**
 * Show cache panel
 */
async function showCachePanel() {
  var overlay = document.getElementById('cache-panel-overlay');
  if (!overlay) return;

  var cacheStats = await loadCacheStats();
  var usedMB = (cacheStats.totalSize / 1048576).toFixed(1);
  var maxMB = (cacheStats.maxSize / 1048576).toFixed(0);
  var usagePercent = cacheStats.maxSize > 0 ? Math.round((cacheStats.totalSize / cacheStats.maxSize) * 100) : 0;

  overlay.innerHTML = '<div class="cache-panel-content" onclick="event.stopPropagation()">' +
    '<div class="cache-header">' +
    '<div class="section-title-group">' +
    '<h3>' + t('apiSettings.cacheSettings') + '</h3>' +
    '</div>' +
    '<button class="btn-icon-sm" onclick="closeCachePanel()">' +
    '<i data-lucide="x"></i>' +
    '</button>' +
    '</div>' +
    '<div class="cache-content">' +
    '<label class="toggle-switch">' +
    '<input type="checkbox" id="global-cache-enabled" ' + (cacheStats.enabled ? 'checked' : '') + ' onchange="toggleGlobalCache(this.checked)" />' +
    '<span class="toggle-track"><span class="toggle-thumb"></span></span>' +
    '<span class="toggle-label">' + t('apiSettings.enableGlobalCaching') + '</span>' +
    '</label>' +
    '<div class="cache-visual">' +
    '<div class="cache-bars">' +
    '<div class="cache-bar-fill" style="width: ' + usagePercent + '%"></div>' +
    '</div>' +
    '<div class="cache-legend">' +
    '<span>' + usedMB + ' MB ' + t('apiSettings.used') + '</span>' +
    '<span>' + maxMB + ' MB ' + t('apiSettings.total') + '</span>' +
    '</div>' +
    '</div>' +
    '<div class="stat-grid">' +
    '<div class="stat-card">' +
    '<span class="stat-value">' + usagePercent + '%</span>' +
    '<span class="stat-desc">' + t('apiSettings.cacheUsage') + '</span>' +
    '</div>' +
    '<div class="stat-card">' +
    '<span class="stat-value">' + cacheStats.entries + '</span>' +
    '<span class="stat-desc">' + t('apiSettings.cacheEntries') + '</span>' +
    '</div>' +
    '</div>' +
    '<button class="btn btn-secondary btn-full" onclick="clearCache()">' +
    '<i data-lucide="trash-2"></i> ' + t('apiSettings.clearCache') +
    '</button>' +
    '</div>' +
    '</div>';

  overlay.classList.add('active');
  if (window.lucide) lucide.createIcons();
}

/**
 * Close cache panel
 */
function closeCachePanel() {
  var overlay = document.getElementById('cache-panel-overlay');
  if (overlay) {
    overlay.classList.remove('active');
  }
}

/**
 * Close cache panel when clicking overlay
 */
function closeCachePanelOverlay(event) {
  if (event.target.id === 'cache-panel-overlay') {
    closeCachePanel();
  }
}

/**
 * Escape HTML special characters
 */
function escapeHtml(str) {
  if (!str) return '';
  return String(str)
    .replace(/&/g, '&amp;')
    .replace(/</g, '&lt;')
    .replace(/>/g, '&gt;')
    .replace(/"/g, '&quot;')
    .replace(/'/g, '&#039;');
}

// ========== Model Management ==========

/**
 * Show add model modal
 */
function showAddModelModal(providerId, modelType) {
  // Default to active tab if no modelType provided
  if (!modelType) {
    modelType = activeModelTab;
  }

  // Get provider to know which presets to show
  const provider = apiSettingsData.providers.find(function(p) { return p.id === providerId; });
  if (!provider) return;

  const isLlm = modelType === 'llm';
  const title = isLlm ? t('apiSettings.addLlmModel') : t('apiSettings.addEmbeddingModel');

  // Get model presets based on provider type
  const presets = isLlm ? getLlmPresetsForType(provider.type) : getEmbeddingPresetsForType(provider.type);

  // Group presets by series
  const groupedPresets = groupPresetsBySeries(presets);

  const modalHtml = '<div class="generic-modal-overlay active" id="add-model-modal">' +
    '<div class="generic-modal" style="max-width: 600px;">' +
    '<div class="generic-modal-header">' +
    '<h3 class="generic-modal-title">' + title + '</h3>' +
    '<button class="generic-modal-close" onclick="closeAddModelModal()">&times;</button>' +
    '</div>' +
    '<div class="generic-modal-body">' +
    '<form id="add-model-form" class="api-settings-form" onsubmit="saveNewModel(event, \'' + providerId + '\', \'' + modelType + '\')">' +

    // Preset Selection
    '<div class="form-group">' +
    '<label>' + t('apiSettings.selectFromPresets') + '</label>' +
    '<select id="model-preset" class="cli-input" onchange="fillModelFromPreset(this.value, \'' + modelType + '\')">' +
    '<option value="">' + t('apiSettings.customModel') + '</option>' +
    Object.keys(groupedPresets).map(function(series) {
      return '<optgroup label="' + series + '">' +
        groupedPresets[series].map(function(m) {
          return '<option value="' + m.id + '">' + m.name + ' ' +
            (isLlm ? '(' + (m.contextWindow/1000) + 'K)' : '(' + m.dimensions + 'D)') +
            '</option>';
        }).join('') +
        '</optgroup>';
    }).join('') +
    '</select>' +
    '</div>' +

    // Model ID
    '<div class="form-group">' +
    '<label>' + t('apiSettings.modelId') + ' *</label>' +
    '<input type="text" id="model-id" class="cli-input" required placeholder="e.g., gpt-4o" />' +
    '</div>' +

    // Display Name
    '<div class="form-group">' +
    '<label>' + t('apiSettings.modelName') + ' *</label>' +
    '<input type="text" id="model-name" class="cli-input" required placeholder="e.g., GPT-4o" />' +
    '</div>' +

    // Series
    '<div class="form-group">' +
    '<label>' + t('apiSettings.modelSeries') + ' *</label>' +
    '<input type="text" id="model-series" class="cli-input" required placeholder="e.g., GPT-4" />' +
    '</div>' +

    // Capabilities based on model type
    (isLlm ?
      '<div class="form-group">' +
      '<label>' + t('apiSettings.contextWindow') + '</label>' +
      '<input type="number" id="model-context-window" class="cli-input" value="128000" min="1000" />' +
      '</div>' +
      '<div class="form-group capabilities-checkboxes">' +
      '<label style="display: block; margin-bottom: 0.5rem;">' + t('apiSettings.capabilities') + '</label>' +
      '<label class="checkbox-label">' +
      '<input type="checkbox" id="cap-streaming" checked /> ' + t('apiSettings.streaming') +
      '</label>' +
      '<label class="checkbox-label">' +
      '<input type="checkbox" id="cap-function-calling" /> ' + t('apiSettings.functionCalling') +
      '</label>' +
      '<label class="checkbox-label">' +
      '<input type="checkbox" id="cap-vision" /> ' + t('apiSettings.vision') +
      '</label>' +
      '</div>'
    :
      '<div class="form-group">' +
      '<label>' + t('apiSettings.embeddingDimensions') + ' *</label>' +
      '<input type="number" id="model-dimensions" class="cli-input" value="1536" min="64" required />' +
      '</div>' +
      '<div class="form-group">' +
      '<label>' + t('apiSettings.embeddingMaxTokens') + '</label>' +
      '<input type="number" id="model-max-tokens" class="cli-input" value="8192" min="128" />' +
      '</div>'
    ) +

    // Description
    '<div class="form-group">' +
    '<label>' + t('apiSettings.description') + '</label>' +
    '<textarea id="model-description" class="cli-input" rows="2" placeholder="' + t('apiSettings.optional') + '"></textarea>' +
    '</div>' +

    '<div class="modal-actions">' +
    '<button type="button" class="btn btn-secondary" onclick="closeAddModelModal()"><i data-lucide="x"></i> ' + t('common.cancel') + '</button>' +
    '<button type="submit" class="btn btn-primary"><i data-lucide="check"></i> ' + t('common.save') + '</button>' +
    '</div>' +
    '</form>' +
    '</div>' +
    '</div>' +
    '</div>';

  document.body.insertAdjacentHTML('beforeend', modalHtml);
  if (window.lucide) lucide.createIcons();
}

/**
 * Close add model modal
 */
function closeAddModelModal() {
  const modal = document.getElementById('add-model-modal');
  if (modal) modal.remove();
}

/**
 * Get LLM presets for provider type
 */
function getLlmPresetsForType(providerType) {
  const presets = {
    openai: [
      { id: 'gpt-4o', name: 'GPT-4o', series: 'GPT-4', contextWindow: 128000 },
      { id: 'gpt-4o-mini', name: 'GPT-4o Mini', series: 'GPT-4', contextWindow: 128000 },
      { id: 'gpt-4-turbo', name: 'GPT-4 Turbo', series: 'GPT-4', contextWindow: 128000 },
      { id: 'gpt-3.5-turbo', name: 'GPT-3.5 Turbo', series: 'GPT-3.5', contextWindow: 16385 },
      { id: 'o1', name: 'O1', series: 'O1', contextWindow: 200000 },
      { id: 'o1-mini', name: 'O1 Mini', series: 'O1', contextWindow: 128000 },
      { id: 'deepseek-chat', name: 'DeepSeek Chat', series: 'DeepSeek', contextWindow: 64000 },
      { id: 'deepseek-coder', name: 'DeepSeek Coder', series: 'DeepSeek', contextWindow: 64000 }
    ],
    anthropic: [
      { id: 'claude-sonnet-4-20250514', name: 'Claude Sonnet 4', series: 'Claude 4', contextWindow: 200000 },
      { id: 'claude-3-5-sonnet-20241022', name: 'Claude 3.5 Sonnet', series: 'Claude 3.5', contextWindow: 200000 },
      { id: 'claude-3-5-haiku-20241022', name: 'Claude 3.5 Haiku', series: 'Claude 3.5', contextWindow: 200000 },
      { id: 'claude-3-opus-20240229', name: 'Claude 3 Opus', series: 'Claude 3', contextWindow: 200000 }
    ],
    custom: [
      { id: 'custom-model', name: 'Custom Model', series: 'Custom', contextWindow: 128000 }
    ]
  };
  return presets[providerType] || presets.custom;
}

/**
 * Get Embedding presets for provider type
 */
function getEmbeddingPresetsForType(providerType) {
  const presets = {
    openai: [
      { id: 'text-embedding-3-small', name: 'Text Embedding 3 Small', series: 'Embedding V3', dimensions: 1536, maxTokens: 8191 },
      { id: 'text-embedding-3-large', name: 'Text Embedding 3 Large', series: 'Embedding V3', dimensions: 3072, maxTokens: 8191 },
      { id: 'text-embedding-ada-002', name: 'Ada 002', series: 'Embedding V2', dimensions: 1536, maxTokens: 8191 }
    ],
    anthropic: [],  // Anthropic doesn't have embedding models
    custom: [
      { id: 'custom-embedding', name: 'Custom Embedding', series: 'Custom', dimensions: 1536, maxTokens: 8192 }
    ]
  };
  return presets[providerType] || presets.custom;
}

/**
 * Group presets by series
 */
function groupPresetsBySeries(presets) {
  const grouped = {};
  presets.forEach(function(preset) {
    if (!grouped[preset.series]) {
      grouped[preset.series] = [];
    }
    grouped[preset.series].push(preset);
  });
  return grouped;
}

/**
 * Fill model form from preset
 */
function fillModelFromPreset(presetId, modelType) {
  if (!presetId) {
    // Clear fields for custom model
    document.getElementById('model-id').value = '';
    document.getElementById('model-name').value = '';
    document.getElementById('model-series').value = '';
    return;
  }

  const provider = apiSettingsData.providers.find(function(p) { return p.id === selectedProviderId; });
  if (!provider) return;

  const isLlm = modelType === 'llm';
  const presets = isLlm ? getLlmPresetsForType(provider.type) : getEmbeddingPresetsForType(provider.type);
  const preset = presets.find(function(p) { return p.id === presetId; });

  if (preset) {
    document.getElementById('model-id').value = preset.id;
    document.getElementById('model-name').value = preset.name;
    document.getElementById('model-series').value = preset.series;

    if (isLlm && preset.contextWindow) {
      document.getElementById('model-context-window').value = preset.contextWindow;
    }
    if (!isLlm && preset.dimensions) {
      document.getElementById('model-dimensions').value = preset.dimensions;
      if (preset.maxTokens) {
        document.getElementById('model-max-tokens').value = preset.maxTokens;
      }
    }
  }
}

/**
 * Save new model
 */
function saveNewModel(event, providerId, modelType) {
  event.preventDefault();

  const isLlm = modelType === 'llm';
  const now = new Date().toISOString();

  const newModel = {
    id: document.getElementById('model-id').value.trim(),
    name: document.getElementById('model-name').value.trim(),
    type: modelType,
    series: document.getElementById('model-series').value.trim(),
    enabled: true,
    description: document.getElementById('model-description').value.trim() || undefined,
    createdAt: now,
    updatedAt: now
  };

  // Add capabilities based on model type
  if (isLlm) {
    newModel.capabilities = {
      contextWindow: parseInt(document.getElementById('model-context-window').value) || 128000,
      streaming: document.getElementById('cap-streaming').checked,
      functionCalling: document.getElementById('cap-function-calling').checked,
      vision: document.getElementById('cap-vision').checked
    };
  } else {
    newModel.capabilities = {
      embeddingDimension: parseInt(document.getElementById('model-dimensions').value) || 1536,
      contextWindow: parseInt(document.getElementById('model-max-tokens').value) || 8192
    };
  }

  // Save to provider
  fetch('/api/litellm-api/providers/' + providerId)
    .then(function(res) { return res.json(); })
    .then(function(provider) {
      const modelsKey = isLlm ? 'llmModels' : 'embeddingModels';
      const models = provider[modelsKey] || [];

      // Check for duplicate ID
      if (models.some(function(m) { return m.id === newModel.id; })) {
        showRefreshToast(t('apiSettings.modelIdExists'), 'error');
        return Promise.reject('Duplicate ID');
      }

      models.push(newModel);
      return fetch('/api/litellm-api/providers/' + providerId, {
        method: 'PUT',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ [modelsKey]: models })
      });
    })
    .then(function() {
      closeAddModelModal();
      return loadApiSettings();
    })
    .then(function() {
      if (selectedProviderId === providerId) {
        selectProvider(providerId);
      }
      showRefreshToast(t('common.saveSuccess'), 'success');
    })
    .catch(function(err) {
      if (err !== 'Duplicate ID') {
        console.error('Failed to save model:', err);
        showRefreshToast(t('common.saveFailed'), 'error');
      }
    });
}

function showManageModelsModal(providerId) {
  // For now, show a helpful message
  showRefreshToast(t('apiSettings.useModelTreeToManage'), 'info');
}

function showModelSettingsModal(providerId, modelId, modelType) {
  var provider = apiSettingsData.providers.find(function(p) { return p.id === providerId; });
  if (!provider) return;

  var isLlm = modelType === 'llm';
  var models = isLlm ? (provider.llmModels || []) : (provider.embeddingModels || []);
  var model = models.find(function(m) { return m.id === modelId; });
  if (!model) return;

  var capabilities = model.capabilities || {};
  var endpointSettings = model.endpointSettings || {};

  // Calculate endpoint preview URL
  var providerBase = provider.apiBase || getDefaultApiBase(provider.type);
  var modelBaseUrl = endpointSettings.baseUrl || providerBase;
  var endpointPath = isLlm ? '/chat/completions' : '/embeddings';
  var endpointPreview = modelBaseUrl + endpointPath;

  var modalHtml = '<div class="modal-overlay" id="model-settings-modal">' +
    '<div class="modal-content" style="max-width: 600px;">' +
    '<div class="modal-header">' +
    '<h3>' + t('apiSettings.modelSettings') + ': ' + escapeHtml(model.name) + '</h3>' +
    '<button class="modal-close" onclick="closeModelSettingsModal()">&times;</button>' +
    '</div>' +
    '<div class="modal-body">' +
    '<form id="model-settings-form" onsubmit="saveModelSettings(event, \'' + providerId + '\', \'' + modelId + '\', \'' + modelType + '\')">' +

    // Endpoint Preview Section (combined view + settings)
    '<div class="form-section endpoint-preview-section">' +
    '<h4><i data-lucide="' + (isLlm ? 'message-square' : 'box') + '"></i> ' + t('apiSettings.endpointPreview') + '</h4>' +
    '<div class="endpoint-preview-box">' +
    '<code id="model-endpoint-preview">' + escapeHtml(endpointPreview) + '</code>' +
    '<button type="button" class="btn-icon-sm" onclick="copyModelEndpoint()" title="' + t('common.copy') + '">' +
    '<i data-lucide="copy"></i>' +
    '</button>' +
    '</div>' +
    '<div class="form-group">' +
    '<label>' + t('apiSettings.modelBaseUrlOverride') + ' <span class="text-muted">(' + t('common.optional') + ')</span></label>' +
    '<input type="text" id="model-settings-baseurl" class="cli-input" value="' + escapeHtml(endpointSettings.baseUrl || '') + '" placeholder="' + escapeHtml(providerBase) + '" oninput="updateModelEndpointPreview(\'' + (isLlm ? 'chat/completions' : 'embeddings') + '\', \'' + escapeHtml(providerBase) + '\')">' +
    '<small class="form-hint">' + t('apiSettings.modelBaseUrlHint') + '</small>' +
    '</div>' +
    '</div>' +

    // Basic Info
    '<div class="form-section">' +
    '<h4>' + t('apiSettings.basicInfo') + '</h4>' +
    '<div class="form-group">' +
    '<label>' + t('apiSettings.modelName') + '</label>' +
    '<input type="text" id="model-settings-name" class="cli-input" value="' + escapeHtml(model.name || '') + '" required>' +
    '</div>' +
    '<div class="form-group">' +
    '<label>' + t('apiSettings.modelSeries') + '</label>' +
    '<input type="text" id="model-settings-series" class="cli-input" value="' + escapeHtml(model.series || '') + '" required>' +
    '</div>' +
    '<div class="form-group">' +
    '<label>' + t('apiSettings.description') + '</label>' +
    '<textarea id="model-settings-description" class="cli-input" rows="2">' + escapeHtml(model.description || '') + '</textarea>' +
    '</div>' +
    '</div>' +

    // Capabilities
    '<div class="form-section">' +
    '<h4>' + t('apiSettings.capabilities') + '</h4>' +
    (isLlm ? (
      '<div class="form-group">' +
      '<label>' + t('apiSettings.contextWindow') + '</label>' +
      '<input type="number" id="model-settings-context" class="cli-input" value="' + (capabilities.contextWindow || 128000) + '" min="1000">' +
      '</div>' +
      '<div class="form-group capabilities-checkboxes">' +
      '<label class="checkbox-label"><input type="checkbox" id="model-settings-streaming"' + (capabilities.streaming ? ' checked' : '') + '> ' + t('apiSettings.streaming') + '</label>' +
      '<label class="checkbox-label"><input type="checkbox" id="model-settings-function-calling"' + (capabilities.functionCalling ? ' checked' : '') + '> ' + t('apiSettings.functionCalling') + '</label>' +
      '<label class="checkbox-label"><input type="checkbox" id="model-settings-vision"' + (capabilities.vision ? ' checked' : '') + '> ' + t('apiSettings.vision') + '</label>' +
      '</div>'
    ) : (
      '<div class="form-group">' +
      '<label>' + t('apiSettings.embeddingDimensions') + '</label>' +
      '<input type="number" id="model-settings-dimensions" class="cli-input" value="' + (capabilities.embeddingDimension || 1536) + '" min="64">' +
      '</div>' +
      '<div class="form-group">' +
      '<label>' + t('apiSettings.embeddingMaxTokens') + '</label>' +
      '<input type="number" id="model-settings-max-tokens" class="cli-input" value="' + (capabilities.contextWindow || 8192) + '" min="128">' +
      '</div>'
    )) +
    '</div>' +

    // Endpoint Settings
    '<div class="form-section">' +
    '<h4>' + t('apiSettings.endpointSettings') + '</h4>' +
    '<div class="form-row">' +
    '<div class="form-group form-group-half">' +
    '<label>' + t('apiSettings.timeout') + ' (' + t('apiSettings.seconds') + ')</label>' +
    '<input type="number" id="model-settings-timeout" class="cli-input" value="' + (endpointSettings.timeout || 300) + '" min="10" max="3600">' +
    '</div>' +
    '<div class="form-group form-group-half">' +
    '<label>' + t('apiSettings.maxRetries') + '</label>' +
    '<input type="number" id="model-settings-retries" class="cli-input" value="' + (endpointSettings.maxRetries || 3) + '" min="0" max="10">' +
    '</div>' +
    '</div>' +
    '</div>' +

    '<div class="modal-actions">' +
    '<button type="button" class="btn-secondary" onclick="closeModelSettingsModal()"><i data-lucide="x"></i> ' + t('common.cancel') + '</button>' +
    '<button type="submit" class="btn-primary"><i data-lucide="check"></i> ' + t('common.save') + '</button>' +
    '</div>' +
    '</form>' +
    '</div>' +
    '</div>' +
    '</div>';

  document.body.insertAdjacentHTML('beforeend', modalHtml);
  if (window.lucide) lucide.createIcons();
}

/**
 * Update model endpoint preview when base URL changes
 */
function updateModelEndpointPreview(endpointPath, defaultBase) {
  var baseUrlInput = document.getElementById('model-settings-baseurl');
  var previewElement = document.getElementById('model-endpoint-preview');
  if (!baseUrlInput || !previewElement) return;

  var baseUrl = baseUrlInput.value.trim() || defaultBase;
  // Remove trailing slash if present
  if (baseUrl.endsWith('/')) {
    baseUrl = baseUrl.slice(0, -1);
  }
  previewElement.textContent = baseUrl + '/' + endpointPath;
}

/**
 * Copy model endpoint URL to clipboard
 */
function copyModelEndpoint() {
  var previewElement = document.getElementById('model-endpoint-preview');
  if (previewElement) {
    navigator.clipboard.writeText(previewElement.textContent);
    showRefreshToast(t('common.copied'), 'success');
  }
}

function closeModelSettingsModal() {
  var modal = document.getElementById('model-settings-modal');
  if (modal) modal.remove();
}

function saveModelSettings(event, providerId, modelId, modelType) {
  event.preventDefault();

  var isLlm = modelType === 'llm';
  var modelsKey = isLlm ? 'llmModels' : 'embeddingModels';

  fetch('/api/litellm-api/providers/' + providerId)
    .then(function(res) { return res.json(); })
    .then(function(provider) {
      var models = provider[modelsKey] || [];
      var modelIndex = models.findIndex(function(m) { return m.id === modelId; });

      if (modelIndex === -1) {
        throw new Error('Model not found');
      }

      // Update model fields
      models[modelIndex].name = document.getElementById('model-settings-name').value.trim();
      models[modelIndex].series = document.getElementById('model-settings-series').value.trim();
      models[modelIndex].description = document.getElementById('model-settings-description').value.trim() || undefined;
      models[modelIndex].updatedAt = new Date().toISOString();

      // Update capabilities
      if (isLlm) {
        models[modelIndex].capabilities = {
          contextWindow: parseInt(document.getElementById('model-settings-context').value) || 128000,
          streaming: document.getElementById('model-settings-streaming').checked,
          functionCalling: document.getElementById('model-settings-function-calling').checked,
          vision: document.getElementById('model-settings-vision').checked
        };
      } else {
        models[modelIndex].capabilities = {
          embeddingDimension: parseInt(document.getElementById('model-settings-dimensions').value) || 1536,
          contextWindow: parseInt(document.getElementById('model-settings-max-tokens').value) || 8192
        };
      }

      // Update endpoint settings
      var baseUrlOverride = document.getElementById('model-settings-baseurl').value.trim();
      // Remove trailing slash if present
      if (baseUrlOverride && baseUrlOverride.endsWith('/')) {
        baseUrlOverride = baseUrlOverride.slice(0, -1);
      }
      models[modelIndex].endpointSettings = {
        baseUrl: baseUrlOverride || undefined,
        timeout: parseInt(document.getElementById('model-settings-timeout').value) || 300,
        maxRetries: parseInt(document.getElementById('model-settings-retries').value) || 3
      };

      var updateData = {};
      updateData[modelsKey] = models;

      return fetch('/api/litellm-api/providers/' + providerId, {
        method: 'PUT',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify(updateData)
      });
    })
    .then(function() {
      closeModelSettingsModal();
      return loadApiSettings();
    })
    .then(function() {
      if (selectedProviderId === providerId) {
        selectProvider(providerId);
      }
      showRefreshToast(t('common.saveSuccess'), 'success');
    })
    .catch(function(err) {
      console.error('Failed to save model settings:', err);
      showRefreshToast(t('common.saveFailed'), 'error');
    });
}

function deleteModel(providerId, modelId, modelType) {
  if (!confirm(t('common.confirmDelete'))) return;

  var isLlm = modelType === 'llm';
  var modelsKey = isLlm ? 'llmModels' : 'embeddingModels';

  fetch('/api/litellm-api/providers/' + providerId)
    .then(function(res) { return res.json(); })
    .then(function(provider) {
      var models = provider[modelsKey] || [];
      var updatedModels = models.filter(function(m) { return m.id !== modelId; });

      var updateData = {};
      updateData[modelsKey] = updatedModels;

      return fetch('/api/litellm-api/providers/' + providerId, {
        method: 'PUT',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify(updateData)
      });
    })
    .then(function() {
      return loadApiSettings();
    })
    .then(function() {
      if (selectedProviderId === providerId) {
        selectProvider(providerId);
      }
      showRefreshToast(t('common.deleteSuccess'), 'success');
    })
    .catch(function(err) {
      console.error('Failed to delete model:', err);
      showRefreshToast(t('common.deleteFailed'), 'error');
    });
}

function copyProviderApiKey(providerId) {
  var provider = apiSettingsData.providers.find(function(p) { return p.id === providerId; });
  if (provider && provider.apiKey) {
    navigator.clipboard.writeText(provider.apiKey);
    showRefreshToast(t('common.copied'), 'success');
  }
}

/**
 * Save provider API base URL
 */
async function saveProviderApiBase(providerId) {
  var input = document.getElementById('provider-detail-apibase');
  if (!input) return;

  var newApiBase = input.value.trim();
  // Remove trailing slash if present
  if (newApiBase.endsWith('/')) {
    newApiBase = newApiBase.slice(0, -1);
  }

  try {
    var response = await fetch('/api/litellm-api/providers/' + providerId, {
      method: 'PUT',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ apiBase: newApiBase || undefined })
    });

    if (!response.ok) throw new Error('Failed to update API base');

    // Update local data (for instant UI feedback)
    var provider = apiSettingsData.providers.find(function(p) { return p.id === providerId; });
    if (provider) {
      provider.apiBase = newApiBase || undefined;
    }

    // Update preview
    updateApiBasePreview(newApiBase);
    showRefreshToast(t('apiSettings.apiBaseUpdated'), 'success');

    // Invalidate cache for next render (but keep current data for immediate UI)
    // This ensures next tab switch or page refresh gets fresh data
    setTimeout(function() {
      apiSettingsData = null;
    }, 100);
  } catch (err) {
    console.error('Failed to save API base:', err);
    showRefreshToast(t('common.error') + ': ' + err.message, 'error');
  }
}

/**
 * Update API base preview text showing full endpoint URL
 */
function updateApiBasePreview(apiBase) {
  var preview = document.getElementById('api-base-preview');
  if (!preview) return;

  var base = apiBase || getDefaultApiBase('openai');
  // Remove trailing slash if present
  if (base.endsWith('/')) {
    base = base.slice(0, -1);
  }
  var endpointPath = activeModelTab === 'embedding' ? '/embeddings' : '/chat/completions';
  preview.textContent = t('apiSettings.preview') + ': ' + base + endpointPath;
}

/**
 * Delete provider with confirmation
 */
async function deleteProviderWithConfirm(providerId) {
  if (!confirm(t('apiSettings.confirmDeleteProvider'))) return;

  try {
    var response = await fetch('/api/litellm-api/providers/' + providerId, {
      method: 'DELETE'
    });

    if (!response.ok) throw new Error('Failed to delete provider');

    // Remove from local data
    apiSettingsData.providers = apiSettingsData.providers.filter(function(p) {
      return p.id !== providerId;
    });

    // Clear selection if deleted provider was selected
    if (selectedProviderId === providerId) {
      selectedProviderId = null;
      if (apiSettingsData.providers.length > 0) {
        selectProvider(apiSettingsData.providers[0].id);
      } else {
        renderProviderEmptyState();
      }
    }

    renderProviderList();
    showRefreshToast(t('apiSettings.providerDeleted'), 'success');
  } catch (err) {
    console.error('Failed to delete provider:', err);
    showRefreshToast(t('common.error') + ': ' + err.message, 'error');
  }
}

/**
 * Sync config to CodexLens (generate YAML config for ccw_litellm)
 */
async function syncConfigToCodexLens() {
  try {
    var response = await fetch('/api/litellm-api/config/sync', {
      method: 'POST'
    });

    if (!response.ok) throw new Error('Failed to sync config');

    var result = await response.json();
    showRefreshToast(t('apiSettings.configSynced') + ' (' + result.yamlPath + ')', 'success');
  } catch (err) {
    console.error('Failed to sync config:', err);
    showRefreshToast(t('common.error') + ': ' + err.message, 'error');
  }
}

/**
 * Get provider icon class based on type
 */
function getProviderIconClass(type) {
  var iconMap = {
    'openai': 'provider-icon-openai',
    'anthropic': 'provider-icon-anthropic'
  };
  return iconMap[type] || 'provider-icon-custom';
}

/**
 * Get provider icon name based on type
 */
function getProviderIcon(type) {
  const iconMap = {
    'openai': 'sparkles',
    'anthropic': 'brain',
    'google': 'cloud',
    'azure': 'cloud-cog',
    'ollama': 'server',
    'mistral': 'wind',
    'deepseek': 'search'
  };
  return iconMap[type] || 'settings';
}

/**
 * Render providers list
 */
function renderProvidersList() {
  const container = document.getElementById('providers-list');
  if (!container) return;

  const providers = apiSettingsData.providers || [];

  if (providers.length === 0) {
    container.innerHTML = '<div class="empty-state">' +
      '<div class="empty-icon-wrapper">' +
      '<i data-lucide="cloud-off"></i>' +
      '</div>' +
      '<h4>' + t('apiSettings.noProviders') + '</h4>' +
      '<p>' + t('apiSettings.noProvidersHint') + '</p>' +
      '</div>';
    if (window.lucide) lucide.createIcons();
    return;
  }

  container.innerHTML = providers.map(function(provider) {
    const statusClass = provider.enabled === false ? 'disabled' : 'enabled';
    const statusText = provider.enabled === false ? t('apiSettings.disabled') : t('apiSettings.enabled');
    const iconClass = getProviderIconClass(provider.type);
    const iconName = getProviderIcon(provider.type);

    return '<div class="api-card' + (provider.enabled === false ? ' disabled' : '') + '">' +
      '<div class="card-header">' +
      '<div class="card-title-group">' +
      '<div class="card-icon ' + iconClass + '">' +
      '<i data-lucide="' + iconName + '"></i>' +
      '</div>' +
      '<div class="card-info">' +
      '<h4 class="card-title">' + provider.name + '</h4>' +
      '<span class="card-subtitle"><span class="provider-type-badge">' + provider.type + '</span></span>' +
      '</div>' +
      '</div>' +
      '<div class="card-actions">' +
      '<button class="btn-icon-sm" onclick="showEditProviderModal(\'' + provider.id + '\')" title="' + t('common.edit') + '">' +
      '<i data-lucide="pencil"></i>' +
      '</button>' +
      '<button class="btn-icon-sm text-destructive" onclick="deleteProvider(\'' + provider.id + '\')" title="' + t('common.delete') + '">' +
      '<i data-lucide="trash-2"></i>' +
      '</button>' +
      '</div>' +
      '</div>' +
      '<div class="card-body">' +
      '<div class="card-meta-grid">' +
      '<div class="meta-item">' +
      '<span class="meta-label">' + t('apiSettings.apiKey') + '</span>' +
      '<span class="meta-value">' + maskApiKey(provider.apiKey) + '</span>' +
      '</div>' +
      '<div class="meta-item">' +
      '<span class="meta-label">' + t('common.status') + '</span>' +
      '<span class="status-badge status-' + statusClass + '">' + statusText + '</span>' +
      '</div>' +
      (provider.apiBase ?
        '<div class="meta-item" style="grid-column: span 2;">' +
        '<span class="meta-label">' + t('apiSettings.apiBaseUrl') + '</span>' +
        '<span class="meta-value">' + provider.apiBase + '</span>' +
        '</div>' : '') +
      '</div>' +
      '</div>' +
      '</div>';
  }).join('');

  if (window.lucide) lucide.createIcons();
}

/**
 * Render endpoints list
 */
function renderEndpointsList() {
  const container = document.getElementById('endpoints-list');
  if (!container) return;

  const endpoints = apiSettingsData.endpoints || [];

  if (endpoints.length === 0) {
    container.innerHTML = '<div class="empty-state">' +
      '<div class="empty-icon-wrapper">' +
      '<i data-lucide="layers"></i>' +
      '</div>' +
      '<h4>' + t('apiSettings.noEndpoints') + '</h4>' +
      '<p>' + t('apiSettings.noEndpointsHint') + '</p>' +
      '</div>';
    if (window.lucide) lucide.createIcons();
    return;
  }

  container.innerHTML = endpoints.map(function(endpoint) {
    const provider = apiSettingsData.providers.find(function(p) { return p.id === endpoint.providerId; });
    const providerName = provider ? provider.name : endpoint.providerId;
    const providerType = provider ? provider.type : 'custom';
    const iconClass = getProviderIconClass(providerType);
    const iconName = getProviderIcon(providerType);

    const cacheEnabled = endpoint.cacheStrategy?.enabled;
    const cacheStatus = cacheEnabled
      ? endpoint.cacheStrategy.ttlMinutes + ' min'
      : t('apiSettings.off');

    return '<div class="api-card">' +
      '<div class="card-header">' +
      '<div class="card-title-group">' +
      '<div class="card-icon ' + iconClass + '">' +
      '<i data-lucide="' + iconName + '"></i>' +
      '</div>' +
      '<div class="card-info">' +
      '<h4 class="card-title">' + endpoint.name + '</h4>' +
      '<code class="endpoint-id">' + endpoint.id + '</code>' +
      '</div>' +
      '</div>' +
      '<div class="card-actions">' +
      '<button class="btn-icon-sm" onclick="showEditEndpointModal(\'' + endpoint.id + '\')" title="' + t('common.edit') + '">' +
      '<i data-lucide="pencil"></i>' +
      '</button>' +
      '<button class="btn-icon-sm text-destructive" onclick="deleteEndpoint(\'' + endpoint.id + '\')" title="' + t('common.delete') + '">' +
      '<i data-lucide="trash-2"></i>' +
      '</button>' +
      '</div>' +
      '</div>' +
      '<div class="card-body">' +
      '<div class="card-meta-grid">' +
      '<div class="meta-item">' +
      '<span class="meta-label">' + t('apiSettings.provider') + '</span>' +
      '<span class="meta-value">' + providerName + '</span>' +
      '</div>' +
      '<div class="meta-item">' +
      '<span class="meta-label">' + t('apiSettings.model') + '</span>' +
      '<span class="meta-value">' + endpoint.model + '</span>' +
      '</div>' +
      '<div class="meta-item">' +
      '<span class="meta-label">' + t('apiSettings.cache') + '</span>' +
      '<span class="badge ' + (cacheEnabled ? 'badge-success' : 'badge-outline') + '">' +
      (cacheEnabled ? '<i data-lucide="database" style="width:12px;height:12px;margin-right:4px;"></i>' : '') +
      cacheStatus + '</span>' +
      '</div>' +
      '</div>' +
      '<div class="usage-hint">' +
      '<i data-lucide="terminal"></i>' +
      '<code>ccw cli -p "..." --model ' + endpoint.id + '</code>' +
      '</div>' +
      '</div>' +
      '</div>';
  }).join('');

  if (window.lucide) lucide.createIcons();
}

/**
 * Render endpoints main panel
 */
function renderEndpointsMainPanel() {
  var container = document.getElementById('provider-detail-panel');
  if (!container) return;

  var endpoints = apiSettingsData.endpoints || [];
  
  var html = '<div class="endpoints-main-panel">' +
    '<div class="panel-header">' +
    '<h2>' + t('apiSettings.endpoints') + '</h2>' +
    '<p class="panel-subtitle">' + t('apiSettings.endpointsDescription') + '</p>' +
    '</div>' +
    '<div class="endpoints-stats">' +
    '<div class="stat-card">' +
    '<div class="stat-value">' + endpoints.length + '</div>' +
    '<div class="stat-label">' + t('apiSettings.totalEndpoints') + '</div>' +
    '</div>' +
    '<div class="stat-card">' +
    '<div class="stat-value">' + endpoints.filter(function(e) { return e.cacheStrategy?.enabled; }).length + '</div>' +
    '<div class="stat-label">' + t('apiSettings.cachedEndpoints') + '</div>' +
    '</div>' +
    '</div>' +
    '</div>';

  container.innerHTML = html;
  if (window.lucide) lucide.createIcons();
}

/**
 * Render cache main panel
 */
async function renderCacheMainPanel() {
  var container = document.getElementById('provider-detail-panel');
  if (!container) return;

  // Load cache stats
  var stats = await loadCacheStats();
  if (!stats) {
    stats = { totalSize: 0, maxSize: 104857600, entries: 0 };
  }

  var globalSettings = apiSettingsData.globalCache || { enabled: false };
  var totalSize = stats.totalSize || 0;
  var maxSize = stats.maxSize || 104857600; // Default 100MB
  var usedMB = (totalSize / 1024 / 1024).toFixed(2);
  var maxMB = (maxSize / 1024 / 1024).toFixed(0);
  var usagePercent = maxSize > 0 ? ((totalSize / maxSize) * 100).toFixed(1) : 0;

  var html = '<div class="cache-main-panel">' +
    '<div class="panel-header">' +
    '<h2>' + t('apiSettings.cacheSettings') + '</h2>' +
    '<p class="panel-subtitle">' + t('apiSettings.cacheDescription') + '</p>' +
    '</div>' +
    // Global Cache Settings
    '<div class="settings-section">' +
    '<div class="section-header">' +
    '<h3>' + t('apiSettings.globalCache') + '</h3>' +
    '<label class="toggle-switch">' +
    '<input type="checkbox" id="global-cache-enabled" ' + (globalSettings.enabled ? 'checked' : '') + ' onchange="updateGlobalCacheEnabled(this.checked)" />' +
    '<span class="toggle-track"><span class="toggle-thumb"></span></span>' +
    '</label>' +
    '</div>' +
    '</div>' +
    // Cache Statistics
    '<div class="settings-section">' +
    '<h3>' + t('apiSettings.cacheStatistics') + '</h3>' +
    '<div class="cache-stats-grid">' +
    '<div class="stat-card">' +
    '<div class="stat-icon"><i data-lucide="database"></i></div>' +
    '<div class="stat-info">' +
    '<div class="stat-value">' + (stats.entries || 0) + '</div>' +
    '<div class="stat-label">' + t('apiSettings.cachedEntries') + '</div>' +
    '</div>' +
    '</div>' +
    '<div class="stat-card">' +
    '<div class="stat-icon"><i data-lucide="hard-drive"></i></div>' +
    '<div class="stat-info">' +
    '<div class="stat-value">' + usedMB + ' MB</div>' +
    '<div class="stat-label">' + t('apiSettings.storageUsed') + '</div>' +
    '</div>' +
    '</div>' +
    '</div>' +
    '<div class="storage-bar-container">' +
    '<div class="storage-bar">' +
    '<div class="storage-bar-fill" style="width: ' + usagePercent + '%"></div>' +
    '</div>' +
    '<div class="storage-label">' + usedMB + ' MB / ' + maxMB + ' MB (' + usagePercent + '%)</div>' +
    '</div>' +
    '</div>' +
    // Cache Actions
    '<div class="settings-section">' +
    '<h3>' + t('apiSettings.cacheActions') + '</h3>' +
    '<button class="btn btn-destructive" onclick="clearCache()">' +
    '<i data-lucide="trash-2"></i> ' + t('apiSettings.clearCache') +
    '</button>' +
    '</div>' +
    '</div>';

  container.innerHTML = html;
  if (window.lucide) lucide.createIcons();
}

/**
 * Render cache settings panel
 */
function renderCacheSettings(stats) {
  const container = document.getElementById('cache-settings-panel');
  if (!container) return;

  const globalSettings = apiSettingsData.globalCache || { enabled: false };
  const totalSize = stats.totalSize || 0;
  const maxSize = stats.maxSize || 104857600; // Default 100MB
  const usedMB = (totalSize / 1024 / 1024).toFixed(2);
  const maxMB = (maxSize / 1024 / 1024).toFixed(0);
  const usagePercent = maxSize > 0 ? ((totalSize / maxSize) * 100).toFixed(1) : 0;

  container.innerHTML = '<div class="cache-panel">' +
    // Cache Header
    '<div class="cache-header">' +
    '<div class="section-title-group">' +
    '<h3>' + t('apiSettings.cacheSettings') + '</h3>' +
    '</div>' +
    '<label class="toggle-switch">' +
    '<input type="checkbox" id="global-cache-enabled" ' + (globalSettings.enabled ? 'checked' : '') + ' onchange="toggleGlobalCache()" />' +
    '<span class="toggle-track"><span class="toggle-thumb"></span></span>' +
    '<span class="toggle-label">' + t('apiSettings.enableGlobalCaching') + '</span>' +
    '</label>' +
    '</div>' +
    // Cache Content
    '<div class="cache-content">' +
    // Visual Bar
    '<div class="cache-visual">' +
    '<div class="cache-bars">' +
    '<div class="cache-bar-fill" style="width: ' + usagePercent + '%"></div>' +
    '</div>' +
    '<div class="cache-legend">' +
    '<span>' + usedMB + ' MB ' + t('apiSettings.used') + '</span>' +
    '<span>' + maxMB + ' MB ' + t('apiSettings.total') + '</span>' +
    '</div>' +
    '</div>' +
    // Stats Grid
    '<div class="stat-grid">' +
    '<div class="stat-card">' +
    '<span class="stat-value">' + usagePercent + '%</span>' +
    '<span class="stat-desc">' + t('apiSettings.cacheUsage') + '</span>' +
    '</div>' +
    '<div class="stat-card">' +
    '<span class="stat-value">' + (stats.entries || 0) + '</span>' +
    '<span class="stat-desc">' + t('apiSettings.cacheEntries') + '</span>' +
    '</div>' +
    '<div class="stat-card">' +
    '<span class="stat-value">' + usedMB + ' MB</span>' +
    '<span class="stat-desc">' + t('apiSettings.cacheSize') + '</span>' +
    '</div>' +
    '</div>' +
    // Clear Button
    '<button class="btn btn-secondary" onclick="clearCache()" style="align-self: flex-start;">' +
    '<i data-lucide="trash-2"></i> ' + t('apiSettings.clearCache') +
    '</button>' +
    '</div>' +
    '</div>';

  if (window.lucide) lucide.createIcons();
}

// ========== Multi-Key Management ==========

/**
 * Generate unique ID for API keys
 */
function generateKeyId() {
  return 'key-' + Date.now() + '-' + Math.random().toString(36).substr(2, 9);
}

// ========== Embedding Pool Management ==========

/**
 * Render embedding pool sidebar summary
 */
function renderEmbeddingPoolSidebar() {
  if (!embeddingPoolConfig) {
    return '<div class="embedding-pool-sidebar-info" style="padding: 1rem;">' +
      '<div style="text-align: center; color: hsl(var(--muted-foreground)); font-size: 0.875rem;">' +
      '<p>' + t('apiSettings.embeddingPoolDesc') + '</p>' +
      '</div>' +
      '</div>';
  }

  const enabled = embeddingPoolConfig.enabled || false;
  const targetModel = embeddingPoolConfig.targetModel || '';
  const strategy = embeddingPoolConfig.strategy || 'round_robin';
  const excludedIds = embeddingPoolConfig.excludedProviderIds || [];

  // Count total providers/keys
  let totalProviders = embeddingPoolDiscoveredProviders.length;
  let totalKeys = 0;
  let activeProviders = 0;

  embeddingPoolDiscoveredProviders.forEach(function(p) {
    totalKeys += p.apiKeys?.length || 1;
    if (excludedIds.indexOf(p.providerId) === -1) {
      activeProviders++;
    }
  });

  const strategyLabels = {
    'round_robin': t('codexlens.strategyRoundRobin') || 'Round Robin',
    'latency_aware': t('codexlens.strategyLatency') || 'Latency-Aware',
    'weighted_random': t('codexlens.strategyWeighted') || 'Weighted Random'
  };

  return '<div class="embedding-pool-sidebar-summary" style="padding: 1rem; display: flex; flex-direction: column; gap: 1rem;">' +
    '<div style="padding: 1rem; background: hsl(var(--muted) / 0.3); border-radius: 0.5rem;">' +
      '<h4 style="margin: 0 0 0.75rem 0; font-size: 0.875rem; font-weight: 600; color: hsl(var(--foreground));">' +
        t('apiSettings.embeddingPool') +
      '</h4>' +
      '<div style="display: flex; flex-direction: column; gap: 0.5rem; font-size: 0.75rem; color: hsl(var(--muted-foreground));">' +
        '<div style="display: flex; align-items: center; gap: 0.5rem; padding: 0.375rem 0; border-bottom: 1px solid hsl(var(--border));">' +
          '<i data-lucide="' + (enabled ? 'check-circle' : 'x-circle') + '" style="width: 14px; height: 14px; color: ' + (enabled ? 'hsl(var(--success))' : 'hsl(var(--muted-foreground))') + ';"></i>' +
          '<span>' + (enabled ? (t('common.enabled') || 'Enabled') : (t('common.disabled') || 'Disabled')) + '</span>' +
        '</div>' +
        (enabled && targetModel ?
          '<div style="display: flex; flex-direction: column; gap: 0.25rem; padding: 0.375rem 0; border-bottom: 1px solid hsl(var(--border));">' +
            '<span style="font-weight: 500; color: hsl(var(--foreground));">' + t('apiSettings.targetModel') + '</span>' +
            '<code style="font-size: 0.6875rem; color: hsl(var(--primary)); word-break: break-all;">' + targetModel + '</code>' +
          '</div>' : '') +
        (enabled ?
          '<div style="display: flex; flex-direction: column; gap: 0.25rem; padding: 0.375rem 0; border-bottom: 1px solid hsl(var(--border));">' +
            '<span style="font-weight: 500; color: hsl(var(--foreground));">' + t('apiSettings.strategy') + '</span>' +
            '<span>' + (strategyLabels[strategy] || strategy) + '</span>' +
          '</div>' : '') +
        (enabled && totalProviders > 0 ?
          '<div style="display: flex; flex-direction: column; gap: 0.25rem; padding: 0.375rem 0;">' +
            '<span style="font-weight: 500; color: hsl(var(--foreground));">' + t('apiSettings.discoveredProviders') + '</span>' +
            '<span>' + activeProviders + ' / ' + totalProviders + ' providers (' + totalKeys + ' keys)</span>' +
          '</div>' : '') +
      '</div>' +
    '</div>' +
    '</div>';
}


/**
 * Render embedding pool main panel
 */
async function renderEmbeddingPoolMainPanel() {
  var container = document.getElementById('provider-detail-panel');
  if (!container) return;

  // Load embedding pool config if not already loaded
  if (!embeddingPoolConfig) {
    await loadEmbeddingPoolConfig();
  }

  const enabled = embeddingPoolConfig?.enabled || false;
  const targetModel = embeddingPoolConfig?.targetModel || '';
  const strategy = embeddingPoolConfig?.strategy || 'round_robin';
  const defaultCooldown = embeddingPoolConfig?.defaultCooldown || 60;
  const defaultMaxConcurrentPerKey = embeddingPoolConfig?.defaultMaxConcurrentPerKey || 4;

  // Build model dropdown options
  let modelOptionsHtml = '<option value="">' + t('apiSettings.selectTargetModel') + '</option>';
  embeddingPoolAvailableModels.forEach(function(model) {
    const providerCount = model.providers.length;
    const selected = model.modelId === targetModel ? ' selected' : '';
    modelOptionsHtml += '<option value="' + model.modelId + '"' + selected + '>' +
      model.modelName + ' (' + providerCount + ' providers)' +
      '</option>';
  });

  var html = '<div class="embedding-pool-main-panel">' +
    '<div class="panel-header">' +
    '<h2><i data-lucide="repeat"></i> ' + t('apiSettings.embeddingPool') + '</h2>' +
    '<p class="panel-subtitle">' + t('apiSettings.embeddingPoolDesc') + '</p>' +
    '</div>' +

    // Enable/Disable Toggle Card
    '<div class="settings-section" style="padding: 1.25rem; background: hsl(var(--muted) / 0.3); border-radius: 0.75rem;">' +
    '<div class="section-header" style="border: none; padding: 0;">' +
    '<div style="display: flex; align-items: center; gap: 0.5rem;">' +
      '<i data-lucide="power" style="width: 1rem; height: 1rem; color: hsl(var(--primary));"></i>' +
      '<h3 style="margin: 0;">' + t('apiSettings.poolEnabled') + '</h3>' +
    '</div>' +
    '<label class="toggle-switch">' +
    '<input type="checkbox" id="embedding-pool-enabled" ' + (enabled ? 'checked' : '') + ' onchange="onEmbeddingPoolEnabledChange(this.checked)" />' +
    '<span class="toggle-track"><span class="toggle-thumb"></span></span>' +
    '</label>' +
    '</div>' +
    '</div>' +

    // Configuration Form Card
    '<div class="settings-section" id="embedding-pool-config" style="' + (enabled ? '' : 'display: none;') + '">' +

    // Model and Strategy in Grid
    '<div style="display: grid; grid-template-columns: 1fr 1fr; gap: 1rem; margin-bottom: 1rem;">' +
      '<div class="form-group" style="margin: 0;">' +
      '<label for="embedding-pool-target-model">' + t('apiSettings.targetModel') + '</label>' +
      '<select id="embedding-pool-target-model" class="cli-input" onchange="onTargetModelChange(this.value)">' +
      modelOptionsHtml +
      '</select>' +
      '</div>' +
      '<div class="form-group" style="margin: 0;">' +
      '<label for="embedding-pool-strategy">' + t('apiSettings.strategy') + '</label>' +
      '<select id="embedding-pool-strategy" class="cli-input">' +
      '<option value="round_robin"' + (strategy === 'round_robin' ? ' selected' : '') + '>Round Robin</option>' +
      '<option value="latency_aware"' + (strategy === 'latency_aware' ? ' selected' : '') + '>Latency Aware</option>' +
      '<option value="weighted_random"' + (strategy === 'weighted_random' ? ' selected' : '') + '>Weighted Random</option>' +
      '</select>' +
      '</div>' +
    '</div>' +

    // Cooldown and Concurrent in Grid
    '<div style="display: grid; grid-template-columns: 1fr 1fr; gap: 1rem;">' +
      '<div class="form-group" style="margin: 0;">' +
      '<label for="embedding-pool-cooldown">' + t('apiSettings.defaultCooldown') + ' (s)</label>' +
      '<input type="number" id="embedding-pool-cooldown" class="cli-input" value="' + defaultCooldown + '" min="1" />' +
      '</div>' +
      '<div class="form-group" style="margin: 0;">' +
      '<label for="embedding-pool-concurrent">' + t('apiSettings.defaultConcurrent') + '</label>' +
      '<input type="number" id="embedding-pool-concurrent" class="cli-input" value="' + defaultMaxConcurrentPerKey + '" min="1" />' +
      '</div>' +
    '</div>' +

    // Discovered Providers Section
    '<div id="discovered-providers-section" style="margin-top: 1.5rem;"></div>' +

    '<div class="form-actions">' +
    '<button class="btn btn-primary" onclick="saveEmbeddingPoolConfig()">' +
    '<i data-lucide="save"></i> ' + t('common.save') +
    '</button>' +
    '</div>' +
    '</div>' +
    '</div>';

  container.innerHTML = html;
  if (window.lucide) lucide.createIcons();

  // Render discovered providers if we have a target model
  if (enabled && targetModel) {
    renderDiscoveredProviders();
  }
}

/**
 * Handle embedding pool enabled/disabled toggle
 */
function onEmbeddingPoolEnabledChange(enabled) {
  const configSection = document.getElementById('embedding-pool-config');
  if (configSection) {
    configSection.style.display = enabled ? '' : 'none';
  }
}

/**
 * Handle target model selection change
 */
async function onTargetModelChange(modelId) {
  if (!modelId) {
    embeddingPoolDiscoveredProviders = [];
    renderDiscoveredProviders();
    return;
  }

  // Discover providers for this model
  await discoverProvidersForTargetModel(modelId);
  renderDiscoveredProviders();
  
  // Update sidebar summary
  const sidebarContainer = document.querySelector('.api-settings-sidebar');
  if (sidebarContainer) {
    const contentArea = sidebarContainer.querySelector('.provider-list, .endpoints-list, .embedding-pool-sidebar-info, .embedding-pool-sidebar-summary, .cache-sidebar-info');
    if (contentArea && contentArea.parentElement) {
      contentArea.parentElement.innerHTML = renderEmbeddingPoolSidebar();
      if (window.lucide) lucide.createIcons();
    }
  }
}

/**
 * Render discovered providers list
 */
function renderDiscoveredProviders() {
  const container = document.getElementById('discovered-providers-section');
  if (!container) return;

  if (embeddingPoolDiscoveredProviders.length === 0) {
    container.innerHTML = '<div class="info-message">' +
      '<i data-lucide="info"></i> ' + t('apiSettings.noProvidersFound') +
      '</div>';
    if (window.lucide) lucide.createIcons();
    return;
  }

  const excludedIds = embeddingPoolConfig?.excludedProviderIds || [];
  let totalProviders = 0;
  let totalKeys = 0;

  embeddingPoolDiscoveredProviders.forEach(function(p) {
    totalProviders++;
    totalKeys += p.apiKeys?.length || 1;
  });

  let providersHtml = '<div>' +
    '<div style="display: flex; align-items: center; justify-content: space-between; margin-bottom: 1rem;">' +
    '<h4 style="margin: 0; font-size: 0.9375rem; font-weight: 600;">' + t('apiSettings.discoveredProviders') + '</h4>' +
    '<span style="font-size: 0.75rem; color: hsl(var(--muted-foreground)); padding: 0.25rem 0.625rem; background: hsl(var(--muted) / 0.5); border-radius: 9999px;">' + 
      totalProviders + ' providers, ' + totalKeys + ' keys' +
    '</span>' +
    '</div>' +
    '<div style="display: flex; flex-direction: column; gap: 0.75rem;">';

  embeddingPoolDiscoveredProviders.forEach(function(provider, index) {
    const isExcluded = excludedIds.indexOf(provider.providerId) > -1;
    const keyCount = provider.apiKeys?.length || 1;
    
    // Get provider icon
    let providerIcon = 'server';
    if (provider.providerName.toLowerCase().includes('openai')) providerIcon = 'brain';
    else if (provider.providerName.toLowerCase().includes('modelscope')) providerIcon = 'cpu';
    else if (provider.providerName.toLowerCase().includes('azure')) providerIcon = 'cloud';
    
    providersHtml += '<div style="border: 1px solid hsl(var(--border)); border-radius: 0.5rem; padding: 1rem; ' + 
      (isExcluded ? 'opacity: 0.5; background: hsl(var(--muted) / 0.3);' : 'background: hsl(var(--card));') + '">' +
      '<div style="display: flex; align-items: center; justify-content: space-between; margin-bottom: 0.75rem;">' +
        '<div style="display: flex; align-items: center; gap: 0.75rem;">' +
          '<div style="width: 2rem; height: 2rem; border-radius: 0.375rem; background: ' + (isExcluded ? 'hsl(var(--muted))' : 'hsl(var(--success) / 0.1)') + '; color: ' + (isExcluded ? 'hsl(var(--muted-foreground))' : 'hsl(var(--success))') + '; display: flex; align-items: center; justify-content: center;">' +
            '<i data-lucide="' + providerIcon + '" style="width: 1.125rem; height: 1.125rem;"></i>' +
          '</div>' +
          '<div>' +
            '<div style="font-weight: 500; font-size: 0.875rem; color: hsl(var(--foreground));">' + escapeHtml(provider.providerName) + '</div>' +
            '<div style="font-size: 0.75rem; color: hsl(var(--muted-foreground));">' + provider.modelName + ' · ' + keyCount + ' key' + (keyCount > 1 ? 's' : '') + '</div>' +
          '</div>' +
        '</div>' +
        '<button class="btn btn-sm ' + (isExcluded ? 'btn-primary' : 'btn-outline') + '" onclick="toggleProviderExclusion(\'' + provider.providerId + '\')" style="flex-shrink: 0;">' +
        '<i data-lucide="' + (isExcluded ? 'plus' : 'x') + '" style="width: 0.875rem; height: 0.875rem;"></i> ' +
        (isExcluded ? t('common.include') : t('apiSettings.excludeProvider')) +
        '</button>' +
      '</div>' +
    '</div>';
  });

  providersHtml += '</div>';
  container.innerHTML = providersHtml;
  if (window.lucide) lucide.createIcons();
}

/**
 * Render API keys section
 */
function renderApiKeysSection(provider) {
  const keys = provider.apiKeys || [];
  const hasMultipleKeys = keys.length > 0;

  let keysHtml = '';
  if (hasMultipleKeys) {
    keysHtml = keys.map(function(key, index) {
      return '<div class="api-key-item" data-key-id="' + key.id + '">' +
        '<input type="text" class="cli-input key-label" ' +
        'value="' + (key.label || '') + '" ' +
        'placeholder="' + t('apiSettings.keyLabel') + '" ' +
        'onchange="updateApiKeyField(\'' + provider.id + '\', \'' + key.id + '\', \'label\', this.value)">' +
        '<div class="key-value-wrapper" style="display: flex; gap: 0.5rem;">' +
        '<input type="password" class="cli-input key-value" ' +
        'value="' + key.key + '" ' +
        'placeholder="' + t('apiSettings.keyValue') + '" ' +
        'onchange="updateApiKeyField(\'' + provider.id + '\', \'' + key.id + '\', \'key\', this.value)">' +
        '<button type="button" class="btn-icon" onclick="toggleKeyVisibility(this)">👁️</button>' +
        '</div>' +
        '<input type="number" class="cli-input key-weight" ' +
        'value="' + (key.weight || 1) + '" min="1" max="100" ' +
        'placeholder="' + t('apiSettings.keyWeight') + '" ' +
        'onchange="updateApiKeyField(\'' + provider.id + '\', \'' + key.id + '\', \'weight\', parseInt(this.value))">' +
        '<div class="key-status">' +
        '<span class="key-status-indicator ' + (key.healthStatus || 'unknown') + '"></span>' +
        '<span class="key-status-text">' + t('apiSettings.' + (key.healthStatus || 'unknown')) + '</span>' +
        '</div>' +
        '<div class="api-key-actions">' +
        '<button type="button" class="test-key-btn" onclick="testApiKey(\'' + provider.id + '\', \'' + key.id + '\')">' +
        t('apiSettings.testKey') +
        '</button>' +
        '<button type="button" class="btn-danger btn-sm" onclick="removeApiKey(\'' + provider.id + '\', \'' + key.id + '\')">' +
        t('apiSettings.removeKey') +
        '</button>' +
        '</div>' +
        '</div>';
    }).join('');
  } else {
    keysHtml = '<div class="no-keys-message">' + t('apiSettings.noKeys') + '</div>';
  }

  return '<div class="api-keys-section">' +
    '<div class="api-keys-header">' +
    '<h4>' + t('apiSettings.apiKeys') + '</h4>' +
    '<button type="button" class="add-key-btn btn-secondary" onclick="addApiKey(\'' + provider.id + '\')">' +
    '+ ' + t('apiSettings.addKey') +
    '</button>' +
    '</div>' +
    '<div class="api-key-list" id="api-key-list-' + provider.id + '">' +
    keysHtml +
    '</div>' +
    '</div>';
}

/**
 * Render routing strategy section
 */
function renderRoutingSection(provider) {
  const strategy = provider.routingStrategy || 'simple-shuffle';

  return '<div class="routing-section">' +
    '<label>' + t('apiSettings.routingStrategy') + '</label>' +
    '<select class="cli-input" onchange="updateProviderRouting(\'' + provider.id + '\', this.value)">' +
    '<option value="simple-shuffle"' + (strategy === 'simple-shuffle' ? ' selected' : '') + '>' + t('apiSettings.simpleShuffleRouting') + '</option>' +
    '<option value="weighted"' + (strategy === 'weighted' ? ' selected' : '') + '>' + t('apiSettings.weightedRouting') + '</option>' +
    '<option value="latency-based"' + (strategy === 'latency-based' ? ' selected' : '') + '>' + t('apiSettings.latencyRouting') + '</option>' +
    '<option value="cost-based"' + (strategy === 'cost-based' ? ' selected' : '') + '>' + t('apiSettings.costRouting') + '</option>' +
    '<option value="least-busy"' + (strategy === 'least-busy' ? ' selected' : '') + '>' + t('apiSettings.leastBusyRouting') + '</option>' +
    '</select>' +
    '<div class="routing-hint">' + t('apiSettings.routingHint') + '</div>' +
    '</div>';
}

/**
 * Render health check section
 */
function renderHealthCheckSection(provider) {
  const health = provider.healthCheck || { enabled: false, intervalSeconds: 300, cooldownSeconds: 5, failureThreshold: 3 };

  return '<div class="health-check-section">' +
    '<div class="health-check-header">' +
    '<h5>' + t('apiSettings.healthCheck') + '</h5>' +
    '<label class="toggle-switch">' +
    '<input type="checkbox"' + (health.enabled ? ' checked' : '') + ' ' +
    'onchange="updateHealthCheckEnabled(\'' + provider.id + '\', this.checked)">' +
    '<span class="toggle-slider"></span>' +
    '</label>' +
    '</div>' +
    '<div class="health-check-grid" style="' + (health.enabled ? '' : 'opacity: 0.5; pointer-events: none;') + '">' +
    '<div class="health-check-field">' +
    '<label>' + t('apiSettings.healthInterval') + '</label>' +
    '<input type="number" class="cli-input" value="' + health.intervalSeconds + '" min="60" max="3600" ' +
    'onchange="updateHealthCheckField(\'' + provider.id + '\', \'intervalSeconds\', parseInt(this.value))">' +
    '</div>' +
    '<div class="health-check-field">' +
    '<label>' + t('apiSettings.healthCooldown') + '</label>' +
    '<input type="number" class="cli-input" value="' + health.cooldownSeconds + '" min="1" max="60" ' +
    'onchange="updateHealthCheckField(\'' + provider.id + '\', \'cooldownSeconds\', parseInt(this.value))">' +
    '</div>' +
    '<div class="health-check-field">' +
    '<label>' + t('apiSettings.failureThreshold') + '</label>' +
    '<input type="number" class="cli-input" value="' + health.failureThreshold + '" min="1" max="10" ' +
    'onchange="updateHealthCheckField(\'' + provider.id + '\', \'failureThreshold\', parseInt(this.value))">' +
    '</div>' +
    '</div>' +
    '</div>';
}

/**
 * Show multi-key settings modal
 */
function showMultiKeyModal(providerId) {
  const provider = apiSettingsData.providers.find(function(p) { return p.id === providerId; });
  if (!provider) return;

  const modalHtml = '<div class="modal-overlay" id="multi-key-modal">' +
    '<div class="modal-content" style="max-width: 700px; max-height: 85vh; overflow-y: auto;">' +
    '<div class="modal-header">' +
    '<h3>' + t('apiSettings.multiKeySettings') + '</h3>' +
    '<button class="modal-close" onclick="closeMultiKeyModal()">&times;</button>' +
    '</div>' +
    '<div class="modal-body">' +
    renderApiKeysSection(provider) +
    renderRoutingSection(provider) +
    renderHealthCheckSection(provider) +
    '</div>' +
    '<div class="modal-actions">' +
    '<button type="button" class="btn-primary" onclick="closeMultiKeyModal()"><i data-lucide="check"></i> ' + t('common.close') + '</button>' +
    '</div>' +
    '</div>' +
    '</div>';

  document.body.insertAdjacentHTML('beforeend', modalHtml);
  if (window.lucide) lucide.createIcons();
}

/**
 * Close multi-key settings modal
 */
function closeMultiKeyModal() {
  const modal = document.getElementById('multi-key-modal');
  if (modal) modal.remove();
}

/**
 * Refresh multi-key modal content
 */
function refreshMultiKeyModal(providerId) {
  const modal = document.getElementById('multi-key-modal');
  if (!modal) return;
  
  const provider = apiSettingsData.providers.find(function(p) { return p.id === providerId; });
  if (!provider) return;
  
  const modalBody = modal.querySelector('.modal-body');
  if (modalBody) {
    modalBody.innerHTML = 
      renderApiKeysSection(provider) +
      renderRoutingSection(provider) +
      renderHealthCheckSection(provider);
    if (window.lucide) lucide.createIcons();
  }
}

/**
 * Add API key to provider
 */
function addApiKey(providerId) {
  const newKey = {
    id: generateKeyId(),
    key: '',
    label: '',
    weight: 1,
    enabled: true,
    healthStatus: 'unknown'
  };

  fetch('/api/litellm-api/providers/' + providerId)
    .then(function(res) { return res.json(); })
    .then(function(provider) {
      const apiKeys = provider.apiKeys || [];
      apiKeys.push(newKey);
      return fetch('/api/litellm-api/providers/' + providerId, {
        method: 'PUT',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ apiKeys: apiKeys })
      });
    })
    .then(function() {
      loadApiSettings().then(function() {
        refreshMultiKeyModal(providerId);
      });
    })
    .catch(function(err) {
      console.error('Failed to add API key:', err);
    });
}

/**
 * Remove API key from provider
 */
function removeApiKey(providerId, keyId) {
  if (!confirm(t('common.confirmDelete'))) return;

  fetch('/api/litellm-api/providers/' + providerId)
    .then(function(res) { return res.json(); })
    .then(function(provider) {
      const apiKeys = (provider.apiKeys || []).filter(function(k) { return k.id !== keyId; });
      return fetch('/api/litellm-api/providers/' + providerId, {
        method: 'PUT',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ apiKeys: apiKeys })
      });
    })
    .then(function() {
      loadApiSettings().then(function() {
        refreshMultiKeyModal(providerId);
      });
    })
    .catch(function(err) {
      console.error('Failed to remove API key:', err);
    });
}

/**
 * Update API key field
 */
function updateApiKeyField(providerId, keyId, field, value) {
  fetch('/api/litellm-api/providers/' + providerId)
    .then(function(res) { return res.json(); })
    .then(function(provider) {
      const apiKeys = provider.apiKeys || [];
      const keyIndex = apiKeys.findIndex(function(k) { return k.id === keyId; });
      if (keyIndex >= 0) {
        apiKeys[keyIndex][field] = value;
      }
      return fetch('/api/litellm-api/providers/' + providerId, {
        method: 'PUT',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ apiKeys: apiKeys })
      });
    })
    .catch(function(err) {
      console.error('Failed to update API key:', err);
    });
}

/**
 * Update provider routing strategy
 */
function updateProviderRouting(providerId, strategy) {
  fetch('/api/litellm-api/providers/' + providerId, {
    method: 'PUT',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ routingStrategy: strategy })
  }).catch(function(err) {
    console.error('Failed to update routing:', err);
  });
}

/**
 * Update health check enabled status
 */
function updateHealthCheckEnabled(providerId, enabled) {
  fetch('/api/litellm-api/providers/' + providerId)
    .then(function(res) { return res.json(); })
    .then(function(provider) {
      const healthCheck = provider.healthCheck || { intervalSeconds: 300, cooldownSeconds: 5, failureThreshold: 3 };
      healthCheck.enabled = enabled;
      return fetch('/api/litellm-api/providers/' + providerId, {
        method: 'PUT',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ healthCheck: healthCheck })
      });
    })
    .then(function() {
      loadApiSettings().then(function() {
        refreshMultiKeyModal(providerId);
      });
    })
    .catch(function(err) {
      console.error('Failed to update health check:', err);
    });
}

/**
 * Update health check field
 */
function updateHealthCheckField(providerId, field, value) {
  fetch('/api/litellm-api/providers/' + providerId)
    .then(function(res) { return res.json(); })
    .then(function(provider) {
      const healthCheck = provider.healthCheck || { enabled: false, intervalSeconds: 300, cooldownSeconds: 5, failureThreshold: 3 };
      healthCheck[field] = value;
      return fetch('/api/litellm-api/providers/' + providerId, {
        method: 'PUT',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ healthCheck: healthCheck })
      });
    })
    .catch(function(err) {
      console.error('Failed to update health check:', err);
    });
}

/**
 * Test API key
 */
function testApiKey(providerId, keyId) {
  const btn = event.target;
  btn.disabled = true;
  btn.classList.add('testing');
  btn.textContent = t('apiSettings.testingKey');

  fetch('/api/litellm-api/providers/' + providerId + '/test-key', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ keyId: keyId })
  })
    .then(function(res) { return res.json(); })
    .then(function(result) {
      btn.disabled = false;
      btn.classList.remove('testing');
      btn.textContent = t('apiSettings.testKey');

      const keyItem = btn.closest('.api-key-item');
      const statusIndicator = keyItem.querySelector('.key-status-indicator');
      const statusText = keyItem.querySelector('.key-status-text');

      if (result.valid) {
        statusIndicator.className = 'key-status-indicator healthy';
        statusText.textContent = t('apiSettings.healthy');
        showToast(t('apiSettings.keyValid'), 'success');
      } else {
        statusIndicator.className = 'key-status-indicator unhealthy';
        statusText.textContent = t('apiSettings.unhealthy');
        showToast(t('apiSettings.keyInvalid') + ': ' + (result.error || ''), 'error');
      }
    })
    .catch(function(err) {
      btn.disabled = false;
      btn.classList.remove('testing');
      btn.textContent = t('apiSettings.testKey');
      showToast('Test failed: ' + err.message, 'error');
    });
}

/**
 * Toggle key visibility
 */
function toggleKeyVisibility(btn) {
  const input = btn.previousElementSibling;
  if (input.type === 'password') {
    input.type = 'text';
    btn.textContent = '🔒';
  } else {
    input.type = 'password';
    btn.textContent = '👁️';
  }
}


// ========== CCW-LiteLLM Management ==========

/**
 * Check ccw-litellm installation status
 * @param {boolean} forceRefresh - Force refresh from server, bypass cache
 */
async function checkCcwLitellmStatus(forceRefresh = false) {
  // Check if cache is valid and not forcing refresh
  if (!forceRefresh && ccwLitellmStatusCache &&
      (Date.now() - ccwLitellmStatusCacheTime < CCW_LITELLM_STATUS_CACHE_TTL)) {
    console.log('[API Settings] Using cached ccw-litellm status');
    window.ccwLitellmStatus = ccwLitellmStatusCache;
    return ccwLitellmStatusCache;
  }

  try {
    console.log('[API Settings] Checking ccw-litellm status from server...');
    // Add refresh=true to bypass backend cache when forceRefresh is true
    var statusUrl = '/api/litellm-api/ccw-litellm/status' + (forceRefresh ? '?refresh=true' : '');
    var response = await fetch(statusUrl);
    console.log('[API Settings] Status response:', response.status);
    var status = await response.json();
    console.log('[API Settings] ccw-litellm status:', status);

    // Update cache
    ccwLitellmStatusCache = status;
    ccwLitellmStatusCacheTime = Date.now();
    window.ccwLitellmStatus = status;

    return status;
  } catch (e) {
    console.warn('[API Settings] Could not check ccw-litellm status:', e);
    var fallbackStatus = { installed: false };

    // Cache the fallback result too
    ccwLitellmStatusCache = fallbackStatus;
    ccwLitellmStatusCacheTime = Date.now();

    return fallbackStatus;
  }
}

/**
 * Render ccw-litellm status card
 */
function renderCcwLitellmStatusCard() {
  var container = document.getElementById('ccwLitellmStatusContainer');
  if (!container) return;

  var status = window.ccwLitellmStatus || { installed: false };

  if (status.installed) {
    container.innerHTML =
      '<div class="flex items-center gap-2 text-sm">' +
        '<span class="inline-flex items-center gap-1.5 px-2.5 py-1 rounded-full bg-success/10 text-success border border-success/20">' +
          '<i data-lucide="check-circle" class="w-3.5 h-3.5"></i>' +
          'ccw-litellm ' + (status.version || '') +
        '</span>' +
        '<button class="btn-sm btn-outline-danger" onclick="uninstallCcwLitellm()" title="Uninstall ccw-litellm">' +
          '<i data-lucide="trash-2" class="w-3.5 h-3.5"></i>' +
        '</button>' +
      '</div>';
  } else {
    container.innerHTML =
      '<div class="flex items-center gap-2">' +
        '<span class="inline-flex items-center gap-1.5 px-2.5 py-1 rounded-full bg-muted text-muted-foreground border border-border text-sm">' +
          '<i data-lucide="circle" class="w-3.5 h-3.5"></i>' +
          'ccw-litellm not installed' +
        '</span>' +
        '<button class="btn-sm btn-primary" onclick="installCcwLitellm()">' +
          '<i data-lucide="download" class="w-3.5 h-3.5"></i> Install' +
        '</button>' +
      '</div>';
  }

  if (window.lucide) lucide.createIcons();
}

/**
 * Install ccw-litellm package
 */
async function installCcwLitellm() {
  var container = document.getElementById('ccwLitellmStatusContainer');
  if (container) {
    container.innerHTML =
      '<div class="flex items-center gap-2 text-sm text-muted-foreground">' +
        '<div class="animate-spin w-4 h-4 border-2 border-primary border-t-transparent rounded-full"></div>' +
        'Installing ccw-litellm...' +
      '</div>';
  }

  try {
    var response = await fetch('/api/litellm-api/ccw-litellm/install', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({})
    });

    var result = await response.json();

    if (result.success) {
      showRefreshToast('ccw-litellm installed successfully!', 'success');
      // Refresh status (force refresh after installation)
      await checkCcwLitellmStatus(true);
      renderCcwLitellmStatusCard();
    } else {
      showRefreshToast('Failed to install ccw-litellm: ' + result.error, 'error');
      renderCcwLitellmStatusCard();
    }
  } catch (e) {
    showRefreshToast('Installation error: ' + e.message, 'error');
    renderCcwLitellmStatusCard();
  }
}

/**
 * Uninstall ccw-litellm package
 */
async function uninstallCcwLitellm() {
  if (!confirm('Are you sure you want to uninstall ccw-litellm? This will disable LiteLLM features.')) {
    return;
  }

  var container = document.getElementById('ccwLitellmStatusContainer');
  if (container) {
    container.innerHTML =
      '<div class="flex items-center gap-2 text-sm text-muted-foreground">' +
        '<div class="animate-spin w-4 h-4 border-2 border-primary border-t-transparent rounded-full"></div>' +
        'Uninstalling ccw-litellm...' +
      '</div>';
  }

  try {
    var response = await fetch('/api/litellm-api/ccw-litellm/uninstall', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({})
    });

    var result = await response.json();

    if (result.success) {
      showRefreshToast('ccw-litellm uninstalled successfully!', 'success');
      await checkCcwLitellmStatus(true);
      renderCcwLitellmStatusCard();
    } else {
      showRefreshToast('Failed to uninstall ccw-litellm: ' + result.error, 'error');
      renderCcwLitellmStatusCard();
    }
  } catch (e) {
    showRefreshToast('Uninstall error: ' + e.message, 'error');
    renderCcwLitellmStatusCard();
  }
}

// Make functions globally accessible
window.checkCcwLitellmStatus = checkCcwLitellmStatus;
window.renderCcwLitellmStatusCard = renderCcwLitellmStatusCard;
window.installCcwLitellm = installCcwLitellm;
window.uninstallCcwLitellm = uninstallCcwLitellm;


// ========== Utility Functions ==========

/**
 * Mask API key for display
 */
function maskApiKey(apiKey) {
  if (!apiKey) return '';
  if (apiKey.startsWith('${')) return apiKey; // Environment variable
  if (apiKey.length <= 8) return '***';
  return apiKey.substring(0, 4) + '...' + apiKey.substring(apiKey.length - 4);
}