
// [核心适配] 创建一个双向映射表，连接前端ID与后端字段
// 这是我们所有“翻译”工作的“密码本”。
const FIELD_MAP = {
    // ==========================================================
    // ========= I. 核心运行时配置 (映射到现有字段) =========
    // ==========================================================
    'MAX_FAILURES': 'blacklist_threshold',
    'TIME_OUT': 'connect_timeout_seconds',
    'MAX_RETRIES': 'max_retries',
    'CHECK_INTERVAL_HOURS': 'health_check_interval_seconds',
    'TEST_MODEL': 'key_check_endpoint',
    'URL_NORMALIZATION_ENABLED': 'enable_smart_gateway',
    // [逻辑收束] 这两个独立的UI开关，都控制同一个后端数据
    'AUTO_DELETE_ERROR_LOGS_DAYS': 'request_log_retention_days',
    'AUTO_DELETE_REQUEST_LOGS_DAYS': 'request_log_retention_days',
    
    // ==========================================================
    // ========= II.新增字段的精确映射 =========
    // ==========================================================
    
    // --- 全局API基础URL ---
    'BASE_URL': 'default_upstream_url',

    // --- 登录安全配置 ---
    'ENABLE_IP_BANNING': 'enable_ip_banning',
    'MAX_LOGIN_ATTEMPTS': 'max_login_attempts',
    'IP_BAN_DURATION_MINUTES': 'ip_ban_duration_minutes',

    // --- API配置 ---
    'CUSTOM_HEADERS': 'custom_headers',
    'PROXIES_USE_CONSISTENCY_HASH_BY_API_KEY': 'use_proxy_hash',
    // --- 模型配置 ---
    'IMAGE_MODELS': 'image_models',
    'SEARCH_MODELS': 'search_models',
    'FILTERED_MODELS': 'filtered_models',
    'TOOLS_CODE_EXECUTION_ENABLED': 'enable_code_executor',
    'URL_CONTEXT_ENABLED': 'enable_url_context',
    'URL_CONTEXT_MODELS': 'url_context_models',
    'SHOW_SEARCH_LINK': 'show_search_link',
    'SHOW_THINKING_PROCESS': 'show_thinking',
    'THINKING_MODELS': 'thinking_models',
    'THINKING_BUDGET_MAP': 'thinking_budget_map',
    'SAFETY_SETTINGS': 'safety_settings',

    // --- 代理检查配置 ---
   'ENABLE_PROXY_CHECK': 'enable_proxy_check',
   'PROXY_CHECK_TIMEOUT_SECONDS': 'proxy_check_timeout_seconds',
   'PROXY_CHECK_CONCURRENCY': 'proxy_check_concurrency',
   'USE_PROXY_HASH': 'use_proxy_hash',

    // --- TTS配置 ---
    'TTS_MODEL': 'tts_model',
    'TTS_VOICE_NAME': 'tts_voice_name',
    'TTS_SPEED': 'tts_speed',
    
    // --- 图像生成配置 ---
    'PAID_KEY': 'paid_key',
    'CREATE_IMAGE_MODEL': 'create_image_model',
    'UPLOAD_PROVIDER': 'upload_provider',
    'SMMS_SECRET_TOKEN': 'smms_secret_token',
    'PICGO_API_KEY': 'picgo_api_key',
    'CLOUDFLARE_IMGBED_URL': 'cloudflare_imgbed_url',
    'CLOUDFLARE_IMGBED_AUTH_CODE': 'cloudflare_imgbed_auth_code',
    'CLOUDFLARE_IMGBED_UPLOAD_FOLDER': 'cloudflare_imgbed_upload_folder',
    
    // --- 流式输出配置 ---
    'STREAM_OPTIMIZER_ENABLED': 'enable_stream_optimizer',
    'STREAM_MIN_DELAY': 'stream_min_delay',
    'STREAM_MAX_DELAY': 'stream_max_delay',
    'STREAM_SHORT_TEXT_THRESHOLD': 'stream_short_text_thresh',
    'STREAM_LONG_TEXT_THRESHOLD': 'stream_long_text_thresh',
    'STREAM_CHUNK_SIZE': 'stream_chunk_size',
    'FAKE_STREAM_ENABLED': 'enable_fake_stream',
    'FAKE_STREAM_EMPTY_DATA_INTERVAL_SECONDS': 'fake_stream_interval',
    // --- 日志配置 ---
    'LOG_LEVEL': 'log_level',
    'AUTO_DELETE_ERROR_LOGS_ENABLED': 'auto_delete_error_logs_enabled',
    'AUTO_DELETE_REQUEST_LOGS_ENABLED': 'auto_delete_request_logs_enabled',
    // --- 定时任务配置 ---
    'TIMEZONE': 'timezone',
    // ==========================================================
    // ========= III. 幻影映射 (由独立API资源提供) =========
    // ==========================================================
    // 备注: 以下字段的数据源不是/admin/settings，
    // 在未来的重构中，将由独立的API端点提供。
    // 当前保留在此，是为了让JS的填充和收集逻辑暂时“兼容”。

  
    //'PROXIES': 'phantom_proxies'
};

// 全局变量，用于缓存从 /admin/tokens 响应中提取的所有可用分组
let ALL_AVAILABLE_GROUPS = [];

// [核心适配] 创建一个反向映射表，用于数据提交
const REVERSE_FIELD_MAP = Object.fromEntries(
    Object.entries(FIELD_MAP).map(([key, value]) => [value, key])
);

// Constants
const SENSITIVE_INPUT_CLASS = "sensitive-input";
const ARRAY_ITEM_CLASS = "array-item";
const ARRAY_INPUT_CLASS = "array-input";
const MAP_ITEM_CLASS = "map-item";
const MAP_KEY_INPUT_CLASS = "map-key-input";
const MAP_VALUE_INPUT_CLASS = "map-value-input";
const CUSTOM_HEADER_ITEM_CLASS = "custom-header-item";
const CUSTOM_HEADER_KEY_INPUT_CLASS = "custom-header-key-input";
const CUSTOM_HEADER_VALUE_INPUT_CLASS = "custom-header-value-input";
const SAFETY_SETTING_ITEM_CLASS = "safety-setting-item";
const SHOW_CLASS = "show"; // For modals
const API_KEY_REGEX = /AIzaSy\S{33}/g;
const PROXY_REGEX =
  /(?:https?|socks5):\/\/(?:[^:@\/]+(?::[^@\/]+)?@)?(?:[^:\/\s]+)(?::\d+)?/g;
const VERTEX_API_KEY_REGEX = /AQ\.[a-zA-Z0-9_\-]{50}/g; // 新增 Vertex Express API Key 正则
const MASKED_VALUE = "••••••••";

// DOM Elements - Global Scope for frequently accessed elements
const safetySettingsContainer = document.getElementById(
  "SAFETY_SETTINGS_container"
);
const thinkingModelsContainer = document.getElementById(
  "THINKING_MODELS_container"
);
const apiKeyModal = document.getElementById("apiKeyModal");
const apiKeyBulkInput = document.getElementById("apiKeyBulkInput");
const apiKeySearchInput = document.getElementById("apiKeySearchInput");
const bulkDeleteApiKeyModal = document.getElementById("bulkDeleteApiKeyModal");
const bulkDeleteApiKeyInput = document.getElementById("bulkDeleteApiKeyInput");
const proxyModal = document.getElementById("proxyModal");
const proxyBulkInput = document.getElementById("proxyBulkInput");
const bulkDeleteProxyModal = document.getElementById("bulkDeleteProxyModal");
const bulkDeleteProxyInput = document.getElementById("bulkDeleteProxyInput");
const resetConfirmModal = document.getElementById("resetConfirmModal");
const configForm = document.getElementById("configForm"); // Added for frequent use

// [核心新增] 令牌配置模态框的元素
const tokenSettingsModal = document.getElementById("tokenSettingsModal");
const closeTokenSettingsModalBtn = document.getElementById("closeTokenSettingsModalBtn");
const cancelTokenSettingsBtn = document.getElementById("cancelTokenSettingsBtn");
const confirmTokenSettingsBtn = document.getElementById("confirmTokenSettingsBtn");
// 模态框内部的交互元素
const tokenSettingsGenerateBtn = document.getElementById("tokenSettingsGenerateBtn");
const tokenSettingsStatusToggle = document.getElementById("tokenSettingsStatusToggle");
const tokenSettingsStatusText = document.getElementById("tokenSettingsStatusText");
const tokenSettingsSelectAllGroupsBtn = document.getElementById("tokenSettingsSelectAllGroupsBtn");
const tokenSettingsDeselectAllGroupsBtn = document.getElementById("tokenSettingsDeselectAllGroupsBtn");

// [核心新增] IP 封禁配置模态框的元素
const ipBanSettingsModal = document.getElementById('ipBanSettingsModal');
const closeIpBanSettingsModalBtn = document.getElementById('closeIpBanSettingsModalBtn');
const cancelIpBanSettingsBtn = document.getElementById('cancelIpBanSettingsBtn');
const confirmIpBanSettingsBtn = document.getElementById('confirmIpBanSettingsBtn');
const ipBanMaxAttemptsInput = document.getElementById('ipBanMaxAttemptsInput');
const ipBanDurationInput = document.getElementById('ipBanDurationInput');

// [核心新增] 代理高级配置模态框的元素
const proxySettingsModal = document.getElementById('proxySettingsModal');
const proxySettingsBtn = document.getElementById('proxySettingsBtn');
const closeProxySettingsModalBtn = document.getElementById('closeProxySettingsModalBtn');
const cancelProxySettingsBtn = document.getElementById('cancelProxySettingsBtn');
const confirmProxySettingsBtn = document.getElementById('confirmProxySettingsBtn');

// 模态框内的输入元素
const enableProxyCheckInput = document.getElementById('enableProxyCheckInput');
const useProxyHashInput = document.getElementById('useProxyHashInput');
const proxyCheckTimeoutInput = document.getElementById('proxyCheckTimeoutInput');
const proxyCheckConcurrencyInput = document.getElementById('proxyCheckConcurrencyInput');


// Vertex Express API Key Modal Elements
const vertexApiKeyModal = document.getElementById("vertexApiKeyModal");
const vertexApiKeyBulkInput = document.getElementById("vertexApiKeyBulkInput");
const bulkDeleteVertexApiKeyModal = document.getElementById(
  "bulkDeleteVertexApiKeyModal"
);
const bulkDeleteVertexApiKeyInput = document.getElementById(
  "bulkDeleteVertexApiKeyInput"
);

// Model Helper Modal Elements
const modelHelperModal = document.getElementById("modelHelperModal");
const modelHelperTitleElement = document.getElementById("modelHelperTitle");
const modelHelperSearchInput = document.getElementById(
  "modelHelperSearchInput"
);
const modelHelperListContainer = document.getElementById(
  "modelHelperListContainer"
);
const closeModelHelperModalBtn = document.getElementById(
  "closeModelHelperModalBtn"
);
const cancelModelHelperBtn = document.getElementById("cancelModelHelperBtn");

let cachedModelsList = null;
let currentModelHelperTarget = null; // { type: 'input'/'array', target: elementOrIdOrKey }

// Modal Control Functions
function openModal(modalElement) {
  if (modalElement) {
    modalElement.classList.add(SHOW_CLASS);
  }
}

function closeModal(modalElement) {
  if (modalElement) {
    modalElement.classList.remove(SHOW_CLASS);
  }
}

document.addEventListener("DOMContentLoaded", function () {
  // Initialize configuration
  initConfig();

  // =============================================================
  // 启动独立的代理数据加载流程
  // =============================================================
  loadAndPopulateProxies();

  // Tab switching
  const tabButtons = document.querySelectorAll(".tab-btn");
  tabButtons.forEach((button) => {
    button.addEventListener("click", function (e) {
      e.stopPropagation();
      const tabId = this.getAttribute("data-tab");
      switchTab(tabId);
    });
  });

  // Upload provider switching
  const uploadProviderSelect = document.getElementById("UPLOAD_PROVIDER");
  if (uploadProviderSelect) {
    uploadProviderSelect.addEventListener("change", function () {
      toggleProviderConfig(this.value);
    });
  }

  // Toggle switch events
  const toggleSwitches = document.querySelectorAll(".toggle-switch");
  toggleSwitches.forEach((toggleSwitch) => {
    toggleSwitch.addEventListener("click", function (e) {
      e.stopPropagation();
      const checkbox = this.querySelector('input[type="checkbox"]');
      if (checkbox) {
        checkbox.checked = !checkbox.checked;
      }
    });
  });

  // Save button
  const saveBtn = document.getElementById("saveBtn");
  if (saveBtn) {
    saveBtn.addEventListener("click", saveConfig);
  }

  // Reset button
  const resetBtn = document.getElementById("resetBtn");
  if (resetBtn) {
    resetBtn.addEventListener("click", resetConfig); // resetConfig will open the modal
  }

  // Scroll buttons
  window.addEventListener("scroll", toggleScrollButtons);

  // API Key Modal Elements and Events
  const addApiKeyBtn = document.getElementById("addApiKeyBtn");
  const closeApiKeyModalBtn = document.getElementById("closeApiKeyModalBtn");
  const cancelAddApiKeyBtn = document.getElementById("cancelAddApiKeyBtn");
  const confirmAddApiKeyBtn = document.getElementById("confirmAddApiKeyBtn");

  if (addApiKeyBtn) {
    addApiKeyBtn.addEventListener("click", () => {
      openModal(apiKeyModal);
      if (apiKeyBulkInput) apiKeyBulkInput.value = "";
    });
  }
  if (closeApiKeyModalBtn)
    closeApiKeyModalBtn.addEventListener("click", () =>
      closeModal(apiKeyModal)
    );
  if (cancelAddApiKeyBtn)
    cancelAddApiKeyBtn.addEventListener("click", () => closeModal(apiKeyModal));
  if (confirmAddApiKeyBtn)
    confirmAddApiKeyBtn.addEventListener("click", handleBulkAddApiKeys);
  if (apiKeySearchInput)
    apiKeySearchInput.addEventListener("input", handleApiKeySearch);

  // Bulk Delete API Key Modal Elements and Events
  const bulkDeleteApiKeyBtn = document.getElementById("bulkDeleteApiKeyBtn");
  const closeBulkDeleteModalBtn = document.getElementById(
    "closeBulkDeleteModalBtn"
  );
  const cancelBulkDeleteApiKeyBtn = document.getElementById(
    "cancelBulkDeleteApiKeyBtn"
  );
  const confirmBulkDeleteApiKeyBtn = document.getElementById(
    "confirmBulkDeleteApiKeyBtn"
  );

  if (bulkDeleteApiKeyBtn) {
    bulkDeleteApiKeyBtn.addEventListener("click", () => {
      openModal(bulkDeleteApiKeyModal);
      if (bulkDeleteApiKeyInput) bulkDeleteApiKeyInput.value = "";
    });
  }
  if (closeBulkDeleteModalBtn)
    closeBulkDeleteModalBtn.addEventListener("click", () =>
      closeModal(bulkDeleteApiKeyModal)
    );
  if (cancelBulkDeleteApiKeyBtn)
    cancelBulkDeleteApiKeyBtn.addEventListener("click", () =>
      closeModal(bulkDeleteApiKeyModal)
    );
  if (confirmBulkDeleteApiKeyBtn)
    confirmBulkDeleteApiKeyBtn.addEventListener(
      "click",
      handleBulkDeleteApiKeys
    );

    // [核心新增] 为令牌配置模态框，绑定所有的事件监听器
  if (closeTokenSettingsModalBtn) {
      closeTokenSettingsModalBtn.addEventListener("click", () => closeModal(tokenSettingsModal));
  }
  if (cancelTokenSettingsBtn) {
      cancelTokenSettingsBtn.addEventListener("click", () => closeModal(tokenSettingsModal));
  }
  if (confirmTokenSettingsBtn) {
      confirmTokenSettingsBtn.addEventListener("click", handleConfirmTokenSettings);
  }
  if (tokenSettingsGenerateBtn) {
      tokenSettingsGenerateBtn.addEventListener("click", () => {
          const input = document.getElementById('tokenSettingsTokenInput');
          if (input) input.value = generateRandomToken();
      });
  }
  if (tokenSettingsStatusToggle) {
      tokenSettingsStatusToggle.addEventListener('change', () => {
          if (tokenSettingsStatusText) {
              tokenSettingsStatusText.textContent = tokenSettingsStatusToggle.checked ? 'Active' : 'Inactive';
          }
      });
  }
  if (tokenSettingsSelectAllGroupsBtn) {
      tokenSettingsSelectAllGroupsBtn.addEventListener('click', () => toggleAllGroups(true));
  }
  if (tokenSettingsDeselectAllGroupsBtn) {
      tokenSettingsDeselectAllGroupsBtn.addEventListener('click', () => toggleAllGroups(false));
  }

  // [核心新增] 为IP封禁配置模态框，绑定所有事件监听器
  const ipBanSettingsBtn = document.getElementById('ipBanSettingsBtn');
  if (ipBanSettingsBtn) {
      ipBanSettingsBtn.addEventListener('click', openIpBanSettings);
  }
  if (closeIpBanSettingsModalBtn) {
      closeIpBanSettingsModalBtn.addEventListener('click', () => closeModal(ipBanSettingsModal));
  }
  if (cancelIpBanSettingsBtn) {
      cancelIpBanSettingsBtn.addEventListener('click', () => closeModal(ipBanSettingsModal));
  }
  if (confirmIpBanSettingsBtn) {
      confirmIpBanSettingsBtn.addEventListener('click', handleConfirmIpBanSettings);
  }

  // [核心新增] 为代理高级配置模态框，绑定所有事件监听器
  if (proxySettingsBtn) {
      proxySettingsBtn.addEventListener('click', openProxySettingsModal);
  }
  if (closeProxySettingsModalBtn) {
      closeProxySettingsModalBtn.addEventListener('click', () => closeModal(proxySettingsModal));
  }
  if (cancelProxySettingsBtn) {
      cancelProxySettingsBtn.addEventListener('click', () => closeModal(proxySettingsModal));
  }
  if (confirmProxySettingsBtn) {
      confirmProxySettingsBtn.addEventListener('click', handleConfirmProxySettings);
  }

  // Proxy Modal Elements and Events
  const addProxyBtn = document.getElementById("addProxyBtn");
  const closeProxyModalBtn = document.getElementById("closeProxyModalBtn");
  const cancelAddProxyBtn = document.getElementById("cancelAddProxyBtn");
  const confirmAddProxyBtn = document.getElementById("confirmAddProxyBtn");
  
  // Proxy Check Elements and Events
  const checkAllProxiesBtn = document.getElementById("checkAllProxiesBtn");
  const proxyCheckModal = document.getElementById("proxyCheckModal");
  const closeProxyCheckModalBtn = document.getElementById("closeProxyCheckModalBtn");
  const closeProxyCheckBtn = document.getElementById("closeProxyCheckBtn");
  const retryFailedProxiesBtn = document.getElementById("retryFailedProxiesBtn");

  if (addProxyBtn) {
    addProxyBtn.addEventListener("click", () => {
      openModal(proxyModal);
      if (proxyBulkInput) proxyBulkInput.value = "";
    });
  }
  
  if (checkAllProxiesBtn) {
    checkAllProxiesBtn.addEventListener("click", checkAllProxies);
  }
  
  if (closeProxyCheckModalBtn) {
    closeProxyCheckModalBtn.addEventListener("click", () => closeModal(proxyCheckModal));
  }
  
  if (closeProxyCheckBtn) {
    closeProxyCheckBtn.addEventListener("click", () => closeModal(proxyCheckModal));
  }
  
  if (retryFailedProxiesBtn) {
    retryFailedProxiesBtn.addEventListener("click", () => {
      // 重试失败的代理检测
      checkAllProxies();
    });
  }
  if (closeProxyModalBtn)
    closeProxyModalBtn.addEventListener("click", () => closeModal(proxyModal));
  if (cancelAddProxyBtn)
    cancelAddProxyBtn.addEventListener("click", () => closeModal(proxyModal));
  if (confirmAddProxyBtn)
    confirmAddProxyBtn.addEventListener("click", handleBulkAddProxies);

  // Bulk Delete Proxy Modal Elements and Events
  const bulkDeleteProxyBtn = document.getElementById("bulkDeleteProxyBtn");
  const closeBulkDeleteProxyModalBtn = document.getElementById(
    "closeBulkDeleteProxyModalBtn"
  );
  const cancelBulkDeleteProxyBtn = document.getElementById(
    "cancelBulkDeleteProxyBtn"
  );
  const confirmBulkDeleteProxyBtn = document.getElementById(
    "confirmBulkDeleteProxyBtn"
  );

  if (bulkDeleteProxyBtn) {
    bulkDeleteProxyBtn.addEventListener("click", () => {
      openModal(bulkDeleteProxyModal);
      if (bulkDeleteProxyInput) bulkDeleteProxyInput.value = "";
    });
  }
  if (closeBulkDeleteProxyModalBtn)
    closeBulkDeleteProxyModalBtn.addEventListener("click", () =>
      closeModal(bulkDeleteProxyModal)
    );
  if (cancelBulkDeleteProxyBtn)
    cancelBulkDeleteProxyBtn.addEventListener("click", () =>
      closeModal(bulkDeleteProxyModal)
    );
  if (confirmBulkDeleteProxyBtn)
    confirmBulkDeleteProxyBtn.addEventListener(
      "click",
      handleBulkDeleteProxies
    );

  // Reset Confirmation Modal Elements and Events
  const closeResetModalBtn = document.getElementById("closeResetModalBtn");
  const cancelResetBtn = document.getElementById("cancelResetBtn");
  const confirmResetBtn = document.getElementById("confirmResetBtn");

  if (closeResetModalBtn)
    closeResetModalBtn.addEventListener("click", () =>
      closeModal(resetConfirmModal)
    );
  if (cancelResetBtn)
    cancelResetBtn.addEventListener("click", () =>
      closeModal(resetConfirmModal)
    );
  if (confirmResetBtn) {
    confirmResetBtn.addEventListener("click", () => {
      closeModal(resetConfirmModal);
      executeReset();
    });
  }

  // Click outside modal to close
  window.addEventListener("click", (event) => {
    const modals = [
      apiKeyModal,
      resetConfirmModal,
      bulkDeleteApiKeyModal,
      proxyModal,
      bulkDeleteProxyModal,
      vertexApiKeyModal, // 新增
      bulkDeleteVertexApiKeyModal, // 新增
      modelHelperModal,
      tokenSettingsModal,  // 新增tokenSettingsModal
      ipBanSettingsModal, // 新增IP封禁配置模态框
      proxySettingsModal, // 新增代理高级配置模态框
      
    ];
    modals.forEach((modal) => {
      if (event.target === modal) {
        closeModal(modal);
      }
    });
  });

  // Removed static token generation button event listener, now handled dynamically if needed or by specific buttons.

  // Authentication token generation button
  const generateAuthTokenBtn = document.getElementById("generateAuthTokenBtn");
  const authTokenInput = document.getElementById("AUTH_TOKEN");
  if (generateAuthTokenBtn && authTokenInput) {
    generateAuthTokenBtn.addEventListener("click", function () {
      const newToken = generateRandomToken(); // Assuming generateRandomToken is defined elsewhere
      authTokenInput.value = newToken;
      if (authTokenInput.classList.contains(SENSITIVE_INPUT_CLASS)) {
        const event = new Event("focusout", {
          bubbles: true,
          cancelable: true,
        });
        authTokenInput.dispatchEvent(event);
      }
      showNotification("已生成新认证令牌", "success");
    });
  }

  // Event delegation for THINKING_MODELS input changes to update budget map keys
  if (thinkingModelsContainer) {
    thinkingModelsContainer.addEventListener("input", function (event) {
      const target = event.target;
      if (
        target &&
        target.classList.contains(ARRAY_INPUT_CLASS) &&
        target.closest(`.${ARRAY_ITEM_CLASS}[data-model-id]`)
      ) {
        const modelInput = target;
        const modelItem = modelInput.closest(`.${ARRAY_ITEM_CLASS}`);
        const modelId = modelItem.getAttribute("data-model-id");
        const budgetKeyInput = document.querySelector(
          `.${MAP_KEY_INPUT_CLASS}[data-model-id="${modelId}"]`
        );
        if (budgetKeyInput) {
          budgetKeyInput.value = modelInput.value;
        }
      }
    });
  }

  // Event delegation for dynamically added remove buttons and generate token buttons within array items
  if (configForm) {
    // Ensure configForm exists before adding event listener
    configForm.addEventListener("click", function (event) {
      const target = event.target;
      const removeButton = target.closest(".remove-btn");
      const generateButton = target.closest(".generate-btn");
      const settingsButton = target.closest(".settings-btn");  // 新增settingsButton

      if (removeButton && removeButton.closest(`.${ARRAY_ITEM_CLASS}`)) {
        const arrayItem = removeButton.closest(`.${ARRAY_ITEM_CLASS}`);
        const parentContainer = arrayItem.parentElement;
        const isThinkingModelItem =
          arrayItem.hasAttribute("data-model-id") &&
          parentContainer &&
          parentContainer.id === "THINKING_MODELS_container";
        const isSafetySettingItem = arrayItem.classList.contains(
          SAFETY_SETTING_ITEM_CLASS
        );

        if (isThinkingModelItem) {
          const modelId = arrayItem.getAttribute("data-model-id");
          const budgetMapItem = document.querySelector(
            `.${MAP_ITEM_CLASS}[data-model-id="${modelId}"]`
          );
          if (budgetMapItem) {
            budgetMapItem.remove();
          }
          // Check and add placeholder for budget map if empty
          const budgetContainer = document.getElementById(
            "THINKING_BUDGET_MAP_container"
          );
          if (budgetContainer && budgetContainer.children.length === 0) {
            budgetContainer.innerHTML =
              '<div class="text-gray-500 text-sm italic">请在上方添加思考模型，预算将自动关联。</div>';
          }
        }
        arrayItem.remove();
        // Check and add placeholder for safety settings if empty
        if (
          isSafetySettingItem &&
          parentContainer &&
          parentContainer.children.length === 0
        ) {
          parentContainer.innerHTML =
            '<div class="text-gray-500 text-sm italic">定义模型的安全过滤阈值。</div>';
        }
      } else if (
        generateButton &&
        generateButton.closest(`.${ARRAY_ITEM_CLASS}`)
      ) {
        const inputField = generateButton
          .closest(`.${ARRAY_ITEM_CLASS}`)
          .querySelector(`.${ARRAY_INPUT_CLASS}`);
        if (inputField) {
          const newToken = generateRandomToken();
          inputField.value = newToken;
          if (inputField.classList.contains(SENSITIVE_INPUT_CLASS)) {
            const event = new Event("focusout", {
              bubbles: true,
              cancelable: true,
            });
            inputField.dispatchEvent(event);
          }
          showNotification("已生成新令牌", "success");
        }
      }
       else if (settingsButton && settingsButton.closest(`.${ARRAY_ITEM_CLASS}`)) {
        // 如果识别到“设置”指令，就命令 openTokenSettings 函数，立即执行！
        openTokenSettings(settingsButton);  // 新增openTokenSettings调用
      }
    });
  }

  // Add Safety Setting button
  const addSafetySettingBtn = document.getElementById("addSafetySettingBtn");
  if (addSafetySettingBtn) {
    addSafetySettingBtn.addEventListener("click", () => addSafetySettingItem());
  }

  // Add Custom Header button
  const addCustomHeaderBtn = document.getElementById("addCustomHeaderBtn");
  if (addCustomHeaderBtn) {
    addCustomHeaderBtn.addEventListener("click", () => addCustomHeaderItem());
  }

  initializeSensitiveFields(); // Initialize sensitive field handling

  // Vertex Express API Key Modal Elements and Events
  const addVertexApiKeyBtn = document.getElementById("addVertexApiKeyBtn");
  const closeVertexApiKeyModalBtn = document.getElementById(
    "closeVertexApiKeyModalBtn"
  );
  const cancelAddVertexApiKeyBtn = document.getElementById(
    "cancelAddVertexApiKeyBtn"
  );
  const confirmAddVertexApiKeyBtn = document.getElementById(
    "confirmAddVertexApiKeyBtn"
  );
  const bulkDeleteVertexApiKeyBtn = document.getElementById(
    "bulkDeleteVertexApiKeyBtn"
  );
  const closeBulkDeleteVertexModalBtn = document.getElementById(
    "closeBulkDeleteVertexModalBtn"
  );
  const cancelBulkDeleteVertexApiKeyBtn = document.getElementById(
    "cancelBulkDeleteVertexApiKeyBtn"
  );
  const confirmBulkDeleteVertexApiKeyBtn = document.getElementById(
    "confirmBulkDeleteVertexApiKeyBtn"
  );

  if (addVertexApiKeyBtn) {
    addVertexApiKeyBtn.addEventListener("click", () => {
      openModal(vertexApiKeyModal);
      if (vertexApiKeyBulkInput) vertexApiKeyBulkInput.value = "";
    });
  }
  if (closeVertexApiKeyModalBtn)
    closeVertexApiKeyModalBtn.addEventListener("click", () =>
      closeModal(vertexApiKeyModal)
    );
  if (cancelAddVertexApiKeyBtn)
    cancelAddVertexApiKeyBtn.addEventListener("click", () =>
      closeModal(vertexApiKeyModal)
    );
  if (confirmAddVertexApiKeyBtn)
    confirmAddVertexApiKeyBtn.addEventListener(
      "click",
      handleBulkAddVertexApiKeys
    );

  if (bulkDeleteVertexApiKeyBtn) {
    bulkDeleteVertexApiKeyBtn.addEventListener("click", () => {
      openModal(bulkDeleteVertexApiKeyModal);
      if (bulkDeleteVertexApiKeyInput) bulkDeleteVertexApiKeyInput.value = "";
    });
  }
  if (closeBulkDeleteVertexModalBtn)
    closeBulkDeleteVertexModalBtn.addEventListener("click", () =>
      closeModal(bulkDeleteVertexApiKeyModal)
    );
  if (cancelBulkDeleteVertexApiKeyBtn)
    cancelBulkDeleteVertexApiKeyBtn.addEventListener("click", () =>
      closeModal(bulkDeleteVertexApiKeyModal)
    );
  if (confirmBulkDeleteVertexApiKeyBtn)
    confirmBulkDeleteVertexApiKeyBtn.addEventListener(
      "click",
      handleBulkDeleteVertexApiKeys
    );

  // Model Helper Modal Event Listeners
  if (closeModelHelperModalBtn) {
    closeModelHelperModalBtn.addEventListener("click", () =>
      closeModal(modelHelperModal)
    );
  }
  if (cancelModelHelperBtn) {
    cancelModelHelperBtn.addEventListener("click", () =>
      closeModal(modelHelperModal)
    );
  }
  if (modelHelperSearchInput) {
    modelHelperSearchInput.addEventListener("input", () =>
      renderModelsInModal()
    );
  }

  // Add event listeners to all model helper trigger buttons
  const modelHelperTriggerBtns = document.querySelectorAll(
    ".model-helper-trigger-btn"
  );
  modelHelperTriggerBtns.forEach((btn) => {
    btn.addEventListener("click", () => {
      const targetInputId = btn.dataset.targetInputId;
      const targetArrayKey = btn.dataset.targetArrayKey;

      if (targetInputId) {
        currentModelHelperTarget = {
          type: "input",
          target: document.getElementById(targetInputId),
        };
      } else if (targetArrayKey) {
        currentModelHelperTarget = { type: "array", targetKey: targetArrayKey };
      }
      openModelHelperModal();
    });
  });
}); // <-- DOMContentLoaded end

/**
 * Initializes sensitive input field behavior (masking/unmasking).
 */
function initializeSensitiveFields() {
  if (!configForm) return;

  // Helper function: Mask field
  function maskField(field) {
    if (field.value && field.value !== MASKED_VALUE) {
      field.setAttribute("data-real-value", field.value);
      field.value = MASKED_VALUE;
    } else if (!field.value) {
      // If field value is empty string
      field.removeAttribute("data-real-value");
      // Ensure empty value doesn't show as asterisks
      if (field.value === MASKED_VALUE) field.value = "";
    }
  }

  // Helper function: Unmask field
  function unmaskField(field) {
    if (field.hasAttribute("data-real-value")) {
      field.value = field.getAttribute("data-real-value");
    }
    // If no data-real-value and value is MASKED_VALUE, it might be an initial empty sensitive field, clear it
    else if (
      field.value === MASKED_VALUE &&
      !field.hasAttribute("data-real-value")
    ) {
      field.value = "";
    }
  }

  // Initial masking for existing sensitive fields on page load
  // This function is called after populateForm and after dynamic element additions (via event delegation)
  function initialMaskAllExisting() {
    const sensitiveFields = configForm.querySelectorAll(
      `.${SENSITIVE_INPUT_CLASS}`
    );
    sensitiveFields.forEach((field) => {
      if (field.type === "password") {
        // For password fields, browser handles it. We just ensure data-original-type is set
        // and if it has a value, we also store data-real-value so it can be shown when switched to text
        if (field.value) {
          field.setAttribute("data-real-value", field.value);
        }
        // No need to set to MASKED_VALUE as browser handles it.
      } else if (
        field.type === "text" ||
        field.tagName.toLowerCase() === "textarea"
      ) {
        maskField(field);
      }
    });
  }
  initialMaskAllExisting();

  // Event delegation for dynamic and static fields
  configForm.addEventListener("focusin", function (event) {
    const target = event.target;
    if (target.classList.contains(SENSITIVE_INPUT_CLASS)) {
      if (target.type === "password") {
        // Record original type to switch back on blur
        if (!target.hasAttribute("data-original-type")) {
          target.setAttribute("data-original-type", "password");
        }
        target.type = "text"; // Switch to text type to show content
        // If data-real-value exists (e.g., set during populateForm), use it
        if (target.hasAttribute("data-real-value")) {
          target.value = target.getAttribute("data-real-value");
        }
        // Otherwise, the browser's existing password value will be shown directly
      } else {
        // For type="text" or textarea
        unmaskField(target);
      }
    }
  });

  configForm.addEventListener("focusout", function (event) {
    const target = event.target;
    if (target.classList.contains(SENSITIVE_INPUT_CLASS)) {
      // First, if the field is currently text and has a value, update data-real-value
      if (
        target.type === "text" ||
        target.tagName.toLowerCase() === "textarea"
      ) {
        if (target.value && target.value !== MASKED_VALUE) {
          target.setAttribute("data-real-value", target.value);
        } else if (!target.value) {
          // If value is empty, remove data-real-value
          target.removeAttribute("data-real-value");
        }
      }

      // Then handle type switching and masking
      if (
        target.getAttribute("data-original-type") === "password" &&
        target.type === "text"
      ) {
        target.type = "password"; // Switch back to password type
        // For password type, browser handles masking automatically, no need to set MASKED_VALUE manually
        // data-real-value has already been updated by the logic above
      } else if (
        target.type === "text" ||
        target.tagName.toLowerCase() === "textarea"
      ) {
        // For text or textarea sensitive fields, perform masking
        maskField(target);
      }
    }
  });
}

/**
 * Generates a UUID.
 * @returns {string} A new UUID.
 */
function generateUUID() {
  return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, function (c) {
    var r = (Math.random() * 16) | 0,
      v = c == "x" ? r : (r & 0x3) | 0x8;
    return v.toString(16);
  });
}

/**
 * [定稿] 页面初始化函数
 * 作为页面加载的唯一入口，负责：
 * 1. 获取并填充系统配置。
 * 2. 获取令牌数据，并调用 addArrayItemWithValue 进行渲染。
 * 3. [新增] 从令牌数据中提取所有唯一的分组，并缓存到全局变量中。
 */
async function initConfig() {
    // --- 第一部分: 加载系统运行时配置 ---
    try {
        showNotification("正在加载系统配置...", "info");
        const settingsResponse = await apiFetch("/admin/settings");
        const settingsResult = await settingsResponse.json();
        populateForm(settingsResult.data); 
        showNotification("系统配置加载成功", "success");
    } catch (error) {
        console.error("加载系统配置失败:", error);
        showNotification("加载系统配置失败: " + error.message, "error");
    }
    // --- 第二部分: 加载令牌，并执行分拣、渲染、缓存 ---
    try {
        const tokensResponse = await apiFetch("/admin/tokens");
        const result = await tokensResponse.json();
        const allTokensData = result.data;
        let adminToken = null;
        let userTokens = [];
        // [核心逻辑] 分拣管理员令牌和用户令牌
        if (allTokensData && Array.isArray(allTokensData)) {
            allTokensData.forEach(token => {
                if (token.IsAdmin) {
                    adminToken = token;
                } else {
                    userTokens.push(token);
                }
            });
        }
        
        // [任务 1] 填充独立的管理员 AUTH_TOKEN 输入框
        if (adminToken) {
            const authTokenInput = document.getElementById("AUTH_TOKEN");
            if (authTokenInput) {
                authTokenInput.value = adminToken.Token;
                // 触发敏感字段的遮蔽逻辑，保持UI一致性
                authTokenInput.dispatchEvent(new Event('focusout', { bubbles: true, cancelable: true }));
            }
        }
        // [任务 2] 渲染过滤后的用户令牌列表
        const container = document.getElementById('ALLOWED_TOKENS_container');
        if (container) {
            container.innerHTML = '';
        }
        if (userTokens.length > 0) {
            userTokens.forEach(token => {
                addArrayItemWithValue('ALLOWED_TOKENS', token);
            });
        } else {
            if (container) {
                container.innerHTML = '<div class="text-gray-500 p-2 text-center italic">系统中暂无用户级认证令牌。</div>';
            }
        }
        // [附加任务] 从所有令牌数据中提取、去重并缓存所有可用分组
        if (allTokensData && Array.isArray(allTokensData)) {
            const groupMap = new Map();
            allTokensData.forEach(token => {
                if (token.AllowedGroups && Array.isArray(token.AllowedGroups)) {
                    token.AllowedGroups.forEach(group => {
                        if (!groupMap.has(group.ID)) {
                            groupMap.set(group.ID, group);
                        }
                    });
                }
            });
            ALL_AVAILABLE_GROUPS = Array.from(groupMap.values());
        }
    } catch (error) {
        console.error("加载认证令牌失败:", error);
        showNotification("加载认证令牌失败: " + error.message, "error");
    }
}

/**
 * [核心修正] 此函数现在是“总调度员”
 * 它负责获取数据，然后命令 addArrayItemWithValue 函数进行渲染。
 * @param {Array<object>} tokens - 从 /admin/tokens 获取的令牌对象数组
 */
function populateAuthTokens(tokens) {
    const container = document.getElementById('ALLOWED_TOKENS_container');
    if (!container) return;
    container.innerHTML = ''; // 清空“正在加载”的提示
    if (!tokens || tokens.length === 0) {
        container.innerHTML = '<div class="text-gray-500 p-2">系统中暂无认证令牌。</div>';
        return;
    }
    // [核心] 遍历所有token数据
    tokens.forEach(token => {
        // 命令我们最终版的 addArrayItemWithValue 函数，使用完整的token对象去创建DOM
        addArrayItemWithValue('ALLOWED_TOKENS', token);
    });
}





/**
 * Populates the configuration form with data.
 * @param {object} config - The configuration object.

 * 它将使用 FIELD_MAP 来查找正确的HTML元素ID，并完整复刻了原版的所有复杂逻辑。
 * @param {object} config - 从后端 /admin/settings 获取的、使用 Go Struct 字段名的配置对象。
 */
function populateForm(config) {
    if (!config) {
        console.error("PopulateForm called with null or undefined config.");
        return;
    }

    const modelIdMap = {}; // 用于关联 Thinking Model 和 Budget Map

    // 1. [适配] 清空所有动态内容容器
    const arrayContainers = document.querySelectorAll(".array-container");
    arrayContainers.forEach(container => {
        container.innerHTML = "";
    });
    // 单独处理特殊容器
    ['THINKING_BUDGET_MAP_container', 'CUSTOM_HEADERS_container', 'SAFETY_SETTINGS_container'].forEach(id => {
        const el = document.getElementById(id);
        if (el) el.innerHTML = "";
    });


    // 2. [适配] 特殊处理：首先填充 THINKING_MODELS，并构建ID映射表
    const thinkingModelsData = config.ThinkingModels || [];
    if (Array.isArray(thinkingModelsData)) {
        thinkingModelsData.forEach(modelName => {
            if (modelName && typeof modelName === 'string' && modelName.trim()) {
                const trimmedModelName = modelName.trim();
                // 使用前端ID 'THINKING_MODELS' 来调用辅助函数
                const modelId = addArrayItemWithValue('THINKING_MODELS', trimmedModelName);
                if (modelId) {
                    modelIdMap[trimmedModelName] = modelId;
                }
            }
        });
    }

    // 3. [适配] 特殊处理：使用映射表填充 THINKING_BUDGET_MAP
    const budgetMapContainer = document.getElementById('THINKING_BUDGET_MAP_container');
    let budgetItemsAdded = false;
    const budgetMapData = config.ThinkingBudgetMap || {};
    if (budgetMapContainer && typeof budgetMapData === 'object') {
        for (const [modelName, budgetValue] of Object.entries(budgetMapData)) {
            const modelId = modelIdMap[modelName.trim()]; // 使用映射表查找ID
            if (modelId) {
                createAndAppendBudgetMapItem(modelName.trim(), budgetValue, modelId);
                budgetItemsAdded = true;
            }
        }
    }
    if (budgetMapContainer && !budgetItemsAdded) {
        budgetMapContainer.innerHTML = '<div class="text-gray-500 text-sm italic">请在上方添加思考模型，预算将自动关联。</div>';
    }

    // 4. [适配] 特殊处理：填充 CUSTOM_HEADERS
    const customHeadersContainer = document.getElementById('CUSTOM_HEADERS_container');
    let customHeadersAdded = false;
    const customHeadersData = config.CustomHeaders || {};
    if (customHeadersContainer && typeof customHeadersData === 'object') {
        for (const [key, value] of Object.entries(customHeadersData)) {
            createAndAppendCustomHeaderItem(key, value);
            customHeadersAdded = true;
        }
    }
    if (customHeadersContainer && !customHeadersAdded) {
        customHeadersContainer.innerHTML = '<div class="text-gray-500 text-sm italic">添加自定义请求头，例如 X-Api-Key: your-key</div>';
    }
    
    // 5. [适配] 特殊处理：填充 SAFETY_SETTINGS
    const safetySettingsContainer = document.getElementById('SAFETY_SETTINGS_container');
    let safetyItemsAdded = false;
    const safetySettingsData = config.SafetySettings || [];
    if (safetySettingsContainer && Array.isArray(safetySettingsData)) {
        safetySettingsData.forEach(setting => {
            if (setting && setting.category && setting.threshold) {
                addSafetySettingItem(setting.category, setting.threshold);
                safetyItemsAdded = true;
            }
        });
    }
    if (safetySettingsContainer && !safetyItemsAdded) {
        safetySettingsContainer.innerHTML = '<div class="text-gray-500 text-sm italic">定义模型的安全过滤阈值。</div>';
    }


    // 6. [适配] 遍历后端数据，填充所有其余的字段
    for (const backendKey in config) {
        if (Object.prototype.hasOwnProperty.call(config, backendKey)) {
            const value = config[backendKey];
            const frontendId = REVERSE_FIELD_MAP[backendKey];

            if (!frontendId) continue; // 如果在映射表中找不到，则跳过

            // 跳过我们已经手动处理过的特殊字段
            if (['ThinkingModels', 'ThinkingBudgetMap', 'CustomHeaders', 'SafetySettings'].includes(backendKey)) {
                continue;
            }
            
            const element = document.getElementById(frontendId);

            if (element) { // 处理简单字段 (input, select, checkbox)
                if (element.type === 'checkbox') {
                    element.checked = !!value;
                } else if (backendKey === 'HealthCheckIntervalSeconds') {
                    // [单位转换] 从秒转换到小时
                    element.value = value > 0 ? Math.round(value / 3600) : 1;
                } else {
                    element.value = value !== null && value !== undefined ? value : "";
                }
            } else if (Array.isArray(value)) { // 处理其余的数组字段
                const container = document.getElementById(`${frontendId}_container`);
                if (container) {
                    value.forEach(itemValue => {
                        if (typeof itemValue === 'string') {
                            addArrayItemWithValue(frontendId, itemValue);
                        }
                    });
                }
            }
        }
    }

    // 7. [适配] 处理依赖UI逻辑（例如，根据checkbox禁用/启用其他控件）
    // 自动删除错误日志
    const autoDeleteErrorEnabled = document.getElementById('AUTO_DELETE_ERROR_LOGS_ENABLED');
    const autoDeleteErrorDays = document.getElementById('AUTO_DELETE_ERROR_LOGS_DAYS');
    if (autoDeleteErrorEnabled && autoDeleteErrorDays) {
        autoDeleteErrorDays.disabled = !autoDeleteErrorEnabled.checked;
        autoDeleteErrorEnabled.addEventListener('change', () => {
            autoDeleteErrorDays.disabled = !autoDeleteErrorEnabled.checked;
        });
    }

    // 自动删除请求日志
    const autoDeleteRequestEnabled = document.getElementById('AUTO_DELETE_REQUEST_LOGS_ENABLED');
    const autoDeleteRequestDays = document.getElementById('AUTO_DELETE_REQUEST_LOGS_DAYS');
    if (autoDeleteRequestEnabled && autoDeleteRequestDays) {
        autoDeleteRequestDays.disabled = !autoDeleteRequestEnabled.checked;
        autoDeleteRequestEnabled.addEventListener('change', () => {
             autoDeleteRequestDays.disabled = !autoDeleteRequestEnabled.checked;
        });
    }

    // 8. [适配] 初始化上传提供商和敏感字段的UI状态
    const uploadProviderSelect = document.getElementById("UPLOAD_PROVIDER");
    if (uploadProviderSelect) {
        toggleProviderConfig(uploadProviderSelect.value);
    }
    initializeSensitiveFields();
}


/**
 * Handles the bulk addition of API keys from the modal input.
 */
function handleBulkAddApiKeys() {
  const apiKeyContainer = document.getElementById("API_KEYS_container");
  if (!apiKeyBulkInput || !apiKeyContainer || !apiKeyModal) return;

  const bulkText = apiKeyBulkInput.value;
  const extractedKeys = bulkText.match(API_KEY_REGEX) || [];

  const currentKeyInputs = apiKeyContainer.querySelectorAll(
    `.${ARRAY_INPUT_CLASS}.${SENSITIVE_INPUT_CLASS}`
  );
  let currentKeys = Array.from(currentKeyInputs)
    .map((input) => {
      return input.hasAttribute("data-real-value")
        ? input.getAttribute("data-real-value")
        : input.value;
    })
    .filter((key) => key && key.trim() !== "" && key !== MASKED_VALUE);

  const combinedKeys = new Set([...currentKeys, ...extractedKeys]);
  const uniqueKeys = Array.from(combinedKeys);

  apiKeyContainer.innerHTML = ""; // Clear existing items more directly

  uniqueKeys.forEach((key) => {
    addArrayItemWithValue("API_KEYS", key);
  });

  const newKeyInputs = apiKeyContainer.querySelectorAll(
    `.${ARRAY_INPUT_CLASS}.${SENSITIVE_INPUT_CLASS}`
  );
  newKeyInputs.forEach((input) => {
    if (configForm && typeof initializeSensitiveFields === "function") {
      const focusoutEvent = new Event("focusout", {
        bubbles: true,
        cancelable: true,
      });
      input.dispatchEvent(focusoutEvent);
    }
  });

  closeModal(apiKeyModal);
  showNotification(`添加/更新了 ${uniqueKeys.length} 个唯一密钥`, "success");
}

/**
 * Handles searching/filtering of API keys in the list.
 */
function handleApiKeySearch() {
  const apiKeyContainer = document.getElementById("API_KEYS_container");
  if (!apiKeySearchInput || !apiKeyContainer) return;

  const searchTerm = apiKeySearchInput.value.toLowerCase();
  const keyItems = apiKeyContainer.querySelectorAll(`.${ARRAY_ITEM_CLASS}`);

  keyItems.forEach((item) => {
    const input = item.querySelector(
      `.${ARRAY_INPUT_CLASS}.${SENSITIVE_INPUT_CLASS}`
    );
    if (input) {
      const realValue = input.hasAttribute("data-real-value")
        ? input.getAttribute("data-real-value").toLowerCase()
        : input.value.toLowerCase();
      item.style.display = realValue.includes(searchTerm) ? "flex" : "none";
    }
  });
}

/**
 * Handles the bulk deletion of API keys based on input from the modal.
 */
function handleBulkDeleteApiKeys() {
  const apiKeyContainer = document.getElementById("API_KEYS_container");
  if (!bulkDeleteApiKeyInput || !apiKeyContainer || !bulkDeleteApiKeyModal)
    return;

  const bulkText = bulkDeleteApiKeyInput.value;
  if (!bulkText.trim()) {
    showNotification("请粘贴需要删除的 API 密钥", "warning");
    return;
  }

  const keysToDelete = new Set(bulkText.match(API_KEY_REGEX) || []);

  if (keysToDelete.size === 0) {
    showNotification("未在输入内容中提取到有效的 API 密钥格式", "warning");
    return;
  }

  const keyItems = apiKeyContainer.querySelectorAll(`.${ARRAY_ITEM_CLASS}`);
  let deleteCount = 0;

  keyItems.forEach((item) => {
    const input = item.querySelector(
      `.${ARRAY_INPUT_CLASS}.${SENSITIVE_INPUT_CLASS}`
    );
    const realValue =
      input &&
      (input.hasAttribute("data-real-value")
        ? input.getAttribute("data-real-value")
        : input.value);
    if (realValue && keysToDelete.has(realValue)) {
      item.remove();
      deleteCount++;
    }
  });

  closeModal(bulkDeleteApiKeyModal);

  if (deleteCount > 0) {
    showNotification(`成功删除了 ${deleteCount} 个匹配的密钥`, "success");
  } else {
    showNotification("列表中未找到您输入的任何密钥进行删除", "info");
  }
  bulkDeleteApiKeyInput.value = "";
}

/**
 * Handles the bulk addition of proxies from the modal input.
 */
function handleBulkAddProxies() {
  const proxyContainer = document.getElementById("PROXIES_container");
  if (!proxyBulkInput || !proxyContainer || !proxyModal) return;

  const bulkText = proxyBulkInput.value;
  const extractedProxies = bulkText.match(PROXY_REGEX) || [];

  const currentProxyInputs = proxyContainer.querySelectorAll(
    `.${ARRAY_INPUT_CLASS}`
  );
  const currentProxies = Array.from(currentProxyInputs)
    .map((input) => input.value)
    .filter((proxy) => proxy.trim() !== "");

  const combinedProxies = new Set([...currentProxies, ...extractedProxies]);
  const uniqueProxies = Array.from(combinedProxies);

  proxyContainer.innerHTML = ""; // Clear existing items

  uniqueProxies.forEach((proxy) => {
    addArrayItemWithValue("PROXIES", proxy);
  });

  closeModal(proxyModal);
  showNotification(`添加/更新了 ${uniqueProxies.length} 个唯一代理`, "success");
}

/**
 * Handles the bulk deletion of proxies based on input from the modal.
 */
function handleBulkDeleteProxies() {
  const proxyContainer = document.getElementById("PROXIES_container");
  if (!bulkDeleteProxyInput || !proxyContainer || !bulkDeleteProxyModal) return;

  const bulkText = bulkDeleteProxyInput.value;
  if (!bulkText.trim()) {
    showNotification("请粘贴需要删除的代理地址", "warning");
    return;
  }

  const proxiesToDelete = new Set(bulkText.match(PROXY_REGEX) || []);

  if (proxiesToDelete.size === 0) {
    showNotification("未在输入内容中提取到有效的代理地址格式", "warning");
    return;
  }

  const proxyItems = proxyContainer.querySelectorAll(`.${ARRAY_ITEM_CLASS}`);
  let deleteCount = 0;

  proxyItems.forEach((item) => {
    const input = item.querySelector(`.${ARRAY_INPUT_CLASS}`);
    if (input && proxiesToDelete.has(input.value)) {
      item.remove();
      deleteCount++;
    }
  });

  closeModal(bulkDeleteProxyModal);

  if (deleteCount > 0) {
    showNotification(`成功删除了 ${deleteCount} 个匹配的代理`, "success");
  } else {
    showNotification("列表中未找到您输入的任何代理进行删除", "info");
  }
  bulkDeleteProxyInput.value = "";
}

/**
 * Handles the bulk addition of Vertex Express API keys from the modal input.
 */
function handleBulkAddVertexApiKeys() {
  const vertexApiKeyContainer = document.getElementById(
    "VERTEX_API_KEYS_container"
  );
  if (!vertexApiKeyBulkInput || !vertexApiKeyContainer || !vertexApiKeyModal) {
    return;
  }

  const bulkText = vertexApiKeyBulkInput.value;
  const extractedKeys = bulkText.match(VERTEX_API_KEY_REGEX) || [];

  const currentKeyInputs = vertexApiKeyContainer.querySelectorAll(
    `.${ARRAY_INPUT_CLASS}.${SENSITIVE_INPUT_CLASS}`
  );
  let currentKeys = Array.from(currentKeyInputs)
    .map((input) => {
      return input.hasAttribute("data-real-value")
        ? input.getAttribute("data-real-value")
        : input.value;
    })
    .filter((key) => key && key.trim() !== "" && key !== MASKED_VALUE);

  const combinedKeys = new Set([...currentKeys, ...extractedKeys]);
  const uniqueKeys = Array.from(combinedKeys);

  vertexApiKeyContainer.innerHTML = ""; // Clear existing items

  uniqueKeys.forEach((key) => {
    addArrayItemWithValue("VERTEX_API_KEYS", key); // VERTEX_API_KEYS are sensitive
  });

  // Ensure new sensitive inputs are masked
  const newKeyInputs = vertexApiKeyContainer.querySelectorAll(
    `.${ARRAY_INPUT_CLASS}.${SENSITIVE_INPUT_CLASS}`
  );
  newKeyInputs.forEach((input) => {
    if (configForm && typeof initializeSensitiveFields === "function") {
      const focusoutEvent = new Event("focusout", {
        bubbles: true,
        cancelable: true,
      });
      input.dispatchEvent(focusoutEvent);
    }
  });

  closeModal(vertexApiKeyModal);
  showNotification(
    `添加/更新了 ${uniqueKeys.length} 个唯一 Vertex 密钥`,
    "success"
  );
  vertexApiKeyBulkInput.value = "";
}

/**
 * Handles the bulk deletion of Vertex Express API keys based on input from the modal.
 */
function handleBulkDeleteVertexApiKeys() {
  const vertexApiKeyContainer = document.getElementById(
    "VERTEX_API_KEYS_container"
  );
  if (
    !bulkDeleteVertexApiKeyInput ||
    !vertexApiKeyContainer ||
    !bulkDeleteVertexApiKeyModal
  ) {
    return;
  }

  const bulkText = bulkDeleteVertexApiKeyInput.value;
  if (!bulkText.trim()) {
    showNotification("请粘贴需要删除的 Vertex Express API 密钥", "warning");
    return;
  }

  const keysToDelete = new Set(bulkText.match(VERTEX_API_KEY_REGEX) || []);

  if (keysToDelete.size === 0) {
    showNotification(
      "未在输入内容中提取到有效的 Vertex Express API 密钥格式",
      "warning"
    );
    return;
  }

  const keyItems = vertexApiKeyContainer.querySelectorAll(
    `.${ARRAY_ITEM_CLASS}`
  );
  let deleteCount = 0;

  keyItems.forEach((item) => {
    const input = item.querySelector(
      `.${ARRAY_INPUT_CLASS}.${SENSITIVE_INPUT_CLASS}`
    );
    const realValue =
      input &&
      (input.hasAttribute("data-real-value")
        ? input.getAttribute("data-real-value")
        : input.value);
    if (realValue && keysToDelete.has(realValue)) {
      item.remove();
      deleteCount++;
    }
  });

  closeModal(bulkDeleteVertexApiKeyModal);

  if (deleteCount > 0) {
    showNotification(
      `成功删除了 ${deleteCount} 个匹配的 Vertex 密钥`,
      "success"
    );
  } else {
    showNotification("列表中未找到您输入的任何 Vertex 密钥进行删除", "info");
  }
  bulkDeleteVertexApiKeyInput.value = "";
}

/**
 * Switches the active configuration tab.
 * @param {string} tabId - The ID of the tab to switch to.
 */
function switchTab(tabId) {
  console.log(`Switching to tab: ${tabId}`);

  // 定义选中态和未选中态的样式
  const activeStyle =
    "background-color: #3b82f6 !important; color: #ffffff !important; border: 2px solid #2563eb !important; box-shadow: 0 4px 12px -2px rgba(59, 130, 246, 0.4), 0 2px 6px -1px rgba(59, 130, 246, 0.2) !important; transform: translateY(-2px) !important; font-weight: 600 !important;";
  const inactiveStyle =
    "background-color: #f8fafc !important; color: #64748b !important; border: 2px solid #e2e8f0 !important; box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.1) !important; font-weight: 500 !important; transform: none !important;";

  // 更新标签按钮状态
  const tabButtons = document.querySelectorAll(".tab-btn");
  console.log(`Found ${tabButtons.length} tab buttons`);

  tabButtons.forEach((button) => {
    const buttonTabId = button.getAttribute("data-tab");
    if (buttonTabId === tabId) {
      // 激活状态：直接设置内联样式
      button.classList.add("active");
      button.setAttribute("style", activeStyle);
      console.log(`Applied active style to button: ${buttonTabId}`);
    } else {
      // 非激活状态：直接设置内联样式
      button.classList.remove("active");
      button.setAttribute("style", inactiveStyle);
      console.log(`Applied inactive style to button: ${buttonTabId}`);
    }
  });

  // 更新内容区域
  const sections = document.querySelectorAll(".config-section");
  sections.forEach((section) => {
    if (section.id === `${tabId}-section`) {
      section.classList.add("active");
    } else {
      section.classList.remove("active");
    }
  });
}

/**
 * Toggles the visibility of configuration sections for different upload providers.
 * @param {string} provider - The selected upload provider.
 */
function toggleProviderConfig(provider) {
  const providerConfigs = document.querySelectorAll(".provider-config");
  providerConfigs.forEach((config) => {
    if (config.getAttribute("data-provider") === provider) {
      config.classList.add("active");
    } else {
      config.classList.remove("active");
    }
  });
}

/**
 * Creates and appends an input field for an array item.
 * @param {string} key - The configuration key for the array.
 * @param {string} value - The initial value for the input field.
 * @param {boolean} isSensitive - Whether the input is for sensitive data.
 * @param {string|null} modelId - Optional model ID for thinking models.
 * @returns {HTMLInputElement} The created input element.
 */
function createArrayInput(key, value, isSensitive, modelId = null) {
  const input = document.createElement("input");
  input.type = "text";
  input.name = `${key}[]`; // Used for form submission if not handled by JS
  input.value = value;
  let inputClasses = `${ARRAY_INPUT_CLASS} flex-grow px-3 py-2 border-none rounded-l-md focus:outline-none form-input-themed`;
  if (isSensitive) {
    inputClasses += ` ${SENSITIVE_INPUT_CLASS}`;
  }
  input.className = inputClasses;
  if (modelId) {
    input.setAttribute("data-model-id", modelId);
    input.placeholder = "思考模型名称";
  }
  return input;
}

/**
 * Creates a generate token button for allowed tokens.
 * @returns {HTMLButtonElement} The created button element.
 */
function createGenerateTokenButton() {
  const generateBtn = document.createElement("button");
  generateBtn.type = "button";
  generateBtn.className =
    "generate-btn px-2 py-2 text-gray-500 hover:text-primary-600 focus:outline-none rounded-r-md bg-gray-100 hover:bg-gray-200 transition-colors";
  generateBtn.innerHTML = '<i class="fas fa-dice"></i>';
  generateBtn.title = "生成随机令牌";
  // Event listener will be added via delegation in DOMContentLoaded
  return generateBtn;
}

/**
 * Creates a remove button for an array item.
 * @returns {HTMLButtonElement} The created button element.
 */
function createRemoveButton() {
  const removeBtn = document.createElement("button");
  removeBtn.type = "button";
  removeBtn.className =
    "remove-btn text-gray-400 hover:text-red-500 focus:outline-none transition-colors duration-150";
  removeBtn.innerHTML = '<i class="fas fa-trash-alt"></i>';
  removeBtn.title = "删除";
  // Event listener will be added via delegation in DOMContentLoaded
  return removeBtn;
}


/**
 * 打开令牌配置窗口，并用现有数据和可用分组填充它
 * @param {HTMLElement} buttonElement - 被点击的“齿轮”按钮
 */
  let currentEditingTokenItem = null;
/**
 */
  async function openTokenSettings(buttonElement) {
    // 1. [定位]
    currentEditingTokenItem = buttonElement.closest('.array-item');
    if (!currentEditingTokenItem) return;
    // 2. [数据恢复]
    const tokenInput = currentEditingTokenItem.querySelector('.array-input');
    const descriptionInput = currentEditingTokenItem.querySelector('.description-input'); 
    const currentToken = tokenInput.getAttribute('data-real-value') || tokenInput.value;
    const currentDescription = descriptionInput ? descriptionInput.value : currentEditingTokenItem.dataset.description || '';
    const currentTag = currentEditingTokenItem.dataset.tag || '';
    const currentStatus = currentEditingTokenItem.dataset.status !== 'inactive';
    const currentGroupIds = JSON.parse(currentEditingTokenItem.dataset.groups || '[]');
    // 3. [表单填充]
    document.getElementById('tokenSettingsTokenInput').value = currentToken;
    document.getElementById('tokenSettingsDescriptionInput').value = currentDescription;
    document.getElementById('tokenSettingsTagInput').value = currentTag;
    const statusToggle = document.getElementById('tokenSettingsStatusToggle');
    statusToggle.checked = currentStatus;
    statusToggle.dispatchEvent(new Event('change'));
    // 4. [打开模态框]
    openModal(tokenSettingsModal);
    // 5. [异步加载分组]使用全局缓存的分组数据，同步渲染分组列表
    const groupsContainer = document.getElementById('tokenSettingsGroupsContainer');
    groupsContainer.innerHTML = ''; // 清空容器
    if (ALL_AVAILABLE_GROUPS && ALL_AVAILABLE_GROUPS.length > 0) {
        ALL_AVAILABLE_GROUPS.forEach(group => {
            const isChecked = currentGroupIds.includes(group.ID); // 注意：此处group.id应为group.ID
            const wrapper = document.createElement('div');
            const checkboxId = `group-checkbox-${group.ID}`;
            const checkbox = document.createElement('input');
            checkbox.type = 'checkbox';
            checkbox.id = checkboxId;
            checkbox.className = 'hidden group-checkbox';
            checkbox.value = group.ID;
            checkbox.checked = isChecked;
            const label = document.createElement('label');
            label.htmlFor = checkboxId;
            label.textContent = group.DisplayName || group.Name; // 同样适配大小写
            label.className = `cursor-pointer text-sm px-3 py-1 rounded-full transition-all ${isChecked ? 'bg-green-500 text-white' : 'bg-gray-200 text-gray-700'}`;
            if (isChecked) {
                label.innerHTML = `<i class="fas fa-check-circle mr-1"></i> ${label.textContent}`;
            }
            checkbox.addEventListener('change', () => {
                label.classList.toggle('bg-green-500', checkbox.checked);
                label.classList.toggle('text-white', checkbox.checked);
                label.classList.toggle('bg-gray-200', !checkbox.checked);
                label.classList.toggle('text-gray-700', !checkbox.checked);
                label.innerHTML = checkbox.checked ? `<i class="fas fa-check-circle mr-1"></i> ${group.DisplayName || group.Name}` : `${group.DisplayName || group.Name}`;
            });
            wrapper.appendChild(checkbox);
            wrapper.appendChild(label);
            groupsContainer.appendChild(wrapper);
        });
    } else {
        groupsContainer.innerHTML = '<span class="text-gray-500 text-sm">系统中暂无可用分组。</span>';
    }
}
/**
 * 当用户点击“确认”时
 */
function handleConfirmTokenSettings() {
    if (!currentEditingTokenItem) return;
    // 1. [数据收集]
    const newToken = document.getElementById('tokenSettingsTokenInput').value;
    const newDescription = document.getElementById('tokenSettingsDescriptionInput').value;
    const newTag = document.getElementById('tokenSettingsTagInput').value;
    const newStatus = document.getElementById('tokenSettingsStatusToggle').checked ? 'active' : 'inactive';
    const selectedGroups = [];
    document.querySelectorAll('#tokenSettingsGroupsContainer .group-checkbox:checked').forEach(cb => {
        selectedGroups.push(parseInt(cb.value, 10));
    });
    // 2. [数据持久化到DOM]
    const tokenInput = currentEditingTokenItem.querySelector('.array-input');
    tokenInput.value = maskToken(newToken);
    tokenInput.setAttribute('data-real-value', newToken);
    currentEditingTokenItem.dataset.description = newDescription;
    currentEditingTokenItem.dataset.tag = newTag;
    currentEditingTokenItem.dataset.status = newStatus;
    currentEditingTokenItem.dataset.groups = JSON.stringify(selectedGroups);
    const descriptionInput = currentEditingTokenItem.querySelector('.description-input');
    if (descriptionInput) {
        descriptionInput.value = newDescription;
    }
    // 3. [收尾]
    closeModal(tokenSettingsModal);
    showNotification("令牌配置已在本地更新，请在页面底部保存以生效。", "success");
    currentEditingTokenItem = null;
}
/**
 * [灵魂-辅助] 处理“全选/全不选”按钮的逻辑
 */
function toggleAllGroups(select) {
    document.querySelectorAll('#tokenSettingsGroupsContainer .group-checkbox').forEach(checkbox => {
        if (checkbox.checked !== select) {
            checkbox.checked = select;
            checkbox.dispatchEvent(new Event('change'));
        }
    });
}

/**
 * [新增] 创建一个“配置”按钮 (齿轮图标)
 * @returns {HTMLButtonElement}
 */
function createSettingsButton() {
    const settingsBtn = document.createElement('button');
    settingsBtn.type = 'button';
    settingsBtn.className = 'settings-btn px-2 py-2 text-gray-400 hover:text-blue-500 focus:outline-none rounded-md hover:bg-gray-100 transition-colors';
    settingsBtn.innerHTML = '<i class="fas fa-cog"></i>';
    settingsBtn.title = '配置此令牌';
   
    return settingsBtn;
}
/**
 * Creates a proxy status icon for displaying proxy check status.
 * @returns {HTMLSpanElement} The status icon element.
 */
function createProxyStatusIcon() {
  const statusIcon = document.createElement("span");
  statusIcon.className = "proxy-status-icon px-2 py-2 text-gray-400";
  statusIcon.innerHTML = '<i class="fas fa-question-circle" title="未检测"></i>';
  statusIcon.setAttribute("data-status", "unknown");
  return statusIcon;
}

/**
 * Creates a proxy check button for individual proxy checking.
 * @returns {HTMLButtonElement} The check button element.
 */
function createProxyCheckButton() {
  const checkBtn = document.createElement("button");
  checkBtn.type = "button";
  checkBtn.className =
    "proxy-check-btn px-2 py-2 text-blue-500 hover:text-blue-700 focus:outline-none transition-colors duration-150 rounded-r-md";
  checkBtn.innerHTML = '<i class="fas fa-globe"></i>';
  checkBtn.title = "检测此代理";
  
  // 添加点击事件监听器
  checkBtn.addEventListener("click", function(e) {
    e.preventDefault();
    e.stopPropagation();
    const inputElement = this.closest('.flex').querySelector('.array-input');
    if (inputElement && inputElement.value.trim()) {
      checkSingleProxy(inputElement.value.trim(), this);
    } else {
      showNotification("请先输入代理地址", "warning");
    }
  });
  
  return checkBtn;
}

// [辅助函数]
function maskToken(token) {
    if (typeof token !== 'string' || token.length <= 4) return token;
    return `${token.substring(0, 2)}...${token.substring(token.length - 2)}`;
}

/**
 * [核心新增] 打开IP封禁配置模态框
 * 从主表单读取当前值，并填充到模态框中
 */
function openIpBanSettings() {
    // 从主表单的原始输入框中读取数据
    const maxAttemptsEl = document.getElementById('MAX_LOGIN_ATTEMPTS');
    const banDurationEl = document.getElementById('IP_BAN_DURATION_MINUTES');
    if (ipBanMaxAttemptsInput && maxAttemptsEl) {
        ipBanMaxAttemptsInput.value = maxAttemptsEl.value;
    }
    if (ipBanDurationInput && banDurationEl) {
        ipBanDurationInput.value = banDurationEl.value;
    }
    
    openModal(ipBanSettingsModal);
}
/**
 * [核心新增] 处理IP封禁配置的确认操作
 * 从模态框读取新值，并写回到主表单中
 */
function handleConfirmIpBanSettings() {
    // 将模态框中的值，写回到主表单的原始输入框
    const maxAttemptsEl = document.getElementById('MAX_LOGIN_ATTEMPTS');
    const banDurationEl = document.getElementById('IP_BAN_DURATION_MINUTES');
    if (maxAttemptsEl && ipBanMaxAttemptsInput) {
        maxAttemptsEl.value = ipBanMaxAttemptsInput.value;
    }
    if (banDurationEl && ipBanDurationInput) {
        banDurationEl.value = ipBanDurationInput.value;
    }
    showNotification("IP封禁规则已更新。", "info");
    closeModal(ipBanSettingsModal);
}


/**
 * Adds a new item to an array configuration section (e.g., API_KEYS, ALLOWED_TOKENS).
 * This function is typically called by a "+" button.
 * @param {string} key - The configuration key for the array (e.g., 'API_KEYS').
 */
function addArrayItem(key) {
  const container = document.getElementById(`${key}_container`);
  if (!container) return;

  const newItemValue = ""; // New items start empty
  const modelId = addArrayItemWithValue(key, newItemValue); // This adds the DOM element

  if (key === "THINKING_MODELS" && modelId) {
    createAndAppendBudgetMapItem(newItemValue, -1, modelId); // Default budget -1
  }
}

/**
 * @param {string} key - The configuration key (e.g., 'API_KEYS', 'THINKING_MODELS').
 * @param {string} value - The value for the array item.
 * @returns {string|null} The generated modelId if it's a thinking model, otherwise null.
 */
function addArrayItemWithValue(key, value) {
  const container = document.getElementById(`${key}_container`);
  if (!container) return null;
  const isThinkingModel = key === "THINKING_MODELS";
  const isAllowedToken = key === "ALLOWED_TOKENS";
  const isVertexApiKey = key === "VERTEX_API_KEYS";
  const isProxy = key === "PROXIES";
  const isSensitive = key === "API_KEYS" || isAllowedToken || isVertexApiKey;
  const modelId = isThinkingModel ? generateUUID() : null;
  // [数据对接] 当是令牌时，将传入的对象分解为具体的值
  let tokenValue = value;
  let descriptionValue = "";
  if (isAllowedToken && typeof value === 'object' && value !== null) {
      tokenValue = value.Token || "";
      descriptionValue = value.Description || "";
  }
  const arrayItem = document.createElement("div");
  arrayItem.className = `${ARRAY_ITEM_CLASS} flex items-center mb-2 gap-2`;
  if (isThinkingModel) {
    arrayItem.setAttribute("data-model-id", modelId);
  }
  // [数据对接] 将令牌的完整数据附加到父元素上，这是后续编辑功能正常工作所必需的
  if (isAllowedToken && typeof value === 'object' && value !== null) {
      arrayItem.dataset.id = value.ID || '';
      arrayItem.dataset.description = value.Description || '';
      arrayItem.dataset.tag = value.Tag || '';
      arrayItem.dataset.status = value.Status || 'active';
      arrayItem.dataset.groups = JSON.stringify((value.AllowedGroups || []).map(g => g.ID));
  }
  
  const inputWrapper = document.createElement("div");

  if (isAllowedToken) {
    // 设置宽度为 3/4
    inputWrapper.className = "flex items-center w-3/4 flex-grow rounded-md focus-within:border-blue-500 focus-within:ring focus-within:ring-blue-500 focus-within:ring-opacity-50";
  } else {
    // 保持所有其他数组类型的原始样式不变
    inputWrapper.className = "flex items-center flex-grow rounded-md focus-within:border-blue-500 focus-within:ring focus-within:ring-blue-500 focus-within:ring-opacity-50";
  }
  inputWrapper.style.border = "1px solid rgba(0, 0, 0, 0.12)";
  inputWrapper.style.backgroundColor = "transparent";
  // createArrayInput 接收分解后的 tokenValue
  const input = createArrayInput(
    key,
    tokenValue,
    isSensitive,
    isThinkingModel ? modelId : null
  );
  inputWrapper.appendChild(input);
  // --- 内部组件的装配逻辑，100%保持不变 ---
  if (isAllowedToken) {
    const generateBtn = createGenerateTokenButton();
    inputWrapper.appendChild(generateBtn);
  } else if (isProxy) {
    const proxyStatusIcon = createProxyStatusIcon();
    inputWrapper.appendChild(proxyStatusIcon);
    const proxyCheckBtn = createProxyCheckButton();
    inputWrapper.appendChild(proxyCheckBtn);
  } else {
    input.classList.add("rounded-r-md");
  }
  // --- 外部组件的创建，100%保持不变 ---
  const removeBtn = createRemoveButton();
  let settingsBtn = null;
  if (isAllowedToken) {
    settingsBtn = createSettingsButton();
  }
  // --- 最终的“总装配”流程 ---
  arrayItem.appendChild(inputWrapper);
  
  // 在令牌输入框后，插入1/4宽度的描述输入框
  if (isAllowedToken) {
      const descriptionInput = document.createElement("input");
      descriptionInput.type = "text";
      // 添加 .description-input 类，以便 handleConfirmTokenSettings 可以找到并更新它
      descriptionInput.className = "w-1/4 px-3 py-2 flex-grow rounded-md focus-within:border-blue-500 focus-within:ring focus-within:ring-blue-500 focus-within:ring-opacity-50 description-input";
      descriptionInput.value = descriptionValue;
      // [添加事件监听器，实时更新dataset
      descriptionInput.addEventListener('input', (event) => {
          const parentArrayItem = event.target.closest('.array-item');
          if (parentArrayItem) {
              parentArrayItem.dataset.description = event.target.value;
          }
      });
      descriptionInput.placeholder = "令牌描述...";
      //descriptionInput.readOnly = true;
      arrayItem.appendChild(descriptionInput);
  }
  if (settingsBtn) {
    arrayItem.appendChild(settingsBtn); 
  }
  
  arrayItem.appendChild(removeBtn);
  container.appendChild(arrayItem);
  // --- 所有收尾逻辑，100%保持不变 ---
  if (isSensitive && input.value) {
    if (configForm && typeof initializeSensitiveFields === "function") {
      const focusoutEvent = new Event("focusout", {
        bubbles: true,
        cancelable: true,
      });
      input.dispatchEvent(focusoutEvent);
    }
  }
  return isThinkingModel ? modelId : null;
}



/**
 * Creates and appends a DOM element for a thinking model's budget mapping.
 * @param {string} mapKey - The model name (key for the map).
 * @param {number|string} mapValue - The budget value.
 * @param {string} modelId - The unique ID of the corresponding thinking model.
 */
function createAndAppendBudgetMapItem(mapKey, mapValue, modelId) {
  const container = document.getElementById("THINKING_BUDGET_MAP_container");
  if (!container) {
    console.error(
      "Cannot add budget item: THINKING_BUDGET_MAP_container not found!"
    );
    return;
  }

  // If container currently only has the placeholder, clear it
  const placeholder = container.querySelector(".text-gray-500.italic");
  // Check if the only child is the placeholder before clearing
  if (
    placeholder &&
    container.children.length === 1 &&
    container.firstChild === placeholder
  ) {
    container.innerHTML = "";
  }

  const mapItem = document.createElement("div");
  mapItem.className = `${MAP_ITEM_CLASS} flex items-center mb-2 gap-2`;
  mapItem.setAttribute("data-model-id", modelId);

  const keyInput = document.createElement("input");
  keyInput.type = "text";
  keyInput.value = mapKey;
  keyInput.placeholder = "模型名称 (自动关联)";
  keyInput.readOnly = true;
  keyInput.className = `${MAP_KEY_INPUT_CLASS} flex-grow px-3 py-2 border border-gray-300 rounded-md focus:outline-none bg-gray-100 text-gray-500`;
  keyInput.setAttribute("data-model-id", modelId);

  const valueInput = document.createElement("input");
  valueInput.type = "number";
  const intValue = parseInt(mapValue, 10);
  valueInput.value = isNaN(intValue) ? -1 : intValue;
  valueInput.placeholder = "预算 (整数)";
  valueInput.className = `${MAP_VALUE_INPUT_CLASS} w-24 px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:border-primary-500 focus:ring focus:ring-primary-200 focus:ring-opacity-50`;
  valueInput.min = -1;
  valueInput.max = 32767;
  valueInput.addEventListener("input", function () {
    let val = this.value.replace(/[^0-9-]/g, "");
    if (val !== "") {
      val = parseInt(val, 10);
      if (val < -1) val = -1;
      if (val > 32767) val = 32767;
    }
    this.value = val; // Corrected variable name
  });

  // Remove Button - Removed for budget map items
  // const removeBtn = document.createElement('button');
  // removeBtn.type = 'button';
  // removeBtn.className = 'remove-btn text-gray-300 cursor-not-allowed focus:outline-none'; // Kept original class for reference
  // removeBtn.innerHTML = '<i class="fas fa-trash-alt"></i>';
  // removeBtn.title = '请从上方模型列表删除';
  // removeBtn.disabled = true;

  mapItem.appendChild(keyInput);
  mapItem.appendChild(valueInput);
  // mapItem.appendChild(removeBtn); // Do not append the remove button

  container.appendChild(mapItem);
}

/**
 * Adds a new custom header item to the DOM.
 */
function addCustomHeaderItem() {
  createAndAppendCustomHeaderItem("", "");
}

/**
 * Creates and appends a DOM element for a custom header.
 * @param {string} key - The header key.
 * @param {string} value - The header value.
 */
function createAndAppendCustomHeaderItem(key, value) {
  const container = document.getElementById("CUSTOM_HEADERS_container");
  if (!container) {
    console.error(
      "Cannot add custom header: CUSTOM_HEADERS_container not found!"
    );
    return;
  }

  const placeholder = container.querySelector(".text-gray-500.italic");
  if (
    placeholder &&
    container.children.length === 1 &&
    container.firstChild === placeholder
  ) {
    container.innerHTML = "";
  }

  const headerItem = document.createElement("div");
  headerItem.className = `${CUSTOM_HEADER_ITEM_CLASS} flex items-center mb-2 gap-2`;

  const keyInput = document.createElement("input");
  keyInput.type = "text";
  keyInput.value = key;
  keyInput.placeholder = "Header Name";
  keyInput.className = `${CUSTOM_HEADER_KEY_INPUT_CLASS} flex-grow px-3 py-2 border border-gray-300 rounded-md focus:outline-none bg-gray-100 text-gray-500`;

  const valueInput = document.createElement("input");
  valueInput.type = "text";
  valueInput.value = value;
  valueInput.placeholder = "Header Value";
  valueInput.className = `${CUSTOM_HEADER_VALUE_INPUT_CLASS} flex-grow px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:border-primary-500 focus:ring focus:ring-primary-200 focus:ring-opacity-50`;

  const removeBtn = createRemoveButton();
  removeBtn.addEventListener("click", () => {
    headerItem.remove();
    if (container.children.length === 0) {
      container.innerHTML =
        '<div class="text-gray-500 text-sm italic">添加自定义请求头，例如 X-Api-Key: your-key</div>';
    }
  });

  headerItem.appendChild(keyInput);
  headerItem.appendChild(valueInput);
  headerItem.appendChild(removeBtn);

  container.appendChild(headerItem);
}



/**
 * [架构对齐版] 收集所有认证令牌的完整数据 (包括管理员令牌)
 * @returns {Array<object>} 一个包含所有令牌完整信息的对象数组
 */
function collectTokenData() {
    const tokens = [];
    const container = document.getElementById('ALLOWED_TOKENS_container');
    
    // 1. [核心增强] 首先，收集并添加“管理员令牌”
    const authTokenInput = document.getElementById('AUTH_TOKEN');
    if (authTokenInput) {
        tokens.push({
            Token: authTokenInput.getAttribute('data-real-value') || authTokenInput.value,
            IsAdmin: true // [关键] 打上“admin”的标签
            // 其他属性（描述、分组等）对于管理员令牌是固定的，前端无需提交
        });
    }
    // 2. 收集所有“用户级令牌”
    if (container) {
        const tokenItems = container.querySelectorAll('.array-item');
        tokenItems.forEach(item => {
            const tokenInput = item.querySelector('.array-input');
            const descriptionInput = item.querySelector('.description-input');
            if (!tokenInput || !descriptionInput) return;
            // 为后端API组装一个干净的用户令牌对象
            const tokenObject = {
                ID: parseInt(item.dataset.id, 10) || 0,
                Token: tokenInput.getAttribute('data-real-value') || tokenInput.value,
                Description: descriptionInput.value,
                Tag: item.dataset.tag || '',
                Status: item.dataset.status || 'active',
                IsAdmin: false, // 明确标记为用户级令牌
                AllowedGroupIDs: JSON.parse(item.dataset.groups || '[]')
            };
            tokens.push(tokenObject);
        });
    }
    
    return tokens;
}

/**
 * [核心对接] 创建一个新的函数，专门用于根据后端数据对象渲染一个代理项UI
 * @param {object} proxy - 从 /admin/proxies API 获取的单个代理对象
 */
function addProxyItem(proxy) {
    const container = document.getElementById('PROXIES_container');
    if (!container || typeof proxy !== 'object' || !proxy.Protocol || !proxy.Address) return;

    const displayValue = `${proxy.Protocol}://${proxy.Address}`;

    const arrayItem = document.createElement("div");
    arrayItem.className = `${ARRAY_ITEM_CLASS} flex items-center mb-2 gap-2`;

    // [数据对接] 将后端的 ID 和 Status 存储在 dataset 中
    arrayItem.dataset.id = proxy.ID;
    arrayItem.dataset.status = proxy.Status;

    const inputWrapper = document.createElement("div");
    inputWrapper.className = "flex items-center flex-grow rounded-md focus-within:border-blue-500";
    inputWrapper.style.border = "1px solid rgba(0, 0, 0, 0.12)";
    inputWrapper.style.backgroundColor = "transparent";

    // 使用现有的辅助函数创建基础 input 元素
    const input = createArrayInput('PROXIES', displayValue, false, null);
    inputWrapper.appendChild(input);

    // [数据对接] 创建图标，并根据后端数据设置初始状态
    const proxyStatusIcon = createProxyStatusIcon();
    updateProxyStatus(proxyStatusIcon, { 
        is_available: proxy.Status === 'active', 
        response_time: 'N/A', 
        error_message: `后台状态: ${proxy.Status}`  
    });
    inputWrapper.appendChild(proxyStatusIcon);
    
    inputWrapper.appendChild(createProxyCheckButton());

    arrayItem.appendChild(inputWrapper);
    arrayItem.appendChild(createRemoveButton());

    container.appendChild(arrayItem);
}

/**
 * [核心对接 & 已校准] 异步从后端加载并填充代理服务器列表
 */
async function loadAndPopulateProxies() {

    try {
        const response = await apiFetch('/admin/proxies');
        if (!response.ok) {
            throw new Error(`Failed to fetch proxies: ${response.statusText}`);
        }
        const responseData = await response.json();
        // [核心修正] 从这里开始，我们不再假设 responseData 就是数组本身
        // 而是从 'data' 字段中，安全地提取我们需要的代理列表
        const proxies = responseData.data || []; 
        const proxyContainer = document.getElementById('PROXIES_container');
        if (proxyContainer) {
            proxyContainer.innerHTML = ''; 
            if (Array.isArray(proxies) && proxies.length > 0) {

                proxies.sort((a, b) => a.ID - b.ID);
                proxies.forEach(proxy => {
                    addProxyItem(proxy);
                });
            } else {
            }
        }
    } catch (error) {

        showNotification("加载代理列表时发生严重错误，请检查控制台。", "error");
    }
}


/**
 * [核心对接] 从UI的代理容器中，收集所有代理的URL字符串
 * @returns {Array<string>} 一个包含所有代理URL的字符串数组
 */
function collectProxyData() {
    const proxies = [];
    const container = document.getElementById('PROXIES_container');
    if (container) {
        const proxyItems = container.querySelectorAll('.array-item .array-input');
        proxyItems.forEach(input => {
            const proxyValue = input.value.trim();
            if (proxyValue) {
                proxies.push(proxyValue);
            }
        });
    }
    return proxies;
}

/**
 * [核心新增] 打开代理高级配置模态框
 * 从主表单的隐藏“数据仓库”中读取当前值，并填充到模态框中
 */
function openProxySettingsModal() {
    // 从隐藏输入框中读取数据
    const enableCheckEl = document.getElementById('ENABLE_PROXY_CHECK');
    const useHashEl = document.getElementById('USE_PROXY_HASH');
    const timeoutEl = document.getElementById('PROXY_CHECK_TIMEOUT_SECONDS');
    const concurrencyEl = document.getElementById('PROXY_CHECK_CONCURRENCY');
    if (enableProxyCheckInput && enableCheckEl) {
        enableProxyCheckInput.checked = enableCheckEl.value === 'true';
    }
    if (useProxyHashInput && useHashEl) {
        useProxyHashInput.checked = useHashEl.value === 'true';
    }
    if (proxyCheckTimeoutInput && timeoutEl) {
        proxyCheckTimeoutInput.value = timeoutEl.value;
    }
    if (proxyCheckConcurrencyInput && concurrencyEl) {
        proxyCheckConcurrencyInput.value = concurrencyEl.value;
    }
   
    openModal(proxySettingsModal);
}
/**
 * [核心新增] 处理代理高级配置的确认操作
 * 从模态框读取新值，并写回到主表单的隐藏“数据仓库”中
 */
function handleConfirmProxySettings() {
    
    const enableCheckEl = document.getElementById('ENABLE_PROXY_CHECK');
    const useHashEl = document.getElementById('USE_PROXY_HASH');
    const timeoutEl = document.getElementById('PROXY_CHECK_TIMEOUT_SECONDS');
    const concurrencyEl = document.getElementById('PROXY_CHECK_CONCURRENCY');
 
    if (enableCheckEl && enableProxyCheckInput) {
        enableCheckEl.value = enableProxyCheckInput.checked;
    }
    if (useHashEl && useProxyHashInput) {
        useHashEl.value = useProxyHashInput.checked;
    }
    if (timeoutEl && proxyCheckTimeoutInput) {
        timeoutEl.value = proxyCheckTimeoutInput.value;
    }
   
    // 从模态框的输入框 (proxyCheckConcurrencyInput) 读取新值，
    if (concurrencyEl && proxyCheckConcurrencyInput) {
        concurrencyEl.value = proxyCheckConcurrencyInput.value;
    }
     showNotification("代理高级配置已更新。", "info");
    closeModal(proxySettingsModal);
}

/**
 * [核心改造] 收集表单数据函数 (完整生产版)
 * 它严格遵循“后端优先”原则，使用 FIELD_MAP 进行翻译，
 * 并完整复刻了原版函数中所有处理复杂数据结构的精密逻辑。
 * @returns {object} 一个键名为后端 Go Struct 字段名的配置对象。
 */
/**
 * [最终架构版] 收集表单数据函数
 * 该函数不再包含任何硬编码的字段名，而是通过读取元素的'data-type'属性，
 * 来智能地对数据进行类型转换，实现了真正的可扩展性。
 * @returns {object} 一个类型完美的、发往后端的配置对象。
 */
function collectFormData() {
    const formData = {};
    for (const frontendId in FIELD_MAP) {
        if (!Object.prototype.hasOwnProperty.call(FIELD_MAP, frontendId)) continue;
        
        const backendKey = FIELD_MAP[frontendId];
        const element = document.getElementById(frontendId);
        if (element) {
            let value;
            // ====================================================================
            // [核心架构升级]
            // 我们不再硬编码任何字段名，而是建立一套通用的类型处理规则。
            // ====================================================================
            
            const dataType = element.dataset.type; // 读取 data-type 属性
            if (element.type === 'checkbox') {
                // 规则1：可见的 checkbox，其值是 .checked
                value = element.checked;
            } else if (dataType === 'boolean') {
                // 规则2：任何带有 data-type="boolean" 的元素，其值从字符串转换
                value = (element.value === 'true');
            } else if (dataType === 'number' || element.type === 'number') {
                // 规则3：任何带有 data-type="number" 或 type="number" 的元素
                const numValue = parseInt(element.value, 10);
                value = isNaN(numValue) ? 0 : numValue;
            } else {
                // 规则4：其他所有情况，作为字符串处理
                if (element.classList.contains('sensitive-input') && element.hasAttribute('data-real-value')) {
                    value = element.getAttribute('data-real-value');
                } else {
                    value = element.value;
                }
            }
            
            // 特殊单位转换（如果需要，可以保留）
            if (backendKey === 'health_check_interval_seconds') {
                value = (value || 1) * 3600;
            }
            formData[backendKey] = value;
        }
    }

    // B. [适配 & 移植] 单独处理复杂的、基于容器的字段 (数组、对象映射、对象数组)
    // 我们将严格复刻原版函数的逻辑，但使用FIELD_MAP中的键来进行赋值。

    // B.1 处理所有常规数组 (e.g., ALLOWED_TOKENS, PROXIES, etc.)
    const arrayContainers = document.querySelectorAll(".array-container");
    arrayContainers.forEach((container) => {
        const frontendId = container.id.replace("_container", "");

        if (frontendId === 'ALLOWED_TOKENS') {
        return; // 'continue' to the next iteration
        }
        const backendKey = FIELD_MAP[frontendId];
        if (backendKey) {
            const arrayInputs = container.querySelectorAll(`.${ARRAY_INPUT_CLASS}`);
            formData[backendKey] = Array.from(arrayInputs)
                .map((input) => {
                    if (input.classList.contains(SENSITIVE_INPUT_CLASS) && input.hasAttribute('data-real-value')) {
                        return input.getAttribute('data-real-value');
                    }
                    return input.value;
                })
                .filter(value => value && value.trim() !== "" && value !== MASKED_VALUE); // [逻辑移植] 严格过滤空值和掩码
        }
    });

    // B.2 处理 THINKING_BUDGET_MAP (对象映射)
    const budgetMapContainer = document.getElementById("THINKING_BUDGET_MAP_container");
    const budgetMapBackendKey = FIELD_MAP['THINKING_BUDGET_MAP'];
    if (budgetMapContainer && budgetMapBackendKey) {
        formData[budgetMapBackendKey] = {};
        const mapItems = budgetMapContainer.querySelectorAll(`.${MAP_ITEM_CLASS}`);
        mapItems.forEach((item) => {
            const keyInput = item.querySelector(`.${MAP_KEY_INPUT_CLASS}`);
            const valueInput = item.querySelector(`.${MAP_VALUE_INPUT_CLASS}`);
            if (keyInput && valueInput && keyInput.value.trim() !== "") {
                const budgetValue = parseInt(valueInput.value, 10);
                // [逻辑移植] 对无效数字提供默认值 -1
                formData[budgetMapBackendKey][keyInput.value.trim()] = isNaN(budgetValue) ? -1 : budgetValue;
            }
        });
    }

    // B.3 处理 CUSTOM_HEADERS (对象映射)
    const customHeadersContainer = document.getElementById("CUSTOM_HEADERS_container");
    const customHeadersBackendKey = FIELD_MAP['CUSTOM_HEADERS'];
    if (customHeadersContainer && customHeadersBackendKey) {
        formData[customHeadersBackendKey] = {};
        const headerItems = customHeadersContainer.querySelectorAll(`.${CUSTOM_HEADER_ITEM_CLASS}`);
        headerItems.forEach((item) => {
            const keyInput = item.querySelector(`.${CUSTOM_HEADER_KEY_INPUT_CLASS}`);
            const valueInput = item.querySelector(`.${CUSTOM_HEADER_VALUE_INPUT_CLASS}`);
            if (keyInput && valueInput && keyInput.value.trim() !== "") {
                formData[customHeadersBackendKey][keyInput.value.trim()] = valueInput.value.trim();
            }
        });
    }

    // B.4 处理 SAFETY_SETTINGS (对象数组)
    const safetySettingsContainer = document.getElementById("SAFETY_SETTINGS_container");
    const safetySettingsBackendKey = FIELD_MAP['SAFETY_SETTINGS'];
    if (safetySettingsContainer && safetySettingsBackendKey) {
        formData[safetySettingsBackendKey] = [];
        const settingItems = safetySettingsContainer.querySelectorAll(`.${SAFETY_SETTING_ITEM_CLASS}`);
        settingItems.forEach((item) => {
            const categorySelect = item.querySelector(".safety-category-select");
            const thresholdSelect = item.querySelector(".safety-threshold-select");
            if (categorySelect && thresholdSelect && categorySelect.value && thresholdSelect.value) {
                formData[safetySettingsBackendKey].push({
                    category: categorySelect.value,
                    threshold: thresholdSelect.value,
                });
            }
        });
    }
    
    return formData;
}


/**
 * Stops the scheduler task on the server.
 */
async function stopScheduler() {
  try {
    const response = await fetch("/api/scheduler/stop", { method: "POST" });
    if (!response.ok) {
      console.warn(`停止定时任务失败: ${response.status}`);
    } else {
      console.log("定时任务已停止");
    }
  } catch (error) {
    console.error("调用停止定时任务API时出错:", error);
  }
}

/**
 * Starts the scheduler task on the server.
 */
async function startScheduler() {
  try {
    const response = await fetch("/api/scheduler/start", { method: "POST" });
    if (!response.ok) {
      console.warn(`启动定时任务失败: ${response.status}`);
    } else {
      console.log("定时任务已启动");
    }
  } catch (error) {
    console.error("调用启动定时任务API时出错:", error);
  }
}


/**
 * [核心重构] 保存配置总指挥函数
 * 它将按顺序分别保存“系统配置”和“认证令牌”
 */
async function saveConfig() {
    console.log("[FINAL] Save process initiated with cache bypass."); 
    showNotification("正在保存配置...", "info");
    
    try {
        await stopScheduler();
        const settingsData = collectFormData();

        // ===================================================================
        // [核心调试代码] 在此处安装我们的“数据探针”
        // ===================================================================
        console.log("=============== 🔴 DEBUG START: Settings Payload 🔴 ===============");
        console.log("整个即将发送的 settingsData 对象:");
        // 使用 JSON.stringify 美化输出，方便查看对象结构
        console.log(JSON.stringify(settingsData, null, 2));
        console.log("\n--- 单独检查关键字段 ---");
        
        // 检查失效的布尔值
        console.log(`[布尔/失效] enable_proxy_check:`, settingsData['enable_proxy_check'], `(类型: ${typeof settingsData['enable_proxy_check']})`);
        console.log(`[布尔/失效] use_proxy_hash:`, settingsData['use_proxy_hash'], `(类型: ${typeof settingsData['use_proxy_hash']})`);
        // 检查有效的布尔值作为“对照组”
        console.log(`[布尔/有效] enable_ip_banning:`, settingsData['enable_ip_banning'], `(类型: ${typeof settingsData['enable_ip_banning']})`);
        // 检查失效的数字
        console.log(`[数字/失效] proxy_check_concurrency:`, settingsData['proxy_check_concurrency'], `(类型: ${typeof settingsData['proxy_check_concurrency']})`);
        // 检查有效的数字作为“对照组”
        console.log(`[数字/有效] proxy_check_timeout_seconds:`, settingsData['proxy_check_timeout_seconds'], `(类型: ${typeof settingsData['proxy_check_timeout_seconds']})`);
        
        console.log("======================= 🔴 DEBUG END 🔴 =======================");
        // ===================================================================
        // [调试结束]
        // ===================================================================
            const settingsResponse = await apiFetch("/admin/settings", {
            method: 'PUT',
            headers: { 'Content-Type': 'application/json' },
            body: JSON.stringify(settingsData),
            noCache: true // [指令] 禁用缓存！
        });
        if (!settingsResponse.ok) {
           const errorText = await settingsResponse.text();
           throw new Error(`保存系统设置失败: ${errorText}`);
        }
        
        const tokenData = collectTokenData();

        const tokensResponse = await apiFetch("/admin/tokens", {
            method: 'PUT',
            headers: { 'Content-Type': 'application/json' },
            body: JSON.stringify(tokenData),
            noCache: true // [指令] 禁用缓存！
        });
        if (!tokensResponse.ok) {
            const errorText = await tokensResponse.text();
            throw new Error(`保存认证令牌失败: ${errorText}`);
        }

        // =============================================================
        // [核心对接] 3. 同步代理服务器列表
        // =============================================================
        console.log("[SYNC] Collecting proxy data...");
        const proxyData = collectProxyData();
        console.log(`[SYNC] Found ${proxyData.length} proxies to sync.`);
        
        const proxySyncResponse = await apiFetch("/admin/proxies/sync", {
            method: 'PUT',
            headers: { 'Content-Type': 'application/json' },
            body: JSON.stringify({ proxies: proxyData }), // [数据对接] 按照后端API要求，封装成 { proxies: [...] }
            noCache: true 
        });
        if (!proxySyncResponse.ok) {
            const errorText = await proxySyncResponse.text();
            throw new Error(`同步代理服务器失败: ${errorText}`);
        }
        const syncResult = await proxySyncResponse.json();
        console.log("[SYNC] Proxy sync task started successfully.", syncResult);


        showNotification("配置保存成功！页面即将刷新...", "success", 2000);
        setTimeout(() => window.location.reload(), 2000);
    } catch (error) {
        console.error("CRITICAL FAILURE in saveConfig:", error);
        showNotification("保存配置失败: " + error.message, "error");
        await startScheduler().catch(e => console.warn("Scheduler restart failed.", e));
    }
}


/**
 * Initiates the configuration reset process by showing a confirmation modal.
 * @param {Event} [event] - The click event, if triggered by a button.
 */
function resetConfig(event) {
  // 阻止事件冒泡和默认行为
  if (event) {
    event.preventDefault();
    event.stopPropagation();
  }

  console.log(
    "resetConfig called. Event target:",
    event ? event.target.id : "No event"
  );

  // Ensure modal is shown only if the event comes from the reset button
  if (
    !event ||
    event.target.id === "resetBtn" ||
    (event.currentTarget && event.currentTarget.id === "resetBtn")
  ) {
    if (resetConfirmModal) {
      openModal(resetConfirmModal);
    } else {
      console.error(
        "Reset confirmation modal not found! Falling back to default confirm."
      );
      if (confirm("确定要重置所有配置吗？这将恢复到默认值。")) {
        executeReset();
      }
    }
  }
}


async function executeReset() {
    try {
        showNotification("正在重置配置...", "info");

        // [核心移植] 1. 在写入操作前，停止定时任务。
        await stopScheduler();

        // [路由适配] 2. 向我们新的 /admin/settings/reset 接口发送 POST 请求。
        const response = await apiFetch("/admin/settings/reset", { 
            method: 'POST' 
        });

        if (!response.ok) {
            const errorData = await response.json();
            throw new Error(errorData.message || `HTTP error! status: ${response.status}`);
        }
        
        // [逻辑移植] 3. 重置成功后，用后端返回的默认配置，重新填充表单。
        const result = await response.json();
        populateForm(result.data); // 假设您的成功响应是 { success: true, data: {...} }

        showNotification("配置已重置为默认值", "success");

    } catch (error) {
        console.error("重置配置失败:", error);
        showNotification("重置配置失败: " + error.message, "error");

    } finally {
        // [核心移植] 4. 无论成功失败，都重启定时任务。
        await startScheduler();
    }
}


/**
 * Displays a notification message to the user.
 * @param {string} message - The message to display.
 * @param {string} [type='info'] - The type of notification ('info', 'success', 'error', 'warning').
 */
function showNotification(message, type = "info") {
  const notification = document.getElementById("notification");
  notification.textContent = message;

  // 统一样式为黑色半透明，与 keys_status.js 保持一致
  notification.classList.remove("bg-danger-500");
  notification.classList.add("bg-black");
  notification.style.backgroundColor = "rgba(0,0,0,0.8)";
  notification.style.color = "#fff";

  // 应用过渡效果
  notification.style.opacity = "1";
  notification.style.transform = "translate(-50%, 0)";

  // 设置自动消失
  setTimeout(() => {
    notification.style.opacity = "0";
    notification.style.transform = "translate(-50%, 10px)";
  }, 3000);
}

/**
 * Refreshes the current page.
 * @param {HTMLButtonElement} [button] - The button that triggered the refresh (to show loading state).
 */
function refreshPage(button) {
  if (button) button.classList.add("loading");
  location.reload();
}

/**
 * Scrolls the page to the top.
 */
function scrollToTop() {
  window.scrollTo({ top: 0, behavior: "smooth" });
}

/**
 * Scrolls the page to the bottom.
 */
function scrollToBottom() {
  window.scrollTo({ top: document.body.scrollHeight, behavior: "smooth" });
}

/**
 * Toggles the visibility of scroll-to-top/bottom buttons based on scroll position.
 */
function toggleScrollButtons() {
  const scrollButtons = document.querySelector(".scroll-buttons");
  if (scrollButtons) {
    scrollButtons.style.display = window.scrollY > 200 ? "flex" : "none";
  }
}

/**
 * Generates a random token string. 
 * @returns {string} A randomly generated token.
 */
function generateRandomToken() {
  const characters =
    "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_";
  const length = 48;
  let result = "sk-";
  for (let i = 0; i < length; i++) {
    result += characters.charAt(Math.floor(Math.random() * characters.length));
  }
  return result;
}

/**
 * Adds a new safety setting item to the DOM.
 * @param {string} [category=''] - The initial category for the setting.
 * @param {string} [threshold=''] - The initial threshold for the setting.
 */
function addSafetySettingItem(category = "", threshold = "") {
  const container = document.getElementById("SAFETY_SETTINGS_container");
  if (!container) {
    console.error(
      "Cannot add safety setting: SAFETY_SETTINGS_container not found!"
    );
    return;
  }

  // 如果容器当前只有占位符，则清除它
  const placeholder = container.querySelector(".text-gray-500.italic");
  if (
    placeholder &&
    container.children.length === 1 &&
    container.firstChild === placeholder
  ) {
    container.innerHTML = "";
  }

  const harmCategories = [
    "HARM_CATEGORY_HARASSMENT",
    "HARM_CATEGORY_HATE_SPEECH",
    "HARM_CATEGORY_SEXUALLY_EXPLICIT",
    "HARM_CATEGORY_DANGEROUS_CONTENT",
    "HARM_CATEGORY_CIVIC_INTEGRITY", // 根据需要添加或移除
  ];
  const harmThresholds = [
    "BLOCK_NONE",
    "BLOCK_LOW_AND_ABOVE",
    "BLOCK_MEDIUM_AND_ABOVE",
    "BLOCK_ONLY_HIGH",
    "OFF", // 根据 Google API 文档添加或移除
  ];

  const settingItem = document.createElement("div");
  settingItem.className = `${SAFETY_SETTING_ITEM_CLASS} flex items-center mb-2 gap-2`;

  const categorySelect = document.createElement("select");
  categorySelect.className =
    "safety-category-select flex-grow px-3 py-2 rounded-md focus:outline-none focus:border-primary-500 focus:ring focus:ring-primary-200 focus:ring-opacity-50 form-select-themed";
  harmCategories.forEach((cat) => {
    const option = document.createElement("option");
    option.value = cat;
    option.textContent = cat.replace("HARM_CATEGORY_", "");
    if (cat === category) option.selected = true;
    categorySelect.appendChild(option);
  });

  const thresholdSelect = document.createElement("select");
  thresholdSelect.className =
    "safety-threshold-select w-48 px-3 py-2 rounded-md focus:outline-none focus:border-primary-500 focus:ring focus:ring-primary-200 focus:ring-opacity-50 form-select-themed";
  harmThresholds.forEach((thr) => {
    const option = document.createElement("option");
    option.value = thr;
    option.textContent = thr.replace("BLOCK_", "").replace("_AND_ABOVE", "+");
    if (thr === threshold) option.selected = true;
    thresholdSelect.appendChild(option);
  });

  const removeBtn = document.createElement("button");
  removeBtn.type = "button";
  removeBtn.className =
    "remove-btn text-gray-400 hover:text-red-500 focus:outline-none transition-colors duration-150";
  removeBtn.innerHTML = '<i class="fas fa-trash-alt"></i>';
  removeBtn.title = "删除此设置";
  // Event listener for removeBtn is now handled by event delegation in DOMContentLoaded

  settingItem.appendChild(categorySelect);
  settingItem.appendChild(thresholdSelect);
  settingItem.appendChild(removeBtn);

  container.appendChild(settingItem);
}

// --- Model Helper Functions ---
async function fetchModels() {
  if (cachedModelsList) {
    return cachedModelsList;
  }
  try {
    showNotification("正在从 /api/config/ui/models 加载模型列表...", "info");
    const response = await fetch("/api/config/ui/models");
    if (!response.ok) {
      const errorData = await response.text();
      throw new Error(`HTTP error ${response.status}: ${errorData}`);
    }
    const responseData = await response.json(); // Changed variable name to responseData
    // The backend returns an object like: { object: "list", data: [{id: "m1"}, {id: "m2"}], success: true }
    if (
      responseData &&
      responseData.success &&
      Array.isArray(responseData.data)
    ) {
      cachedModelsList = responseData.data; // Use responseData.data
      showNotification("模型列表加载成功", "success");
      return cachedModelsList;
    } else {
      console.error("Invalid model list format received:", responseData);
      throw new Error("模型列表格式无效或请求未成功");
    }
  } catch (error) {
    console.error("加载模型列表失败:", error);
    showNotification(`加载模型列表失败: ${error.message}`, "error");
    cachedModelsList = []; // Avoid repeated fetches on error for this session, or set to null to retry
    return [];
  }
}

function renderModelsInModal() {
  if (!modelHelperListContainer) return;
  if (!cachedModelsList) {
    modelHelperListContainer.innerHTML =
      '<p class="text-gray-400 text-sm italic">模型列表尚未加载。</p>';
    return;
  }

  const searchTerm = modelHelperSearchInput.value.toLowerCase();
  const filteredModels = cachedModelsList.filter((model) =>
    model.id.toLowerCase().includes(searchTerm)
  );

  modelHelperListContainer.innerHTML = ""; // Clear previous items

  if (filteredModels.length === 0) {
    modelHelperListContainer.innerHTML =
      '<p class="text-gray-400 text-sm italic">未找到匹配的模型。</p>';
    return;
  }

  filteredModels.forEach((model) => {
    const modelItemElement = document.createElement("button");
    modelItemElement.type = "button";
    modelItemElement.textContent = model.id;
    modelItemElement.className =
      "block w-full text-left px-4 py-2 rounded-md hover:bg-blue-100 focus:bg-blue-100 focus:outline-none transition-colors text-gray-700 hover:text-gray-800";
    // Add any other classes for styling, e.g., from existing modals or array items

    modelItemElement.addEventListener("click", () =>
      handleModelSelection(model.id)
    );
    modelHelperListContainer.appendChild(modelItemElement);
  });
}

async function openModelHelperModal() {
  if (!currentModelHelperTarget) {
    console.error("Model helper target not set.");
    showNotification("无法打开模型助手：目标未设置", "error");
    return;
  }

  await fetchModels(); // Ensure models are loaded
  renderModelsInModal(); // Render them (handles empty/error cases internally)

  if (modelHelperTitleElement) {
    if (
      currentModelHelperTarget.type === "input" &&
      currentModelHelperTarget.target
    ) {
      const label = document.querySelector(
        `label[for="${currentModelHelperTarget.target.id}"]`
      );
      modelHelperTitleElement.textContent = label
        ? `为 "${label.textContent.trim()}" 选择模型`
        : "选择模型";
    } else if (currentModelHelperTarget.type === "array") {
      modelHelperTitleElement.textContent = `为 ${currentModelHelperTarget.targetKey} 添加模型`;
    } else {
      modelHelperTitleElement.textContent = "选择模型";
    }
  }
  if (modelHelperSearchInput) modelHelperSearchInput.value = ""; // Clear search on open
  if (modelHelperModal) openModal(modelHelperModal);
}

function handleModelSelection(selectedModelId) {
  if (!currentModelHelperTarget) return;

  if (
    currentModelHelperTarget.type === "input" &&
    currentModelHelperTarget.target
  ) {
    const inputElement = currentModelHelperTarget.target;
    inputElement.value = selectedModelId;
    // If the input is a sensitive field, dispatch focusout to trigger masking behavior if needed
    if (inputElement.classList.contains(SENSITIVE_INPUT_CLASS)) {
      const event = new Event("focusout", { bubbles: true, cancelable: true });
      inputElement.dispatchEvent(event);
    }
    // Dispatch input event for any other listeners
    inputElement.dispatchEvent(new Event("input", { bubbles: true }));
  } else if (
    currentModelHelperTarget.type === "array" &&
    currentModelHelperTarget.targetKey
  ) {
    const modelId = addArrayItemWithValue(
      currentModelHelperTarget.targetKey,
      selectedModelId
    );
    if (currentModelHelperTarget.targetKey === "THINKING_MODELS" && modelId) {
      // Automatically add corresponding budget map item with default budget 0
      createAndAppendBudgetMapItem(selectedModelId, -1, modelId);
    }
  }

  if (modelHelperModal) closeModal(modelHelperModal);
  currentModelHelperTarget = null; // Reset target
}

// -- End Model Helper Functions --


// -- Proxy Check Functions --

/**
 * [最终对齐版] 检测单个代理是否可用
 * 严格遵循 apiFetch 返回原始 Response 对象的合同
 * @param {string} proxy - 代理地址
 * @param {HTMLElement} buttonElement - 触发检测的按钮元素
 */
async function checkSingleProxy(proxy, buttonElement) {
  const statusIcon = buttonElement.parentElement.querySelector('.proxy-status-icon');
  const originalButtonContent = buttonElement.innerHTML;
  
  try {
    // 1. 进入“检测中”状态
    buttonElement.innerHTML = `<i class="fa fa-spinner fa-spin"></i>`;
    buttonElement.disabled = true;
    if (statusIcon) {
        statusIcon.className = "proxy-status-icon px-2 py-2 text-blue-500";
        statusIcon.innerHTML = `<i class="fa fa-spinner fa-spin" title="检测中..."></i>`;
        statusIcon.setAttribute("data-status", "checking");
    }
    
    // 2. `apiFetch` 返回原始的 Response 对象
    const response = await apiFetch('/admin/proxies/check', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ proxy: proxy }),
      noCache: true
    });
    // 3. 动调用 .json() 来解析响应体
    const responseData = await response.json();
    // 4. 从解析后的对象中提取 .data 字段
    const result = responseData.data;
    // =======================================================================
    // 5. 最终验证
    if (!result || typeof result.is_available === 'undefined') {
        throw new Error("API响应的数据结构不符合预期，缺少'data'字段或'is_available'属性。");
    }
    // 6. 更新UI和通知
    updateProxyStatus(statusIcon, result);
    if (result.is_available) {
      showNotification(`代理可用 (${result.response_time.toFixed(3)}s)`, "success");
    } else {
      showNotification(`代理不可用: ${result.error_message}`, "error");
    }
    
  } catch (error) {
    console.error('代理检测失败:', error);
    if (statusIcon) {
      statusIcon.className = "proxy-status-icon px-2 py-2 text-red-500";
      statusIcon.innerHTML = `<i class="fa fa-times-circle" title="检测失败: ${error.message}"></i>`;
      statusIcon.setAttribute("data-status", "error");
    }
    const errorMessage = error.message || "未知错误";
    showNotification(`检测失败: ${errorMessage}`, "error");
  } finally {
    // 7. 恢复按钮状态
    buttonElement.innerHTML = originalButtonContent;
    buttonElement.disabled = false;
  }
}

/**
 * 更新代理状态图标
 * @param {HTMLElement} statusIcon - 状态图标元素
 * @param {Object} result - 检测结果
 */
function updateProxyStatus(statusIcon, result) {
  if (!statusIcon) return;
  
  if (result.is_available) {
    statusIcon.className = "proxy-status-icon px-2 py-2 text-green-500";
    statusIcon.innerHTML = `<i class="fas fa-check-circle" title="可用 (${result.response_time}s)"></i>`;
    statusIcon.setAttribute("data-status", "available");
  } else {
    statusIcon.className = "proxy-status-icon px-2 py-2 text-red-500";
    statusIcon.innerHTML = `<i class="fas fa-times-circle" title="不可用: ${result.error_message}"></i>`;
    statusIcon.setAttribute("data-status", "unavailable");
  }
}

/**
 * 检测所有代理
 */
async function checkAllProxies() {
  const proxyContainer = document.getElementById("PROXIES_container");
  if (!proxyContainer) return;
  
  const proxyInputs = proxyContainer.querySelectorAll('.array-input');
  const proxies = Array.from(proxyInputs)
    .map(input => input.value.trim())
    .filter(proxy => proxy.length > 0);
  
  if (proxies.length === 0) {
    showNotification("没有代理需要检测", "warning");
    return;
  }
  
  // 打开检测结果模态框
  const proxyCheckModal = document.getElementById("proxyCheckModal");
  if (proxyCheckModal) {
    openModal(proxyCheckModal);
    
    // 显示进度
    const progressContainer = document.getElementById("proxyCheckProgress");
    const summaryContainer = document.getElementById("proxyCheckSummary");
    const resultsContainer = document.getElementById("proxyCheckResults");
    
    if (progressContainer) progressContainer.classList.remove("hidden");
    if (summaryContainer) summaryContainer.classList.add("hidden");
    if (resultsContainer) resultsContainer.innerHTML = "";
    
    // 更新总数
    const totalCountElement = document.getElementById("totalCount");
    if (totalCountElement) totalCountElement.textContent = proxies.length;
    
    try {
      const response = await apiFetch('/admin/proxies/check-all', {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
        },
        body: JSON.stringify({
          proxies: proxies,
          noCache: true ,
          max_concurrent: 5
        })
      });
      
      if (!response.ok) {
        throw new Error(`批量检测请求失败: ${response.status}`);
      }
      
      const responseData = await response.json();
      const results = responseData.data; // 直接使用返回的data字段作为结果数组
      displayProxyCheckResults(results);
      updateProxyStatusInList(results);
      
    } catch (error) {
      console.error('批量代理检测失败:', error);
      showNotification(`批量检测失败: ${error.message}`, "error");
      if (resultsContainer) {
        resultsContainer.innerHTML = `<div class="text-red-500 text-center py-4">检测失败: ${error.message}</div>`;
      }
    } finally {
      // 隐藏进度
      if (progressContainer) progressContainer.classList.add("hidden");
    }
  }
}

/**
 * 显示代理检测结果
 * @param {Array} results - 检测结果数组
 */
function displayProxyCheckResults(results) {
  const summaryContainer = document.getElementById("proxyCheckSummary");
  const resultsContainer = document.getElementById("proxyCheckResults");
  const availableCountElement = document.getElementById("availableCount");
  const unavailableCountElement = document.getElementById("unavailableCount");
  const retryButton = document.getElementById("retryFailedProxiesBtn");
  
  if (!resultsContainer) return;
  
  // 统计结果
  const availableCount = results.filter(r => r.is_available).length;
  const unavailableCount = results.length - availableCount;
  
  // 更新概览
  if (availableCountElement) availableCountElement.textContent = availableCount;
  if (unavailableCountElement) unavailableCountElement.textContent = unavailableCount;
  if (summaryContainer) summaryContainer.classList.remove("hidden");
  
  // 显示重试按钮（如果有失败的代理）
  if (retryButton) {
    if (unavailableCount > 0) {
      retryButton.classList.remove("hidden");
    } else {
      retryButton.classList.add("hidden");
    }
  }
  
  // 清空并填充结果
  resultsContainer.innerHTML = "";
  
  results.forEach(result => {
    const resultItem = document.createElement("div");
    resultItem.className = `flex items-center justify-between p-3 border rounded-lg ${
      result.is_available ? 'border-green-200 bg-green-50' : 'border-red-200 bg-red-50'
    }`;
    
    const statusIcon = result.is_available ? 
      '<i class="fas fa-check-circle text-green-500"></i>' : 
      '<i class="fas fa-times-circle text-red-500"></i>';
    
    const responseTimeText = result.response_time ? 
      ` (${result.response_time}s)` : '';
    
    const errorText = result.error_message ? 
      `<span class="text-red-600 text-sm ml-2">${result.error_message}</span>` : '';
    
    resultItem.innerHTML = `
      <div class="flex items-center gap-3">
        ${statusIcon}
        <span class="font-mono text-sm">${result.proxy}</span>
        ${responseTimeText}
      </div>
      <div class="flex items-center">
        <span class="text-sm ${result.is_available ? 'text-green-700' : 'text-red-700'}">
          ${result.is_available ? '可用' : '不可用'}
        </span>
        ${errorText}
      </div>
    `;
    
    resultsContainer.appendChild(resultItem);
  });
}

/**
 * 根据检测结果更新代理列表中的状态图标
 * @param {Array} results - 检测结果数组
 */
function updateProxyStatusInList(results) {
  const proxyContainer = document.getElementById("PROXIES_container");
  if (!proxyContainer) return;
  
  results.forEach(result => {
    const proxyInputs = proxyContainer.querySelectorAll('.array-input');
    proxyInputs.forEach(input => {
      if (input.value.trim() === result.proxy) {
        const statusIcon = input.parentElement.querySelector('.proxy-status-icon');
        updateProxyStatus(statusIcon, result);
      }
    });
  });
}

// -- End Proxy Check Functions --
