import { MinusCircleOutlined, PlusOutlined, ReloadOutlined, SaveOutlined, SyncOutlined } from '@ant-design/icons'
import { useEffect, useMemo, useState } from 'react'
import {
  Button,
  Card,
  Col,
  Empty,
  Form,
  Input,
  InputNumber,
  Row,
  Select,
  Space,
  Statistic,
  Switch,
  Tabs,
  Tag,
  Typography,
  message,
} from 'antd'
import { systemApi } from '@/lib/api'

type ConfigMap = Record<string, unknown>
type ConfigPath = Array<string | number>
type ConfigOption = { label: string; value: string | number }
type ConfigFieldSchema = {
  label?: string
  description?: string
  options?: ConfigOption[]
  template?: unknown
  inputType?: 'password' | 'textarea'
}

const groupMetaMap: Record<string, { title: string; summary: string }> = {
  system: {
    title: '系统',
    summary: '服务监听、路由前缀、认证与运行策略。',
  },
  jwt: {
    title: 'JWT',
    summary: '签名密钥、过期时间与签发者配置。',
  },
  zap: {
    title: '日志',
    summary: '日志级别、格式、落盘目录与保留策略。',
  },
  redis: {
    title: 'Redis',
    summary: '默认 Redis 连接与集群模式配置。',
  },
  'redis-list': {
    title: 'Redis 列表',
    summary: '多 Redis 实例配置。',
  },
  mysql: {
    title: 'MySQL',
    summary: 'MySQL 数据源连接参数。',
  },
  pgsql: {
    title: 'PostgreSQL',
    summary: 'PostgreSQL 数据源连接参数。',
  },
  sqlite: {
    title: 'SQLite',
    summary: 'SQLite 数据源连接参数。',
  },
  mssql: {
    title: 'MSSQL',
    summary: 'MSSQL 数据源连接参数。',
  },
  oracle: {
    title: 'Oracle',
    summary: 'Oracle 数据源连接参数。',
  },
  mongo: {
    title: 'MongoDB',
    summary: 'MongoDB 连接与连接池配置。',
  },
  captcha: {
    title: '验证码',
    summary: '验证码开关、有效期与尺寸。',
  },
  cors: {
    title: 'CORS',
    summary: '跨域白名单与请求头策略。',
  },
  email: {
    title: '邮件',
    summary: 'SMTP 发件配置。',
  },
  local: {
    title: '本地存储',
    summary: '本地文件上传路径配置。',
  },
  minio: {
    title: 'MinIO',
    summary: 'MinIO 对象存储配置。',
  },
  qiniu: {
    title: '七牛云',
    summary: '七牛对象存储配置。',
  },
  'aliyun-oss': {
    title: '阿里云 OSS',
    summary: '阿里云对象存储配置。',
  },
  'aws-s3': {
    title: 'AWS S3',
    summary: 'S3 存储桶与访问参数。',
  },
  'hua-wei-obs': {
    title: '华为云 OBS',
    summary: '华为云对象存储配置。',
  },
  'tencent-cos': {
    title: '腾讯云 COS',
    summary: '腾讯云对象存储配置。',
  },
  'cloudflare-r2': {
    title: 'Cloudflare R2',
    summary: 'R2 存储桶与密钥配置。',
  },
  mcp: {
    title: 'MCP',
    summary: 'MCP 服务监听、对外地址与鉴权头。',
  },
  'disk-list': {
    title: '磁盘监控',
    summary: '服务器状态页磁盘挂载点来源。',
  },
  'db-list': {
    title: '数据库列表',
    summary: '多业务数据库配置。',
  },
}

const fieldLabelMap: Record<string, string> = {
  addr: '监听端口',
  'db-type': '数据库类型',
  'router-prefix': '路由前缀',
  'use-strict-auth': '严格权限校验',
  'use-multipoint': '多点登录',
  'use-redis': '启用 Redis',
  'use-mongo': '启用 MongoDB',
  'disable-auto-migrate': '禁用自动迁移',
  'signing-key': '签名密钥',
  'expires-time': '过期时间',
  'buffer-time': '缓冲时间',
  issuer: '签发者',
  level: '日志级别',
  format: '输出格式',
  director: '日志目录',
  'show-line': '显示行号',
  'log-in-console': '控制台输出',
  'retention-day': '保留天数',
  'open-captcha': '验证码开关',
  'open-captcha-timeout': '验证码超时',
  'img-width': '图片宽度',
  'img-height': '图片高度',
  'allow-origin': '允许来源',
  'allow-methods': '允许方法',
  'allow-headers': '允许请求头',
  'expose-headers': '暴露响应头',
  'allow-credentials': '允许携带凭证',
  'mount-point': '挂载点',
  'access-key-id': 'Access Key ID',
  'access-key-secret': 'Access Key Secret',
  'secret-access-key': 'Secret Access Key',
  'secret-key': 'Secret Key',
  'base-url': '基础地址',
  'base-path': '基础路径',
  'path-prefix': '路径前缀',
  'bucket-name': 'Bucket 名称',
  'bucket-url': 'Bucket 地址',
  'auth-header': '鉴权请求头',
  'request_timeout': '请求超时',
}

const dbTypeOptions: ConfigOption[] = [
  { label: 'MySQL', value: 'mysql' },
  { label: 'PostgreSQL', value: 'pgsql' },
  { label: 'SQLite', value: 'sqlite' },
  { label: 'MSSQL', value: 'mssql' },
  { label: 'Oracle', value: 'oracle' },
]

const logModeOptions: ConfigOption[] = [
  { label: 'Silent', value: 'silent' },
  { label: 'Error', value: 'error' },
  { label: 'Warn', value: 'warn' },
  { label: 'Info', value: 'info' },
]

const configFieldSchemaMap: Record<string, ConfigFieldSchema> = {
  'system.db-type': {
    description: '控制主业务数据库驱动类型。',
    options: dbTypeOptions,
  },
  'system.oss-type': {
    description: '控制上传模块实际使用的对象存储实现。',
    options: [
      { label: '本地存储', value: 'local' },
      { label: 'MinIO', value: 'minio' },
      { label: '七牛云', value: 'qiniu' },
      { label: '阿里云 OSS', value: 'aliyun-oss' },
      { label: '华为云 OBS', value: 'hua-wei-obs' },
      { label: '腾讯云 COS', value: 'tencent-cos' },
      { label: 'AWS S3', value: 'aws-s3' },
      { label: 'Cloudflare R2', value: 'cloudflare-r2' },
    ],
  },
  'system.addr': {
    description: '服务监听端口。',
  },
  'system.router-prefix': {
    description: '接口统一前缀，留空表示不追加额外前缀。',
  },
  'system.use-strict-auth': {
    description: '开启后使用树形权限分配模式。',
  },
  'system.disable-auto-migrate': {
    description: '生产环境通常建议开启，避免启动时自动变更表结构。',
  },
  'jwt.signing-key': {
    description: 'JWT 签名密钥。修改后旧 token 会失效。',
    inputType: 'password',
  },
  'jwt.expires-time': {
    description: 'JWT 过期时间，支持 7d、24h 这类时长表达。',
  },
  'jwt.buffer-time': {
    description: '刷新 token 的缓冲时间窗口。',
  },
  'zap.level': {
    description: '日志输出最低级别。',
    options: [
      { label: 'Debug', value: 'debug' },
      { label: 'Info', value: 'info' },
      { label: 'Warn', value: 'warn' },
      { label: 'Error', value: 'error' },
      { label: 'DPanic', value: 'dpanic' },
      { label: 'Panic', value: 'panic' },
      { label: 'Fatal', value: 'fatal' },
    ],
  },
  'zap.format': {
    description: 'console 更便于本地查看，json 更适合日志采集。',
    options: [
      { label: 'Console', value: 'console' },
      { label: 'JSON', value: 'json' },
    ],
  },
  'zap.encode-level': {
    description: '日志级别编码方式。',
    options: [
      { label: 'LowercaseLevelEncoder', value: 'LowercaseLevelEncoder' },
      { label: 'LowercaseColorLevelEncoder', value: 'LowercaseColorLevelEncoder' },
      { label: 'CapitalLevelEncoder', value: 'CapitalLevelEncoder' },
      { label: 'CapitalColorLevelEncoder', value: 'CapitalColorLevelEncoder' },
    ],
  },
  'redis.addr': {
    description: '单实例模式使用的 Redis 地址。',
  },
  'redis.password': {
    description: 'Redis 访问密码。',
    inputType: 'password',
  },
  'redis.clusterAddrs': {
    description: '集群节点地址列表。',
    template: '127.0.0.1:7000',
  },
  'redis-list': {
    description: '多实例 Redis 配置列表。',
    template: {
      name: '',
      addr: '127.0.0.1:6379',
      password: '',
      db: 0,
      useCluster: false,
      clusterAddrs: ['127.0.0.1:7000'],
    },
  },
  'redis-list.[].password': {
    description: 'Redis 访问密码。',
    inputType: 'password',
  },
  'redis-list.[].clusterAddrs': {
    description: '集群节点地址列表。',
    template: '127.0.0.1:7000',
  },
  'mongo.hosts': {
    description: 'MongoDB 主机列表。',
    template: {
      host: '127.0.0.1',
      port: '27017',
    },
  },
  'mongo.password': {
    description: 'MongoDB 访问密码。',
    inputType: 'password',
  },
  'email.secret': {
    description: '邮箱 SMTP 授权码，不建议直接填写登录密码。',
    inputType: 'password',
  },
  'captcha.open-captcha': {
    description: '0 表示每次登录都需要验证码，其他数字表示连续错误次数阈值。',
  },
  'cors.mode': {
    description: '跨域处理策略。',
    options: [
      { label: 'Allow All', value: 'allow-all' },
      { label: 'Whitelist', value: 'whitelist' },
      { label: 'Strict Whitelist', value: 'strict-whitelist' },
    ],
  },
  'cors.whitelist': {
    description: '跨域白名单条目。',
    template: {
      'allow-origin': 'https://example.com',
      'allow-methods': 'POST, GET',
      'allow-headers': 'Content-Type,AccessToken,X-CSRF-Token, Authorization, Token,X-Token,X-User-Id',
      'expose-headers': 'Content-Length, Access-Control-Allow-Origin, Access-Control-Allow-Headers, Content-Type',
      'allow-credentials': true,
    },
  },
  'mysql.log-mode': {
    description: 'Gorm SQL 日志级别。',
    options: logModeOptions,
  },
  'pgsql.log-mode': {
    description: 'Gorm SQL 日志级别。',
    options: logModeOptions,
  },
  'sqlite.log-mode': {
    description: 'Gorm SQL 日志级别。',
    options: logModeOptions,
  },
  'mssql.log-mode': {
    description: 'Gorm SQL 日志级别。',
    options: logModeOptions,
  },
  'oracle.log-mode': {
    description: 'Gorm SQL 日志级别。',
    options: logModeOptions,
  },
  'db-list': {
    description: '附加业务数据库列表。',
    template: {
      type: 'pgsql',
      'alias-name': '',
      prefix: '',
      port: '5432',
      config: '',
      'db-name': '',
      username: '',
      password: '',
      path: '127.0.0.1',
      engine: '',
      'log-mode': 'error',
      'max-idle-conns': 10,
      'max-open-conns': 100,
      singular: false,
      'log-zap': false,
      disable: false,
    },
  },
  'db-list.[].type': {
    description: '数据库驱动类型。',
    options: dbTypeOptions,
  },
  'db-list.[].password': {
    description: '数据库访问密码。',
    inputType: 'password',
  },
  'db-list.[].log-mode': {
    description: 'Gorm SQL 日志级别。',
    options: logModeOptions,
  },
  'qiniu.zone': {
    description: '七牛云存储区域。',
    options: [
      { label: 'ZoneHuaDong', value: 'ZoneHuaDong' },
      { label: 'ZoneHuaBei', value: 'ZoneHuaBei' },
      { label: 'ZoneHuaNan', value: 'ZoneHuaNan' },
      { label: 'ZoneBeiMei', value: 'ZoneBeiMei' },
      { label: 'ZoneXinJiaPo', value: 'ZoneXinJiaPo' },
    ],
  },
  'disk-list': {
    description: '服务器状态页读取的磁盘挂载点列表。',
    template: {
      'mount-point': '/',
    },
  },
}

function isPlainObject(value: unknown): value is ConfigMap {
  return typeof value === 'object' && value !== null && !Array.isArray(value)
}

function cloneConfigValue<T>(value: T): T {
  if (Array.isArray(value)) {
    return value.map((item) => cloneConfigValue(item)) as T
  }

  if (isPlainObject(value)) {
    return Object.fromEntries(
      Object.entries(value).map(([key, item]) => [key, cloneConfigValue(item)]),
    ) as T
  }

  return value
}

function normalizeSchemaPath(path: ConfigPath) {
  return path.map((segment) => (typeof segment === 'number' ? '[]' : String(segment))).join('.')
}

function getFieldSchema(path: ConfigPath) {
  return configFieldSchemaMap[normalizeSchemaPath(path)]
}

function formatLabel(key: string) {
  if (fieldLabelMap[key]) {
    return fieldLabelMap[key]
  }

  return key
    .split(/[-_]/)
    .filter(Boolean)
    .map((segment) => segment[0].toUpperCase() + segment.slice(1))
    .join(' ')
}

function isSensitiveField(path: ConfigPath) {
  return /(password|secret|signing-key|auth-header|token)/i.test(path.join('.'))
}

function shouldUseTextArea(path: ConfigPath, value: string) {
  const leaf = String(path.at(-1) || '')
  return value.includes('\n') || value.length > 60 || /(headers|methods|config|options)/i.test(leaf)
}

export function SystemConfigPage() {
  const [form] = Form.useForm<ConfigMap>()
  const [config, setConfig] = useState<Record<string, unknown>>({})
  const [loading, setLoading] = useState(false)
  const [saving, setSaving] = useState(false)

  const summary = useMemo(() => {
    const system = (config.system || {}) as Record<string, unknown>
    return {
      addr: system.addr || '-',
      dbType: system['db-type'] || '-',
      routerPrefix: system['router-prefix'] || '/',
      strictAuth: String(system['use-strict-auth'] ?? false),
    }
  }, [config])

  const reloadConfig = async () => {
    setLoading(true)
    try {
      const response = await systemApi.getSystemConfig()
      setConfig(response.data.config)
      form.setFieldsValue(cloneConfigValue(response.data.config) as never)
    } finally {
      setLoading(false)
    }
  }

  useEffect(() => {
    let ignore = false

    const bootstrap = async () => {
      setLoading(true)
      try {
        const response = await systemApi.getSystemConfig()
        if (ignore) {
          return
        }

        setConfig(response.data.config)
        form.setFieldsValue(cloneConfigValue(response.data.config) as never)
      } finally {
        if (!ignore) {
          setLoading(false)
        }
      }
    }

    void bootstrap()

    return () => {
      ignore = true
    }
  }, [form])

  const saveConfig = async (reloadAfterSave: boolean) => {
    setSaving(true)
    try {
      await form.validateFields()
      const nextConfig = cloneConfigValue(form.getFieldsValue(true))
      await systemApi.setSystemConfig({ config: nextConfig })
      setConfig(nextConfig)

      if (reloadAfterSave) {
        await systemApi.reloadSystem()
        await reloadConfig()
        message.success('配置已保存，系统已按新配置重新初始化')
        return
      }

      message.success('配置已保存')
    } finally {
      setSaving(false)
    }
  }

  const renderPrimitiveField = (
    namePath: ConfigPath,
    key: string,
    value: unknown,
    labelOverride?: string,
  ) => {
    const fieldKey = namePath.join('.')
    const schema = getFieldSchema(namePath)
    const label = labelOverride || schema?.label || formatLabel(key)

    if (typeof value === 'boolean') {
      return (
        <div key={fieldKey}>
          <Form.Item label={label} name={namePath} valuePropName="checked" extra={schema?.description}>
            <Switch checkedChildren="启用" unCheckedChildren="关闭" />
          </Form.Item>
        </div>
      )
    }

    if (typeof value === 'number') {
      return (
        <div key={fieldKey}>
          <Form.Item label={label} name={namePath} extra={schema?.description}>
            <InputNumber style={{ width: '100%' }} />
          </Form.Item>
        </div>
      )
    }

    const stringValue = typeof value === 'string' ? value : value == null ? '' : String(value)
    const input = schema?.options ? (
      <Select options={schema.options} />
    ) : schema?.inputType === 'textarea' || shouldUseTextArea(namePath, stringValue) ? (
      <Input.TextArea autoSize={{ minRows: 2, maxRows: 4 }} />
    ) : schema?.inputType === 'password' || isSensitiveField(namePath) ? (
      <Input.Password />
    ) : (
      <Input />
    )

    return (
      <div key={fieldKey}>
        <Form.Item label={label} name={namePath} extra={schema?.description}>
          {input}
        </Form.Item>
      </div>
    )
  }

  const renderField = (namePath: ConfigPath, key: string, value: unknown): React.ReactNode => {
    const fieldKey = namePath.join('.')

    if (Array.isArray(value)) {
      const schema = getFieldSchema(namePath)
      const sampleItem = cloneConfigValue(
        schema?.template !== undefined ? schema.template : value.find((item) => item !== undefined) ?? '',
      )

      return (
        <div key={fieldKey} className="config-grid-span-full">
          <Form.List name={namePath}>
            {(fields, { add, remove }) => (
              <Card
                size="small"
                className="config-section-card"
                title={formatLabel(key)}
                extra={
                  <Space size={12}>
                    {schema?.description ? (
                      <Typography.Text className="text-muted">{schema.description}</Typography.Text>
                    ) : null}
                    <Button
                      type="dashed"
                      size="small"
                      icon={<PlusOutlined />}
                      onClick={() => add(cloneConfigValue(sampleItem))}
                    >
                      新增项
                    </Button>
                  </Space>
                }
              >
                {fields.length ? (
                  <div className="config-array-list">
                    {fields.map((field, index) => {
                      const sourceItem = value[index] ?? sampleItem

                      if (isPlainObject(sourceItem)) {
                        return (
                          <Card
                            key={field.key}
                            size="small"
                            className="config-array-item"
                            title={`${formatLabel(key)} ${index + 1}`}
                            extra={
                              <Button
                                type="text"
                                danger
                                size="small"
                                icon={<MinusCircleOutlined />}
                                onClick={() => remove(field.name)}
                              >
                                删除
                              </Button>
                            }
                          >
                            <div className="config-form-grid">
                              {Object.entries(sourceItem).map(([childKey, childValue]) =>
                                renderField([...namePath, field.name, childKey], childKey, childValue),
                              )}
                            </div>
                          </Card>
                        )
                      }

                      return (
                        <Card
                          key={field.key}
                          size="small"
                          className="config-array-item"
                          title={`${formatLabel(key)} ${index + 1}`}
                          extra={
                            <Button
                              type="text"
                              danger
                              size="small"
                              icon={<MinusCircleOutlined />}
                              onClick={() => remove(field.name)}
                            >
                              删除
                            </Button>
                          }
                        >
                          {renderPrimitiveField(
                            [...namePath, field.name],
                            key,
                            sourceItem,
                            `${formatLabel(key)} ${index + 1}`,
                          )}
                        </Card>
                      )
                    })}
                  </div>
                ) : (
                  <Empty image={Empty.PRESENTED_IMAGE_SIMPLE} description={`暂无${formatLabel(key)}配置项`} />
                )}
              </Card>
            )}
          </Form.List>
        </div>
      )
    }

    if (isPlainObject(value)) {
      return (
        <div key={fieldKey} className="config-grid-span-full">
          <Card size="small" className="config-section-card" title={formatLabel(key)}>
            <div className="config-form-grid">
              {Object.entries(value).map(([childKey, childValue]) => renderField([...namePath, childKey], childKey, childValue))}
            </div>
          </Card>
        </div>
      )
    }

    return renderPrimitiveField(namePath, key, value)
  }

  const groupItems = Object.entries(config).map(([groupKey, groupValue]) => {
    const meta = groupMetaMap[groupKey] || {
      title: formatLabel(groupKey),
      summary: '当前分组未登记说明，使用原始配置结构渲染。',
    }

    return {
      key: groupKey,
      label: (
        <div className="config-tab-label">
          <span>{meta.title}</span>
          <small>{meta.summary}</small>
        </div>
      ),
      children: (
        <div className="config-panel-stack">
          <div className="config-group-header">
            <div>
              <Typography.Title level={4} style={{ margin: 0 }}>
                {meta.title}
              </Typography.Title>
              <Typography.Paragraph className="text-muted" style={{ margin: '8px 0 0' }}>
                {meta.summary}
              </Typography.Paragraph>
            </div>
            <Tag color="processing">{groupKey}</Tag>
          </div>
          <div className="config-form-grid">
            {isPlainObject(groupValue)
              ? Object.entries(groupValue).map(([childKey, childValue]) => renderField([groupKey, childKey], childKey, childValue))
              : renderField([groupKey], groupKey, groupValue)}
          </div>
        </div>
      ),
    }
  })

  return (
    <div className="page-stack">
      <Card className="glass-panel page-panel">
        <div className="section-heading">
          <div>
            <Typography.Title level={2} style={{ marginBottom: 8 }}>
              系统配置
            </Typography.Title>
            <Typography.Paragraph className="text-muted" style={{ marginBottom: 0 }}>
              顶部按配置分组切换，表单直接对应服务端配置结构。保存后可以立即触发系统重新初始化，使用新配置生效。
            </Typography.Paragraph>
          </div>
          <Space>
            <Button icon={<ReloadOutlined />} onClick={() => void reloadConfig()} loading={loading}>
              重新拉取
            </Button>
            <Button
              icon={<SyncOutlined />}
              onClick={async () => {
                await systemApi.reloadSystem()
                message.success('系统重载命令已发送')
              }}
            >
              仅重新初始化
            </Button>
            <Button icon={<SaveOutlined />} loading={saving} onClick={() => void saveConfig(false)}>
              保存配置
            </Button>
            <Button type="primary" icon={<SyncOutlined />} loading={saving} onClick={() => void saveConfig(true)}>
              保存并重新初始化
            </Button>
          </Space>
        </div>
        <Row gutter={16}>
          <Col xs={24} md={6}>
            <Card bordered={false}>
              <Statistic title="服务端口" value={String(summary.addr)} />
            </Card>
          </Col>
          <Col xs={24} md={6}>
            <Card bordered={false}>
              <Statistic title="数据库类型" value={String(summary.dbType)} />
            </Card>
          </Col>
          <Col xs={24} md={6}>
            <Card bordered={false}>
              <Statistic title="路由前缀" value={String(summary.routerPrefix)} />
            </Card>
          </Col>
          <Col xs={24} md={6}>
            <Card bordered={false}>
              <Statistic title="严格权限模式" value={String(summary.strictAuth)} />
            </Card>
          </Col>
        </Row>
      </Card>
      <Card className="glass-panel page-panel" loading={loading}>
        <Form form={form} layout="vertical" initialValues={config}>
          <Tabs className="config-tabs" tabPosition="top" items={groupItems} />
        </Form>
      </Card>
    </div>
  )
}
