<template>
  <dialog ref="dialogRef" class="app-dialog icon-manage-dialog" @close="unlockScroll(); $emit('close')">
    <form class="dialog-form" method="dialog" @submit.prevent>
      <header>
        <h2>图标管理</h2>
        <button type="button" aria-label="关闭" @click="closeDialog">×</button>
      </header>

      <!-- 列表视图 -->
      <div v-if="!showForm" class="icon-list-view">
        <div v-if="loading" class="icon-loading">加载中…</div>
        <div v-else-if="!iconList.length" class="icon-empty">
          <p>暂无图标，点击下方按钮添加</p>
        </div>
        <div v-else class="icon-grid">
          <div
            v-for="icon in iconList"
            :key="icon.id"
            class="icon-grid-item"
          >
            <div class="icon-grid-thumb">
              <img
                :src="icon.logoUrl || getFaviconUrl(icon.url)"
                :alt="icon.name"
                @error="(e) => { e.target.style.display = 'none'; e.target.nextElementSibling.style.display = 'flex' }"
              />
              <span class="icon-grid-fallback" style="display:none">{{ (icon.name || '?')[0] }}</span>
            </div>
            <span class="icon-grid-name">
              {{ icon.name }}
              <span v-if="icon.linkType" class="link-type-badge" :class="`link-type-badge--${icon.linkType}`">
                {{ icon.linkType === 'external' ? '外网' : icon.linkType === 'internal' ? '内网' : '内外' }}
              </span>
            </span>
            <span class="icon-grid-url" :title="icon.url || icon.internalUrl">{{ icon.url || icon.internalUrl }}</span>
            <div class="icon-grid-actions">
              <button type="button" class="action-btn" title="编辑" @click="startEdit(icon)">✏️</button>
              <button type="button" class="action-btn action-btn--danger" title="删除" @click="confirmDeleteIcon(icon)">🗑️</button>
            </div>
          </div>
        </div>
        <button type="button" class="icon-add-btn" @click="startCreate">+ 添加图标</button>
      </div>

      <!-- 表单视图 -->
      <div v-else class="icon-form-view">
        <div class="field-grid">
          <label class="field-span-2">
            <span>名称 <em>*</em></span>
            <input v-model="form.name" type="text" placeholder="如：百度" required />
          </label>
          <!-- 链接类型选择 -->
          <div class="field-span-2">
            <span class="field-label">链接类型</span>
            <div class="link-type-group">
              <label class="link-type-option" :class="{ 'link-type-option--active': form.linkType === 'external' }">
                <input type="radio" v-model="form.linkType" value="external" />🌐 外网
              </label>
              <label class="link-type-option" :class="{ 'link-type-option--active': form.linkType === 'internal' }">
                <input type="radio" v-model="form.linkType" value="internal" />🔒 内网
              </label>
              <label class="link-type-option" :class="{ 'link-type-option--active': form.linkType === 'both' }">
                <input type="radio" v-model="form.linkType" value="both" />↔️ 内外网
              </label>
            </div>
          </div>
          <!-- 外网链接 -->
          <label v-if="form.linkType === 'external' || form.linkType === 'both'" class="field-span-2">
            <span>外网链接 <em v-if="form.linkType === 'external' || form.linkType === 'both'">*</em></span>
            <input v-model="form.url" type="url" placeholder="https://www.baidu.com" />
          </label>
          <!-- 内网链接 -->
          <label v-if="form.linkType === 'internal' || form.linkType === 'both'" class="field-span-2">
            <span>内网链接 <em v-if="form.linkType === 'internal' || form.linkType === 'both'">*</em></span>
            <input v-model="form.internalUrl" type="url" placeholder="http://192.168.x.x 或内网域名" />
          </label>
          <label class="field-span-2">
            <span>描述</span>
            <input v-model="form.description" type="text" placeholder="简短描述（可选）" />
          </label>
          <!-- 自定义图标上传 -->
          <div class="field-span-2">
            <span class="field-label">图标图片</span>
            <div class="icon-upload-area">
              <div v-if="form.logoPreview" class="icon-upload-preview">
                <img :src="form.logoPreview" :alt="form.name" />
                <div class="icon-upload-actions">
                  <button type="button" class="icon-upload-btn" @click="$refs.iconInputRef.click()">更换</button>
                  <button type="button" class="icon-upload-btn icon-upload-btn--remove" @click="removeIconImage">移除</button>
                </div>
              </div>
              <div v-else class="icon-upload-placeholder" @click="$refs.iconInputRef.click()">
                <span class="icon-upload-plus">+</span>
                <span>点击上传图片</span>
              </div>
              <input ref="iconInputRef" type="file" accept="image/png,image/jpeg,image/gif,image/webp" style="display:none" @change="handleIconChange" />
            </div>
            <span class="icon-upload-tip">支持 PNG/JPG/GIF/WebP，最大 5MB，留空则抓取网站 favicon</span>
          </div>
          <label>
            <span>排序权重</span>
            <input v-model.number="form.sortOrder" type="number" min="0" placeholder="越小越靠前" />
          </label>
        </div>
        <div v-if="form.url || form.internalUrl || form.logoPreview" class="icon-form-preview">
          <span>预览：</span>
          <div class="icon-grid-thumb">
            <img :src="form.logoPreview || getFaviconUrl(form.url || form.internalUrl)" :alt="form.name" @error="(e) => { e.target.style.display = 'none'; e.target.nextElementSibling.style.display = 'flex' }" />
            <span class="icon-grid-fallback" style="display:none">{{ (form.name || '?')[0] }}</span>
          </div>
          <span>{{ form.name || '未命名' }}</span>
        </div>
      </div>

      <footer>
        <template v-if="!showForm">
          <span></span>
          <span></span>
          <button type="button" class="secondary" @click="closeDialog">关闭</button>
        </template>
        <template v-else>
          <button type="button" class="danger" v-if="isEditing" @click="confirmDeleteIcon(editingIcon)">删除</button>
          <span v-else></span>
          <span></span>
          <button type="button" class="secondary" @click="showForm = false">取消</button>
          <button type="button" @click="handleSubmit" :disabled="submitting || !isFormValid">
            {{ submitting ? '保存中…' : (isEditing ? '保存' : '创建') }}
          </button>
        </template>
      </footer>
    </form>

    <!-- 确认删除弹窗 -->
    <Teleport to="body">
      <dialog ref="confirmRef" class="confirm-overlay" @click.self="closeConfirm" @close="closeConfirm">
        <Transition name="confirm-scale-in">
          <div v-if="showConfirm" class="confirm-dialog">
            <header><span class="confirm-icon">⚠️</span> 确认删除</header>
            <div class="confirm-body">
              <p>确定要删除图标 <strong>"{{ deleteTarget?.name }}"</strong> 吗？</p>
            </div>
            <footer>
              <button type="button" class="confirm-btn-cancel" @click="closeConfirm">取消</button>
              <button type="button" class="confirm-btn-danger" @click="doDelete">确认删除</button>
            </footer>
          </div>
        </Transition>
      </dialog>
    </Teleport>
  </dialog>
</template>

<script setup>
import { ref, watch, computed } from 'vue'
import { fetchIconList, createIcon, updateIcon, deleteIcon, uploadIconLogo } from '../api'
import { lockScroll, unlockScroll } from '../utils/scrollLock'

const props = defineProps({ open: Boolean })
const emit = defineEmits(['close', 'success', 'error', 'refresh'])

const dialogRef = ref(null)
const confirmRef = ref(null)
const iconInputRef = ref(null)

const loading = ref(false)
const submitting = ref(false)
const showForm = ref(false)
const isEditing = ref(false)
const editingIcon = ref(null)
const iconList = ref([])

const form = ref({ name: '', url: '', internalUrl: '', linkType: 'external', logoPreview: '', logoFile: null, description: '', sortOrder: 0 })

const showConfirm = ref(false)
const deleteTarget = ref(null)

/** 表单是否有效 */
const isFormValid = computed(() => {
  if (!form.value.name?.trim()) return false
  const lt = form.value.linkType
  if ((lt === 'external' || lt === 'both') && !form.value.url?.trim()) return false
  if ((lt === 'internal' || lt === 'both') && !form.value.internalUrl?.trim()) return false
  return true
})

function getFaviconUrl(url) {
  try {
    const u = new URL(url)
    return `https://www.google.com/s2/favicons?domain=${u.hostname}&sz=64`
  } catch {
    return ''
  }
}

/** 处理图标图片上传 */
function handleIconChange(event) {
  const file = event.target.files[0]
  if (!file) return

  const allowedTypes = ['image/jpeg', 'image/png', 'image/gif', 'image/webp']
  if (!allowedTypes.includes(file.type)) {
    emit('error', '仅支持 JPG、PNG、GIF、WebP 格式的图片')
    event.target.value = ''
    return
  }

  const maxSize = 5 * 1024 * 1024
  if (file.size > maxSize) {
    emit('error', '图片大小不能超过 5MB')
    event.target.value = ''
    return
  }

  form.value.logoFile = file
  const reader = new FileReader()
  reader.onload = (e) => {
    form.value.logoPreview = e.target.result
  }
  reader.readAsDataURL(file)
}

/** 移除已上传的图标图片 */
function removeIconImage() {
  form.value.logoFile = null
  form.value.logoPreview = ''
  if (iconInputRef.value) {
    iconInputRef.value.value = ''
  }
}

watch(
  () => props.open,
  (val) => {
    if (!dialogRef.value) return
    if (val && !dialogRef.value.open) {
      dialogRef.value.showModal()
      lockScroll()
      loadIcons()
    } else if (!val && dialogRef.value.open) {
      dialogRef.value.close()
      unlockScroll()
    }
  },
)

async function loadIcons() {
  loading.value = true
  try {
    const res = await fetchIconList()
    if (res?.code === 200 && res?.data) {
      const list = Array.isArray(res.data) ? res.data : (res.data.list || res.data.records || [])
      iconList.value = list.sort((a, b) => (a.sortOrder ?? 0) - (b.sortOrder ?? 0))
    } else {
      emit('error', res?.message || '获取图标列表失败')
    }
  } catch (err) {
    emit('error', err?.message || '加载图标列表失败')
  } finally {
    loading.value = false
  }
}

function startCreate() {
  isEditing.value = false
  editingIcon.value = null
  form.value = { name: '', url: '', internalUrl: '', linkType: 'external', logoPreview: '', logoFile: null, description: '', sortOrder: 0 }
  showForm.value = true
}

function startEdit(icon) {
  isEditing.value = true
  editingIcon.value = icon
  form.value = {
    name: icon.name || '',
    url: icon.url || '',
    internalUrl: icon.internalUrl || '',
    linkType: icon.linkType || 'external',
    logoPreview: icon.logoUrl || '', // 编辑时用已有图片作为预览
    logoFile: null,
    description: icon.description || '',
    sortOrder: icon.sortOrder ?? 0,
  }
  showForm.value = true
}

async function handleSubmit() {
  if (!form.value.name?.trim()) return
  // 根据链接类型校验必填字段
  const lt = form.value.linkType
  if ((lt === 'external' || lt === 'both') && !form.value.url?.trim()) return
  if ((lt === 'internal' || lt === 'both') && !form.value.internalUrl?.trim()) return
  submitting.value = true
  try {
    const payload = {
      name: form.value.name.trim(),
      url: form.value.url?.trim() || '',
      internalUrl: form.value.internalUrl?.trim() || '',
      linkType: form.value.linkType || 'external',
      description: form.value.description?.trim() || '',
      sortOrder: Number(form.value.sortOrder) || 0,
    }

    let iconId = null
    let result = null

    if (isEditing.value) {
      iconId = editingIcon.value.id
      result = await updateIcon(iconId, payload)
    } else {
      result = await createIcon(payload)
      iconId = result?.data?.id
    }

    if (result?.code === 200) {
      // 如果用户选择了新的 logo 图片文件，单独上传
      if (form.value.logoFile && iconId) {
        try {
          const uploadRes = await uploadIconLogo(iconId, form.value.logoFile)
          if (uploadRes?.code !== 200) {
            emit('error', uploadRes?.message || '图标图片上传失败，但基本信息已保存')
          }
        } catch (uploadErr) {
          emit('error', `图标图片上传失败：${uploadErr?.message || ''}，但基本信息已保存`)
        }
      }
      emit('success', isEditing.value ? `图标“${payload.name}”已更新` : `图标“${payload.name}”创建成功`)
      emit('refresh')
      showForm.value = false
      await loadIcons()
    } else {
      emit('error', result?.message || (isEditing.value ? '更新失败' : '创建失败'))
    }
  } catch (err) {
    emit('error', `${isEditing.value ? '更新' : '创建'}图标失败：${err?.message || ''}`)
  } finally {
    submitting.value = false
  }
}

function confirmDeleteIcon(icon) {
  deleteTarget.value = icon
  showConfirm.value = true
  try { confirmRef.value?.showModal() } catch {}
}

function closeConfirm() {
  showConfirm.value = false
  deleteTarget.value = null
  try { confirmRef.value?.close() } catch {}
}

async function doDelete() {
  if (!deleteTarget.value) return
  const target = deleteTarget.value
  closeConfirm()
  try {
    const result = await deleteIcon(target.id)
    if (result?.code === 200) {
      emit('success', `图标"${target.name}"已删除`)
      emit('refresh')
      showForm.value = false
      await loadIcons()
    } else {
      emit('error', result?.message || '删除图标失败')
    }
  } catch (err) {
    emit('error', `删除图标失败：${err?.message || ''}`)
  }
}

function closeDialog() {
  dialogRef.value?.close()
}
</script>

<style scoped>
.icon-manage-dialog .dialog-form {
  min-width: 560px;
  max-width: 720px;
}

.icon-loading,
.icon-empty {
  text-align: center;
  padding: 40px 20px;
  color: #94a3b8;
  font-size: 14px;
}

.icon-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(100px, 1fr));
  gap: 16px;
  padding: 8px 0 16px;
  max-height: 400px;
  overflow-y: auto;
}

.icon-grid-item {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 6px;
  padding: 12px 8px;
  border-radius: 12px;
  background: #f8fafc;
  transition: all 0.2s;
  position: relative;
  cursor: default;
}

.icon-grid-item:hover {
  background: #f0f4ff;
  box-shadow: 0 2px 8px rgba(99, 102, 241, 0.1);
}

.icon-grid-thumb {
  width: 48px;
  height: 48px;
  border-radius: 12px;
  background: linear-gradient(135deg, #e0e7ff 0%, #c7d2fe 100%);
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: hidden;
  flex-shrink: 0;
}

.icon-grid-thumb img {
  width: 32px;
  height: 32px;
  object-fit: contain;
}

.icon-grid-fallback {
  width: 100%;
  height: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 20px;
  font-weight: 700;
  color: #6366f1;
}

.icon-grid-name {
  font-size: 12px;
  font-weight: 600;
  color: #1e293b;
  text-align: center;
  max-width: 100%;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.icon-grid-url {
  font-size: 10px;
  color: #94a3b8;
  max-width: 100%;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.icon-grid-actions {
  display: flex;
  gap: 4px;
  opacity: 0;
  transition: opacity 0.2s;
}

.icon-grid-item:hover .icon-grid-actions {
  opacity: 1;
}

.icon-grid-actions .action-btn {
  padding: 2px 6px;
  border: none;
  border-radius: 6px;
  background: transparent;
  cursor: pointer;
  font-size: 12px;
  transition: all 0.2s;
}

.icon-grid-actions .action-btn:hover {
  background: rgba(99, 102, 241, 0.15);
}

.icon-grid-actions .action-btn--danger:hover {
  background: rgba(239, 68, 68, 0.15);
}

.icon-add-btn {
  display: block;
  width: 100%;
  padding: 12px;
  border: 2px dashed #c7d2fe;
  border-radius: 12px;
  background: rgba(99, 102, 241, 0.04);
  color: #6366f1;
  font-size: 14px;
  font-weight: 600;
  cursor: pointer;
  transition: all 0.2s;
  margin-top: 12px;
}

.icon-add-btn:hover {
  background: rgba(99, 102, 241, 0.1);
  border-color: #6366f1;
}

.icon-form-view {
  padding: 8px 0;
}

.icon-form-preview {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-top: 16px;
  padding: 12px;
  background: #f8fafc;
  border-radius: 10px;
  font-size: 13px;
  color: #64748b;
}

.icon-form-preview .icon-grid-thumb {
  width: 36px;
  height: 36px;
  border-radius: 8px;
}

.icon-form-preview .icon-grid-thumb img {
  width: 24px;
  height: 24px;
}

/* 确认弹窗 */
.confirm-overlay {
  position: fixed;
  inset: 0;
  background: transparent;
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 2147483647;
  border: none;
  padding: 0;
  overflow: hidden;
  border-radius: 14px;
}
.confirm-overlay::backdrop {
  background: rgba(0, 0, 0, 0.45);
  backdrop-filter: blur(3px);
}
.confirm-dialog {
  background: #fff;
  border-radius: 14px;
  padding: 24px 28px;
  min-width: 400px;
  max-width: 90vw;
  box-shadow: 0 20px 70px rgba(0, 0, 0, 0.25);
  border: none;
}
.confirm-dialog header {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 17px;
  font-weight: 700;
  color: #303133;
  margin-bottom: 16px;
  padding-bottom: 12px;
  border-bottom: 1px solid #ebeef5;
}
.confirm-icon { font-size: 20px; }
.confirm-body {
  font-size: 15px;
  color: #606266;
  line-height: 1.65;
}
.confirm-body strong { color: #f56c6c; font-weight: 700; }
.confirm-dialog footer {
  display: flex;
  justify-content: flex-end;
  gap: 12px;
  margin-top: 20px;
  padding-top: 16px;
  border-top: 1px solid #ebeef5;
}
.confirm-dialog footer button {
  padding: 9px 22px;
  border-radius: 8px;
  font-size: 14px;
  font-weight: 600;
  cursor: pointer;
  transition: all 0.25s ease;
  border: none;
}
.confirm-btn-cancel {
  background: #fff;
  color: #606266;
  border: 1px solid #dcdfe6 !important;
}
.confirm-btn-cancel:hover { background: #f5f7fa; }
.confirm-btn-danger {
  background: linear-gradient(135deg, #f56c6c 0%, #e74c3c 100%) !important;
  color: #fff !important;
}
.confirm-btn-danger:hover {
  transform: translateY(-1px);
  box-shadow: 0 6px 18px rgba(245, 108, 108, 0.35);
}
.confirm-scale-in-enter-active {
  transition: all 0.3s cubic-bezier(0.34, 1.56, 0.64, 1);
}
.confirm-scale-in-leave-active { transition: all 0.2s ease; }
.confirm-scale-in-enter-from {
  opacity: 0;
  transform: scale(0.85) translateY(15px);
}
.confirm-scale-in-leave-to {
  opacity: 0;
  transform: scale(0.95) translateY(-8px);
}

/* 链接类型选择组 */
.field-label {
  display: block;
  font-size: 13px;
  font-weight: 600;
  color: #475569;
  margin-bottom: 8px;
}

.link-type-group {
  display: flex;
  gap: 8px;
}

.link-type-option {
  display: flex;
  align-items: center;
  gap: 4px;
  padding: 7px 14px;
  border: 1.5px solid #e2e8f0;
  border-radius: 10px;
  font-size: 13px;
  font-weight: 500;
  color: #64748b;
  cursor: pointer;
  transition: all 0.2s;
  background: #fff;
}

.link-type-option input[type="radio"] {
  display: none;
}

.link-type-option:hover {
  border-color: #a5b4fc;
  color: #6366f1;
}

.link-type-option--active {
  border-color: #6366f1;
  background: rgba(99, 102, 241, 0.06);
  color: #6366f1;
  font-weight: 600;
}

/* 链接类型标签 */
.link-type-badge {
  display: inline-block;
  font-size: 10px;
  font-weight: 600;
  padding: 1px 5px;
  border-radius: 4px;
  vertical-align: middle;
  margin-left: 4px;
}
.link-type-badge--external { background: rgba(59, 130, 246, 0.12); color: #3b82f6; }
.link-type-badge--internal { background: rgba(234, 179, 8, 0.12); color: #ca8a04; }
.link-type-badge--both      { background: rgba(139, 92, 246, 0.12); color: #7c3aed; }

/* 图标图片上传区域 */
.icon-upload-area {
  margin-top: 4px;
}

.icon-upload-placeholder {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 6px;
  width: 100%;
  height: 100px;
  border: 2px dashed #d1d5db;
  border-radius: 12px;
  background: rgba(99, 102, 241, 0.02);
  cursor: pointer;
  transition: all 0.2s;
  color: #94a3b8;
  font-size: 13px;
}

.icon-upload-placeholder:hover {
  border-color: #a5b4fc;
  background: rgba(99, 102, 241, 0.06);
  color: #6366f1;
}

.icon-upload-plus {
  font-size: 28px;
  font-weight: 300;
  line-height: 1;
}

.icon-upload-preview {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 10px;
  background: #f8fafc;
  border-radius: 12px;
  border: 1.5px solid #e2e8f0;
}

.icon-upload-preview img {
  width: 56px;
  height: 56px;
  object-fit: contain;
  border-radius: 8px;
  background: #fff;
  border: 1px solid #e2e8f0;
}

.icon-upload-actions {
  display: flex;
  gap: 6px;
}

.icon-upload-btn {
  padding: 5px 12px;
  border: 1.5px solid #e2e8f0;
  border-radius: 8px;
  background: #fff;
  font-size: 12px;
  font-weight: 600;
  color: #6366f1;
  cursor: pointer;
  transition: all 0.15s;
}

.icon-upload-btn:hover {
  border-color: #6366f1;
  background: rgba(99, 102, 241, 0.06);
}

.icon-upload-btn--remove {
  color: #ef4444;
}

.icon-upload-btn--remove:hover {
  border-color: #ef4444;
  background: rgba(239, 68, 68, 0.06);
}

.icon-upload-tip {
  display: block;
  margin-top: 6px;
  font-size: 11px;
  color: #94a3b8;
}
</style>
