import type { SystemConfigDocLink } from '../types/systemConfig';

export interface SettingsHelpContent {
  title: string;
  summary?: string;
  usage?: string;
  valueNotes?: string[];
  impact?: string[];
  notes?: string[];
  docs?: SystemConfigDocLink[];
}

type SettingsHelpMap = Record<string, SettingsHelpContent>;

const settingsHelpZhCN: SettingsHelpMap = {
  'settings.base.STOCK_LIST': {
    title: '自选股列表',
    summary: '配置需要分析的股票代码列表，是手动分析、定时任务和通知报告的基础输入。',
    usage: '多个股票代码使用英文逗号分隔。A 股可直接填写 6 位代码，港股可使用 hk 前缀，美股可填写 ticker。',
    valueNotes: [
      '定时模式每次触发前会重新读取当前保存的 STOCK_LIST。',
      '如果命令行临时传入 --stocks，只影响本次手动运行，不会锁定后续计划任务。',
      '邮件分组里的 STOCK_GROUP_N 应写成 STOCK_LIST 的子集，只影响邮件收件人，不改变分析范围。',
    ],
    impact: [
      '影响主分析任务、市场报告中的个股范围、通知推送内容和历史报告记录。',
    ],
    notes: [
      '股票代码之间不要使用中文逗号。',
      '修改后保存配置即可供后续任务读取。',
    ],
  },
  'settings.ai_model.LITELLM_MODEL': {
    title: '主模型',
    summary: '指定普通分析流程默认使用的 LLM 模型。',
    usage: '推荐使用 provider/model 格式，例如 deepseek/deepseek-v4-flash、gemini/gemini-3.1-pro-preview 或 ollama/qwen3:8b。',
    valueNotes: [
      '系统配置优先级为 LITELLM_CONFIG > LLM_CHANNELS > legacy provider keys。',
      '如果留空，系统会尝试根据已配置的 API Key 或渠道声明自动推断。',
      'Agent 可通过 AGENT_LITELLM_MODEL 单独指定模型；留空时继承主模型。',
    ],
    impact: [
      '影响普通个股分析、大盘复盘、报告生成，以及未单独覆盖模型的 Agent 调用。',
    ],
    notes: [
      '无 provider 前缀时，LiteLLM 可能无法判断应该使用哪组 API Key。',
      'Ollama 本地模型应配合 OLLAMA_API_BASE 或 Ollama 渠道使用，不要误用 OPENAI_BASE_URL。',
    ],
  },
  'settings.ai_model.LLM_CHANNELS': {
    title: 'LLM 渠道列表',
    summary: '声明多个模型渠道，用于多 provider、多 Key、备用模型和可视化渠道管理。',
    usage: '填写逗号分隔的渠道名，例如 deepseek,aihubmix；每个渠道再配置 LLM_<NAME>_BASE_URL、LLM_<NAME>_API_KEY(S)、LLM_<NAME>_MODELS 等字段。',
    valueNotes: [
      '启用渠道模式后，同层运行时优先读取渠道配置。',
      '在 Docker 或 GitHub Actions 中显式注入的环境变量会覆盖 Web 设置页写入的 .env。',
      '渠道编辑器保存时只更新本次提交的 key，不会静默迁移整个旧配置。',
    ],
    impact: [
      '影响主模型、Agent 模型、fallback 模型和 Vision 模型的可选来源。',
    ],
    notes: [
      '不要把极简 legacy key 和 Channels 混用后期待两边同时生效。',
      '自定义渠道名在 GitHub Actions 中通常还需要 workflow 显式映射对应环境变量。',
    ],
  },
  'settings.ai_model.AGENT_LITELLM_MODEL': {
    title: 'Agent 主模型',
    summary: '为问股、策略 Agent 等 Agent 链路单独指定模型。',
    usage: '使用 provider/model 格式。留空时继承普通分析主模型；裸模型名会按兼容逻辑归一到 openai/<model>。',
    valueNotes: [
      '适合给 Agent 使用推理能力更强或上下文更长的模型。',
      '该字段只影响 Agent 链路，不会改变普通个股分析的主模型。',
    ],
    impact: ['影响 Agent 问答、策略选择和相关工具调用的模型选择。'],
    notes: ['请确认该模型存在于已启用渠道、YAML 路由或 legacy provider key 可达范围内。'],
  },
  'settings.ai_model.LITELLM_FALLBACK_MODELS': {
    title: '备用模型',
    summary: '主模型失败时按顺序尝试的备用模型列表。',
    usage: '多个模型使用英文逗号分隔，推荐仍使用 provider/model 格式。',
    valueNotes: [
      '备用模型只在主模型失败、超时或响应不可用时使用。',
      '渠道编辑器保存时会清理已不可达的托管 provider 模型引用。',
    ],
    impact: ['提升 LLM 调用失败时的可用性，但可能增加跨 provider 成本和响应差异。'],
    notes: ['不要把主模型重复加入备用模型列表。'],
  },
  'settings.ai_model.LITELLM_CONFIG': {
    title: '高级模型路由 YAML',
    summary: '指定 LiteLLM 原生 YAML 路由文件，适合复杂路由、限流和专家配置。',
    usage: '填写项目可访问的 YAML 文件路径，例如 ./litellm_config.yaml。',
    valueNotes: [
      '可解析且包含 model_list 时，优先级高于 LLM_CHANNELS 和 legacy provider keys。',
      'Web 渠道编辑器不会修改 YAML 文件本身。',
    ],
    impact: ['影响模型选择、路由、fallback 和可用模型声明。'],
    notes: ['如果 YAML 配置失效，系统会回退到渠道或 legacy 配置路径。'],
  },
  'settings.ai_model.LLM_TEMPERATURE': {
    title: 'Temperature',
    summary: '控制模型输出随机性。',
    usage: '取值范围 0.0 到 2.0；越低越稳定，越高越发散。',
    valueNotes: [
      '0 更适合稳定结构化输出。',
      '0.7 是通用默认值，兼顾稳定性和表达弹性。',
    ],
    impact: ['影响分析文本、报告语气和结构化输出稳定性。'],
    notes: ['不同 provider 对 temperature 的实际支持范围可能不同。'],
  },
  'settings.ai_model.provider_keys': {
    title: '模型服务 API Key',
    summary: '配置模型服务商或聚合网关的访问密钥。',
    usage: '在对应服务商控制台创建 API Key 后填入；如需轮换或负载均衡，对应的多 Key 变体字段使用英文逗号分隔。',
    valueNotes: [
      '密钥字段会在 Web 设置页以密码控件展示，保存后通常只显示掩码。',
      '渠道模式优先读取 LLM_<NAME>_API_KEY(S)，legacy key 主要用于兼容旧配置。',
    ],
    impact: ['影响对应 provider 的模型调用、连接测试和可用模型发现。'],
    notes: ['不要在 issue、日志或截图里暴露真实 Key。'],
  },
  'settings.ai_model.anspire_llm': {
    title: 'Anspire LLM 网关',
    summary: '使用 Anspire API Key 作为 OpenAI-compatible 模型网关的兼容入口。',
    usage: 'ANSPIRE_LLM_ENABLED 控制是否启用该兼容路径；ANSPIRE_LLM_BASE_URL 指定网关地址；ANSPIRE_LLM_MODEL 指定未显式选择主模型时的默认模型。',
    valueNotes: [
      '该路径主要用于兼容未配置 LLM_CHANNELS 或 LITELLM_MODEL 的简化场景。',
      '如果已配置 LITELLM_CONFIG、LLM_CHANNELS 或明确的 LITELLM_MODEL，运行时会按既有优先级选择模型来源。',
    ],
    impact: ['影响 Anspire API Key 参与 LLM 调用时的默认模型和网关地址。'],
    notes: ['不要把 Base URL 改成其他 provider 的地址后继续复用 Anspire Key。'],
  },
  'settings.ai_model.legacy_provider_params': {
    title: 'Legacy Provider 参数',
    summary: '为旧版 provider 专用配置路径设置模型名、温度或 token 上限。',
    usage: '这些字段用于兼容历史配置；新配置优先使用 LITELLM_MODEL、LITELLM_FALLBACK_MODELS、VISION_MODEL、LLM_TEMPERATURE 或 LLM Channels。',
    valueNotes: [
      '启用 LLM Channels 后，相关 legacy 字段通常会从通用表单隐藏。',
      '字段只影响对应 provider 的 legacy 路径，不会自动迁移到渠道配置。',
    ],
    impact: ['影响未使用渠道/YAML 路由时的 legacy provider 模型选择和采样参数。'],
    notes: ['如果同时维护 legacy 字段和 Channels，请以设置页实际显示的运行时模型来源为准。'],
  },
  'settings.ai_model.OPENAI_BASE_URL': {
    title: 'OpenAI 兼容 Base URL',
    summary: '指定 OpenAI-compatible 服务的接口根地址。',
    usage: '通常以 /v1 结尾；官方接口、中转网关和本地兼容服务的地址各不相同。',
    valueNotes: [
      'Base URL 必须与 API Key 所属服务匹配。',
      'Gemini、Anthropic 等官方 SDK 路径通常不需要填 OPENAI_BASE_URL。',
    ],
    impact: ['影响 OpenAI-compatible legacy 配置路径下的模型请求。'],
    notes: ['渠道模式下优先维护各渠道自己的 LLM_<NAME>_BASE_URL。'],
  },
  'settings.data_source.TUSHARE_TOKEN': {
    title: 'Tushare Token',
    summary: '用于访问 Tushare Pro 数据接口。',
    usage: '在 Tushare 账户中获取 token 后填入。',
    valueNotes: ['不同 Tushare 权限会影响可用接口和数据完整度。'],
    impact: ['影响部分 A 股基础数据、股票列表和相关增强数据获取。'],
    notes: ['不要把 token 提交到仓库或公开日志。'],
  },
  'settings.data_source.TICKFLOW_API_KEY': {
    title: 'TickFlow API Key',
    summary: '用于增强大盘复盘中的指数、市场统计等数据。',
    usage: '在 TickFlow 获取 API Key 后填入；未配置时系统会继续使用其他可用数据源和降级路径。',
    valueNotes: ['该 Key 是可选增强项，不是运行主分析流程的必填项。'],
    impact: ['影响大盘复盘和市场统计增强数据的覆盖度。'],
    notes: ['不要在 issue、日志或截图中暴露真实 Key。'],
  },
  'settings.data_source.REALTIME_SOURCE_PRIORITY': {
    title: '实时行情源优先级',
    summary: '配置多个实时行情源的尝试顺序。',
    usage: '优先级使用英文逗号分隔；系统会按顺序尝试可用数据源。',
    valueNotes: ['前面的数据源优先使用，失败后再降级到后续数据源。'],
    impact: ['影响现价、盘中分析和依赖实时价格的报告字段。'],
    notes: ['单一数据源失败应降级到后续数据源，不应拖垮主流程。'],
  },
  'settings.data_source.realtime_quotes': {
    title: '实时行情配置',
    summary: '控制实时行情和盘中技术指标是否启用。',
    usage: '开关字段使用 true/false；行情源顺序由 REALTIME_SOURCE_PRIORITY 单独配置。',
    valueNotes: [
      '关闭实时行情后，分析会更依赖历史收盘价。',
      '实时技术指标会把盘中价格纳入均线和趋势判断。',
    ],
    impact: ['影响现价、技术指标、盘中分析和部分报告字段。'],
    notes: ['单一数据源失败应降级到后续数据源，不应拖垮主流程。'],
  },
  'settings.data_source.search_api_keys': {
    title: '搜索服务 API Key',
    summary: '配置新闻与搜索增强所需的第三方搜索服务密钥。',
    usage: '多 Key 字段使用英文逗号分隔；系统会按现有搜索优先级和可用性选择服务。',
    valueNotes: ['搜索结果用于补充新闻、公告和市场信息上下文。'],
    impact: ['影响新闻检索覆盖度、时效性和 Agent/报告中的外部信息。'],
    notes: ['搜索服务可能有额度、限流和地区可用性差异。'],
  },
  'settings.data_source.SEARXNG_BASE_URLS': {
    title: 'SearXNG 实例地址',
    summary: '配置自建或可信 SearXNG 搜索实例。',
    usage: '多个实例使用英文逗号分隔；自建实例需要启用 JSON 输出格式。',
    valueNotes: ['禁用公开实例自动发现后，只会使用这里配置的实例。'],
    impact: ['影响无商业搜索 Key 时的新闻和网页搜索兜底能力。'],
    notes: ['公共实例稳定性不可控，生产环境建议使用自建或可信实例。'],
  },
  'settings.data_source.ENABLE_CHIP_DISTRIBUTION': {
    title: '筹码分布分析',
    summary: '控制是否启用筹码分布相关分析。',
    usage: '云部署或数据源不稳定时可设为 false。',
    valueNotes: ['关闭后会减少相关数据请求和失败噪音。'],
    impact: ['影响报告中的筹码分布、成本区间等相关判断。'],
    notes: ['该能力依赖外部数据源稳定性。'],
  },
  'settings.data_source.BIAS_THRESHOLD': {
    title: '乖离率阈值',
    summary: '设置股价偏离 MA5 的风险提示阈值。',
    usage: '填写百分比数值；当价格偏离 MA5 超过阈值时，报告会提示避免追高或注意回归风险。',
    valueNotes: ['强趋势股票可能按运行时规则适当放宽阈值。'],
    impact: ['影响技术分析中追高风险、均线偏离和操作建议的提示强度。'],
    notes: ['阈值过低会增加风险提示噪声，过高可能弱化追高提醒。'],
  },
  'settings.data_source.pytdx': {
    title: 'Pytdx 通达信服务器',
    summary: '配置通达信行情服务器地址，覆盖内置默认服务器。',
    usage: '可分别填写 PYTDX_HOST/PYTDX_PORT，也可使用 PYTDX_SERVERS 填写多个 ip:port；PYTDX_SERVERS 优先级更高。',
    valueNotes: ['多个服务器使用英文逗号分隔，系统会按既有数据源逻辑尝试连接。'],
    impact: ['影响使用 Pytdx 数据源时的行情连接目标和可用性。'],
    notes: ['服务器不可达时应依赖数据源 fallback，不建议只配置单个不稳定地址。'],
  },
  'settings.data_source.news_window': {
    title: '新闻时间窗口',
    summary: '控制纳入分析上下文的新闻时效范围。',
    usage: 'NEWS_MAX_AGE_DAYS 设最大天数，NEWS_STRATEGY_PROFILE 设窗口策略。',
    valueNotes: ['实际窗口会受 profile 与最大天数共同约束。'],
    impact: ['影响新闻上下文数量、时效性和报告长度。'],
    notes: ['窗口过长可能引入陈旧信息，过短可能遗漏慢发酵事件。'],
  },
  'settings.notification.FEISHU_WEBHOOK_URL': {
    title: '飞书群机器人 Webhook',
    summary: '配置飞书自定义群机器人，用于把分析报告推送到指定飞书群。',
    usage: '在飞书群中添加自定义机器人后，复制 open-apis/bot/v2/hook 开头的 Webhook URL 到这里。',
    valueNotes: [
      '如果机器人开启“签名校验”，还需要填写 FEISHU_WEBHOOK_SECRET。',
      '如果机器人开启“关键词”，还需要填写 FEISHU_WEBHOOK_KEYWORD，系统会自动补到消息前。',
      'FEISHU_APP_ID / FEISHU_APP_SECRET 用于飞书应用、云文档或 Stream Bot，不会直接启用群 Webhook 推送。',
    ],
    impact: [
      '影响飞书通知渠道；失败时不应拖垮主分析流程，只影响该渠道送达。',
    ],
    notes: [
      '不要把 FEISHU_APP_SECRET 当作 FEISHU_WEBHOOK_SECRET 使用。',
      '如果飞书侧配置 IP 白名单，需要确认当前运行环境出口 IP 已加入白名单。',
    ],
  },
  'settings.notification.webhooks': {
    title: '企业微信 Webhook',
    summary: '配置企业微信群机器人 Webhook，用于把分析报告推送到指定群。',
    usage: '在企业微信群中创建机器人后，复制 qyapi.weixin.qq.com/cgi-bin/webhook/send 开头的 Webhook URL。',
    valueNotes: [
      'Webhook URL 通常包含敏感 token，应按密钥处理。',
      '不同平台对消息长度、格式和频率限制不同。',
    ],
    impact: ['影响对应 Webhook 通知渠道的报告送达。'],
    notes: ['单个通知渠道失败不应阻断主分析流程。'],
  },
  'settings.notification.CUSTOM_WEBHOOK_URLS': {
    title: '自定义 Webhook',
    summary: '向任意支持 POST JSON 的服务推送报告。',
    usage: '多个 URL 使用英文逗号分隔；如需自定义 body，可配置 CUSTOM_WEBHOOK_BODY_TEMPLATE。',
    valueNotes: [
      '模板必须渲染为 JSON object。',
      '推荐使用 $content_json、$title_json 避免换行和引号破坏 JSON。',
    ],
    impact: ['影响 AstrBot、NapCat、自建服务等自定义推送。'],
    notes: ['先用一个 Webhook 验证成功，再扩展到多个目标。'],
  },
  'settings.notification.WEBHOOK_VERIFY_SSL': {
    title: 'Webhook SSL 校验',
    summary: '控制发送 HTTPS Webhook 时是否校验证书。',
    usage: '默认保持 true；只有可信内网自签证书场景才考虑 false。',
    valueNotes: ['关闭校验会降低中间人攻击防护。'],
    impact: ['影响所有自定义 Webhook HTTPS 请求的 TLS 校验行为。'],
    notes: ['公网环境不要关闭 SSL 校验。'],
  },
  'settings.notification.telegram': {
    title: 'Telegram 推送',
    summary: '通过 Telegram Bot 向个人、群组或 Topic 推送报告。',
    usage: '使用 @BotFather 创建 Bot，填写 Bot Token 和目标 Chat ID；群组 Topic 可额外填写 Thread ID。',
    valueNotes: ['Bot 需要被加入目标群组并具备发言权限。'],
    impact: ['影响 Telegram 通知渠道。'],
    notes: ['群组 Chat ID 通常是负数或 -100 开头。'],
  },
  'settings.notification.email': {
    title: '邮件通知',
    summary: '通过 SMTP 邮箱发送分析报告。',
    usage: '填写发件邮箱、SMTP 授权码和收件人列表；多个收件人使用英文逗号分隔。',
    valueNotes: [
      'EMAIL_PASSWORD 通常是邮箱授权码，不是网页登录密码。',
      '可用 STOCK_GROUP_N / EMAIL_GROUP_N 配置分组收件人。',
    ],
    impact: ['影响邮件报告发送、分组收件和大盘复盘邮件送达。'],
    notes: ['不同邮箱服务商需要先开启 SMTP 服务。'],
  },
  'settings.notification.chat_bots': {
    title: '聊天平台 Bot',
    summary: '配置 Discord、Slack、Pushover、ServerChan 等聊天或推送平台。',
    usage: '按平台选择 Webhook 或 Bot Token 模式；Bot 模式通常还需要频道 ID。',
    valueNotes: ['同一平台同时配置 Bot 与 Webhook 时，代码可能按既定优先级选择其中一种。'],
    impact: ['影响对应聊天平台通知渠道。'],
    notes: ['Bot Token、Webhook URL、SendKey 都应按密钥处理。'],
  },
  'settings.notification.report_output': {
    title: '报告输出设置',
    summary: '控制通知报告的详细程度、语言和模板输出。',
    usage: 'REPORT_TYPE 可选 simple/full/brief，REPORT_LANGUAGE 可选 zh/en。',
    valueNotes: ['报告语言影响默认模板和通知文案，不等同于前端界面语言。'],
    impact: ['影响通知正文长度、语言和阅读体验。'],
    notes: ['full 报告可能更长，部分平台可能触发分段发送。'],
  },
  'settings.system.WEBUI_HOST': {
    title: 'WebUI 监听地址',
    summary: '控制 WebUI 服务绑定在哪个网络地址上。',
    usage: '本机访问通常使用 127.0.0.1；云服务器、Docker 或需要外部访问时通常使用 0.0.0.0。',
    valueNotes: [
      '当前启动逻辑会在 host 为默认 0.0.0.0 时读取 WEBUI_HOST；即使显式传入 --host 0.0.0.0，也可能被 .env 中的 WEBUI_HOST 覆盖。',
      '在设置页保存后，只会写入 .env 并重载运行时配置对象，不会让当前 WebUI/API 进程重新绑定监听地址。',
      'Docker Compose 中通常会在容器内使用 0.0.0.0，宿主机访问还取决于端口映射。',
    ],
    impact: [
      '影响重启后浏览器能否从本机、局域网或公网访问 WebUI。',
    ],
    notes: [
      '修改 WEBUI_HOST 后需要重启当前进程、Docker 容器或服务管理器才会生效。',
      '直连公网时建议同时启用 ADMIN_AUTH_ENABLED。',
      '如果部署在反向代理后面，登录限流与真实 IP 识别还需要评估 TRUST_X_FORWARDED_FOR。',
    ],
  },
  'settings.system.WEBUI_PORT': {
    title: 'WebUI 端口',
    summary: '控制 WebUI 服务监听的端口。',
    usage: '本地默认 8000；如端口冲突可改为其他 1-65535 范围内端口。',
    valueNotes: [
      'Docker 或云服务器访问还取决于宿主机端口映射和安全组。',
      '设置页保存只会写入 .env，不会让当前 WebUI/API 进程重新绑定端口。',
    ],
    impact: ['影响重启后浏览器访问 WebUI 的 URL 端口。'],
    notes: ['修改 WEBUI_PORT 后需要重启当前进程、Docker 容器或服务管理器才会生效。'],
  },
  'settings.system.ADMIN_AUTH_ENABLED': {
    title: 'Web 登录保护',
    summary: '启用 WebUI 管理员密码保护。',
    usage: '请通过 WebUI 的认证设置入口启用或关闭；忘记密码可运行 python -m src.auth reset_password。',
    valueNotes: ['直连公网、局域网共享或反向代理部署时建议启用。', '该字段在通用配置页仅作说明展示，避免绕过认证设置流程。'],
    impact: ['影响 WebUI 登录、设置页访问和管理操作保护。'],
    notes: ['启用前请确认部署环境可以持久化认证数据；手动改 .env 后需要重启进程或使用认证设置流程刷新状态。'],
  },
  'settings.system.TRUST_X_FORWARDED_FOR': {
    title: '信任 X-Forwarded-For',
    summary: '在可信反向代理后使用 X-Forwarded-For 识别真实客户端 IP。',
    usage: '仅单层可信反向代理场景设为 true；直连公网保持 false。',
    valueNotes: ['多级代理或 CDN 场景下限流 key 可能退化为边缘代理 IP。'],
    impact: ['影响登录限流、审计和真实 IP 识别。'],
    notes: ['不可信代理链上开启会允许客户端伪造来源 IP。'],
  },
  'settings.system.schedule': {
    title: '定时任务',
    summary: '控制是否启用每日定时分析以及启动时是否立即执行一次。',
    usage: 'SCHEDULE_TIME 使用 HH:MM 24 小时格式；SCHEDULE_ENABLED 和 SCHEDULE_RUN_IMMEDIATELY 控制定时模式启动行为。',
    valueNotes: [
      '已运行的 schedule 模式会在下一轮调度检查中读取新的 SCHEDULE_TIME 并重建 daily job。',
      'SCHEDULE_ENABLED 和 SCHEDULE_RUN_IMMEDIATELY 属于启动期行为，保存后不会启动、停止或重建当前 scheduler。',
      '定时任务触发时会读取当前保存的 STOCK_LIST。',
    ],
    impact: ['影响 schedule 模式下自动分析频率、启动行为和通知推送时间。'],
    notes: [
      '注意运行环境时区，容器和服务器时区可能与本地不同。',
      '若当前进程未以 schedule 模式启动，保存这些字段不会自动创建调度器。',
    ],
  },
  'settings.system.RUN_IMMEDIATELY': {
    title: '启动后立即运行',
    summary: '控制非定时模式启动时是否立即执行一次分析。',
    usage: '需要只启动服务、不立即分析时设为 false。',
    valueNotes: ['与 SCHEDULE_RUN_IMMEDIATELY 分别控制非定时和定时模式。'],
    impact: ['影响服务启动后的首次分析行为。'],
    notes: [
      '这是非 schedule 模式的启动期单次运行配置，保存后不会让当前 WebUI/API 进程立即触发分析。',
      'CLI 参数和运行模式也会影响最终行为；修改后需重启非 schedule 进程后生效。',
    ],
  },
  'settings.system.TRADING_DAY_CHECK_ENABLED': {
    title: '交易日检查',
    summary: '控制非交易日是否跳过分析。',
    usage: '默认 true；需要强制运行可设为 false 或使用 --force-run。',
    valueNotes: ['会结合市场日历判断 A 股、港股、美股等市场是否开市。'],
    impact: ['影响定时任务和手动运行是否在休市日执行。'],
    notes: ['关闭后休市日可能生成缺少实时行情的报告。'],
  },
  'settings.system.HTTP_PROXY': {
    title: '网络代理',
    summary: '为外部 API、模型服务或搜索请求配置代理地址。',
    usage: '填写 http://host:port 形式；HTTPS_PROXY 可用于 HTTPS 请求代理。',
    valueNotes: ['代理是否生效取决于底层库和运行环境变量读取方式。'],
    impact: ['影响数据源、LLM、搜索和通知等外部网络请求。'],
    notes: ['不要把代理地址写成只在本机可见但容器不可达的 127.0.0.1。'],
  },
  'settings.llm_channel.channel_name': {
    title: '渠道名称',
    summary: '渠道名称用于生成 LLM_<NAME>_* 环境变量。',
    usage: '只能使用小写字母、数字和下划线；保存后会写入 LLM_CHANNELS。',
    valueNotes: ['例如 deepseek 会对应 LLM_DEEPSEEK_BASE_URL、LLM_DEEPSEEK_API_KEY(S)、LLM_DEEPSEEK_MODELS。'],
    impact: ['影响渠道环境变量命名、运行时选择和 GitHub Actions 显式映射。'],
    notes: ['修改名称不会自动迁移旧渠道的所有外部环境变量。'],
  },
  'settings.llm_channel.protocol': {
    title: '渠道协议',
    summary: '声明该渠道使用哪类兼容协议。',
    usage: 'OpenAI Compatible 适合大多数中转和兼容服务；官方 Gemini/Anthropic/DeepSeek 可选择对应协议。',
    valueNotes: ['协议会影响模型名前缀归一、连接测试和模型发现方式。'],
    impact: ['影响请求适配器、模型列表解析和运行时模型引用。'],
    notes: ['协议与 Base URL、API Key 所属服务必须匹配。'],
  },
  'settings.llm_channel.base_url': {
    title: 'Base URL',
    summary: '该渠道的接口根地址。',
    usage: 'OpenAI-compatible 服务通常填写以 /v1 结尾的地址；部分官方 SDK 渠道可留空。',
    valueNotes: ['服务商预设只提供参考值，实际可用性取决于账号、地区和 provider 当前接口。'],
    impact: ['影响连接测试、模型发现和所有该渠道的 LLM 请求。'],
    notes: ['不要把不同 provider 的 API Key 和 Base URL 混用。'],
  },
  'settings.llm_channel.api_key': {
    title: 'API Key',
    summary: '该渠道调用模型服务所需的访问密钥。',
    usage: '单个 Key 直接填写；多个 Key 使用英文逗号分隔。',
    valueNotes: ['本地 Ollama 等无需鉴权的服务可留空。'],
    impact: ['影响连接测试、模型发现、运行时调用和 Key 轮换。'],
    notes: ['不要在截图、日志或 issue 中暴露真实 Key。'],
  },
  'settings.llm_channel.models': {
    title: '渠道模型列表',
    summary: '声明该渠道可供运行时选择的模型。',
    usage: '可点击“获取模型”从支持 /models 的渠道拉取，也可手动填写逗号分隔列表。',
    valueNotes: ['保存时运行时主模型、Agent 模型、Vision 模型和 fallback 会引用这里的模型。'],
    impact: ['影响可选择模型、保存前失效模型清理和运行时模型路由。'],
    notes: ['模型是否真正可用仍取决于服务商权限和运行时连接测试。'],
  },
  'settings.llm_channel.capability_checks': {
    title: '运行时能力检测',
    summary: '手动验证当前渠道模型是否支持 JSON、tools、stream 或 vision。',
    usage: '选择能力后点击检测；检测会发起真实 LLM 请求。',
    valueNotes: ['多选检测可能需要 20-40 秒，并可能消耗 provider 额度。'],
    impact: ['仅影响当前页面诊断结果，不会改变保存配置。'],
    notes: ['能力标签是参考，最终以检测结果和实际调用为准。'],
  },
  'settings.llm_channel.temperature': {
    title: 'Temperature',
    summary: '运行时统一采样温度。',
    usage: '滑块范围 0 到 2；低值更稳定，高值更随机。',
    valueNotes: ['保存后写入 LLM_TEMPERATURE。'],
    impact: ['影响普通分析、Agent 和报告生成中的模型输出稳定性。'],
    notes: ['结构化输出不稳定时优先降低 temperature。'],
  },
  'settings.llm_channel.primary_model': {
    title: '主模型',
    summary: '普通分析流程默认使用的运行时模型。',
    usage: '从已启用渠道的模型列表中选择；自动模式使用第一个可用模型。',
    valueNotes: ['保存后写入 LITELLM_MODEL。'],
    impact: ['影响个股分析、大盘复盘和默认报告生成。'],
    notes: ['如果模型不在已启用渠道列表中，保存时可能被清理或要求重新选择。'],
  },
  'settings.llm_channel.agent_primary_model': {
    title: 'Agent 主模型',
    summary: 'Agent 链路专用主模型。',
    usage: '可选择独立模型；自动模式继承普通分析主模型。',
    valueNotes: ['保存后写入 AGENT_LITELLM_MODEL。'],
    impact: ['影响问股、策略 Agent 和相关工具调用。'],
    notes: ['Agent 模型可比普通分析模型更强，但成本和延迟也可能更高。'],
  },
  'settings.llm_channel.fallback_models': {
    title: '备选模型',
    summary: '主模型失败时使用的备用模型集合。',
    usage: '勾选一个或多个模型；主模型不会重复加入备选模型。',
    valueNotes: ['保存后写入 LITELLM_FALLBACK_MODELS。'],
    impact: ['影响 LLM 失败时的降级成功率和跨 provider 行为差异。'],
    notes: ['备用模型应先经过连接测试或实际调用验证。'],
  },
  'settings.llm_channel.vision_model': {
    title: 'Vision 模型',
    summary: '用于截图识别、图像输入或视觉相关能力的模型。',
    usage: '选择支持图像输入的模型；自动模式跟随默认 Vision 逻辑。',
    valueNotes: ['保存后写入 VISION_MODEL。'],
    impact: ['影响图片/截图相关提取和视觉分析能力。'],
    notes: ['DeepSeek 等文本模型不一定支持 vision，请用能力检测确认。'],
  },
  // ------------------------------------------------------------------
  // Agent configuration
  // ------------------------------------------------------------------
  'settings.agent.AGENT_MODE': {
    title: 'Agent 模式',
    summary: '启用 ReAct Agent 进行股票分析，替代普通分析流程。',
    usage: '开启后，系统使用多步推理 Agent 替代单轮 LLM 分析，可调用工具、检索新闻和执行复杂推理链路。',
    valueNotes: [
      '关闭时使用普通单轮 LLM 分析模式。',
      'Agent 模式可配合 AGENT_ARCH 选择 single（经典 ReAct）或 multi（编排器 pipeline）。',
    ],
    impact: ['影响个股分析流程、报告生成质量和 LLM 调用次数。'],
    notes: ['Agent 模式会消耗更多 token 和时间，适合需要深度推理的场景。'],
  },
  'settings.agent.AGENT_MAX_STEPS': {
    title: 'Agent 最大推理步数',
    summary: '控制 Agent 推理链路的最大步数上限。',
    usage: '设为默认值时，每个子 Agent 使用各自预设步数；调高后所有子 Agent 统一提升；调低后会裁剪子 Agent 的预设步数。',
    valueNotes: [
      '步数越高，推理越深入，但耗时和 token 消耗也越大。',
      '部分复杂场景（如多策略编排）可能需要更高步数。',
    ],
    impact: ['影响 Agent 推理深度、耗时和 token 消耗。'],
    notes: ['设为 0 或极低值可能导致推理不完整。'],
  },
  'settings.agent.AGENT_SKILLS': {
    title: 'Agent 策略列表',
    summary: '指定 Agent 使用的策略技能列表。',
    usage: '使用英文逗号分隔策略名；留空使用默认策略（bull_trend）；设为 all 启用全部策略。',
    valueNotes: [
      '设置具体策略（非 all）时，定时任务会自动使用 Agent pipeline。',
      '可用策略取决于 strategies/ 目录中的定义文件。',
    ],
    impact: ['影响 Agent 分析时使用的策略选择和最终信号综合。'],
    notes: ['自定义策略需放在 AGENT_SKILL_DIR 指定的目录中。'],
  },
  'settings.agent.AGENT_SKILL_DIR': {
    title: '策略目录',
    summary: '存放 Agent 策略定义文件的目录。',
    usage: '填写相对于项目根目录的路径；目录内可放置 YAML 或 SKILL.md 格式的策略定义。',
    valueNotes: ['默认 strategies 目录包含内置策略。'],
    impact: ['影响 Agent 可发现的策略列表。'],
    notes: ['修改目录后需要确保新目录中包含有效的策略定义文件。'],
  },
  'settings.agent.AGENT_NL_ROUTING': {
    title: '自然语言路由',
    summary: '允许 bot dispatcher 通过自然语言识别将股票查询路由到 Agent。',
    usage: '开启后，私聊中高置信度的股票相关消息（或群聊 @机器人）会自动路由到 Agent，无需显式命令。',
    valueNotes: ['仅影响 bot 接入场景（飞书、Telegram 等），不影响 Web API。'],
    impact: ['影响 bot 交互体验和 Agent 触发方式。'],
    notes: ['需要同时启用 Agent 模式和对应 bot 渠道。'],
  },
  'settings.agent.AGENT_ARCH': {
    title: 'Agent 架构',
    summary: '选择 Agent 执行架构。',
    usage: 'single 使用经典 ReAct 执行器；multi 使用编排器 pipeline，可分配多个专项子 Agent。',
    valueNotes: [
      'single 适合简单场景，推理链路短。',
      'multi 适合复杂分析，支持技术分析、情报收集、风险评估等专项子 Agent 协作。',
    ],
    impact: ['影响 Agent 分析流程、子 Agent 调度和最终报告结构。'],
    notes: ['选择 multi 后可通过 AGENT_ORCHESTRATOR_MODE 调整 pipeline 模式。'],
  },
  'settings.agent.AGENT_ORCHESTRATOR_MODE': {
    title: '编排器模式',
    summary: '仅在 AGENT_ARCH=multi 时生效，控制 pipeline 包含哪些子 Agent。',
    usage: 'quick：技术→决策；standard：技术→情报→决策；full：技术→情报→风险→决策；specialist：full + 每策略专项 Agent。',
    valueNotes: [
      '模式越完整，分析越深入，但耗时和 token 消耗也越大。',
      'specialist 模式会为每个策略启动独立 Agent。',
    ],
    impact: ['影响多 Agent 分析流程的深度和资源消耗。'],
    notes: ['该字段仅在 AGENT_ARCH=multi 时生效。'],
  },
  'settings.agent.AGENT_ORCHESTRATOR_TIMEOUT_S': {
    title: 'Agent 超时',
    summary: 'Agent 执行的共享超时预算（秒）。',
    usage: 'single 模式下作为整体 ReAct 循环超时；multi 模式下作为协作 pipeline 总超时。设为 0 禁用超时。',
    valueNotes: [
      '超时后 Agent 会返回已完成的部分结果。',
      '分析多只股票或 specialist 模式建议适当调高。',
    ],
    impact: ['影响 Agent 分析的最大等待时间。'],
    notes: ['超时不影响其他股票的分析流程。'],
  },
  'settings.agent.AGENT_RISK_OVERRIDE': {
    title: '风险 Agent 否决权',
    summary: '允许风险 Agent 在检测到关键风险信号时否决买入信号。',
    usage: '开启后，full/specialist 模式中的风险 Agent 可将买入建议降级为观望或卖出。',
    valueNotes: ['仅在 AGENT_ORCHESTRATOR_MODE 包含风险阶段时生效。'],
    impact: ['影响最终投资建议的风险保守程度。'],
    notes: ['关闭后风险 Agent 的意见仅作参考，不会否决决策。'],
  },
  'settings.agent.DEEP_RESEARCH': {
    title: 'Deep Research',
    summary: '控制 Deep Research 的 token 预算和超时。',
    usage: 'AGENT_DEEP_RESEARCH_BUDGET 设定最大 token 预算；AGENT_DEEP_RESEARCH_TIMEOUT 设定超时秒数。',
    valueNotes: [
      '预算覆盖规划、后续研究和最终综合所有阶段。',
      '预算越高，研究越深入，但消耗也越大。',
    ],
    impact: ['影响 Deep Research 功能的深度和耗时。'],
    notes: ['Deep Research 在 Agent 模式下可用。'],
  },
  'settings.agent.AGENT_MEMORY_ENABLED': {
    title: 'Agent 记忆系统',
    summary: '启用记忆与校准系统，跟踪 Agent 预测准确率并调整置信度。',
    usage: '开启后，系统会记录每次预测结果，与后续实际走势对比，用于校准未来分析的置信度。',
    valueNotes: ['记忆数据需要积累一定量后才产生校准效果。'],
    impact: ['影响 Agent 置信度校准和长期分析质量。'],
    notes: ['需要配合回测功能使用效果更佳。'],
  },
  'settings.agent.AGENT_SKILL_AUTOWEIGHT': {
    title: '策略自动权重',
    summary: '根据历史回测表现自动调整策略权重。',
    usage: '开启后，系统按各策略的历史回测准确率加权综合信号。',
    valueNotes: ['依赖回测数据；回测记录不足时可能无法有效加权。'],
    impact: ['影响多策略综合时的信号权重分配。'],
    notes: ['需要先开启回测功能并积累足够的回测数据。'],
  },
  'settings.agent.AGENT_SKILL_ROUTING': {
    title: '策略路由模式',
    summary: '控制策略选择方式。',
    usage: 'auto 模式根据市场环境自动检测并选择相关策略；manual 模式仅使用 AGENT_SKILLS 中手动指定的策略。',
    valueNotes: ['auto 模式会根据市场状态（牛市/熊市/震荡等）动态调整策略选择。'],
    impact: ['影响 Agent 分析时的策略覆盖面。'],
    notes: ['manual 模式下需要确保 AGENT_SKILLS 已正确配置。'],
  },
  'settings.agent.context_compression': {
    title: '问股上下文压缩',
    summary: '控制问股可见对话历史的滚动摘要压缩，默认关闭以保持既有行为。',
    usage: 'AGENT_CONTEXT_COMPRESSION_ENABLED 开启后，仅压缩同一 session_id 下用户可见的 user/assistant 文本历史；profile 控制默认触发阈值和保留轮次。',
    valueNotes: [
      'cost、balanced、long_context_raw_first 分别偏向节省 token、均衡推荐和保留更多原文。',
      'AGENT_CONTEXT_COMPRESSION_TRIGGER_TOKENS 和 AGENT_CONTEXT_PROTECTED_TURNS 留空时跟随当前 profile preset，显式填写时覆盖 preset。',
    ],
    impact: ['降低长问股会话的 token 消耗，但可能让更早的对话细节以摘要形式参与后续回答。'],
    notes: [
      '该功能不处理 provider trace、thinking blocks、tool calls 或 tool results，也不改变同轮工具调用透传。',
      '该配置只影响问股可见历史压缩，不改变 LLM provider、模型、Base URL、保存清理或运行时优先级语义。',
    ],
  },
  'settings.agent.event_monitor': {
    title: '事件监控',
    summary: '在定时模式下启用后台事件监控，定期轮询告警规则。',
    usage: 'AGENT_EVENT_MONITOR_ENABLED 开启后台监控；AGENT_EVENT_MONITOR_INTERVAL_MINUTES 设定轮询间隔（分钟）。',
    valueNotes: [
      '仅在定时（schedule）模式下生效。',
      '轮询间隔过短可能增加 API 调用频率。',
    ],
    impact: ['影响后台告警检测频率和通知推送时机。'],
    notes: ['需要配合告警规则使用。'],
  },
  'settings.agent.EVENT_ALERT_RULES_JSON': {
    title: '事件告警规则（Legacy JSON）',
    summary: '通过 JSON 数组配置基础价格和成交量告警规则。',
    usage: 'JSON 数组格式，每条规则包含 alert_type、stock_code 和条件字段。仅支持 price_cross、price_change_percent 和 volume_spike 三种基础类型。',
    valueNotes: [
      '技术指标、自选股、持仓、大盘红绿灯等高级规则需通过 Alert API 或 Web 告警中心管理，不在此 JSON 中配置。',
      '规则在定时模式下由事件监控定期评估。',
    ],
    impact: ['影响后台告警检测和通知推送。'],
    notes: ['该字段为 Legacy 配置方式，高级规则请使用告警中心。'],
  },
  // ------------------------------------------------------------------
  // Backtest configuration
  // ------------------------------------------------------------------
  'settings.backtest.BACKTEST_ENABLED': {
    title: '回测开关',
    summary: '启用或关闭历史分析回测功能。',
    usage: '开启后，系统会定期将历史分析结果与后续实际走势对比，评估策略准确率。',
    valueNotes: [
      '回测数据用于策略自动权重（AGENT_SKILL_AUTOWEIGHT）和记忆校准。',
      '关闭回测不影响已有回测记录，但会停止新回测评估。',
    ],
    impact: ['影响策略权重校准、记忆校准和回测报告生成。'],
    notes: ['Agent 策略自动权重功能依赖回测数据。'],
  },
  'settings.backtest.eval_params': {
    title: '回测评估参数',
    summary: '控制回测评估窗口、最小记录年龄和中性回报带的参数组。',
    usage: 'BACKTEST_EVAL_WINDOW_DAYS 设定评估窗口（交易日数）；BACKTEST_MIN_AGE_DAYS 仅评估创建时间超过此天数的记录；BACKTEST_NEUTRAL_BAND_PCT 设定中性回报带百分比。',
    valueNotes: [
      '评估窗口越长，包含的交易日越多，结果越稳定但延迟越高。',
      'BACKTEST_MIN_AGE_DAYS 用于排除过新的分析记录，等待足够后续走势数据。',
      'BACKTEST_NEUTRAL_BAND_PCT 内的涨跌标记为中性，不判定为正确或错误。',
    ],
    impact: ['影响回测结果的判定标准、覆盖范围和策略权重计算。'],
    notes: ['三个参数共同影响回测结果，建议组合调整。'],
  },
  'settings.backtest.BACKTEST_ENGINE_VERSION': {
    title: '回测引擎版本',
    summary: '回测引擎版本标签。',
    usage: '一般无需修改；版本标签用于标识当前使用的回测逻辑版本。',
    valueNotes: ['不同版本可能使用不同的评估算法或判定规则。'],
    impact: ['影响回测评估算法和结果。'],
    notes: ['除非明确要求切换版本，否则保持默认。'],
  },
  // ------------------------------------------------------------------
  // Report configuration
  // ------------------------------------------------------------------
  'settings.report.REPORT_SUMMARY_ONLY': {
    title: '仅推送摘要',
    summary: '只推送分析摘要，不推送个股详情。适合跟踪大量股票时快速概览。',
    usage: '开启后，通知只包含整体摘要信息；关闭后包含每只股票的详细分析。',
    valueNotes: ['跟踪股票较多时开启可减少通知篇幅。'],
    impact: ['影响通知推送的内容详细程度。'],
    notes: ['不影响 Web 端报告查看。'],
  },
  'settings.report.REPORT_SHOW_LLM_MODEL': {
    title: '报告显示模型名',
    summary: '在报告页脚展示本次分析使用的 LLM 模型名称。',
    usage: '开启后，通知报告页脚会显示模型标识；关闭后隐藏。',
    valueNotes: ['仅影响报告渲染，不改变模型选择、运行时路由或迁移行为。'],
    impact: ['影响通知报告中的模型信息可见性。'],
    notes: ['用于排查模型切换问题时可以临时开启。'],
  },
  'settings.report.REPORT_TEMPLATES_DIR': {
    title: '报告模板目录',
    summary: 'Jinja2 报告模板的存放目录。',
    usage: '填写相对于项目根目录的路径；目录内放置 Jinja2 模板文件。',
    valueNotes: ['需要同时开启 REPORT_RENDERER_ENABLED 才会使用模板渲染。'],
    impact: ['影响报告渲染使用的模板来源。'],
    notes: ['自定义模板需要符合 Jinja2 语法并包含必要的变量占位。'],
  },
  'settings.report.REPORT_RENDERER_ENABLED': {
    title: '报告渲染引擎',
    summary: '启用 Jinja2 模板渲染引擎处理报告输出。',
    usage: '默认关闭；开启后报告会通过 Jinja2 模板渲染，支持自定义格式。',
    valueNotes: ['默认关闭以确保零回归风险。'],
    impact: ['影响报告最终输出格式。'],
    notes: ['开启前请确认 REPORT_TEMPLATES_DIR 中有有效的模板文件。'],
  },
  'settings.report.REPORT_INTEGRITY_ENABLED': {
    title: '报告完整性校验',
    summary: 'LLM 输出后校验必填字段，缺失时重试或使用占位符。',
    usage: '开启后系统会检查报告是否包含必要的分析字段；REPORT_INTEGRITY_RETRY 控制重试次数。',
    valueNotes: [
      '校验失败的字段会用占位符填充。',
      '重试会增加 LLM 调用次数和耗时。',
    ],
    impact: ['影响报告完整度和 LLM 调用次数。'],
    notes: ['REPORT_INTEGRITY_RETRY=0 时不重试，仅用占位符。'],
  },
  'settings.report.REPORT_HISTORY_COMPARE_N': {
    title: '历史信号对比',
    summary: '展示每只股票最近 N 次分析的信号对比。设为 0 关闭。',
    usage: '开启后，报告中会展示最近 N 次分析信号的对比表格。',
    valueNotes: ['N 越大对比范围越广，但表格越长。'],
    impact: ['影响报告中历史信号对比部分的展示。'],
    notes: ['设为 0 关闭该功能。'],
  },
  'settings.report.SINGLE_STOCK_NOTIFY': {
    title: '逐股即时推送',
    summary: '每完成一只股票分析后立即推送，而不是等全部完成后批量推送。',
    usage: '开启后，每只股票分析完成后独立发送通知；关闭后汇总发送。',
    valueNotes: ['开启后通知更及时，但推送频率更高。'],
    impact: ['影响通知推送时机和频率。'],
    notes: ['跟踪大量股票时可能产生较多通知消息。'],
  },
  'settings.report.MERGE_EMAIL_NOTIFICATION': {
    title: '合并邮件通知',
    summary: '将个股分析与大盘复盘合并为一封邮件发送。',
    usage: '开启后，个股分析和大盘复盘会合并在同一封邮件中发送。',
    valueNotes: ['仅在同时启用了个股分析和大盘复盘时有效。'],
    impact: ['影响邮件通知的封数和内容组织。'],
    notes: ['关闭后个股分析和大盘复盘会分别发送邮件。'],
  },
  // ------------------------------------------------------------------
  // Notification routing
  // ------------------------------------------------------------------
  'settings.notification.channel_routing': {
    title: '通知渠道路由',
    summary: '为不同类型的通知指定目标推送渠道。',
    usage: '三个路由字段分别控制报告推送、告警推送和系统错误推送的目标渠道。使用英文逗号分隔渠道名；留空则推送到所有已配置渠道。',
    valueNotes: [
      'NOTIFICATION_REPORT_CHANNELS 控制日常分析报告推送渠道。',
      'NOTIFICATION_ALERT_CHANNELS 控制事件告警推送渠道。',
      'NOTIFICATION_SYSTEM_ERROR_CHANNELS 控制系统错误推送渠道。',
      '可用渠道取决于已配置的通知渠道（如 email、feishu、telegram 等）。',
    ],
    impact: ['影响不同通知类型的推送目标。'],
    notes: ['指定的渠道必须已完成对应配置，否则不会生效。'],
  },
  'settings.notification.dedup': {
    title: '通知去重与冷却',
    summary: '控制静态通知的去重时间窗口和冷却时间。',
    usage: 'NOTIFICATION_DEDUP_TTL_SECONDS 设定去重时间窗口，同一去重 key 在窗口内只推送一次；NOTIFICATION_COOLDOWN_SECONDS 设定冷却时间，同一冷却 key 在窗口内只推送一次。',
    valueNotes: [
      '两个机制独立生效，互不影响。',
      '都设为 0 时关闭对应去重或冷却功能。',
    ],
    impact: ['影响通知推送频率和重复控制。'],
    notes: ['动态通知（如告警）有独立的触发和冷却逻辑。'],
  },
  'settings.notification.quiet_hours': {
    title: '静默时段',
    summary: '在指定时间段内抑制通知推送。',
    usage: 'NOTIFICATION_QUIET_HOURS 使用 HH:MM-HH:MM 格式，支持跨夜；NOTIFICATION_TIMEZONE 指定对应时区。',
    valueNotes: [
      '留空关闭静默时段。',
      '时区留空时使用系统本地时区。',
    ],
    impact: ['影响通知推送的时段。'],
    notes: ['静默时段内的静态通知会被抑制并跳过，不会在时段结束后补发。'],
  },
  'settings.notification.MIN_SEVERITY': {
    title: '最低通知等级',
    summary: '过滤低于指定等级的静态通知。',
    usage: '设为 warning 时，只有 warning 及以上等级的通知会被推送；留空保留当前行为。',
    valueNotes: ['等级从低到高依次为 info、warning、error、critical。'],
    impact: ['影响静态通知的推送量。'],
    notes: ['动态通知（如告警）有独立的事件和等级评估。'],
  },
  'settings.notification.DAILY_DIGEST_ENABLED': {
    title: '每日摘要（预留）',
    summary: '预留功能开关，当前不会发送每日摘要。',
    usage: '该字段为 P4 预留功能，当前开启后不会产生任何效果。',
    valueNotes: ['保留用于后续每日摘要聚合推送功能。'],
    impact: ['当前无实际影响。'],
    notes: ['未来版本启用后会聚合当日通知为一条摘要推送。'],
  },
  // ------------------------------------------------------------------
  // System runtime
  // ------------------------------------------------------------------
  'settings.system.LOG_LEVEL': {
    title: '日志级别',
    summary: '控制应用日志输出的详细程度。',
    usage: '可选 DEBUG、INFO、WARNING、ERROR、CRITICAL；级别越高输出越少。',
    valueNotes: [
      'DEBUG 输出最详细的日志，适合排查问题。',
      '部分运行时组件可能在重启后才完全生效。',
    ],
    impact: ['影响日志输出量和详细程度。'],
    notes: ['修改后部分运行时组件可能需要重启才能完全生效。'],
  },
  'settings.system.DEBUG': {
    title: '调试模式',
    summary: '开启调试模式，输出详细日志信息。',
    usage: '开启后会输出更多内部状态和调试信息。',
    valueNotes: ['生产环境建议关闭以减少日志量。'],
    impact: ['影响日志详细程度和运行时行为。'],
    notes: ['调试模式可能影响性能，不建议长期开启。'],
  },
  'settings.system.MAX_WORKERS': {
    title: '最大并发线程数',
    summary: '控制同时执行的股票分析线程数量。',
    usage: '设置并发分析的工作线程数；数值越高并发越高，但 API 限流风险也越大。',
    valueNotes: [
      '建议保持较低值以避免触发数据源或 LLM API 的频率限制。',
      '受限于 API Key 配额和网络带宽。',
    ],
    impact: ['影响分析总耗时和 API 调用频率。'],
    notes: ['并发过高可能导致 API 返回限流错误。'],
  },
  'settings.system.ANALYSIS_DELAY': {
    title: '分析间隔',
    summary: '控制每只股票分析之间的间隔秒数，用于限速。',
    usage: '设为 0 无间隔；设为正值时每完成一只股票后等待指定秒数再分析下一只。',
    valueNotes: ['适合在 API 有严格频率限制时使用。'],
    impact: ['影响分析总耗时。'],
    notes: ['总耗时 ≈ 股票数 × 单股耗时 + (股票数-1) × ANALYSIS_DELAY。'],
  },
  'settings.system.market_review': {
    title: '大盘分析',
    summary: '控制大盘分析功能的开关、覆盖市场和配色方案。',
    usage: 'MARKET_REVIEW_ENABLED 开启大盘分析；MARKET_REVIEW_REGION 选择市场（cn/hk/us/both）；MARKET_REVIEW_COLOR_SCHEME 选择配色。',
    valueNotes: [
      'cn 覆盖 A 股，hk 覆盖港股，us 覆盖美股，both 覆盖全部。',
      '配色方案影响大盘报告中指数涨跌的颜色显示：green_up 为绿涨红跌，red_up 为红涨绿跌。',
    ],
    impact: ['影响分析报告中大盘概览部分的内容和视觉呈现。'],
    notes: ['大盘分析依赖对应市场的指数数据源可用性。'],
  },
};

const settingsHelpEnUS: SettingsHelpMap = {
  'settings.base.STOCK_LIST': {
    title: 'Watchlist',
    summary: 'Defines the stock codes used by analysis jobs and notification reports.',
    usage: 'Separate symbols with commas. A-shares can use six-digit codes, HK stocks can use the hk prefix, and US stocks can use ticker symbols.',
    valueNotes: [
      'Scheduled mode rereads the saved STOCK_LIST before each run.',
      'A temporary --stocks argument only affects that manual run.',
      'STOCK_GROUP_N should be a subset of STOCK_LIST and only affects grouped email routing.',
    ],
    impact: ['Affects analysis scope, notification content, and saved history reports.'],
    notes: ['Use English commas between symbols.', 'Save the setting before later tasks can read it.'],
  },
  'settings.ai_model.LITELLM_MODEL': {
    title: 'Primary Model',
    summary: 'Selects the default LLM model for regular analysis flows.',
    usage: 'Use provider/model format, such as deepseek/deepseek-v4-flash, gemini/gemini-3.1-pro-preview, or ollama/qwen3:8b.',
    valueNotes: [
      'Runtime priority is LITELLM_CONFIG > LLM_CHANNELS > legacy provider keys.',
      'When empty, the system tries to infer a model from available API keys or channels.',
      'Agent can use AGENT_LITELLM_MODEL; when empty, it inherits the primary model.',
    ],
    impact: ['Affects regular stock analysis, market review, report generation, and Agent calls without a dedicated model.'],
    notes: [
      'Without a provider prefix, LiteLLM may not know which API key to use.',
      'For Ollama, use OLLAMA_API_BASE or an Ollama channel instead of OPENAI_BASE_URL.',
    ],
  },
  'settings.ai_model.LLM_CHANNELS': {
    title: 'LLM Channels',
    summary: 'Declares model channels for multiple providers, keys, fallbacks, and visual channel management.',
    usage: 'Use comma-separated names such as deepseek,aihubmix; then configure LLM_<NAME>_BASE_URL, LLM_<NAME>_API_KEY(S), and LLM_<NAME>_MODELS for each channel.',
    valueNotes: [
      'Once channel mode is active, runtime selection reads channel configuration first.',
      'Environment variables injected by Docker or GitHub Actions can override values saved from the Web settings page.',
      'Saving in the channel editor updates submitted keys only and does not silently migrate all old config.',
    ],
    impact: ['Affects available sources for primary, Agent, fallback, and Vision models.'],
    notes: [
      'Do not expect legacy keys and Channels to be active at the same time.',
      'Custom channel names in GitHub Actions usually need explicit workflow env mappings.',
    ],
  },
  'settings.ai_model.AGENT_LITELLM_MODEL': {
    title: 'Agent Primary Model',
    summary: 'Sets a dedicated model for Agent workflows.',
    usage: 'Use provider/model format. When empty, Agent inherits the regular primary model.',
    valueNotes: ['Useful when Agent needs stronger reasoning or longer context.', 'Only affects Agent flows.'],
    impact: ['Affects Agent chat, strategy selection, and Agent tool calls.'],
    notes: ['Make sure the model is reachable through enabled channels, YAML routing, or legacy provider keys.'],
  },
  'settings.ai_model.LITELLM_FALLBACK_MODELS': {
    title: 'Fallback Models',
    summary: 'Models tried in order when the primary model fails.',
    usage: 'Use comma-separated provider/model values.',
    valueNotes: ['Fallbacks run only after primary model failures.', 'The channel editor removes unreachable managed-provider references on save.'],
    impact: ['Improves LLM availability, but can change cost, latency, and provider behavior.'],
    notes: ['Do not duplicate the primary model in the fallback list.'],
  },
  'settings.ai_model.LITELLM_CONFIG': {
    title: 'Advanced Routing YAML',
    summary: 'Points to a native LiteLLM YAML routing file for expert routing setups.',
    usage: 'Use a path reachable by the running process, such as ./litellm_config.yaml.',
    valueNotes: ['A valid model_list has higher priority than channels and legacy keys.', 'The Web channel editor does not edit the YAML file.'],
    impact: ['Affects model routing, fallbacks, and available model declarations.'],
    notes: ['If the YAML cannot be parsed, the system falls back to channels or legacy configuration.'],
  },
  'settings.ai_model.LLM_TEMPERATURE': {
    title: 'Temperature',
    summary: 'Controls output randomness.',
    usage: 'Use 0.0 to 2.0. Lower values are more deterministic; higher values are more varied.',
    valueNotes: ['Use low values for stable structured output.', '0.7 is the general default.'],
    impact: ['Affects report wording and structured-output stability.'],
    notes: ['Provider-specific limits can differ.'],
  },
  'settings.ai_model.provider_keys': {
    title: 'Provider API Key',
    summary: 'Configures credentials for model providers or gateways.',
    usage: 'Create a key in the provider console. Related multi-key variants use English commas for rotation or load balancing.',
    valueNotes: ['Secret fields are masked in the Web settings page.', 'Channel mode reads LLM_<NAME>_API_KEY(S) first.'],
    impact: ['Affects model calls, connection tests, and model discovery for the provider.'],
    notes: ['Do not expose real keys in issues, logs, or screenshots.'],
  },
  'settings.ai_model.anspire_llm': {
    title: 'Anspire LLM Gateway',
    summary: 'Uses Anspire API keys as a compatible OpenAI-style LLM gateway.',
    usage: 'ANSPIRE_LLM_ENABLED controls this compatibility path; ANSPIRE_LLM_BASE_URL sets the gateway endpoint; ANSPIRE_LLM_MODEL sets the default model when no primary model is explicitly selected.',
    valueNotes: [
      'This path is mainly for simplified setups without LLM_CHANNELS or LITELLM_MODEL.',
      'When LITELLM_CONFIG, LLM_CHANNELS, or an explicit LITELLM_MODEL is configured, runtime selection follows the existing priority order.',
    ],
    impact: ['Affects the default gateway and model used when Anspire keys participate in LLM calls.'],
    notes: ['Do not point the Base URL at another provider while reusing an Anspire key.'],
  },
  'settings.ai_model.legacy_provider_params': {
    title: 'Legacy Provider Parameters',
    summary: 'Configures model names, temperature, or token limits for legacy provider-specific paths.',
    usage: 'These fields preserve older configurations. Prefer LITELLM_MODEL, LITELLM_FALLBACK_MODELS, VISION_MODEL, LLM_TEMPERATURE, or LLM Channels for new setups.',
    valueNotes: [
      'When LLM Channels are active, related legacy fields are often hidden from the generic form.',
      'These fields affect only the matching legacy provider path and are not automatically migrated into channels.',
    ],
    impact: ['Affects legacy provider model selection and sampling parameters when channel/YAML routing is not used.'],
    notes: ['If both legacy fields and Channels exist, trust the runtime source shown by the settings page.'],
  },
  'settings.ai_model.OPENAI_BASE_URL': {
    title: 'OpenAI-compatible Base URL',
    summary: 'Sets the endpoint root for an OpenAI-compatible service.',
    usage: 'Often ends with /v1. Official APIs, gateways, and local services use different URLs.',
    valueNotes: ['The Base URL must match the API key provider.', 'Gemini or Anthropic official paths usually do not use OPENAI_BASE_URL.'],
    impact: ['Affects legacy OpenAI-compatible model calls.'],
    notes: ['In channel mode, prefer each channel-specific LLM_<NAME>_BASE_URL.'],
  },
  'settings.data_source.TUSHARE_TOKEN': {
    title: 'Tushare Token',
    summary: 'Token used for Tushare Pro data access.',
    usage: 'Paste the token from your Tushare account.',
    valueNotes: ['Available APIs depend on your Tushare permission level.'],
    impact: ['Affects some A-share base data, stock lists, and enrichment data.'],
    notes: ['Do not commit the token or print it in public logs.'],
  },
  'settings.data_source.TICKFLOW_API_KEY': {
    title: 'TickFlow API Key',
    summary: 'Enhances market review with index and market-statistics data.',
    usage: 'Paste a TickFlow API key here. When empty, the system continues with other data sources and fallback paths.',
    valueNotes: ['This key is an optional enhancement, not required for the main analysis flow.'],
    impact: ['Affects market-review and market-statistics coverage.'],
    notes: ['Do not expose real keys in issues, logs, or screenshots.'],
  },
  'settings.data_source.REALTIME_SOURCE_PRIORITY': {
    title: 'Realtime Source Priority',
    summary: 'Configures the provider order for realtime quotes.',
    usage: 'Use comma-separated provider names; the system tries them in order.',
    valueNotes: ['Earlier providers are preferred; failures fall back to later providers.'],
    impact: ['Affects current price, intraday analysis, and report fields that depend on realtime prices.'],
    notes: ['A single provider failure should fall back to the next source.'],
  },
  'settings.data_source.realtime_quotes': {
    title: 'Realtime Quotes',
    summary: 'Controls whether realtime quotes and intraday technical indicators are enabled.',
    usage: 'Switch fields use true/false. Provider order is configured separately by REALTIME_SOURCE_PRIORITY.',
    valueNotes: ['Disabling realtime quotes falls back toward historical close prices.', 'Realtime technical indicators use intraday prices.'],
    impact: ['Affects current price, technical indicators, intraday analysis, and report fields.'],
    notes: ['A single provider failure should fall back to the next source.'],
  },
  'settings.data_source.search_api_keys': {
    title: 'Search API Keys',
    summary: 'Configures third-party search services for news and web context.',
    usage: 'Multi-key fields use English commas.',
    valueNotes: ['Search results enrich news, announcements, and market context.'],
    impact: ['Affects news coverage and external information in reports or Agent flows.'],
    notes: ['Search services can differ in quota, rate limits, and regional availability.'],
  },
  'settings.data_source.SEARXNG_BASE_URLS': {
    title: 'SearXNG URLs',
    summary: 'Configures self-hosted or trusted SearXNG search instances.',
    usage: 'Use comma-separated URLs. Self-hosted instances should enable JSON output.',
    valueNotes: ['When public discovery is disabled, only these instances are used.'],
    impact: ['Affects fallback web search when commercial search keys are absent.'],
    notes: ['For production, prefer self-hosted or trusted instances over public ones.'],
  },
  'settings.data_source.ENABLE_CHIP_DISTRIBUTION': {
    title: 'Chip Distribution',
    summary: 'Toggles chip distribution analysis.',
    usage: 'Set false when cloud deployments or data sources are unstable.',
    valueNotes: ['Disabling reduces related data calls and failure noise.'],
    impact: ['Affects chip distribution and cost-area analysis in reports.'],
    notes: ['This feature depends on external data-source stability.'],
  },
  'settings.data_source.BIAS_THRESHOLD': {
    title: 'BIAS Threshold',
    summary: 'Sets the risk-warning threshold for price deviation from MA5.',
    usage: 'Enter a percentage. When price deviation from MA5 exceeds the threshold, reports can warn against chasing or highlight mean-reversion risk.',
    valueNotes: ['Strong-trend stocks may widen the threshold according to runtime rules.'],
    impact: ['Affects technical-analysis warnings about chasing, MA deviation, and trading advice.'],
    notes: ['Too low can add noisy warnings; too high can weaken chase-risk alerts.'],
  },
  'settings.data_source.pytdx': {
    title: 'Pytdx Servers',
    summary: 'Configures Tongdaxin quote servers and overrides built-in defaults.',
    usage: 'Use PYTDX_HOST/PYTDX_PORT for a single server, or PYTDX_SERVERS for multiple ip:port entries. PYTDX_SERVERS takes priority.',
    valueNotes: ['Separate multiple servers with English commas; runtime data-source logic tries them as configured.'],
    impact: ['Affects quote connectivity and availability when the Pytdx data source is used.'],
    notes: ['If a server is unreachable, rely on data-source fallback and avoid a single unstable endpoint.'],
  },
  'settings.data_source.news_window': {
    title: 'News Window',
    summary: 'Controls how old news can be before it is excluded from analysis context.',
    usage: 'NEWS_MAX_AGE_DAYS sets the cap; NEWS_STRATEGY_PROFILE selects the profile.',
    valueNotes: ['The effective window is constrained by both values.'],
    impact: ['Affects news context size, freshness, and report length.'],
    notes: ['Too wide can include stale news; too narrow can miss slow-moving events.'],
  },
  'settings.notification.FEISHU_WEBHOOK_URL': {
    title: 'Feishu Webhook URL',
    summary: 'Sends analysis reports to a Feishu group through a custom bot webhook.',
    usage: 'Create a custom bot in the target Feishu group and paste the open-apis/bot/v2/hook webhook URL here.',
    valueNotes: [
      'If signing is enabled, also set FEISHU_WEBHOOK_SECRET.',
      'If keyword protection is enabled, also set FEISHU_WEBHOOK_KEYWORD; the sender prepends it automatically.',
      'FEISHU_APP_ID / FEISHU_APP_SECRET are for app, cloud-doc, or Stream Bot modes and do not enable group webhook delivery.',
    ],
    impact: ['Affects only the Feishu notification channel; delivery failure should not block the main analysis flow.'],
    notes: [
      'Do not use FEISHU_APP_SECRET as FEISHU_WEBHOOK_SECRET.',
      'If IP allowlisting is enabled in Feishu, add the outbound IP of your runtime environment.',
    ],
  },
  'settings.notification.webhooks': {
    title: 'Enterprise WeChat Webhook',
    summary: 'Configures an Enterprise WeChat group bot webhook for report delivery.',
    usage: 'Create a group bot in Enterprise WeChat and paste the Webhook URL that starts with qyapi.weixin.qq.com/cgi-bin/webhook/send.',
    valueNotes: ['Webhook URLs often contain sensitive tokens.', 'Platforms differ in message length, format, and rate limits.'],
    impact: ['Affects delivery for the corresponding webhook channel.'],
    notes: ['A single notification failure should not block the main analysis flow.'],
  },
  'settings.notification.CUSTOM_WEBHOOK_URLS': {
    title: 'Custom Webhooks',
    summary: 'Pushes reports to any service that accepts POST JSON.',
    usage: 'Use comma-separated URLs. CUSTOM_WEBHOOK_BODY_TEMPLATE can customize the JSON body.',
    valueNotes: ['The template must render to a JSON object.', 'Prefer $content_json and $title_json to avoid invalid JSON.'],
    impact: ['Affects AstrBot, NapCat, or self-hosted push integrations.'],
    notes: ['Validate one webhook before adding multiple targets.'],
  },
  'settings.notification.WEBHOOK_VERIFY_SSL': {
    title: 'Webhook SSL Verification',
    summary: 'Controls HTTPS certificate verification for webhook requests.',
    usage: 'Keep true by default. Use false only for trusted internal self-signed certificates.',
    valueNotes: ['Disabling verification weakens MITM protection.'],
    impact: ['Affects TLS verification for custom webhook HTTPS requests.'],
    notes: ['Do not disable SSL verification on public networks.'],
  },
  'settings.notification.telegram': {
    title: 'Telegram Delivery',
    summary: 'Sends reports through a Telegram Bot.',
    usage: 'Create a bot with @BotFather, then set Bot Token and Chat ID. Topic delivery can also set Thread ID.',
    valueNotes: ['The bot must be added to the target group and allowed to post.'],
    impact: ['Affects Telegram notifications.'],
    notes: ['Group Chat IDs are often negative or start with -100.'],
  },
  'settings.notification.email': {
    title: 'Email Delivery',
    summary: 'Sends analysis reports through SMTP.',
    usage: 'Set sender, SMTP authorization code, and comma-separated receivers.',
    valueNotes: ['EMAIL_PASSWORD is usually an app authorization code, not the web login password.', 'STOCK_GROUP_N and EMAIL_GROUP_N can route groups to different receivers.'],
    impact: ['Affects email reports, grouped recipients, and market-review emails.'],
    notes: ['Enable SMTP in the mailbox provider first.'],
  },
  'settings.notification.chat_bots': {
    title: 'Chat Platform Bots',
    summary: 'Configures Discord, Slack, Pushover, ServerChan, and similar channels.',
    usage: 'Choose Webhook or Bot Token mode for the platform; Bot mode usually also needs a channel ID.',
    valueNotes: ['When both Bot and Webhook are configured, existing code may prefer one mode.'],
    impact: ['Affects the corresponding chat notification channel.'],
    notes: ['Bot tokens, webhook URLs, and SendKeys are secrets.'],
  },
  'settings.notification.report_output': {
    title: 'Report Output',
    summary: 'Controls notification detail level, language, and template output.',
    usage: 'REPORT_TYPE supports simple/full/brief. REPORT_LANGUAGE supports zh/en.',
    valueNotes: ['Report language affects default report and notification text, not the Web UI language.'],
    impact: ['Affects notification length, language, and readability.'],
    notes: ['Full reports can be long and may be split by some platforms.'],
  },
  'settings.system.WEBUI_HOST': {
    title: 'WebUI Host',
    summary: 'Controls the network address the WebUI service binds to.',
    usage: 'Use 127.0.0.1 for local-only access. Use 0.0.0.0 for cloud, Docker, or external access.',
    valueNotes: [
      'Current startup logic reads WEBUI_HOST when the host is the default 0.0.0.0; even an explicit --host 0.0.0.0 can still be overwritten by WEBUI_HOST in .env.',
      'Saving it from the settings page writes .env and reloads runtime config objects, but the running WebUI/API process will not rebind its host.',
      'Docker Compose commonly binds 0.0.0.0 inside the container; host access also depends on port mapping.',
    ],
    impact: ['Affects whether the WebUI can be reached locally, on the LAN, or from the public internet after restart.'],
    notes: [
      'Restart the process, Docker container, or service manager after changing WEBUI_HOST.',
      'Enable ADMIN_AUTH_ENABLED when exposing the service publicly.',
      'Behind a reverse proxy, also evaluate TRUST_X_FORWARDED_FOR for login rate limiting and real IP detection.',
    ],
  },
  'settings.system.WEBUI_PORT': {
    title: 'WebUI Port',
    summary: 'Controls the port the WebUI service listens on.',
    usage: 'Default is 8000. Use another port in the 1-65535 range when needed.',
    valueNotes: [
      'Docker or cloud access also depends on host port mappings and firewall rules.',
      'Saving from the settings page only writes .env; it does not rebind the running WebUI/API process.',
    ],
    impact: ['Affects the browser URL used to open WebUI after restart.'],
    notes: ['Restart the process, Docker container, or service manager after changing WEBUI_PORT.'],
  },
  'settings.system.ADMIN_AUTH_ENABLED': {
    title: 'Web Login Protection',
    summary: 'Enables admin password protection for WebUI.',
    usage: 'Use the WebUI auth settings entry to enable or disable this. Reset with python -m src.auth reset_password if needed.',
    valueNotes: ['Recommended for public, shared LAN, or reverse-proxy deployments.', 'This field is shown read-only in the generic config page to avoid bypassing the auth settings flow.'],
    impact: ['Affects WebUI login, settings access, and admin operations.'],
    notes: ['Make sure auth data is persisted in the deployment environment. Manual .env edits require a process restart or the auth settings flow to refresh state.'],
  },
  'settings.system.TRUST_X_FORWARDED_FOR': {
    title: 'Trust X-Forwarded-For',
    summary: 'Uses X-Forwarded-For for client IP detection behind a trusted reverse proxy.',
    usage: 'Set true only behind one trusted reverse proxy. Keep false for direct public access.',
    valueNotes: ['With multiple proxies or CDNs, rate-limit keys may collapse to edge proxy IPs.'],
    impact: ['Affects login rate limiting, auditing, and client IP detection.'],
    notes: ['Do not enable it on an untrusted proxy chain.'],
  },
  'settings.system.schedule': {
    title: 'Schedule',
    summary: 'Controls daily scheduled analysis and whether startup runs immediately.',
    usage: 'SCHEDULE_TIME uses HH:MM 24-hour format. SCHEDULE_ENABLED and SCHEDULE_RUN_IMMEDIATELY control schedule-mode startup behavior.',
    valueNotes: [
      'An already-running schedule mode reads a new SCHEDULE_TIME on the next scheduler check and rebuilds the daily job.',
      'SCHEDULE_ENABLED and SCHEDULE_RUN_IMMEDIATELY are startup-time settings; saving them does not start, stop, or rebuild the current scheduler.',
      'Scheduled runs read the currently saved STOCK_LIST.',
    ],
    impact: ['Affects automatic analysis frequency, startup behavior, and notification timing in schedule mode.'],
    notes: [
      'Check the runtime timezone, especially in containers and servers.',
      'If the current process was not started in schedule mode, saving these fields will not create a scheduler.',
    ],
  },
  'settings.system.RUN_IMMEDIATELY': {
    title: 'Run Immediately',
    summary: 'Controls whether non-schedule startup runs one analysis immediately.',
    usage: 'Set false when you want to start the service without analysis.',
    valueNotes: ['SCHEDULE_RUN_IMMEDIATELY controls schedule mode separately.'],
    impact: ['Affects the first analysis after service startup.'],
    notes: [
      'This is a startup-time setting for non-schedule mode; saving it will not trigger analysis in the running WebUI/API process.',
      'CLI arguments and run mode can also affect final behavior. Restart a non-schedule process for changes to take effect.',
    ],
  },
  'settings.system.TRADING_DAY_CHECK_ENABLED': {
    title: 'Trading Day Check',
    summary: 'Controls whether analysis is skipped on non-trading days.',
    usage: 'Default true. Set false or use --force-run to override.',
    valueNotes: ['Uses market calendars for A-share, HK, US, and other supported markets.'],
    impact: ['Affects whether manual and scheduled runs execute on holidays.'],
    notes: ['Disabling it can produce reports with missing realtime quotes on closed markets.'],
  },
  'settings.system.HTTP_PROXY': {
    title: 'Network Proxy',
    summary: 'Sets a proxy for external API, model, or search requests.',
    usage: 'Use http://host:port format. HTTPS_PROXY can be used for HTTPS proxying.',
    valueNotes: ['Whether it applies depends on the underlying library and environment handling.'],
    impact: ['Affects data sources, LLM, search, and notification network calls.'],
    notes: ['Inside containers, 127.0.0.1 points to the container, not the host machine.'],
  },
  'settings.llm_channel.channel_name': {
    title: 'Channel Name',
    summary: 'Generates the LLM_<NAME>_* environment variable names.',
    usage: 'Use lowercase letters, numbers, and underscores only. Saving also writes LLM_CHANNELS.',
    valueNotes: ['deepseek maps to LLM_DEEPSEEK_BASE_URL, LLM_DEEPSEEK_API_KEY(S), and LLM_DEEPSEEK_MODELS.'],
    impact: ['Affects env key names, runtime selection, and GitHub Actions mappings.'],
    notes: ['Renaming does not migrate every external environment variable automatically.'],
  },
  'settings.llm_channel.protocol': {
    title: 'Channel Protocol',
    summary: 'Declares which compatibility protocol the channel uses.',
    usage: 'OpenAI Compatible fits most gateways. Official Gemini, Anthropic, and DeepSeek can use their protocol.',
    valueNotes: ['Protocol affects model prefix normalization, connection tests, and discovery.'],
    impact: ['Affects request adapters, model parsing, and runtime model references.'],
    notes: ['Protocol, Base URL, and API Key must belong to the same service.'],
  },
  'settings.llm_channel.base_url': {
    title: 'Base URL',
    summary: 'Endpoint root for this channel.',
    usage: 'OpenAI-compatible services often use a /v1 URL. Some official SDK channels can leave it empty.',
    valueNotes: ['Provider presets are references; actual availability depends on account, region, and provider APIs.'],
    impact: ['Affects connection tests, model discovery, and all calls through the channel.'],
    notes: ['Do not mix one provider key with another provider Base URL.'],
  },
  'settings.llm_channel.api_key': {
    title: 'API Key',
    summary: 'Credential used by this channel.',
    usage: 'Use one key directly, or multiple keys separated by English commas.',
    valueNotes: ['Local unauthenticated services such as Ollama can leave it empty.'],
    impact: ['Affects connection tests, discovery, runtime calls, and key rotation.'],
    notes: ['Do not expose real keys in screenshots, logs, or issues.'],
  },
  'settings.llm_channel.models': {
    title: 'Channel Models',
    summary: 'Declares models available for runtime selection.',
    usage: 'Use model discovery when /models is supported, or manually enter comma-separated model names.',
    valueNotes: ['Runtime primary, Agent, Vision, and fallback choices reference this list.'],
    impact: ['Affects selectable models, stale-model cleanup, and routing.'],
    notes: ['Actual availability still depends on provider permissions and runtime tests.'],
  },
  'settings.llm_channel.capability_checks': {
    title: 'Runtime Capability Checks',
    summary: 'Manually checks JSON, tools, stream, or vision support for the current channel model.',
    usage: 'Select capabilities and run the check. It sends real LLM requests.',
    valueNotes: ['Multiple checks can take 20-40 seconds and may consume quota.'],
    impact: ['Only affects page diagnostics; it does not change saved configuration.'],
    notes: ['Capability labels are hints; runtime checks and real calls are the final signal.'],
  },
  'settings.llm_channel.temperature': {
    title: 'Temperature',
    summary: 'Unified runtime sampling temperature.',
    usage: 'Slider range is 0 to 2. Lower is steadier; higher is more random.',
    valueNotes: ['Saving writes LLM_TEMPERATURE.'],
    impact: ['Affects regular analysis, Agent output, and reports.'],
    notes: ['Lower it first when structured output is unstable.'],
  },
  'settings.llm_channel.primary_model': {
    title: 'Primary Model',
    summary: 'Default runtime model for regular analysis.',
    usage: 'Choose from enabled channel models. Auto uses the first available model.',
    valueNotes: ['Saving writes LITELLM_MODEL.'],
    impact: ['Affects stock analysis, market review, and default report generation.'],
    notes: ['Unreachable managed-provider models can be cleaned up on save.'],
  },
  'settings.llm_channel.agent_primary_model': {
    title: 'Agent Primary Model',
    summary: 'Dedicated primary model for Agent flows.',
    usage: 'Choose an independent model, or auto-inherit the regular primary model.',
    valueNotes: ['Saving writes AGENT_LITELLM_MODEL.'],
    impact: ['Affects Agent chat, strategy workflows, and tool calls.'],
    notes: ['A stronger Agent model can also increase cost and latency.'],
  },
  'settings.llm_channel.fallback_models': {
    title: 'Fallback Models',
    summary: 'Backup models used when the primary model fails.',
    usage: 'Check one or more models. The primary model is not duplicated into fallbacks.',
    valueNotes: ['Saving writes LITELLM_FALLBACK_MODELS.'],
    impact: ['Affects LLM failure recovery and cross-provider behavior.'],
    notes: ['Validate fallback models with connection tests or real calls first.'],
  },
  'settings.llm_channel.vision_model': {
    title: 'Vision Model',
    summary: 'Model used for image or screenshot inputs.',
    usage: 'Choose a model with image-input support, or use the automatic Vision default.',
    valueNotes: ['Saving writes VISION_MODEL.'],
    impact: ['Affects screenshot extraction and vision analysis.'],
    notes: ['Text-only models may not support vision; use capability checks to confirm.'],
  },
  // ------------------------------------------------------------------
  // Agent configuration
  // ------------------------------------------------------------------
  'settings.agent.AGENT_MODE': {
    title: 'Agent Mode',
    summary: 'Enables the ReAct Agent for stock analysis, replacing the single-turn LLM flow.',
    usage: 'When enabled, the system uses a multi-step reasoning Agent that can call tools, search news, and execute complex reasoning chains.',
    valueNotes: [
      'When disabled, the regular single-turn LLM analysis is used.',
      'Agent mode can be combined with AGENT_ARCH to choose single (classic ReAct) or multi (orchestrator pipeline).',
    ],
    impact: ['Affects stock analysis flow, report quality, and LLM call count.'],
    notes: ['Agent mode consumes more tokens and time; best for scenarios requiring deep reasoning.'],
  },
  'settings.agent.AGENT_MAX_STEPS': {
    title: 'Agent Max Steps',
    summary: 'Controls the maximum reasoning-step limit for the Agent.',
    usage: 'At the default, each sub-agent keeps its preset. Raising it lifts all sub-agents; lowering it caps sub-agents that exceed it.',
    valueNotes: [
      'Higher steps enable deeper reasoning but increase time and token cost.',
      'Complex scenarios (e.g. multi-strategy orchestration) may need higher values.',
    ],
    impact: ['Affects reasoning depth, duration, and token consumption.'],
    notes: ['Very low values may cause incomplete reasoning.'],
  },
  'settings.agent.AGENT_SKILLS': {
    title: 'Agent Strategies',
    summary: 'Specifies the list of strategy skills the Agent uses.',
    usage: 'Use comma-separated strategy names. Leave empty for the default (bull_trend). Set to all to enable all strategies.',
    valueNotes: [
      'Setting specific strategies (not all) makes scheduled tasks automatically use the Agent pipeline.',
      'Available strategies depend on the definition files in the strategies/ directory.',
    ],
    impact: ['Affects strategy selection and final signal aggregation in Agent analysis.'],
    notes: ['Custom strategies must be placed in the AGENT_SKILL_DIR directory.'],
  },
  'settings.agent.AGENT_SKILL_DIR': {
    title: 'Strategy Directory',
    summary: 'Directory containing Agent strategy definition files.',
    usage: 'Enter a path relative to the project root. The directory can contain YAML or SKILL.md strategy definitions.',
    valueNotes: ['The default strategies directory includes built-in strategies.'],
    impact: ['Affects which strategies the Agent can discover.'],
    notes: ['After changing the directory, make sure it contains valid strategy definition files.'],
  },
  'settings.agent.AGENT_NL_ROUTING': {
    title: 'Natural Language Routing',
    summary: 'Allows the bot dispatcher to route stock queries to the Agent via natural language.',
    usage: 'When enabled, high-confidence stock messages in private chat (or @mentions in groups) are automatically routed to the Agent without an explicit command.',
    valueNotes: ['Only affects bot integrations (Feishu, Telegram, etc.), not the Web API.'],
    impact: ['Affects bot interaction experience and Agent trigger method.'],
    notes: ['Requires both Agent mode and the corresponding bot channel to be enabled.'],
  },
  'settings.agent.AGENT_ARCH': {
    title: 'Agent Architecture',
    summary: 'Selects the Agent execution architecture.',
    usage: 'single uses the classic ReAct executor; multi uses the orchestrator pipeline with specialised sub-agents.',
    valueNotes: [
      'single is suitable for simple scenarios with short reasoning chains.',
      'multi supports collaboration among technical analysis, intel, risk, and other specialist sub-agents.',
    ],
    impact: ['Affects the Agent analysis flow, sub-agent scheduling, and report structure.'],
    notes: ['When multi is selected, use AGENT_ORCHESTRATOR_MODE to adjust the pipeline.'],
  },
  'settings.agent.AGENT_ORCHESTRATOR_MODE': {
    title: 'Orchestrator Mode',
    summary: 'Only effective when AGENT_ARCH=multi. Controls which sub-agents the pipeline includes.',
    usage: 'quick: tech→decision; standard: tech→intel→decision; full: tech→intel→risk→decision; specialist: full + per-strategy agents.',
    valueNotes: [
      'More complete modes produce deeper analysis but consume more time and tokens.',
      'specialist mode starts a dedicated Agent for each strategy.',
    ],
    impact: ['Affects multi-Agent analysis depth and resource consumption.'],
    notes: ['This field only takes effect when AGENT_ARCH=multi.'],
  },
  'settings.agent.AGENT_ORCHESTRATOR_TIMEOUT_S': {
    title: 'Agent Timeout',
    summary: 'Shared timeout budget in seconds for Agent execution.',
    usage: 'In single mode it is the overall ReAct loop budget; in multi mode it is the cooperative pipeline budget. Set 0 to disable.',
    valueNotes: [
      'When timed out, the Agent returns partial results.',
      'Consider raising it for multi-stock analysis or specialist mode.',
    ],
    impact: ['Affects the maximum wait time for Agent analysis.'],
    notes: ['Timeout does not affect other stocks in the analysis pipeline.'],
  },
  'settings.agent.AGENT_RISK_OVERRIDE': {
    title: 'Risk Agent Veto',
    summary: 'Allows the risk agent to veto buy signals when critical risk flags are detected.',
    usage: 'When enabled, the risk agent in full/specialist mode can downgrade buy recommendations to hold or sell.',
    valueNotes: ['Only effective when AGENT_ORCHESTRATOR_MODE includes the risk stage.'],
    impact: ['Affects the risk conservatism of final investment recommendations.'],
    notes: ['When disabled, the risk agent opinion is advisory only and cannot override decisions.'],
  },
  'settings.agent.DEEP_RESEARCH': {
    title: 'Deep Research',
    summary: 'Controls the token budget and timeout for Deep Research.',
    usage: 'AGENT_DEEP_RESEARCH_BUDGET sets the maximum token budget; AGENT_DEEP_RESEARCH_TIMEOUT sets the timeout in seconds.',
    valueNotes: [
      'The budget covers planning, follow-up research, and final synthesis.',
      'Higher budgets enable deeper research but increase cost.',
    ],
    impact: ['Affects Deep Research depth and duration.'],
    notes: ['Deep Research is available in Agent mode.'],
  },
  'settings.agent.AGENT_MEMORY_ENABLED': {
    title: 'Agent Memory',
    summary: 'Enables the memory and calibration system that tracks prediction accuracy over time.',
    usage: 'When enabled, the system records each prediction and compares it with actual outcomes to calibrate future confidence.',
    valueNotes: ['Calibration takes effect after sufficient prediction data accumulates.'],
    impact: ['Affects Agent confidence calibration and long-term analysis quality.'],
    notes: ['Works best when combined with the backtest feature.'],
  },
  'settings.agent.AGENT_SKILL_AUTOWEIGHT': {
    title: 'Auto-Weight Strategies',
    summary: 'Automatically weights strategy opinions by their historical backtest performance.',
    usage: 'When enabled, strategies with higher historical accuracy receive more weight in signal aggregation.',
    valueNotes: ['Depends on backtest data; insufficient records may prevent effective weighting.'],
    impact: ['Affects signal weight distribution when multiple strategies contribute.'],
    notes: ['Requires the backtest feature to be enabled with sufficient historical data.'],
  },
  'settings.agent.AGENT_SKILL_ROUTING': {
    title: 'Strategy Routing Mode',
    summary: 'Controls how strategies are selected.',
    usage: 'auto mode detects market regime and picks relevant strategies; manual mode uses only the strategies listed in AGENT_SKILLS.',
    valueNotes: ['auto mode dynamically adjusts strategy selection based on market conditions (bull/bear/range).'],
    impact: ['Affects the strategy coverage during Agent analysis.'],
    notes: ['In manual mode, make sure AGENT_SKILLS is correctly configured.'],
  },
  'settings.agent.context_compression': {
    title: 'Ask-Stock Context Compression',
    summary: 'Controls rolling summary compression for visible ask-stock chat history. It is off by default to preserve existing behavior.',
    usage: 'When AGENT_CONTEXT_COMPRESSION_ENABLED is on, only visible user/assistant text history under the same session_id is compressed; the profile controls the default trigger threshold and protected turns.',
    valueNotes: [
      'cost, balanced, and long_context_raw_first respectively prioritize token savings, balanced behavior, and retaining more raw context.',
      'AGENT_CONTEXT_COMPRESSION_TRIGGER_TOKENS and AGENT_CONTEXT_PROTECTED_TURNS follow the current profile preset when blank, and override the preset when explicitly set.',
    ],
    impact: ['Reduces token usage in long ask-stock conversations, while older details may participate in later answers as summaries.'],
    notes: [
      'This feature does not process provider traces, thinking blocks, tool calls, or tool results, and does not change same-turn tool passthrough.',
      'It only affects visible ask-stock history compression; it does not change LLM provider, model, Base URL, save cleanup, or runtime priority semantics.',
    ],
  },
  'settings.agent.event_monitor': {
    title: 'Event Monitor',
    summary: 'Enables background event monitoring in schedule mode with periodic rule polling.',
    usage: 'AGENT_EVENT_MONITOR_ENABLED turns on monitoring; AGENT_EVENT_MONITOR_INTERVAL_MINUTES sets the polling interval.',
    valueNotes: [
      'Only effective in schedule mode.',
      'Very short intervals may increase API call frequency.',
    ],
    impact: ['Affects background alert detection frequency and notification timing.'],
    notes: ['Must be used with alert rules.'],
  },
  'settings.agent.EVENT_ALERT_RULES_JSON': {
    title: 'Event Alert Rules (Legacy JSON)',
    summary: 'Configures basic price and volume alert rules via a JSON array.',
    usage: 'JSON array format. Each rule has alert_type, stock_code, and condition fields. Only price_cross, price_change_percent, and volume_spike are supported.',
    valueNotes: [
      'Technical indicator, watchlist, portfolio, and market light rules are managed through the Alert API or Web alert center, not this JSON.',
      'Rules are evaluated periodically by the event monitor in schedule mode.',
    ],
    impact: ['Affects background alert detection and notification delivery.'],
    notes: ['This is a legacy configuration method. For advanced rules, use the alert center.'],
  },
  // ------------------------------------------------------------------
  // Backtest configuration
  // ------------------------------------------------------------------
  'settings.backtest.BACKTEST_ENABLED': {
    title: 'Backtest Switch',
    summary: 'Enables or disables historical analysis backtesting.',
    usage: 'When enabled, the system periodically compares past analysis results with subsequent actual price movements to evaluate strategy accuracy.',
    valueNotes: [
      'Backtest data feeds into strategy auto-weighting (AGENT_SKILL_AUTOWEIGHT) and memory calibration.',
      'Disabling backtest stops new evaluations but preserves existing records.',
    ],
    impact: ['Affects strategy weight calibration, memory calibration, and backtest report generation.'],
    notes: ['The Agent strategy auto-weight feature depends on backtest data.'],
  },
  'settings.backtest.eval_params': {
    title: 'Backtest Evaluation Parameters',
    summary: 'Controls the evaluation window, minimum record age, and neutral return band.',
    usage: 'BACKTEST_EVAL_WINDOW_DAYS sets the window in trading days; BACKTEST_MIN_AGE_DAYS only evaluates records older than this; BACKTEST_NEUTRAL_BAND_PCT sets the neutral return band percentage.',
    valueNotes: [
      'Longer evaluation windows include more trading days and produce more stable but delayed results.',
      'BACKTEST_MIN_AGE_DAYS excludes very recent analysis records until enough follow-up price data is available.',
      'Returns within BACKTEST_NEUTRAL_BAND_PCT are labeled neutral, not judged as correct or incorrect.',
    ],
    impact: ['Affects backtest judgment criteria, coverage, and strategy weight calculations.'],
    notes: ['All three parameters jointly affect backtest results; adjust them together.'],
  },
  'settings.backtest.BACKTEST_ENGINE_VERSION': {
    title: 'Backtest Engine Version',
    summary: 'Backtest engine version label.',
    usage: 'Usually no need to change. The label identifies the current evaluation logic version.',
    valueNotes: ['Different versions may use different evaluation algorithms or judgment rules.'],
    impact: ['Affects the evaluation algorithm and results.'],
    notes: ['Keep the default unless instructed to switch versions.'],
  },
  // ------------------------------------------------------------------
  // Report configuration
  // ------------------------------------------------------------------
  'settings.report.REPORT_SUMMARY_ONLY': {
    title: 'Summary Only',
    summary: 'Push only the analysis summary without per-stock details. Useful for quick overview when tracking many stocks.',
    usage: 'When enabled, notifications contain only overall summary info. When disabled, detailed per-stock analysis is included.',
    valueNotes: ['Enable when tracking many stocks to reduce notification length.'],
    impact: ['Affects notification content detail level.'],
    notes: ['Does not affect report viewing in the Web UI.'],
  },
  'settings.report.REPORT_SHOW_LLM_MODEL': {
    title: 'Show Model Name in Reports',
    summary: 'Display the LLM model name in report footers.',
    usage: 'When enabled, the notification footer shows the model identifier. When disabled, it is hidden.',
    valueNotes: ['Only affects report rendering, not model selection, routing, or migration.'],
    impact: ['Affects model information visibility in notification reports.'],
    notes: ['Enable temporarily when diagnosing model switching issues.'],
  },
  'settings.report.REPORT_TEMPLATES_DIR': {
    title: 'Report Templates Directory',
    summary: 'Directory for Jinja2 report templates.',
    usage: 'Enter a path relative to the project root. Place Jinja2 template files in the directory.',
    valueNotes: ['REPORT_RENDERER_ENABLED must also be on for templates to take effect.'],
    impact: ['Affects the template source used for report rendering.'],
    notes: ['Custom templates must follow Jinja2 syntax and include required variable placeholders.'],
  },
  'settings.report.REPORT_RENDERER_ENABLED': {
    title: 'Report Rendering Engine',
    summary: 'Enable the Jinja2 template rendering engine for report output.',
    usage: 'Off by default. When enabled, reports are rendered through Jinja2 templates for custom formatting.',
    valueNotes: ['Default is off for zero regression risk.'],
    impact: ['Affects the final report output format.'],
    notes: ['Make sure REPORT_TEMPLATES_DIR contains valid template files before enabling.'],
  },
  'settings.report.REPORT_INTEGRITY_ENABLED': {
    title: 'Report Integrity Check',
    summary: 'Validate mandatory fields after LLM output; retry or use placeholders for missing fields.',
    usage: 'When enabled, the system checks whether reports contain required analysis fields. REPORT_INTEGRITY_RETRY controls retry count.',
    valueNotes: [
      'Missing fields are filled with placeholders.',
      'Retries increase LLM call count and latency.',
    ],
    impact: ['Affects report completeness and LLM call count.'],
    notes: ['REPORT_INTEGRITY_RETRY=0 disables retries and uses placeholders only.'],
  },
  'settings.report.REPORT_HISTORY_COMPARE_N': {
    title: 'Historical Signal Comparison',
    summary: 'Show the last N analyses signal comparison per stock. Set 0 to disable.',
    usage: 'When enabled, reports include a comparison table of the last N analysis signals.',
    valueNotes: ['Larger N gives a broader comparison but longer tables.'],
    impact: ['Affects the historical signal comparison section in reports.'],
    notes: ['Set to 0 to disable.'],
  },
  'settings.report.SINGLE_STOCK_NOTIFY': {
    title: 'Per-Stock Immediate Notify',
    summary: 'Push immediately after each stock analysis instead of batching all results.',
    usage: 'When enabled, each stock analysis sends a separate notification. When disabled, results are batched.',
    valueNotes: ['Enabled mode is more timely but increases push frequency.'],
    impact: ['Affects notification timing and frequency.'],
    notes: ['Tracking many stocks can produce a large number of notifications when enabled.'],
  },
  'settings.report.MERGE_EMAIL_NOTIFICATION': {
    title: 'Merge Email Notification',
    summary: 'Merge stock analysis and market review into a single email.',
    usage: 'When enabled, stock analysis and market review are combined into one email.',
    valueNotes: ['Only effective when both stock analysis and market review are enabled.'],
    impact: ['Affects email count and content organization.'],
    notes: ['When disabled, stock analysis and market review are sent as separate emails.'],
  },
  // ------------------------------------------------------------------
  // Notification routing
  // ------------------------------------------------------------------
  'settings.notification.channel_routing': {
    title: 'Notification Channel Routing',
    summary: 'Specifies target push channels for different notification types.',
    usage: 'Three routing fields control the target channels for report pushes, alert pushes, and system error pushes. Use comma-separated channel names. Leave empty to push to all configured channels.',
    valueNotes: [
      'NOTIFICATION_REPORT_CHANNELS controls daily analysis report delivery.',
      'NOTIFICATION_ALERT_CHANNELS controls event alert delivery.',
      'NOTIFICATION_SYSTEM_ERROR_CHANNELS controls system error delivery.',
      'Available channels depend on configured notification channels (e.g. email, feishu, telegram).',
    ],
    impact: ['Affects the push targets for different notification types.'],
    notes: ['Specified channels must be properly configured, or they will not work.'],
  },
  'settings.notification.dedup': {
    title: 'Notification Dedup & Cooldown',
    summary: 'Controls the dedup window and cooldown period for static notifications.',
    usage: 'NOTIFICATION_DEDUP_TTL_SECONDS sets the dedup window where the same dedup key is pushed only once. NOTIFICATION_COOLDOWN_SECONDS sets the cooldown window for the same cooldown key.',
    valueNotes: [
      'The two mechanisms work independently.',
      'Setting either to 0 disables that mechanism.',
    ],
    impact: ['Affects notification push frequency and duplicate control.'],
    notes: ['Dynamic notifications (e.g. alerts) have independent trigger and cooldown logic.'],
  },
  'settings.notification.quiet_hours': {
    title: 'Quiet Hours',
    summary: 'Suppress notification delivery during a specified time window.',
    usage: 'NOTIFICATION_QUIET_HOURS uses HH:MM-HH:MM format and supports overnight ranges. NOTIFICATION_TIMEZONE specifies the timezone.',
    valueNotes: [
      'Leave empty to disable quiet hours.',
      'When timezone is empty, the local system timezone is used.',
    ],
    impact: ['Affects when notifications are delivered.'],
    notes: ['Static notifications during quiet hours are suppressed and skipped; they are not queued for later delivery.'],
  },
  'settings.notification.MIN_SEVERITY': {
    title: 'Minimum Notification Severity',
    summary: 'Filters static notifications below the specified severity level.',
    usage: 'When set to warning, only warning and above are pushed. Leave empty for current behavior.',
    valueNotes: ['Severity levels from low to high: info, warning, error, critical.'],
    impact: ['Affects static notification volume.'],
    notes: ['Dynamic notifications (e.g. alerts) have independent event and severity evaluation.'],
  },
  'settings.notification.DAILY_DIGEST_ENABLED': {
    title: 'Daily Digest (Reserved)',
    summary: 'Reserved feature flag. Currently does not send daily digests.',
    usage: 'This is a P4 reserved feature. Enabling it has no effect at this time.',
    valueNotes: ['Preserved for a future daily digest aggregation feature.'],
    impact: ['No current effect.'],
    notes: ['A future version will aggregate the day\'s notifications into a single digest push.'],
  },
  // ------------------------------------------------------------------
  // System runtime
  // ------------------------------------------------------------------
  'settings.system.LOG_LEVEL': {
    title: 'Log Level',
    summary: 'Controls application log verbosity.',
    usage: 'Choose DEBUG, INFO, WARNING, ERROR, or CRITICAL. Higher levels produce fewer logs.',
    valueNotes: [
      'DEBUG outputs the most detailed logs, useful for troubleshooting.',
      'Some runtime components may require a restart to fully apply the new level.',
    ],
    impact: ['Affects log output volume and detail.'],
    notes: ['Some runtime components may need a restart for full effect.'],
  },
  'settings.system.DEBUG': {
    title: 'Debug Mode',
    summary: 'Enables debug mode with verbose logging.',
    usage: 'When enabled, more internal state and debug information is output.',
    valueNotes: ['Disable in production to reduce log volume.'],
    impact: ['Affects log detail and runtime behavior.'],
    notes: ['Debug mode can affect performance; not recommended for long-term use.'],
  },
  'settings.system.MAX_WORKERS': {
    title: 'Max Workers',
    summary: 'Controls the number of concurrent stock analysis threads.',
    usage: 'Set the number of parallel analysis workers. Higher values increase concurrency but also API rate-limit risk.',
    valueNotes: [
      'Keep low to avoid triggering data-source or LLM API rate limits.',
      'Limited by API key quotas and network bandwidth.',
    ],
    impact: ['Affects total analysis time and API call frequency.'],
    notes: ['Too many workers can cause API rate-limit errors.'],
  },
  'settings.system.ANALYSIS_DELAY': {
    title: 'Analysis Delay',
    summary: 'Delay in seconds between stock analyses for rate limiting.',
    usage: 'Set 0 for no delay. A positive value waits the specified seconds after each stock before starting the next.',
    valueNotes: ['Useful when APIs have strict rate limits.'],
    impact: ['Affects total analysis time.'],
    notes: ['Total time ≈ stock count × per-stock time + (count-1) × ANALYSIS_DELAY.'],
  },
  'settings.system.market_review': {
    title: 'Market Review',
    summary: 'Controls the market review feature: on/off, coverage region, and color scheme.',
    usage: 'MARKET_REVIEW_ENABLED toggles market review; MARKET_REVIEW_REGION selects markets (cn/hk/us/both); MARKET_REVIEW_COLOR_SCHEME selects colors.',
    valueNotes: [
      'cn covers A-shares, hk covers Hong Kong, us covers US stocks, both covers all.',
      'Color scheme affects how index changes are displayed: green_up = green for gains/red for losses; red_up = red for gains/green for losses.',
    ],
    impact: ['Affects the market overview section in analysis reports.'],
    notes: ['Market review depends on the availability of index data sources for the selected markets.'],
  },
};

function getPreferredHelpMap(locale?: string | null): SettingsHelpMap {
  if (locale?.toLowerCase().startsWith('en')) {
    return settingsHelpEnUS;
  }
  return settingsHelpZhCN;
}

export function getSettingsHelpContent(
  helpKey?: string | null,
  fallbackDescription?: string,
  locale?: string | null,
): SettingsHelpContent | null {
  if (!helpKey) {
    return null;
  }

  const localized = getPreferredHelpMap(locale)[helpKey] ?? settingsHelpZhCN[helpKey];
  if (localized) {
    return localized;
  }

  if (fallbackDescription) {
    return {
      title: '配置说明',
      summary: fallbackDescription,
    };
  }

  return null;
}
