<script setup lang="ts">
import { computed, onMounted, reactive, ref } from 'vue'
import { ElMessage, ElMessageBox } from 'element-plus'
import { Plus, Refresh, Search, UploadFilled } from '@element-plus/icons-vue'

import {
  batchCreateQrCodes,
  deleteQrCode,
  fetchQrCodeStats,
  fetchQrCodes,
  updateQrCode,
  type ChatQrCode,
  type CreateQrCodePayload,
  type QrCodeStatus,
  type QrCodeStats,
} from '@/features/admin/api/adminQrCodes'
import { uploadAdminFile } from '@/shared/api/files'
import { formatDateTime } from '@/shared/utils/time'
import AdminTablePagination from '../components/AdminTablePagination.vue'
import AuthImage from '@/shared/components/business/AuthImage.vue'

const loading = ref(false)
const qrcodes = ref<ChatQrCode[]>([])
const stats = ref<QrCodeStats>({ unused_count: 0, used_count: 0, disabled_count: 0, total_count: 0 })

const currentPage = ref(1)
const currentPageSize = ref(20)
const total = ref(0)
const statusFilter = ref<QrCodeStatus | ''>('')

// 上传弹窗
const uploadVisible = ref(false)
const uploadPendingCount = ref(0)
const uploadSaving = ref(false)
const uploadedImages = ref<{ url: string; file: File }[]>([])
const uploadForm = reactive({
  note: '',
  expires_at: '' as string,
})

// 编辑弹窗
const editVisible = ref(false)
const editUploading = ref(false)
const editForm = reactive({
  id: 0,
  image_url: '',
  note: '',
  status: 'unused' as QrCodeStatus,
  expires_at: '' as string,
})

const statusOptions: { label: string; value: QrCodeStatus | ''; type: string }[] = [
  { label: '全部', value: '', type: 'info' },
  { label: '待用', value: 'unused', type: 'success' },
  { label: '已发放', value: 'used', type: 'primary' },
  { label: '已停用', value: 'disabled', type: 'danger' },
]

const statusMap = computed(() => {
  const m: Record<string, { label: string; type: string }> = {}
  statusOptions.forEach(o => {
    if (o.value) m[o.value] = { label: o.label, type: o.type }
  })
  return m
})

const maxBatchUploadCount = 20
const uploading = computed(() => uploadPendingCount.value > 0)
const uploadBusy = computed(() => uploading.value || uploadSaving.value)
const uploadedImageCountText = computed(() => `${uploadedImages.value.length}/${maxBatchUploadCount}`)

async function loadList() {
  loading.value = true
  try {
    const res = await fetchQrCodes({
      status: statusFilter.value || undefined,
      page: currentPage.value,
      limit: currentPageSize.value,
    })
    qrcodes.value = res.items
    total.value = res.total
  } finally {
    loading.value = false
  }
}

async function loadStats() {
  stats.value = await fetchQrCodeStats()
}

async function reloadAll() {
  await Promise.all([loadList(), loadStats()])
}

function handleFilter() {
  currentPage.value = 1
  loadList()
}

function handlePageChange() {
  loadList()
}

// 上传：逐个上传图片拿 URL
async function handleFileUpload(options: { file: File }) {
  if (uploadedImages.value.length + uploadPendingCount.value >= maxBatchUploadCount) {
    ElMessage.warning(`单次最多添加 ${maxBatchUploadCount} 张二维码`)
    return
  }
  if (!options.file.type.startsWith('image/')) {
    ElMessage.warning('只能上传图片文件')
    return
  }

  uploadPendingCount.value += 1
  try {
    const uploaded = await uploadAdminFile(options.file, 'qrcode')
    uploadedImages.value.push({ url: uploaded.url, file: options.file })
  } catch {
    ElMessage.error('图片上传失败')
  } finally {
    uploadPendingCount.value = Math.max(0, uploadPendingCount.value - 1)
  }
}

function removeImage(index: number) {
  uploadedImages.value.splice(index, 1)
}

function handleUploadExceed() {
  ElMessage.warning(`单次最多添加 ${maxBatchUploadCount} 张二维码`)
}

function openUpload() {
  uploadedImages.value = []
  uploadForm.note = ''
  uploadForm.expires_at = ''
  uploadVisible.value = true
}

async function submitUpload() {
  if (uploadPendingCount.value > 0) {
    ElMessage.warning('图片还在上传中，请稍后保存')
    return
  }
  if (uploadedImages.value.length === 0) {
    ElMessage.warning('请先上传二维码图片')
    return
  }
  uploadSaving.value = true
  try {
    const expiresAt = uploadForm.expires_at
      ? new Date(uploadForm.expires_at).toISOString()
      : null
    const items: CreateQrCodePayload[] = uploadedImages.value.map(img => ({
      image_url: img.url,
      note: uploadForm.note,
      expires_at: expiresAt,
    }))
    await batchCreateQrCodes(items)
    ElMessage.success(`已批量添加 ${items.length} 张二维码`)
    uploadVisible.value = false
    await reloadAll()
  } finally {
    uploadSaving.value = false
  }
}

function openEdit(row: ChatQrCode) {
  editForm.id = row.id
  editForm.image_url = row.image_url
  editForm.note = row.note
  editForm.status = row.status
  editForm.expires_at = row.expires_at ? row.expires_at.replace('T', ' ').slice(0, 16) : ''
  editVisible.value = true
}

function clearEditExpiresAt() {
  editForm.expires_at = ''
}

async function handleEditImageUpload(options: { file: File }) {
  editUploading.value = true
  try {
    const uploaded = await uploadAdminFile(options.file, 'qrcode')
    editForm.image_url = uploaded.url
    ElMessage.success('图片已上传')
  } catch {
    ElMessage.error('图片上传失败')
  } finally {
    editUploading.value = false
  }
}

async function submitEdit() {
  await updateQrCode(editForm.id, {
    image_url: editForm.image_url,
    note: editForm.note,
    status: editForm.status,
    expires_at: editForm.expires_at ? new Date(editForm.expires_at).toISOString() : undefined,
    clear_expires_at: !editForm.expires_at,
  })
  ElMessage.success('已更新')
  editVisible.value = false
  await reloadAll()
}

async function handleDisable(row: ChatQrCode) {
  await ElMessageBox.confirm('确定停用该二维码？停用后不再发放给新发布群。', '停用确认', {
    type: 'warning',
  })
  await updateQrCode(row.id, { status: 'disabled' })
  ElMessage.success('已停用')
  await reloadAll()
}

async function handleDelete(row: ChatQrCode) {
  await ElMessageBox.confirm('确定删除该二维码？仅未使用的二维码可删除。', '删除确认', {
    type: 'warning',
  })
  await deleteQrCode(row.id)
  ElMessage.success('已删除')
  await reloadAll()
}

onMounted(reloadAll)
</script>

<template>
  <div class="qrcode-pool-view">
    <!-- 库存统计卡片 -->
    <div class="stats-cards">
      <el-card shadow="hover" class="stat-card">
        <div class="stat-value success">{{ stats.unused_count }}</div>
        <div class="stat-label">待用库存</div>
      </el-card>
      <el-card shadow="hover" class="stat-card">
        <div class="stat-value primary">{{ stats.used_count }}</div>
        <div class="stat-label">已发放</div>
      </el-card>
      <el-card shadow="hover" class="stat-card">
        <div class="stat-value danger">{{ stats.disabled_count }}</div>
        <div class="stat-label">已停用</div>
      </el-card>
      <el-card shadow="hover" class="stat-card">
        <div class="stat-value">{{ stats.total_count }}</div>
        <div class="stat-label">合计</div>
      </el-card>
    </div>

    <!-- 工具栏 -->
    <el-card shadow="never" class="toolbar-card">
      <div class="toolbar">
        <div class="filter-area">
          <el-select
            v-model="statusFilter"
            placeholder="状态筛选"
            clearable
            style="width: 140px"
            @change="handleFilter"
          >
            <el-option
              v-for="opt in statusOptions.filter(o => o.value)"
              :key="opt.value"
              :label="opt.label"
              :value="opt.value"
            />
          </el-select>
          <el-button :icon="Search" @click="handleFilter">筛选</el-button>
        </div>
        <div class="action-area">
          <el-button :icon="Refresh" @click="reloadAll">刷新</el-button>
          <el-button type="primary" :icon="Plus" @click="openUpload">添加二维码</el-button>
        </div>
      </div>
    </el-card>

    <!-- 列表 -->
    <el-card shadow="never" class="table-card">
      <el-table v-loading="loading" :data="qrcodes" class="table-panel qrcode-table" :fit="true">
        <el-table-column label="二维码" class-name="qr-col" align="center">
          <template #default="{ row }">
            <div class="qrcode-thumb">
              <AuthImage
                :source="row.image_url"
                fit="cover"
                :image-style="{ width: '56px', height: '56px', borderRadius: '6px' }"
                :preview-src-list="[row.image_url]"
              />
            </div>
          </template>
        </el-table-column>
        <el-table-column label="状态" class-name="status-col" align="center">
          <template #default="{ row }">
            <el-tag :type="(statusMap[row.status]?.type as any) || 'info'" size="small">
              {{ statusMap[row.status]?.label || row.status }}
            </el-tag>
          </template>
        </el-table-column>
        <el-table-column label="备注" class-name="note-col" show-overflow-tooltip>
          <template #default="{ row }">
            <span class="note-cell">{{ row.note || '-' }}</span>
          </template>
        </el-table-column>
        <el-table-column label="绑定群" class-name="group-col" align="center">
          <template #default="{ row }">
            <span class="group-cell">{{ row.conversation_id ? `#${row.conversation_id}` : '-' }}</span>
          </template>
        </el-table-column>
        <el-table-column label="过期时间" class-name="expire-col" align="center">
          <template #default="{ row }">
            <span
              class="expire-cell"
              :class="{ 'expired-tag': row.expires_at && new Date(row.expires_at) < new Date() }"
            >
              {{ row.expires_at ? formatDateTime(row.expires_at) : '永久' }}
            </span>
          </template>
        </el-table-column>
        <el-table-column label="操作" class-name="action-col" align="center">
          <template #default="{ row }">
            <div class="table-actions">
              <el-button text type="primary" size="small" @click="openEdit(row)">编辑</el-button>
              <el-button
                v-if="row.status !== 'disabled'"
                text
                type="warning"
                size="small"
                @click="handleDisable(row)"
                >停用</el-button
              >
              <el-button
                v-if="row.status === 'unused'"
                text
                type="danger"
                size="small"
                @click="handleDelete(row)"
                >删除</el-button
              >
            </div>
          </template>
        </el-table-column>
      </el-table>

      <AdminTablePagination
        v-model:current-page="currentPage"
        v-model:page-size="currentPageSize"
        :total="total"
        :loading="loading"
        @page-change="handlePageChange"
      />
    </el-card>

    <!-- 上传弹窗 -->
    <el-dialog v-model="uploadVisible" title="批量添加企业微信群二维码" width="680px">
      <el-form class="qrcode-upload-form" label-width="108px">
        <el-form-item label="二维码图片" required>
          <div class="batch-upload-area">
            <el-upload
              :auto-upload="true"
              :show-file-list="false"
              :http-request="(opt: any) => handleFileUpload(opt)"
              accept="image/*"
              multiple
              drag
              :limit="maxBatchUploadCount"
              :disabled="uploadBusy || uploadedImages.length >= maxBatchUploadCount"
              :on-exceed="handleUploadExceed"
            >
              <el-icon class="el-icon--upload"><UploadFilled /></el-icon>
              <div class="el-upload__text">点击或拖拽上传，支持多选</div>
              <template #tip>
                <div class="upload-tip">
                  已选择 {{ uploadedImageCountText }}
                  <span v-if="uploadPendingCount > 0">，{{ uploadPendingCount }} 张上传中</span>
                </div>
              </template>
            </el-upload>
            <div v-if="uploadedImages.length" class="uploaded-list">
              <div v-for="(img, idx) in uploadedImages" :key="idx" class="uploaded-item">
                <div class="uploaded-thumb">
                  <AuthImage
                    :source="img.url"
                    fit="cover"
                    :image-style="{ width: '52px', height: '52px', borderRadius: '6px' }"
                    :preview-src-list="uploadedImages.map(item => item.url)"
                  />
                  <button
                    class="uploaded-remove"
                    type="button"
                    :disabled="uploadBusy"
                    @click="removeImage(idx)"
                  >
                    ×
                  </button>
                </div>
                <div class="uploaded-name" :title="img.file.name">{{ img.file.name }}</div>
              </div>
            </div>
          </div>
        </el-form-item>
        <el-form-item label="备注">
          <el-input v-model="uploadForm.note" placeholder="如：7月企微群A（统一备注，适用于同一批次）" maxlength="50" />
        </el-form-item>
        <el-form-item label="过期时间">
          <el-date-picker
            v-model="uploadForm.expires_at"
            type="datetime"
            placeholder="留空默认7天后过期"
            format="YYYY-MM-DD HH:mm"
            value-format="YYYY-MM-DDTHH:mm"
            style="width: 100%"
          />
        </el-form-item>
      </el-form>
      <template #footer>
        <el-button :disabled="uploadBusy" @click="uploadVisible = false">取消</el-button>
        <el-button type="primary" :loading="uploadBusy" @click="submitUpload">
          保存{{ uploadedImages.length > 0 ? `（${uploadedImages.length} 张）` : '' }}
        </el-button>
      </template>
    </el-dialog>

    <!-- 编辑弹窗 -->
    <el-dialog v-model="editVisible" title="编辑二维码" width="440px">
      <el-form label-width="90px">
        <el-form-item label="二维码图片">
          <div class="edit-image-area">
            <div class="edit-image-preview">
              <AuthImage
                v-if="editForm.image_url"
                :source="editForm.image_url"
                fit="cover"
                :preview-src-list="[editForm.image_url]"
                :image-style="{ width: '100%', height: '100%', borderRadius: '6px' }"
              />
              <div v-else class="edit-image-empty">暂无图片</div>
            </div>
            <el-upload
              :auto-upload="true"
              :show-file-list="false"
              :http-request="(opt: any) => handleEditImageUpload(opt)"
              accept="image/*"
              :disabled="editUploading"
            >
              <el-button size="small" :loading="editUploading">
                {{ editForm.image_url ? '替换图片' : '上传图片' }}
              </el-button>
            </el-upload>
          </div>
        </el-form-item>
        <el-form-item label="状态">
          <el-select v-model="editForm.status" style="width: 100%">
            <el-option label="待用" value="unused" />
            <el-option label="已停用" value="disabled" />
          </el-select>
        </el-form-item>
        <el-form-item label="备注">
          <el-input v-model="editForm.note" placeholder="如：7月企微群A" maxlength="50" />
        </el-form-item>
        <el-form-item label="过期时间">
          <div class="expire-editor">
            <el-date-picker
              v-model="editForm.expires_at"
              type="datetime"
              placeholder="留空为永久"
              format="YYYY-MM-DD HH:mm"
              value-format="YYYY-MM-DDTHH:mm"
              style="width: 100%"
            />
            <el-button :disabled="!editForm.expires_at" @click="clearEditExpiresAt">清空</el-button>
          </div>
        </el-form-item>
      </el-form>
      <template #footer>
        <el-button @click="editVisible = false">取消</el-button>
        <el-button type="primary" @click="submitEdit">保存</el-button>
      </template>
    </el-dialog>
  </div>
</template>

<style scoped>
.qrcode-pool-view {
  display: flex;
  flex-direction: column;
  gap: 16px;
}

.stats-cards {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 16px;
}

.stat-card {
  text-align: center;
}

.toolbar-card,
.table-card {
  border-radius: 10px;
}

.table-card :deep(.el-card__body) {
  padding: 20px;
}

.stat-value {
  font-size: 28px;
  font-weight: 600;
  line-height: 1.2;
}

.stat-value.success {
  color: var(--el-color-success);
}
.stat-value.primary {
  color: var(--el-color-primary);
}
.stat-value.danger {
  color: var(--el-color-danger);
}

.stat-label {
  margin-top: 6px;
  color: var(--el-text-color-secondary);
  font-size: 13px;
}

.toolbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
}

.filter-area,
.action-area {
  display: flex;
  gap: 8px;
  align-items: center;
}

.qrcode-table {
  border-radius: 10px;
  box-shadow: none;
  padding: 0;
}

.qrcode-table :deep(.el-table__inner-wrapper) {
  min-width: 0;
}

.qrcode-table :deep(.el-table__header th) {
  height: 42px;
  background: #f8f9fb;
}

.qrcode-table :deep(.el-table__cell) {
  padding: 10px 0;
}

.qrcode-table :deep(.cell) {
  padding: 0 14px;
}

.qrcode-table :deep(.el-table__fixed-right) {
  box-shadow: -8px 0 12px rgba(31, 45, 61, 0.04);
}

.qrcode-table :deep(.el-table__header),
.qrcode-table :deep(.el-table__body) {
  width: 100% !important;
}

.qrcode-table :deep(.el-table__header-wrapper),
.qrcode-table :deep(.el-table__body-wrapper) {
  overflow-x: hidden;
}

.qrcode-table :deep(.qr-col) {
  width: 12%;
}

.qrcode-table :deep(.status-col) {
  width: 10%;
}

.qrcode-table :deep(.note-col) {
  width: 40%;
}

.qrcode-table :deep(.group-col) {
  width: 10%;
}

.qrcode-table :deep(.expire-col) {
  width: 16%;
}

.qrcode-table :deep(.action-col) {
  width: 12%;
}

.qrcode-thumb {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 64px;
  height: 64px;
  border: 1px solid #eef1f5;
  border-radius: 8px;
  background: #ffffff;
}

.note-cell {
  color: #303846;
  font-weight: 500;
}

.group-cell,
.expire-cell {
  color: #5f6b7a;
  font-size: 13px;
}

.table-actions {
  display: flex;
  justify-content: center;
  gap: 6px;
  white-space: nowrap;
}

.table-actions :deep(.el-button) {
  margin-left: 0;
  padding: 4px 6px;
}

.upload-preview {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
}

.batch-upload-area {
  width: 100%;
}

.qrcode-upload-form :deep(.el-form-item__label) {
  align-items: center;
  padding-right: 18px;
  line-height: 32px;
  white-space: nowrap;
  word-break: keep-all;
}

.qrcode-upload-form :deep(.el-form-item) {
  margin-bottom: 18px;
}

.qrcode-upload-form :deep(.el-form-item__content) {
  min-width: 0;
}

.batch-upload-area :deep(.el-upload) {
  width: 100%;
}

.batch-upload-area :deep(.el-upload-dragger) {
  width: 100%;
  padding: 12px 18px;
}

.batch-upload-area :deep(.el-icon--upload) {
  margin-bottom: 4px;
  font-size: 28px;
  line-height: 1;
}

.batch-upload-area :deep(.el-upload__text) {
  line-height: 20px;
}

.upload-tip {
  color: var(--el-text-color-secondary);
  font-size: 12px;
  line-height: 18px;
}

.uploaded-list {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(72px, 1fr));
  gap: 10px;
  margin-top: 10px;
  max-height: 224px;
  overflow-y: auto;
  padding: 10px;
  border: 1px solid #eef1f5;
  border-radius: 8px;
  background: #fafbfc;
}

.uploaded-item {
  min-width: 0;
}

.uploaded-thumb {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 60px;
  height: 60px;
  margin: 0 auto;
  border: 1px solid #e7ebf2;
  border-radius: 8px;
  background: #ffffff;
}

.uploaded-remove {
  position: absolute;
  top: -7px;
  right: -7px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 18px;
  height: 18px;
  padding: 0;
  border: 1px solid #ffffff;
  border-radius: 50%;
  background: var(--el-color-danger);
  color: #ffffff;
  cursor: pointer;
  font-size: 14px;
  line-height: 1;
}

.uploaded-remove:disabled {
  cursor: not-allowed;
  opacity: 0.45;
}

.uploaded-name {
  margin-top: 5px;
  overflow: hidden;
  color: var(--el-text-color-secondary);
  font-size: 12px;
  line-height: 16px;
  text-align: center;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.expired-tag {
  color: var(--el-color-danger);
}

.edit-image-area {
  display: flex;
  align-items: center;
  gap: 12px;
}

.edit-image-preview {
  flex: 0 0 auto;
  width: 88px;
  height: 88px;
  overflow: hidden;
  border: 1px solid #e7ebf2;
  border-radius: 8px;
  background: #fafbfc;
}

.edit-image-preview :deep(.el-image),
.edit-image-preview :deep(img) {
  display: block;
  width: 100%;
  height: 100%;
}

.edit-image-empty {
  display: grid;
  width: 100%;
  height: 100%;
  place-items: center;
  color: var(--el-text-color-secondary);
  font-size: 12px;
}

.expire-editor {
  display: flex;
  align-items: center;
  gap: 8px;
  width: 100%;
}
</style>
