<script setup lang="ts">
defineOptions({
  name: 'website-edit'
})

import type { MessageReactive } from 'naive-ui'
import { NButton } from 'naive-ui'
import { useGettext } from 'vue3-gettext'
import draggable from 'vuedraggable'

import cert from '@/api/panel/cert'
import home from '@/api/panel/home'
import website from '@/api/panel/website'

const { $gettext } = useGettext()
let messageReactive: MessageReactive | null = null

const current = ref('listen')
const route = useRoute()
const { id } = route.params
const { data: setting, send: fetchSetting } = useRequest(website.config(Number(id)), {
  initialData: {
    id: 0,
    name: '',
    type: 'proxy',
    listens: [],
    domains: [],
    path: '',
    root: '',
    index: [],
    ssl: false,
    ssl_cert: '',
    ssl_key: '',
    hsts: false,
    ocsp: false,
    http_redirect: false,
    ssl_protocols: [],
    ssl_ciphers: '',
    ssl_not_before: '',
    ssl_not_after: '',
    ssl_dns_names: [],
    ssl_issuer: '',
    ssl_ocsp_server: [],
    access_log: '',
    error_log: '',
    php: 0,
    rewrite: '',
    open_basedir: false,
    upstreams: [],
    proxies: []
  }
})
const { data: installedEnvironment } = useRequest(home.installedEnvironment, {
  initialData: {
    webserver: 'nginx',
    php: [
      {
        label: $gettext('Not used'),
        value: 0
      }
    ],
    db: [
      {
        label: '',
        value: ''
      }
    ]
  }
})

// 是否为 Nginx
const isNginx = computed(() => installedEnvironment.value.webserver === 'nginx')
const certs = ref<any>([])
useRequest(cert.certs(1, 10000)).onSuccess(({ data }) => {
  certs.value = data.items
})
const { data: rewrites } = useRequest(website.rewrites, {
  initialData: {}
})
const rewriteOptions = computed(() => {
  return Object.keys(rewrites.value).map((key) => ({
    label: key,
    value: key
  }))
})
const rewriteValue = ref(null)
const title = computed(() => {
  if (setting.value) {
    return $gettext('Edit Website - %{ name }', { name: setting.value.name })
  }
  return $gettext('Edit Website')
})
const certOptions = computed(() => {
  return certs.value.map((item: any) => ({
    label: item.domains.join(', '),
    value: item.id
  }))
})
const selectedCert = ref(null)

const handleSave = () => {
  // 如果开启了ssl但没有任何监听地址设置了ssl，则自动添加443
  if (setting.value.ssl && !setting.value.listens.some((item: any) => item.args?.includes('ssl'))) {
    const args = ['ssl']
    if (isNginx.value) {
      args.push('quic')
    }
    setting.value.listens.push({
      address: '443',
      args
    })
  }
  // 如果关闭了ssl，自动禁用所有ssl和quic
  if (!setting.value.ssl) {
    setting.value.listens = setting.value.listens.filter((item: any) => item.address !== '443') // 443直接删掉
    setting.value.listens.forEach((item: any) => {
      item.args = []
    })
  }

  useRequest(website.saveConfig(Number(id), setting.value)).onSuccess(() => {
    fetchSetting()
    window.$message.success($gettext('Saved successfully'))
  })
}

const handleReset = () => {
  useRequest(website.resetConfig(Number(id))).onSuccess(() => {
    fetchSetting()
    window.$message.success($gettext('Reset successfully'))
  })
}

const handleRewrite = (value: string) => {
  setting.value.rewrite = rewrites.value[value] || ''
}

const isObtainCert = ref(false)
const handleObtainCert = () => {
  isObtainCert.value = true
  messageReactive = window.$message.loading($gettext('Please wait...'), {
    duration: 0
  })
  useRequest(website.obtainCert(Number(id)))
    .onSuccess(() => {
      fetchSetting()
      window.$message.success($gettext('Issued successfully'))
    })
    .onComplete(() => {
      isObtainCert.value = false
      messageReactive?.destroy()
    })
}

const handleSelectCert = (value: number) => {
  const cert = certs.value.find((item: any) => item.id === value)
  if (cert && cert.cert !== '' && cert.key !== '') {
    setting.value.ssl_certificate = cert.cert
    setting.value.ssl_certificate_key = cert.key
  } else {
    window.$message.error($gettext('The selected certificate is invalid'))
  }
}

const clearLog = async () => {
  useRequest(website.clearLog(Number(id))).onSuccess(() => {
    fetchSetting()
    window.$message.success($gettext('Cleared successfully'))
  })
}

const onCreateListen = () => {
  return {
    address: '',
    args: []
  }
}

const toggleArg = (args: string[], arg: string, checked: boolean) => {
  const index = args.indexOf(arg)
  if (checked && index === -1) {
    args.push(arg)
  } else if (!checked && index !== -1) {
    args.splice(index, 1)
  }
}

const hasArg = (args: string[], arg: string) => {
  return args.includes(arg)
}

// ========== Upstreams 相关 ==========
// 添加新的上游
const addUpstream = () => {
  const name = `${setting.value.name.replace(/-/g, '_')}_upstream_${(setting.value.upstreams?.length || 0) + 1}`
  if (!setting.value.upstreams) {
    setting.value.upstreams = []
  }
  setting.value.upstreams.push({
    name,
    servers: {},
    algo: '',
    keepalive: 32,
    resolver: [],
    resolver_timeout: 5 * 1000000000 // 5秒，以纳秒为单位
  })
}

// 删除上游
const removeUpstream = (index: number) => {
  if (setting.value.upstreams) {
    setting.value.upstreams.splice(index, 1)
  }
}

// 为上游添加服务器
const addServerToUpstream = (index: number) => {
  const upstream = setting.value.upstreams[index]
  if (!upstream.servers) {
    upstream.servers = {}
  }
  upstream.servers[`127.0.0.1:${8080 + Object.keys(upstream.servers).length}`] = ''
}

// 更新上游超时时间值
const updateUpstreamTimeoutValue = (upstream: any, value: number) => {
  const parsed = parseDuration(upstream.resolver_timeout)
  upstream.resolver_timeout = buildDuration(value, parsed.unit)
}

// 更新上游超时时间单位
const updateUpstreamTimeoutUnit = (upstream: any, unit: string) => {
  const parsed = parseDuration(upstream.resolver_timeout)
  upstream.resolver_timeout = buildDuration(parsed.value, unit)
}

// ========== Proxies 相关 ==========
// Location 匹配类型选项
const locationMatchTypes = [
  { label: $gettext('Exact Match (=)'), value: '=' },
  { label: $gettext('Priority Prefix Match (^~)'), value: '^~' },
  { label: $gettext('Prefix Match'), value: '' },
  { label: $gettext('Case-sensitive Regex (~)'), value: '~' },
  { label: $gettext('Case-insensitive Regex (~*)'), value: '~*' }
]

// 解析 location 字符串，返回匹配类型和表达式
const parseLocation = (location: string): { type: string; expression: string } => {
  if (!location) return { type: '', expression: '/' }
  // 精确匹配 =
  if (location.startsWith('= ')) {
    return { type: '=', expression: location.slice(2) }
  }
  // 优先前缀匹配 ^~
  if (location.startsWith('^~ ')) {
    return { type: '^~', expression: location.slice(3) }
  }
  // 不区分大小写正则 ~*
  if (location.startsWith('~* ')) {
    return { type: '~*', expression: location.slice(3) }
  }
  // 区分大小写正则 ~
  if (location.startsWith('~ ')) {
    return { type: '~', expression: location.slice(2) }
  }
  // 普通前缀匹配
  return { type: '', expression: location }
}

// 组合 location 字符串
const buildLocation = (type: string, expression: string): string => {
  if (!expression) expression = '/'
  if (type === '') return expression
  return `${type} ${expression}`
}

// 从 URL 提取主机名
const extractHostFromUrl = (url: string): string => {
  try {
    const urlObj = new URL(url)
    return urlObj.hostname
  } catch {
    return ''
  }
}

// 添加新的代理
const addProxy = () => {
  if (!setting.value.proxies) {
    setting.value.proxies = []
  }
  setting.value.proxies.push({
    location: '/',
    pass: 'http://127.0.0.1:8080',
    host: '$host',
    sni: '',
    cache: false,
    buffering: true,
    resolver: [],
    resolver_timeout: 5 * 1000000000, // 5秒，以纳秒为单位
    replaces: {}
  })
}

// 删除代理
const removeProxy = (index: number) => {
  if (setting.value.proxies) {
    setting.value.proxies.splice(index, 1)
  }
}

// 处理 Proxy Pass 变化，自动更新 Host
const handleProxyPassChange = (proxy: any, value: string) => {
  proxy.pass = value
  const extracted = extractHostFromUrl(value)
  if (extracted !== '') {
    proxy.host = extracted
  } else {
    proxy.host = '$host'
  }
}

// 更新 Location 匹配类型
const updateLocationType = (proxy: any, type: string) => {
  const parsed = parseLocation(proxy.location)
  proxy.location = buildLocation(type, parsed.expression)
}

// 更新 Location 表达式
const updateLocationExpression = (proxy: any, expression: string) => {
  const parsed = parseLocation(proxy.location)
  proxy.location = buildLocation(parsed.type, expression)
}

// ========== 时间单位相关 ==========
// Go time.Duration 在 JSON 中以纳秒表示
const NANOSECOND = 1
const SECOND = 1000000000 * NANOSECOND
const MINUTE = 60 * SECOND
const HOUR = 60 * MINUTE

// 时间单位选项
const timeUnitOptions = [
  { label: $gettext('Seconds'), value: 's' },
  { label: $gettext('Minutes'), value: 'm' },
  { label: $gettext('Hours'), value: 'h' }
]

// 从纳秒解析为 {value, unit} 格式
const parseDuration = (ns: number): { value: number; unit: string } => {
  if (!ns || ns <= 0) return { value: 5, unit: 's' }

  if (ns >= HOUR && ns % HOUR === 0) {
    return { value: ns / HOUR, unit: 'h' }
  }
  if (ns >= MINUTE && ns % MINUTE === 0) {
    return { value: ns / MINUTE, unit: 'm' }
  }
  return { value: Math.floor(ns / SECOND), unit: 's' }
}

// 将 {value, unit} 转换为纳秒
const buildDuration = (value: number, unit: string): number => {
  if (!value || value <= 0) value = 5
  switch (unit) {
    case 'h':
      return value * HOUR
    case 'm':
      return value * MINUTE
    default:
      return value * SECOND
  }
}

// 更新超时时间值
const updateTimeoutValue = (proxy: any, value: number) => {
  const parsed = parseDuration(proxy.resolver_timeout)
  proxy.resolver_timeout = buildDuration(value, parsed.unit)
}

// 更新超时时间单位
const updateTimeoutUnit = (proxy: any, unit: string) => {
  const parsed = parseDuration(proxy.resolver_timeout)
  proxy.resolver_timeout = buildDuration(parsed.value, unit)
}
</script>

<template>
  <common-page show-footer :title="title">
    <n-tabs v-model:value="current" type="line" animated>
      <n-tab-pane name="listen" :tab="$gettext('Domain & Listening')">
        <n-form v-if="setting">
          <n-form-item :label="$gettext('Domain')">
            <n-dynamic-input
              v-model:value="setting.domains"
              placeholder="example.com"
              :min="1"
              show-sort-button
            />
          </n-form-item>
          <n-form-item :label="$gettext('Listening Address')">
            <n-dynamic-input
              v-model:value="setting.listens"
              show-sort-button
              :on-create="onCreateListen"
            >
              <template #default="{ value }">
                <div flex w-full items-center>
                  <n-input v-model:value="value.address" clearable />
                  <n-checkbox
                    :checked="hasArg(value.args, 'ssl')"
                    @update:checked="(checked) => toggleArg(value.args, 'ssl', checked)"
                    ml-20
                    mr-20
                    w-120
                  >
                    HTTPS
                  </n-checkbox>
                  <n-checkbox
                    v-if="isNginx"
                    :checked="hasArg(value.args, 'quic')"
                    @update:checked="(checked) => toggleArg(value.args, 'quic', checked)"
                    w-200
                  >
                    QUIC(HTTP3)
                  </n-checkbox>
                </div>
              </template>
            </n-dynamic-input>
          </n-form-item>
        </n-form>
        <n-skeleton v-else text :repeat="10" />
      </n-tab-pane>
      <n-tab-pane name="basic" :tab="$gettext('Basic Settings')">
        <n-form v-if="setting">
          <n-form-item :label="$gettext('Website Directory')">
            <n-input
              v-model:value="setting.path"
              :placeholder="$gettext('Enter website directory (absolute path)')"
            />
          </n-form-item>
          <n-form-item :label="$gettext('Running Directory')">
            <n-input
              v-model:value="setting.root"
              :placeholder="
                $gettext('Enter running directory (needed for Laravel etc.) (absolute path)')
              "
            />
          </n-form-item>
          <n-form-item :label="$gettext('Default Document')">
            <n-dynamic-tags v-model:value="setting.index" />
          </n-form-item>
          <n-form-item v-if="setting.type == 'php'" :label="$gettext('PHP Version')">
            <n-select
              v-model:value="setting.php"
              :default-value="0"
              :options="installedEnvironment.php"
              :placeholder="$gettext('Select PHP Version')"
              @keydown.enter.prevent
            >
            </n-select>
          </n-form-item>
          <n-form-item v-if="setting.type == 'php'" :label="$gettext('Anti-cross-site Attack')">
            <n-switch v-model:value="setting.open_basedir" />
          </n-form-item>
        </n-form>
        <n-skeleton v-else text :repeat="10" />
      </n-tab-pane>
      <n-tab-pane v-if="setting.type === 'proxy'" name="upstreams" :tab="$gettext('Upstreams')">
        <n-flex vertical>
          <!-- 上游卡片列表 -->
          <draggable
            v-model="setting.upstreams"
            item-key="name"
            handle=".drag-handle"
            :animation="200"
            ghost-class="ghost-card"
          >
            <template #item="{ element: upstream, index }">
              <n-card closable @close="removeUpstream(index)" style="margin-bottom: 16px">
                <template #header>
                  <n-flex align="center" :size="8">
                    <!-- 拖拽手柄 -->
                    <div class="drag-handle" cursor-grab>
                      <the-icon icon="mdi:drag" :size="20" />
                    </div>
                    <span>{{ $gettext('Upstream') }}</span>
                    <n-input
                      v-model:value="upstream.name"
                      :placeholder="$gettext('Upstream name')"
                      size="small"
                      style="width: 200px"
                    />
                  </n-flex>
                </template>
                <n-form label-placement="left" label-width="140px">
                  <n-grid :cols="24" :x-gap="16">
                    <n-form-item-gi :span="12" :label="$gettext('Load Balancing Algorithm')">
                      <n-select
                        v-model:value="upstream.algo"
                        :options="[
                          { label: $gettext('Round Robin (default)'), value: '' },
                          { label: 'least_conn', value: 'least_conn' },
                          { label: 'ip_hash', value: 'ip_hash' },
                          { label: 'hash', value: 'hash' },
                          { label: 'random', value: 'random' }
                        ]"
                      />
                    </n-form-item-gi>
                    <n-form-item-gi :span="12" :label="$gettext('Keepalive Connections')">
                      <n-input-number
                        v-model:value="upstream.keepalive"
                        :min="0"
                        :max="1000"
                        style="width: 100%"
                      />
                    </n-form-item-gi>
                    <n-form-item-gi v-if="isNginx" :span="12" :label="$gettext('DNS Resolver')">
                      <n-dynamic-tags
                        v-model:value="upstream.resolver"
                        :placeholder="$gettext('e.g., 8.8.8.8')"
                      />
                    </n-form-item-gi>
                    <n-form-item-gi
                      v-if="isNginx && upstream.resolver?.length"
                      :span="12"
                      :label="$gettext('Resolver Timeout')"
                    >
                      <n-input-group>
                        <n-input-number
                          :value="parseDuration(upstream.resolver_timeout).value"
                          :min="1"
                          :max="3600"
                          style="flex: 1"
                          @update:value="
                            (v: number | null) => updateUpstreamTimeoutValue(upstream, v ?? 5)
                          "
                        />
                        <n-select
                          :value="parseDuration(upstream.resolver_timeout).unit"
                          :options="timeUnitOptions"
                          style="width: 100px"
                          @update:value="(v: string) => updateUpstreamTimeoutUnit(upstream, v)"
                        />
                      </n-input-group>
                    </n-form-item-gi>
                  </n-grid>
                  <n-form-item :label="$gettext('Backend Servers')">
                    <n-flex vertical :size="8" style="width: 100%">
                      <n-flex
                        v-for="(options, address) in upstream.servers"
                        :key="String(address)"
                        :size="8"
                        align="center"
                      >
                        <n-input
                          :default-value="String(address)"
                          :placeholder="$gettext('Server address, e.g., 127.0.0.1:8080')"
                          style="flex: 1"
                          @change="
                            (newAddr: string) => {
                              const oldAddr = String(address)
                              if (newAddr && newAddr !== oldAddr) {
                                upstream.servers[newAddr] = upstream.servers[oldAddr]
                                delete upstream.servers[oldAddr]
                              }
                            }
                          "
                        />
                        <n-input
                          :value="String(options)"
                          :placeholder="$gettext('Options, e.g., weight=5 backup')"
                          style="flex: 1"
                          @update:value="(v: string) => (upstream.servers[String(address)] = v)"
                        />
                        <n-button
                          type="error"
                          secondary
                          size="small"
                          style="flex-shrink: 0"
                          @click="delete upstream.servers[String(address)]"
                        >
                          {{ $gettext('Remove') }}
                        </n-button>
                      </n-flex>
                      <n-button dashed size="small" @click="addServerToUpstream(index)">
                        {{ $gettext('Add Server') }}
                      </n-button>
                    </n-flex>
                  </n-form-item>
                </n-form>
              </n-card>
            </template>
          </draggable>

          <!-- 空状态 -->
          <n-empty v-if="!setting.upstreams || setting.upstreams.length === 0">
            {{ $gettext('No upstreams configured') }}
          </n-empty>

          <!-- 添加按钮 -->
          <n-button type="primary" dashed @click="addUpstream" mb-20>
            {{ $gettext('Add Upstream') }}
          </n-button>
        </n-flex>
      </n-tab-pane>
      <n-tab-pane v-if="setting.type === 'proxy'" name="proxies" :tab="$gettext('Proxies')">
        <n-flex vertical>
          <!-- 代理卡片列表 -->
          <draggable
            v-model="setting.proxies"
            item-key="location"
            handle=".drag-handle"
            :animation="200"
            ghost-class="ghost-card"
          >
            <template #item="{ element: proxy, index }">
              <n-card closable @close="removeProxy(index)" style="margin-bottom: 16px">
                <template #header>
                  <n-flex align="center" :size="8">
                    <!-- 拖拽手柄 -->
                    <div class="drag-handle" cursor-grab>
                      <the-icon icon="mdi:drag" :size="20" />
                    </div>
                    <span>{{ $gettext('Rule') }} #{{ index + 1 }}</span>
                    <n-tag size="small">{{ proxy.location }}</n-tag>
                    <the-icon icon="mdi:arrow-right-bold" :size="20" />
                    <n-tag size="small" type="success">{{ proxy.pass }}</n-tag>
                  </n-flex>
                </template>
                <n-form label-placement="left" label-width="140px">
                  <n-grid :cols="24" :x-gap="16">
                    <n-form-item-gi v-if="isNginx" :span="12" :label="$gettext('Match Type')">
                      <n-select
                        :value="parseLocation(proxy.location).type"
                        :options="locationMatchTypes"
                        @update:value="(v: string) => updateLocationType(proxy, v)"
                      />
                    </n-form-item-gi>
                    <n-form-item-gi :span="isNginx ? 12 : 24" :label="$gettext('Match Expression')">
                      <n-input
                        :value="parseLocation(proxy.location).expression"
                        :placeholder="$gettext('e.g., /, /api, ^/api/v[0-9]+/')"
                        @update:value="(v: string) => updateLocationExpression(proxy, v)"
                      />
                    </n-form-item-gi>
                    <n-form-item-gi :span="12" :label="$gettext('Proxy Pass')">
                      <n-input
                        :value="proxy.pass"
                        :placeholder="
                          $gettext(
                            'Backend address, e.g., http://127.0.0.1:8080 or http://upstream_name'
                          )
                        "
                        @update:value="(v: string) => handleProxyPassChange(proxy, v)"
                      />
                    </n-form-item-gi>
                    <n-form-item-gi :span="12" :label="$gettext('Proxy Host')">
                      <n-input
                        v-model:value="proxy.host"
                        :placeholder="$gettext('Default: $host, or extracted from Proxy Pass')"
                      />
                    </n-form-item-gi>
                    <n-form-item-gi :span="12" :label="$gettext('Proxy SNI')">
                      <n-input
                        v-model:value="proxy.sni"
                        :placeholder="$gettext('Optional, for HTTPS backends')"
                      />
                    </n-form-item-gi>
                    <n-form-item-gi :span="6" :label="$gettext('Enable Cache')">
                      <n-switch v-model:value="proxy.cache" />
                    </n-form-item-gi>
                    <n-form-item-gi :span="6" :label="$gettext('Enable Buffering')">
                      <n-switch v-model:value="proxy.buffering" />
                    </n-form-item-gi>
                    <n-form-item-gi v-if="isNginx" :span="12" :label="$gettext('DNS Resolver')">
                      <n-dynamic-tags
                        v-model:value="proxy.resolver"
                        :placeholder="$gettext('e.g., 8.8.8.8')"
                      />
                    </n-form-item-gi>
                    <n-form-item-gi
                      v-if="isNginx && proxy.resolver.length"
                      :span="12"
                      :label="$gettext('Resolver Timeout')"
                    >
                      <n-input-group>
                        <n-input-number
                          :value="parseDuration(proxy.resolver_timeout).value"
                          :min="1"
                          :max="3600"
                          style="flex: 1"
                          @update:value="(v: number | null) => updateTimeoutValue(proxy, v ?? 5)"
                        />
                        <n-select
                          :value="parseDuration(proxy.resolver_timeout).unit"
                          :options="timeUnitOptions"
                          style="width: 100px"
                          @update:value="(v: string) => updateTimeoutUnit(proxy, v)"
                        />
                      </n-input-group>
                    </n-form-item-gi>
                  </n-grid>
                  <n-divider>{{ $gettext('Response Content Replacement') }}</n-divider>
                  <n-flex vertical :size="8">
                    <n-flex
                      v-for="(toValue, fromValue) in proxy.replaces"
                      :key="String(fromValue)"
                      :size="8"
                      align="center"
                    >
                      <n-input
                        :value="String(fromValue)"
                        :placeholder="$gettext('Original content')"
                        style="flex: 1"
                        @blur="
                          (e: FocusEvent) => {
                            const newFrom = (e.target as HTMLInputElement).value
                            const oldFrom = String(fromValue)
                            if (newFrom && newFrom !== oldFrom) {
                              proxy.replaces[newFrom] = proxy.replaces[oldFrom]
                              delete proxy.replaces[oldFrom]
                            }
                          }
                        "
                      />
                      <span style="flex-shrink: 0">=></span>
                      <n-input
                        :value="String(toValue)"
                        :placeholder="$gettext('Replacement content')"
                        style="flex: 1"
                        @update:value="(v: string) => (proxy.replaces[String(fromValue)] = v)"
                      />
                      <n-button
                        type="error"
                        secondary
                        size="small"
                        style="flex-shrink: 0"
                        @click="delete proxy.replaces[String(fromValue)]"
                      >
                        {{ $gettext('Remove') }}
                      </n-button>
                    </n-flex>
                    <n-button
                      dashed
                      size="small"
                      @click="
                        () => {
                          if (!proxy.replaces) proxy.replaces = {}
                          proxy.replaces[`/old_${Object.keys(proxy.replaces).length}`] = '/new'
                        }
                      "
                    >
                      {{ $gettext('Add Replacement Rule') }}
                    </n-button>
                  </n-flex>
                </n-form>
              </n-card>
            </template>
          </draggable>

          <!-- 空状态 -->
          <n-empty v-if="!setting.proxies || setting.proxies.length === 0">
            {{ $gettext('No proxy rules configured') }}
          </n-empty>

          <!-- 添加按钮 -->
          <n-button type="primary" dashed @click="addProxy" mb-20>
            {{ $gettext('Add Proxy Rule') }}
          </n-button>
        </n-flex>
      </n-tab-pane>
      <n-tab-pane name="https" tab="HTTPS">
        <n-flex vertical v-if="setting">
          <n-card v-if="setting.ssl && setting.ssl_issuer != ''">
            <n-descriptions :title="$gettext('Certificate Information')" :column="2">
              <n-descriptions-item>
                <template #label>{{ $gettext('Certificate Validity') }}</template>
                <n-flex>
                  <n-tag>{{ setting.ssl_not_before }}</n-tag>
                  -
                  <n-tag>{{ setting.ssl_not_after }}</n-tag>
                </n-flex>
              </n-descriptions-item>
              <n-descriptions-item>
                <template #label>{{ $gettext('Issuer') }}</template>
                <n-flex>
                  <n-tag>{{ setting.ssl_issuer }}</n-tag>
                </n-flex>
              </n-descriptions-item>
              <n-descriptions-item>
                <template #label>{{ $gettext('Domains') }}</template>
                <n-flex>
                  <n-tag v-for="item in setting.ssl_dns_names" :key="item">{{ item }}</n-tag>
                </n-flex>
              </n-descriptions-item>
              <n-descriptions-item>
                <template #label>OCSP</template>
                <n-flex>
                  <n-tag v-for="item in setting.ssl_ocsp_server" :key="item">{{ item }}</n-tag>
                </n-flex>
              </n-descriptions-item>
            </n-descriptions>
          </n-card>
          <n-form>
            <n-grid :cols="24" :x-gap="24">
              <n-form-item-gi :span="12" :label="$gettext('Main Switch')">
                <n-switch v-model:value="setting.ssl" />
              </n-form-item-gi>
              <n-form-item-gi
                v-if="setting.ssl"
                :span="12"
                :label="$gettext('Use Existing Certificate')"
              >
                <n-select
                  v-model:value="selectedCert"
                  :options="certOptions"
                  @update-value="handleSelectCert"
                />
              </n-form-item-gi>
            </n-grid>
          </n-form>
          <n-form inline v-if="setting.ssl">
            <n-form-item label="HSTS">
              <n-switch v-model:value="setting.hsts" />
            </n-form-item>
            <n-form-item :label="$gettext('HTTP Redirect')">
              <n-switch v-model:value="setting.http_redirect" />
            </n-form-item>
            <n-form-item :label="$gettext('OCSP Stapling')">
              <n-switch v-model:value="setting.ocsp" />
            </n-form-item>
          </n-form>
          <n-form v-if="setting.ssl">
            <n-form-item :label="$gettext('TLS Version')">
              <n-select
                v-model:value="setting.ssl_protocols"
                :options="[
                  { label: 'TLS 1.0', value: 'TLSv1.0' },
                  { label: 'TLS 1.1', value: 'TLSv1.1' },
                  { label: 'TLS 1.2', value: 'TLSv1.2' },
                  { label: 'TLS 1.3', value: 'TLSv1.3' }
                ]"
                multiple
              />
            </n-form-item>
            <n-form-item :label="$gettext('Cipher Suites')">
              <n-input
                type="textarea"
                v-model:value="setting.ssl_ciphers"
                :placeholder="$gettext('Enter the cipher suite, leave blank to reset to default')"
                rows="4"
              />
            </n-form-item>
            <n-form-item :label="$gettext('Certificate')">
              <n-input
                v-model:value="setting.ssl_cert"
                type="textarea"
                :placeholder="$gettext('Enter the content of the PEM certificate file')"
                :autosize="{ minRows: 10, maxRows: 15 }"
              />
            </n-form-item>
            <n-form-item :label="$gettext('Private Key')">
              <n-input
                v-model:value="setting.ssl_key"
                type="textarea"
                :placeholder="$gettext('Enter the content of the KEY private key file')"
                :autosize="{ minRows: 10, maxRows: 15 }"
              />
            </n-form-item>
          </n-form>
        </n-flex>
        <n-skeleton v-else text :repeat="10" />
      </n-tab-pane>
      <n-tab-pane v-if="setting.type == 'php'" name="rewrite" :tab="$gettext('Rewrite')">
        <n-flex vertical>
          <n-form label-placement="left" label-width="auto">
            <n-form-item :label="$gettext('Presets')">
              <n-select
                v-model:value="rewriteValue"
                clearable
                :options="rewriteOptions"
                @update-value="handleRewrite"
              />
            </n-form-item>
          </n-form>
          <common-editor v-if="setting" v-model:value="setting.rewrite" height="60vh" />
        </n-flex>
      </n-tab-pane>
      <n-tab-pane name="log" :tab="$gettext('Access Log')">
        <n-flex vertical>
          <n-flex flex items-center>
            <n-alert type="warning" w-full>
              {{ $gettext('All logs can be viewed by downloading the file') }}
              <n-tag>{{ setting.access_log }}</n-tag>
              {{ $gettext('view') }}.
            </n-alert>
            <n-popconfirm @positive-click="clearLog">
              <template #trigger>
                <n-button type="primary">
                  {{ $gettext('Clear Logs') }}
                </n-button>
              </template>
              {{ $gettext('Are you sure you want to clear?') }}
            </n-popconfirm>
          </n-flex>
          <realtime-log :path="setting.access_log" />
        </n-flex>
      </n-tab-pane>
      <n-tab-pane name="error_log" :tab="$gettext('Error Log')">
        <n-flex vertical>
          <n-flex flex items-center>
            <n-alert type="warning" w-full>
              {{ $gettext('All logs can be viewed by downloading the file') }}
              <n-tag>{{ setting.error_log }}</n-tag>
              {{ $gettext('view') }}.
            </n-alert>
          </n-flex>
          <realtime-log :path="setting.error_log" />
        </n-flex>
      </n-tab-pane>
    </n-tabs>
    <n-button v-if="current !== 'log'" type="primary" @click="handleSave">
      {{ $gettext('Save') }}
    </n-button>
    <n-button
      v-if="current === 'https' && setting && setting.domains.length > 0"
      :loading="isObtainCert"
      :disabled="isObtainCert"
      class="ml-16"
      type="info"
      @click="handleObtainCert"
    >
      {{ $gettext('One-click Certificate Issuance') }}
    </n-button>
    <n-popconfirm v-if="current === 'config'" @positive-click="handleReset">
      <template #trigger>
        <n-button type="warning" ml-16>
          {{ $gettext('Reset Configuration') }}
        </n-button>
      </template>
      {{ $gettext('Are you sure you want to reset the configuration?') }}
    </n-popconfirm>
  </common-page>
</template>

<style scoped>
/* 拖拽时的占位卡片 */
:deep(.ghost-card) {
  opacity: 0.5;
}
</style>
