import {
  buildDefaultHermesEmployeeForm,
  isHermesEmployeeSettingsReady,
  mergeHermesEmployeeForm
} from './hermesEmployeeSettingsModel.js'

export const SETTINGS_STORAGE_KEY = 'x-financial-settings-draft'
export const CURRENT_YEAR = new Date().getFullYear()
export const CUSTOM_OPENAI_PROVIDER = 'Custom OpenAI Compatible'
export const MODEL_SECRET_MASK = '********'
export const RENDER_SECRET_MASK = '********'

export const SECTION_DEFINITIONS = [
  {
    id: 'profile',
    label: '企业信息',
    title: '系统基本信息',
    desc: '公司名称、品牌与版权',
    longDesc: '统一维护企业名称、系统显示名称和版权信息，保存后会同步更新当前系统品牌展示。',
    actionLabel: '保存企业信息'
  },
  {
    id: 'appearance',
    label: '主题设置',
    title: '主题风格与界面体验',
    desc: '动感、沉稳与智能风格',
    longDesc: '选择当前系统的整体体验风格。主题会联动全局主色、控件状态和 AI 模式的对话呈现。',
    actionLabel: '保存主题设置'
  },
  {
    id: 'admin',
    label: '管理员安全',
    title: '管理员账号与安全策略',
    desc: '账号、密码与登录安全',
    longDesc: '集中管理管理员账号、邮箱和登录安全策略。密码仅在当前输入时可见，不会写入浏览器草稿。',
    actionLabel: '保存安全设置'
  },
  {
    id: 'session',
    label: '会话设置',
    title: '会话留存设置',
    desc: '会话保留天数',
    longDesc: '统一配置智能体会话的保留天数。超过保留期的历史会话会在后端清理，避免上下文和管理成本无限增长。',
    actionLabel: '保存会话设置'
  },
  {
    id: 'aiMemory',
    label: 'AI 记忆',
    title: 'AI 记忆策略',
    desc: '企业与部门智能填充',
    longDesc: '显式维护企业和部门的费用申请记忆，统一控制作用域、版本与有效期。',
    actionLabel: ''
  },
  {
    id: 'hermes',
    label: '数字员工设置',
    title: '数字员工设置',
    desc: '自动任务',
    longDesc: '选择需要自动执行的任务，并设置每天的执行时间。无需了解 Cron 或复杂调度规则。',
    actionLabel: '保存数字员工设置'
  },
  {
    id: 'llm',
    label: '大语言模型',
    title: '模型接入配置',
    desc: '主模型、备份模型与检索模型',
    longDesc: '集中维护主模型、备份模型、Embedding 模型和 Reranker 模型的接入参数，供 AI 助手和检索链路调用。',
    actionLabel: '保存模型配置'
  },
  {
    id: 'rendering',
    label: '文件渲染',
    title: '文件渲染',
    desc: '文档预览服务与访问密钥',
    longDesc: '维护文件渲染开关、文档服务对外地址和 JWT 密钥，后端回调地址继续由部署配置管理。',
    actionLabel: '保存文件渲染配置'
  },
  {
    id: 'logs',
    label: '日志策略',
    title: '日志策略',
    desc: '日志级别、留存与路径',
    longDesc: '定义系统日志级别、留存周期和写入路径，保证问题排查过程可追溯。',
    actionLabel: '保存日志策略'
  },
  {
    id: 'systemLogs',
    label: '系统日志',
    title: '系统日志',
    desc: '运行事件、请求追踪与异常排查',
    longDesc: '查看系统运行日志、结构化事件和请求追踪信息，作为系统设置下的排障与审计子项。',
    actionLabel: ''
  },
  {
    id: 'cacheManagement',
    label: '缓存管理',
    title: '系统缓存管理',
    desc: 'OCR、模型与索引缓存',
    longDesc: '手动清理 OCR 识别结果、模型失败冷却、知识库本地索引和运行时配置等进程内缓存。',
    actionLabel: ''
  },
  {
    id: 'mail',
    label: '邮箱设置',
    title: '邮箱通知配置',
    desc: 'SMTP 与通知投递策略',
    longDesc: '维护系统邮件发送配置和通知投递策略，审批、告警和摘要邮件都会依赖这里的设置。',
    actionLabel: '保存邮箱配置'
  }
]

export const LOG_LEVELS = ['DEBUG', 'INFO', 'WARN', 'ERROR']

export const PROVIDER_OPTIONS = [
  'MiniMax',
  'GLM',
  'Kimi',
  'Ali',
  'Codex',
  'Claude',
  'Gemini',
  CUSTOM_OPENAI_PROVIDER
]

export const PROVIDER_ENDPOINTS = {
  MiniMax: 'https://api.minimaxi.com/v1',
  GLM: 'https://open.bigmodel.cn/api/paas/v4/',
  Kimi: 'https://api.moonshot.ai/v1',
  Ali: 'https://dashscope.aliyuncs.com/compatible-mode/v1',
  Codex: 'https://api.openai.com/v1',
  Claude: 'https://api.anthropic.com/v1/',
  Gemini: 'https://generativelanguage.googleapis.com/v1beta/openai/',
  [CUSTOM_OPENAI_PROVIDER]: ''
}

export const RERANKER_PROVIDER_ENDPOINTS = {
  Ali: 'https://dashscope.aliyuncs.com/api/v1/services/rerank/text-rerank/text-rerank',
  [CUSTOM_OPENAI_PROVIDER]: ''
}

export const LEGACY_PROVIDER_MAP = {
  'OpenAI Compatible': 'Codex',
  'Azure OpenAI': CUSTOM_OPENAI_PROVIDER,
  Ollama: CUSTOM_OPENAI_PROVIDER,
  '自定义网关': CUSTOM_OPENAI_PROVIDER
}

export const MODEL_TEST_CONFIGS = {
  main: {
    label: '主模型',
    providerKey: 'mainProvider',
    modelKey: 'mainModel',
    endpointKey: 'mainEndpoint',
    apiKeyKey: 'mainApiKey',
    capability: 'chat'
  },
  backup: {
    label: '备份模型',
    providerKey: 'backupProvider',
    modelKey: 'backupModel',
    endpointKey: 'backupEndpoint',
    apiKeyKey: 'backupApiKey',
    capability: 'chat'
  },
  embedding: {
    label: 'Embedding 模型',
    providerKey: 'embeddingProvider',
    modelKey: 'embeddingModel',
    endpointKey: 'embeddingEndpoint',
    apiKeyKey: 'embeddingApiKey',
    capability: 'embedding'
  },
  reranker: {
    label: 'Reranker 模型',
    providerKey: 'rerankerProvider',
    modelKey: 'rerankerModel',
    endpointKey: 'rerankerEndpoint',
    apiKeyKey: 'rerankerApiKey',
    capability: 'reranker'
  }
}

export const MODEL_API_KEY_CONFIGS = Object.values(MODEL_TEST_CONFIGS)
export const MODEL_TYPE_OPTIONS = [
  { label: '大语言模型', value: 'llm', capability: 'chat' },
  { label: 'Embedding', value: 'embedding', capability: 'embedding' },
  { label: 'Rerank', value: 'rerank', capability: 'reranker' }
]
export const MODEL_TYPE_LABELS = Object.fromEntries(MODEL_TYPE_OPTIONS.map((option) => [option.value, option.label]))
export const FIXED_MODEL_ROW_DEFINITIONS = [
  {
    slot: 'main',
    type: 'llm',
    providerKey: 'mainProvider',
    modelKey: 'mainModel',
    endpointKey: 'mainEndpoint',
    apiKeyKey: 'mainApiKey',
    configuredKey: 'mainApiKeyConfigured'
  },
  {
    slot: 'backup',
    type: 'llm',
    providerKey: 'backupProvider',
    modelKey: 'backupModel',
    endpointKey: 'backupEndpoint',
    apiKeyKey: 'backupApiKey',
    configuredKey: 'backupApiKeyConfigured'
  },
  {
    slot: 'embedding',
    type: 'embedding',
    providerKey: 'embeddingProvider',
    modelKey: 'embeddingModel',
    endpointKey: 'embeddingEndpoint',
    apiKeyKey: 'embeddingApiKey',
    configuredKey: 'embeddingApiKeyConfigured'
  },
  {
    slot: 'reranker',
    type: 'rerank',
    providerKey: 'rerankerProvider',
    modelKey: 'rerankerModel',
    endpointKey: 'rerankerEndpoint',
    apiKeyKey: 'rerankerApiKey',
    configuredKey: 'rerankerApiKeyConfigured'
  }
]
export const SESSION_RETENTION_OPTIONS = Array.from({ length: 10 }, (_item, index) => ({
  value: index + 1,
  label: `${index + 1} 天`
}))

const FIXED_MODEL_ROW_SLOTS = new Set(FIXED_MODEL_ROW_DEFINITIONS.map((definition) => definition.slot))
const MODEL_TYPE_VALUES = new Set(MODEL_TYPE_OPTIONS.map((option) => option.value))

export function normalizeValue(value) {
  return String(value ?? '').trim()
}

export function normalizeProviderValue(value, fallback = 'Codex') {
  const normalized = normalizeValue(value)

  if (PROVIDER_OPTIONS.includes(normalized)) {
    return normalized
  }

  if (LEGACY_PROVIDER_MAP[normalized]) {
    return LEGACY_PROVIDER_MAP[normalized]
  }

  return fallback
}

export function getProviderEndpoint(provider) {
  return PROVIDER_ENDPOINTS[provider] ?? ''
}

export function getRerankerEndpoint(provider) {
  return RERANKER_PROVIDER_ENDPOINTS[provider] ?? getProviderEndpoint(provider)
}

function normalizeModelType(type, fallback = 'llm') {
  const normalized = normalizeValue(type)
  return MODEL_TYPE_VALUES.has(normalized) ? normalized : fallback
}

export function normalizeLlmModelRows(rows) {
  if (!Array.isArray(rows)) {
    return []
  }

  return rows
    .map((row) => ({
      slot: normalizeValue(row?.slot),
      provider: normalizeProviderValue(row?.provider, CUSTOM_OPENAI_PROVIDER),
      url: normalizeValue(row?.url ?? row?.endpoint),
      apiKey: normalizeValue(row?.apiKey),
      apiKeyConfigured: Boolean(row?.apiKeyConfigured),
      modelId: normalizeValue(row?.modelId ?? row?.model),
      type: normalizeModelType(row?.type)
    }))
    .filter((row) => row.slot)
}

function buildFixedModelRow(llmForm, definition) {
  return {
    slot: definition.slot,
    provider: normalizeProviderValue(llmForm?.[definition.providerKey], 'Codex'),
    url: normalizeValue(llmForm?.[definition.endpointKey]),
    apiKey: normalizeValue(llmForm?.[definition.apiKeyKey]),
    apiKeyConfigured: Boolean(llmForm?.[definition.configuredKey]),
    modelId: normalizeValue(llmForm?.[definition.modelKey]),
    type: definition.type
  }
}

export function buildLlmModelRows(llmForm) {
  const fixedRows = FIXED_MODEL_ROW_DEFINITIONS.map((definition) => buildFixedModelRow(llmForm, definition))
  const customRows = normalizeLlmModelRows(llmForm?.models).filter((row) => !FIXED_MODEL_ROW_SLOTS.has(row.slot))

  return normalizeLlmModelRows([...fixedRows, ...customRows])
}

export function syncLegacyModelFieldsFromRows(llmForm) {
  const rows = normalizeLlmModelRows(llmForm?.models)
  const nextForm = { ...llmForm, models: rows }

  for (const definition of FIXED_MODEL_ROW_DEFINITIONS) {
    const row = rows.find((item) => item.slot === definition.slot)
    if (!row) {
      continue
    }

    nextForm[definition.providerKey] = row.provider
    nextForm[definition.modelKey] = row.modelId
    nextForm[definition.endpointKey] = row.url
    nextForm[definition.apiKeyKey] = row.apiKey
    nextForm[definition.configuredKey] = row.apiKeyConfigured
  }

  return nextForm
}

export function buildDefaultState(companyProfile, currentUser) {
  const companyName = normalizeValue(companyProfile?.name) || 'X-Financial'
  const companyCode = normalizeValue(companyProfile?.code) || 'XF-001'
  const adminEmail =
    normalizeValue(companyProfile?.adminEmail) ||
    normalizeValue(currentUser?.email) ||
    'admin@example.com'
  const adminAccount = normalizeValue(currentUser?.username) || 'superadmin'

  return {
    companyForm: {
      companyName,
      displayName: companyName,
      companyCode,
      logo: normalizeValue(companyProfile?.logo) || '',
      recordNumber: '',
      copyright: `Copyright © 2024-${CURRENT_YEAR} ${companyName}. All Rights Reserved.`
    },
    appearanceForm: {
      themeSkin: 'enterprise'
    },
    adminForm: {
      adminAccount,
      adminEmail,
      newPassword: '',
      confirmPassword: '',
      sessionTimeout: Number(import.meta.env.VITE_AUTH_IDLE_TIMEOUT_MINUTES || 30),
      noticeEmail: adminEmail,
      mfaEnabled: true,
      strongPassword: true,
      loginAlertEnabled: true,
      adminPasswordConfigured: false
    },
    sessionForm: {
      conversationRetentionDays: 3
    },
    llmForm: {
      mainProvider: 'Codex',
      mainModel: 'codex-mini-latest',
      mainEndpoint: getProviderEndpoint('Codex'),
      mainApiKey: '',
      mainApiKeyConfigured: false,
      backupProvider: 'GLM',
      backupModel: 'glm-5.1',
      backupEndpoint: getProviderEndpoint('GLM'),
      backupApiKey: '',
      backupApiKeyConfigured: false,
      embeddingProvider: 'GLM',
      embeddingModel: 'Embedding-3',
      embeddingEndpoint: getProviderEndpoint('GLM'),
      embeddingApiKey: '',
      embeddingApiKeyConfigured: false,
      rerankerProvider: 'Ali',
      rerankerModel: 'gte-rerank-v2',
      rerankerEndpoint: getRerankerEndpoint('Ali'),
      rerankerApiKey: '',
      rerankerApiKeyConfigured: false,
      models: buildLlmModelRows({
        mainProvider: 'Codex',
        mainModel: 'codex-mini-latest',
        mainEndpoint: getProviderEndpoint('Codex'),
        mainApiKey: '',
        mainApiKeyConfigured: false,
        backupProvider: 'GLM',
        backupModel: 'glm-5.1',
        backupEndpoint: getProviderEndpoint('GLM'),
        backupApiKey: '',
        backupApiKeyConfigured: false,
        embeddingProvider: 'GLM',
        embeddingModel: 'Embedding-3',
        embeddingEndpoint: getProviderEndpoint('GLM'),
        embeddingApiKey: '',
        embeddingApiKeyConfigured: false,
        rerankerProvider: 'Ali',
        rerankerModel: 'gte-rerank-v2',
        rerankerEndpoint: getRerankerEndpoint('Ali'),
        rerankerApiKey: '',
        rerankerApiKeyConfigured: false
      })
    },
    renderForm: {
      enabled: false,
      publicUrl: '',
      jwtSecret: '',
      jwtSecretConfigured: false
    },
    logForm: {
      level: 'INFO',
      retentionDays: 180,
      archiveCycle: 'weekly',
      logPath: 'server/logs/app.log',
      alertEmail: adminEmail,
      operationAudit: true,
      loginAudit: true,
      maskSensitive: true
    },
    hermesForm: buildDefaultHermesEmployeeForm(),
    mailForm: {
      smtpHost: 'smtp.exmail.qq.com',
      port: 465,
      encryption: 'SSL/TLS',
      senderName: companyName,
      senderAddress: adminEmail,
      username: adminEmail,
      password: '',
      passwordConfigured: false,
      alertEnabled: true,
      digestEnabled: false,
      digestTime: '09:00',
      defaultReceiver: adminEmail
    }
  }
}

export function readStoredSettings() {
  if (typeof window === 'undefined') {
    return null
  }

  const raw = window.sessionStorage.getItem(SETTINGS_STORAGE_KEY)
  if (!raw) {
    return null
  }

  try {
    return JSON.parse(raw)
  } catch {
    return null
  }
}

export function mergeState(baseState, overrideState) {
  const mergedLlmForm = { ...baseState.llmForm, ...(overrideState?.llmForm || {}) }

  mergedLlmForm.mainProvider = normalizeProviderValue(mergedLlmForm.mainProvider, baseState.llmForm.mainProvider)
  mergedLlmForm.backupProvider = normalizeProviderValue(mergedLlmForm.backupProvider, baseState.llmForm.backupProvider)
  mergedLlmForm.embeddingProvider = normalizeProviderValue(
    mergedLlmForm.embeddingProvider,
    baseState.llmForm.embeddingProvider
  )
  mergedLlmForm.rerankerProvider = normalizeProviderValue(
    mergedLlmForm.rerankerProvider,
    baseState.llmForm.rerankerProvider
  )
  mergedLlmForm.models = buildLlmModelRows(mergedLlmForm)

  return {
    companyForm: { ...baseState.companyForm, ...(overrideState?.companyForm || {}) },
    appearanceForm: { ...baseState.appearanceForm, ...(overrideState?.appearanceForm || {}) },
    adminForm: { ...baseState.adminForm, ...(overrideState?.adminForm || {}) },
    sessionForm: { ...baseState.sessionForm, ...(overrideState?.sessionForm || {}) },
    hermesForm: mergeHermesEmployeeForm({
      ...baseState.hermesForm,
      ...(overrideState?.hermesForm || {})
    }),
    llmForm: mergedLlmForm,
    renderForm: { ...baseState.renderForm, ...(overrideState?.renderForm || {}) },
    logForm: { ...baseState.logForm, ...(overrideState?.logForm || {}) },
    mailForm: { ...baseState.mailForm, ...(overrideState?.mailForm || {}) }
  }
}

export function sanitizeForStorage(state) {
  return {
    companyForm: { ...state.companyForm },
    appearanceForm: { ...state.appearanceForm },
    adminForm: {
      ...state.adminForm,
      newPassword: '',
      confirmPassword: ''
    },
    sessionForm: { ...state.sessionForm },
    hermesForm: mergeHermesEmployeeForm(state.hermesForm),
    llmForm: {
      ...syncLegacyModelFieldsFromRows(state.llmForm),
      mainApiKey: '',
      backupApiKey: '',
      embeddingApiKey: '',
      rerankerApiKey: '',
      models: normalizeLlmModelRows(state.llmForm.models).map((row) => ({
        ...row,
        apiKey: ''
      }))
    },
    renderForm: {
      ...state.renderForm,
      jwtSecret: ''
    },
    logForm: { ...state.logForm },
    mailForm: {
      ...state.mailForm,
      password: ''
    }
  }
}

export function getModelConfiguredKey(apiKeyKey) {
  return `${apiKeyKey}Configured`
}

export function isModelSecretMask(value) {
  return value === MODEL_SECRET_MASK
}

export function maskConfiguredModelSecrets(state) {
  for (const config of MODEL_API_KEY_CONFIGS) {
    const configuredKey = getModelConfiguredKey(config.apiKeyKey)

    if (state.llmForm[configuredKey] && !normalizeValue(state.llmForm[config.apiKeyKey])) {
      state.llmForm[config.apiKeyKey] = MODEL_SECRET_MASK
    }
  }

  state.llmForm.models = normalizeLlmModelRows(state.llmForm.models).map((row) => {
    if (row.apiKeyConfigured && !normalizeValue(row.apiKey)) {
      return { ...row, apiKey: MODEL_SECRET_MASK }
    }
    return row
  })

  return state
}

export function buildLlmPayload(llmForm) {
  const payload = syncLegacyModelFieldsFromRows({
    ...llmForm,
    models: normalizeLlmModelRows(llmForm.models)
  })

  for (const config of MODEL_API_KEY_CONFIGS) {
    if (isModelSecretMask(payload[config.apiKeyKey])) {
      payload[config.apiKeyKey] = ''
    }
  }

  payload.models = normalizeLlmModelRows(payload.models).map((row) => ({
    ...row,
    apiKey: isModelSecretMask(row.apiKey) ? '' : row.apiKey
  }))

  return payload
}

export function isRenderSecretMask(value) {
  return value === RENDER_SECRET_MASK
}

export function maskConfiguredRenderSecret(state) {
  if (state.renderForm.jwtSecretConfigured && !normalizeValue(state.renderForm.jwtSecret)) {
    state.renderForm.jwtSecret = RENDER_SECRET_MASK
  }

  return state
}

export function buildRenderPayload(renderForm) {
  const payload = { ...renderForm }

  if (isRenderSecretMask(payload.jwtSecret)) {
    payload.jwtSecret = ''
  }

  return payload
}

export function persistSettings(state) {
  if (typeof window === 'undefined') {
    return
  }

  window.sessionStorage.setItem(SETTINGS_STORAGE_KEY, JSON.stringify(sanitizeForStorage(state)))
}

export function isModelConfigReady(provider, model, endpoint) {
  return Boolean(normalizeValue(provider) && normalizeValue(model) && normalizeValue(endpoint))
}

export function computeSectionStatus(state) {
  return {
    profile: Boolean(
      normalizeValue(state.companyForm.companyName) &&
        normalizeValue(state.companyForm.displayName) &&
        normalizeValue(state.companyForm.copyright)
    ),
    appearance: true,
    admin: Boolean(
      normalizeValue(state.adminForm.adminAccount) &&
        normalizeValue(state.adminForm.adminEmail) &&
        Number(state.adminForm.sessionTimeout) >= 5
    ),
    session: Boolean(
      Number(state.sessionForm.conversationRetentionDays) >= 1 &&
        Number(state.sessionForm.conversationRetentionDays) <= 10
    ),
    aiMemory: true,
    hermes: isHermesEmployeeSettingsReady(state.hermesForm),
    llm: (() => {
      const rows = normalizeLlmModelRows(state.llmForm.models)
      return Boolean(
        rows.length > 0 &&
          rows.every((row) => isModelConfigReady(row.provider, row.modelId, row.url))
      )
    })(),
    rendering: Boolean(
      !state.renderForm.enabled ||
        (normalizeValue(state.renderForm.publicUrl) &&
          (normalizeValue(state.renderForm.jwtSecret) || state.renderForm.jwtSecretConfigured))
    ),
    logs: Boolean(
      normalizeValue(state.logForm.level) &&
        Number(state.logForm.retentionDays) > 0 &&
        normalizeValue(state.logForm.logPath)
    ),
    systemLogs: true,
    cacheManagement: true,
    mail: Boolean(
      normalizeValue(state.mailForm.smtpHost) &&
        Number(state.mailForm.port) > 0 &&
        normalizeValue(state.mailForm.senderAddress) &&
        normalizeValue(state.mailForm.username)
    )
  }
}
