<template>
  <div class="site-domain-page">
    <div class="site-domain-header">
      <div>
        <h2 class="ops-page-title site-domain-title">站点映射</h2>
        <div class="site-domain-summary">
          <span>全部 {{ total }}</span>
          <span>本页启用 {{ activeRows }}</span>
          <span>本页停用 {{ inactiveRows }}</span>
        </div>
      </div>
      <a-button type="primary" @click="openCreate">
        <template #icon><PlusOutlined /></template>
        新增映射
      </a-button>
    </div>

    <div class="ops-card site-domain-card">
      <div class="ops-toolbar site-domain-toolbar">
        <a-input
          v-model:value="filter.keyword"
          class="site-domain-search"
          placeholder="搜索域名 / Key / 中文名"
          allow-clear
          @press-enter="reload"
          @change="onKeywordChange"
        />
        <a-select
          v-model:value="filter.status"
          class="site-domain-status"
          :options="statusOptions"
          placeholder="状态"
          allow-clear
          @change="onStatusChange"
        />
        <a-button @click="reload">
          <template #icon><ReloadOutlined /></template>
          刷新
        </a-button>
      </div>

      <a-table
        :columns="columns"
        :data-source="rows"
        :loading="loading"
        :pagination="pagination"
        row-key="id"
        @change="onTableChange"
      >
        <template #bodyCell="{ column, record }">
          <template v-if="column.key === 'registrable_domain'">
            <div class="domain-cell">
              <span class="domain-name">{{ record.registrable_domain }}</span>
              <span class="domain-key">{{ record.site_key }}</span>
            </div>
          </template>
          <template v-else-if="column.key === 'site_name'">
            <span class="site-name">{{ record.site_name }}</span>
          </template>
          <template v-else-if="column.key === 'is_active'">
            <a-switch
              :checked="record.is_active"
              :loading="statusLoadingId === record.id"
              checked-children="启用"
              un-checked-children="停用"
              @change="onActiveSwitchChange(record, $event)"
            />
          </template>
          <template v-else-if="column.key === 'updated_at'">
            {{ formatDate(record.updated_at) }}
          </template>
          <template v-else-if="column.key === 'actions'">
            <div class="table-actions-row" style="justify-content: flex-end">
              <a-tooltip title="编辑">
                <a-button
                  type="text"
                  shape="circle"
                  size="small"
                  class="action-btn action-edit"
                  @click="openEdit(record)"
                >
                  <EditOutlined />
                </a-button>
              </a-tooltip>
              <a-tooltip title="删除">
                <a-popconfirm title="确认删除该映射？" @confirm="deleteMapping(record)">
                  <a-button
                    type="text"
                    shape="circle"
                    size="small"
                    class="action-btn action-delete"
                  >
                    <DeleteOutlined />
                  </a-button>
                </a-popconfirm>
              </a-tooltip>
            </div>
          </template>
        </template>
      </a-table>
    </div>

    <a-drawer
      v-model:open="drawerOpen"
      :title="editingRow ? '编辑映射' : '新增映射'"
      width="480"
      :destroy-on-close="true"
      @close="closeDrawer"
    >
      <a-form layout="vertical" :model="form">
        <a-form-item label="匹配域名" required>
          <a-input v-model:value="form.registrable_domain" placeholder="zhihu.com" />
        </a-form-item>
        <a-form-item label="站点 Key">
          <a-input v-model:value="form.site_key" placeholder="默认同匹配域名" />
        </a-form-item>
        <a-form-item label="中文名" required>
          <a-input v-model:value="form.site_name" placeholder="知乎" />
        </a-form-item>
        <a-form-item label="状态">
          <a-switch
            v-model:checked="form.is_active"
            checked-children="启用"
            un-checked-children="停用"
          />
        </a-form-item>
      </a-form>

      <template #footer>
        <div class="drawer-footer">
          <a-button @click="closeDrawer">取消</a-button>
          <a-button type="primary" :loading="saving" @click="submitForm">保存</a-button>
        </div>
      </template>
    </a-drawer>
  </div>
</template>

<script setup lang="ts">
import { DeleteOutlined, EditOutlined, PlusOutlined, ReloadOutlined } from '@ant-design/icons-vue'
import type { TablePaginationConfig } from 'ant-design-vue'
import { message } from 'ant-design-vue'
import dayjs from 'dayjs'
import { computed, onMounted, reactive, ref } from 'vue'

import { showOpsError } from '@/lib/errors'
import { http } from '@/lib/http'

interface SiteDomainMappingRow {
  id: number
  registrable_domain: string
  site_key: string
  site_name: string
  is_active: boolean
  created_at: string
  updated_at: string
}

interface ListResult {
  items: SiteDomainMappingRow[]
  total: number
  page: number
  size: number
}

const filter = reactive({
  keyword: '',
  status: undefined as string | undefined,
})

const statusOptions = [
  { label: '启用', value: 'true' },
  { label: '停用', value: 'false' },
]

const columns = [
  { title: '域名 / Key', key: 'registrable_domain', dataIndex: 'registrable_domain', width: '34%' },
  { title: '中文名', key: 'site_name', dataIndex: 'site_name', width: '22%' },
  { title: '状态', key: 'is_active', width: 120 },
  { title: '更新时间', key: 'updated_at', width: 180 },
  { title: '操作', key: 'actions', width: 120, align: 'right' as const },
]

const rows = ref<SiteDomainMappingRow[]>([])
const loading = ref(false)
const page = ref(1)
const size = ref(20)
const total = ref(0)
const statusLoadingId = ref<number | null>(null)

const activeRows = computed(() => rows.value.filter((row) => row.is_active).length)
const inactiveRows = computed(() => rows.value.length - activeRows.value)

const pagination = computed<TablePaginationConfig>(() => ({
  current: page.value,
  pageSize: size.value,
  total: total.value,
  showSizeChanger: true,
  pageSizeOptions: ['10', '20', '50', '100'],
}))

let keywordTimer: number | null = null

function onKeywordChange() {
  if (keywordTimer) window.clearTimeout(keywordTimer)
  keywordTimer = window.setTimeout(() => {
    page.value = 1
    void reload()
  }, 300)
}

function onStatusChange() {
  page.value = 1
  void reload()
}

async function reload() {
  loading.value = true
  try {
    const result = await http.get<ListResult>('/site-domain-mappings', {
      keyword: filter.keyword || undefined,
      is_active: filter.status || undefined,
      page: page.value,
      size: size.value,
    })
    rows.value = result.items
    total.value = result.total
  } catch (error) {
    handleError(error)
  } finally {
    loading.value = false
  }
}

function onTableChange(pag: TablePaginationConfig) {
  page.value = pag.current ?? 1
  size.value = pag.pageSize ?? 20
  void reload()
}

const drawerOpen = ref(false)
const saving = ref(false)
const editingRow = ref<SiteDomainMappingRow | null>(null)
const form = reactive({
  registrable_domain: '',
  site_key: '',
  site_name: '',
  is_active: true,
})

function resetForm() {
  form.registrable_domain = ''
  form.site_key = ''
  form.site_name = ''
  form.is_active = true
  editingRow.value = null
}

function openCreate() {
  resetForm()
  drawerOpen.value = true
}

function openEdit(row: SiteDomainMappingRow) {
  editingRow.value = row
  form.registrable_domain = row.registrable_domain
  form.site_key = row.site_key
  form.site_name = row.site_name
  form.is_active = row.is_active
  drawerOpen.value = true
}

function closeDrawer() {
  drawerOpen.value = false
}

async function submitForm() {
  const domain = form.registrable_domain.trim()
  const siteName = form.site_name.trim()
  if (!domain) {
    message.warning('请输入匹配域名')
    return
  }
  if (!siteName) {
    message.warning('请输入中文名')
    return
  }

  saving.value = true
  try {
    const payload = {
      registrable_domain: domain,
      site_key: form.site_key.trim(),
      site_name: siteName,
      is_active: form.is_active,
    }
    if (editingRow.value) {
      await http.patch(`/site-domain-mappings/${editingRow.value.id}`, payload)
      message.success('已保存')
    } else {
      await http.post('/site-domain-mappings', payload)
      message.success('已新增')
    }
    drawerOpen.value = false
    resetForm()
    void reload()
  } catch (error) {
    handleError(error)
  } finally {
    saving.value = false
  }
}

async function setActive(row: SiteDomainMappingRow, active: boolean) {
  statusLoadingId.value = row.id
  try {
    await http.post(`/site-domain-mappings/${row.id}/active`, { is_active: active })
    message.success(active ? '已启用' : '已停用')
    row.is_active = active
  } catch (error) {
    handleError(error)
  } finally {
    statusLoadingId.value = null
  }
}

function onActiveSwitchChange(row: SiteDomainMappingRow, checked: unknown) {
  void setActive(row, Boolean(checked))
}

async function deleteMapping(row: SiteDomainMappingRow) {
  try {
    await http.delete(`/site-domain-mappings/${row.id}`)
    message.success('已删除')
    void reload()
  } catch (error) {
    handleError(error)
  }
}

function formatDate(value: string | null | undefined): string {
  return value ? dayjs(value).format('YYYY-MM-DD HH:mm:ss') : '—'
}

function handleError(error: unknown) {
  showOpsError(error)
}

onMounted(() => {
  void reload()
})
</script>

<style scoped>
.site-domain-page {
  display: flex;
  flex-direction: column;
  gap: 16px;
}

.site-domain-header {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 16px;
}

.site-domain-title {
  margin-bottom: 8px;
}

.site-domain-summary {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  color: #64748b;
  font-size: 13px;
}

.site-domain-summary span {
  border: 1px solid #e2e8f0;
  border-radius: 6px;
  background: #fff;
  padding: 4px 8px;
}

.site-domain-card {
  padding-top: 20px;
}

.site-domain-toolbar {
  margin-bottom: 18px;
}

.site-domain-search {
  width: 280px;
}

.site-domain-status {
  width: 140px;
}

.domain-cell {
  display: flex;
  flex-direction: column;
  gap: 4px;
  min-width: 0;
}

.domain-name {
  color: #0f172a;
  font-weight: 650;
  word-break: break-all;
}

.domain-key {
  color: #94a3b8;
  font-size: 12px;
  word-break: break-all;
}

.site-name {
  color: #334155;
  font-weight: 600;
}

.drawer-footer {
  display: flex;
  justify-content: flex-end;
  gap: 8px;
}

@media (max-width: 768px) {
  .site-domain-header {
    align-items: stretch;
    flex-direction: column;
  }

  .site-domain-search,
  .site-domain-status {
    width: 100%;
  }
}
</style>
