<script setup lang="ts">
import { ref, computed, onMounted } from 'vue'
import {
  listMemberCards,
  createMemberCard,
  updateMemberCard,
  deleteMemberCard,
  type MemberCard,
  type CreateMemberCardDto,
  type UpdateMemberCardDto,
} from '@/api/memberCard'
import { verifyPassword } from '@/api/auth'
import AppLayout from '@/components/AppLayout.vue'
import { useToast } from '@/composables/useToast'
import { useAuthStore } from '@/stores/auth'

const toast = useToast()
const authStore = useAuthStore()

// --- 数据 ---
const cards = ref<MemberCard[]>([])
const loading = ref(false)

// --- 筛选 ---
const keyword = ref('')
type TypeFilter = '' | 'TIME_CARD' | 'COUNT_CARD' | 'STORED_VALUE_CARD'
type StatusFilter = '' | '1' | '0'
const typeFilter = ref<TypeFilter>('')
const statusFilter = ref<StatusFilter>('')

// --- 排序 ---
type SortKey = 'id_desc' | 'id_asc' | 'price_desc' | 'price_asc'
const sortKey = ref<SortKey>('id_desc')

// --- 分页 ---
const currentPage = ref(0)
const pageSize = ref(10)

// --- 弹窗 ---
const showModal = ref(false)
const isEdit = ref(false)
const editId = ref<number | null>(null)
const saveLoading = ref(false)

// --- 密码验证弹窗 ---
const showPasswordModal = ref(false)
const pendingDeleteCardId = ref<number | null>(null)
const adminPassword = ref('')
const passwordError = ref('')
const verifying = ref(false)

const cardTypeMap: Record<string, string> = {
  TIME_CARD: '时长卡',
  COUNT_CARD: '次卡',
  STORED_VALUE_CARD: '储值卡',
}

function getTypeLabel(type: string): string {
  return cardTypeMap[type] || '未知'
}

const form = ref<CreateMemberCardDto>({
  memberCardName: '',
  memberCardType: 'TIME_CARD',
  memberCardPrice: 0,
  memberCardValidityDays: undefined,
  memberCardTotalTimes: undefined,
  memberCardAmount: undefined,
  memberCardStatus: 1,
})

function formatPrice(p: number): string {
  return '¥' + (p ?? 0).toFixed(2)
}

function formatTime(t: string | null): string {
  if (!t) return '--'
  return new Date(t).toLocaleString('zh-CN')
}

// --- 数据过滤 ---
const filteredCards = computed(() => {
  let list = cards.value

  if (typeFilter.value) {
    list = list.filter((c) => c.memberCardType === typeFilter.value)
  }
  if (statusFilter.value) {
    list = list.filter((c) => c.memberCardStatus === Number(statusFilter.value))
  }
  if (keyword.value.trim()) {
    const kw = keyword.value.trim().toLowerCase()
    list = list.filter(
      (c) =>
        c.memberCardName.toLowerCase().includes(kw) ||
        String(c.memberCardId).includes(kw),
    )
  }

  // 排序
  if (sortKey.value === 'id_desc') {
    list.sort((a, b) => b.memberCardId - a.memberCardId)
  } else if (sortKey.value === 'id_asc') {
    list.sort((a, b) => a.memberCardId - b.memberCardId)
  } else if (sortKey.value === 'price_desc') {
    list.sort((a, b) => (b.memberCardPrice ?? 0) - (a.memberCardPrice ?? 0))
  } else if (sortKey.value === 'price_asc') {
    list.sort((a, b) => (a.memberCardPrice ?? 0) - (b.memberCardPrice ?? 0))
  }

  return list
})

const totalElements = computed(() => filteredCards.value.length)
const totalPages = computed(() => Math.max(1, Math.ceil(totalElements.value / pageSize.value)))

const pagedCards = computed(() => {
  const start = currentPage.value * pageSize.value
  return filteredCards.value.slice(start, start + pageSize.value)
})

function changePage(page: number) {
  if (page >= 0 && page < totalPages.value) {
    currentPage.value = page
  }
}

// --- 数据加载 ---
async function fetchCards() {
  loading.value = true
  try {
    const list = await listMemberCards({ page: 0, size: 200 })
    cards.value = list
  } catch {
    cards.value = []
  } finally {
    loading.value = false
  }
}

function handleSearch() {
  currentPage.value = 0
}

function handleTypeChange() {
  currentPage.value = 0
}

function handleStatusChange() {
  currentPage.value = 0
}

// --- CRUD ---
function resetForm() {
  form.value = {
    memberCardName: '',
    memberCardType: 'TIME_CARD',
    memberCardPrice: 0,
    memberCardValidityDays: undefined,
    memberCardTotalTimes: undefined,
    memberCardAmount: undefined,
    memberCardStatus: 1,
  }
}

function handleCreate() {
  isEdit.value = false
  editId.value = null
  resetForm()
  showModal.value = true
}

function handleEdit(card: MemberCard) {
  isEdit.value = true
  editId.value = card.memberCardId
  form.value = {
    memberCardName: card.memberCardName,
    memberCardType: card.memberCardType,
    memberCardPrice: card.memberCardPrice,
    memberCardValidityDays: card.memberCardValidityDays ?? undefined,
    memberCardTotalTimes: card.memberCardTotalTimes ?? undefined,
    memberCardAmount: card.memberCardAmount ?? undefined,
    memberCardStatus: card.memberCardStatus,
  }
  showModal.value = true
}

async function handleSave() {
  if (!form.value.memberCardName.trim()) {
    toast.error('请输入会员卡名称')
    return
  }
  if (!(form.value.memberCardPrice >= 0)) {
    toast.error('请输入有效的价格')
    return
  }
  // 根据卡类型校验必填字段
  if (form.value.memberCardType === 'TIME_CARD') {
    if (!form.value.memberCardValidityDays || form.value.memberCardValidityDays <= 0) {
      toast.error('时长卡必须输入有效天数')
      return
    }
  } else if (form.value.memberCardType === 'COUNT_CARD') {
    if (!form.value.memberCardTotalTimes || form.value.memberCardTotalTimes <= 0) {
      toast.error('次卡必须输入有效次数')
      return
    }
  } else if (form.value.memberCardType === 'STORED_VALUE_CARD') {
    if (!(form.value.memberCardAmount && form.value.memberCardAmount > 0)) {
      toast.error('储值卡必须输入有效面额')
      return
    }
  }
  saveLoading.value = true
  try {
    if (isEdit.value && editId.value) {
      await updateMemberCard(editId.value, form.value as UpdateMemberCardDto)
      toast.success('会员卡更新成功')
    } else {
      await createMemberCard(form.value)
      toast.success('会员卡创建成功')
    }
    showModal.value = false
    fetchCards()
  } catch (e: any) {
    toast.error(e?.response?.data?.message || '操作失败')
  } finally {
    saveLoading.value = false
  }
}

function handleDelete(card: MemberCard) {
  // 前置校验：会员卡必须已下架
  if (card.memberCardStatus !== 0) {
    toast.error('请先将会员卡下架后再删除')
    return
  }
  pendingDeleteCardId.value = card.memberCardId
  adminPassword.value = ''
  passwordError.value = ''
  showPasswordModal.value = true
}

async function handleVerifyPassword() {
  if (!adminPassword.value) {
    passwordError.value = '请输入管理员密码'
    return
  }
  verifying.value = true
  passwordError.value = ''
  try {
    await verifyPassword({
      username: authStore.username,
      password: adminPassword.value,
    })
    showPasswordModal.value = false
    if (pendingDeleteCardId.value != null) {
      await executeDelete(pendingDeleteCardId.value)
    }
  } catch {
    passwordError.value = '密码验证失败，请重新输入'
  } finally {
    verifying.value = false
  }
}

async function executeDelete(id: number) {
  try {
    await deleteMemberCard(id)
    toast.success('删除成功')
    pendingDeleteCardId.value = null
    fetchCards()
  } catch (e: any) {
    const data = e?.response?.data
    const msg = typeof data === 'string' ? data : (data?.message || '删除失败')
    toast.error(msg)
  }
}

onMounted(() => {
  fetchCards()
})
</script>

<template>
  <AppLayout>
    <!-- 工具栏 -->
    <div class="toolbar">
      <div class="toolbar-row">
        <input
          v-model="keyword"
          type="text"
          placeholder="搜索会员卡名称或编号..."
          class="search-input"
          @keyup.enter="handleSearch"
        />
        <select v-model="typeFilter" class="filter-select" @change="handleTypeChange">
          <option value="">全部类型</option>
          <option value="TIME_CARD">时长卡</option>
          <option value="COUNT_CARD">次卡</option>
          <option value="STORED_VALUE_CARD">储值卡</option>
        </select>
        <select v-model="statusFilter" class="filter-select" @change="handleStatusChange">
          <option value="">全部状态</option>
          <option value="1">已上架</option>
          <option value="0">已下架</option>
        </select>
        <select v-model="sortKey" class="filter-select" @change="handleSearch">
          <option value="id_desc">编号 ↓</option>
          <option value="id_asc">编号 ↑</option>
          <option value="price_desc">价格 ↓</option>
          <option value="price_asc">价格 ↑</option>
        </select>
        <button class="btn btn-primary" @click="handleCreate" v-if="authStore.hasPermission('business:memberCard:create')">
          <i class="fas fa-plus"></i> 新增会员卡
        </button>
      </div>
    </div>

    <!-- 表格 -->
    <div class="table-wrapper">
      <div class="table-header">
        <h3>会员卡列表 ({{ totalElements }} 条)</h3>
      </div>

      <!-- skeleton -->
      <table v-if="loading">
        <thead>
          <tr>
            <th>编号</th><th>名称</th><th>类型</th><th>价格</th>
            <th>有效期/次数/面额</th><th>状态</th><th>创建时间</th><th>操作</th>
          </tr>
        </thead>
        <tbody>
          <tr v-for="i in 5" :key="'sk-' + i">
            <td v-for="j in 8" :key="j">
              <span class="sk-td skeleton"></span>
            </td>
          </tr>
        </tbody>
      </table>

      <!-- real table -->
      <table v-else>
        <thead>
          <tr>
            <th>编号</th><th>名称</th><th>类型</th><th>价格</th>
            <th>有效期/次数/面额</th><th>状态</th><th>创建时间</th><th>操作</th>
          </tr>
        </thead>
        <tbody>
          <tr v-for="card in pagedCards" :key="card.memberCardId">
            <td>{{ card.memberCardId }}</td>
            <td>{{ card.memberCardName }}</td>
            <td>{{ getTypeLabel(card.memberCardType) }}</td>
            <td>{{ formatPrice(card.memberCardPrice) }}</td>
            <td>
              <span v-if="card.memberCardType === 'TIME_CARD'">{{ card.memberCardValidityDays ?? '--' }} 天</span>
              <span v-else-if="card.memberCardType === 'COUNT_CARD'">{{ card.memberCardTotalTimes ?? '--' }} 次</span>
              <span v-else-if="card.memberCardType === 'STORED_VALUE_CARD'">{{ formatPrice(card.memberCardAmount ?? 0) }}</span>
              <span v-else>--</span>
            </td>
            <td>
              <span :class="card.memberCardStatus === 1 ? 'badge-green' : 'badge-gray'">
                {{ card.memberCardStatus === 1 ? '已上架' : '已下架' }}
              </span>
            </td>
            <td>{{ formatTime(card.createdAt) }}</td>
            <td class="actions">
              <button class="btn-sm" @click="handleEdit(card)" v-if="authStore.hasPermission('business:memberCard:edit')">编辑</button>
              <button class="btn-sm btn-sm-danger" @click="handleDelete(card)" v-if="authStore.hasPermission('business:memberCard:delete')">删除</button>
            </td>
          </tr>
          <tr v-if="pagedCards.length === 0">
            <td colspan="8" class="empty">暂无会员卡数据</td>
          </tr>
        </tbody>
      </table>

      <!-- pagination -->
      <div class="pagination" v-if="totalPages > 1">
        <button :disabled="currentPage === 0" @click="changePage(currentPage - 1)">上一页</button>
        <span>第 {{ currentPage + 1 }} / {{ totalPages }} 页</span>
        <button :disabled="currentPage >= totalPages - 1" @click="changePage(currentPage + 1)">下一页</button>
      </div>
    </div>

    <!-- 新建/编辑弹窗 -->
    <div v-if="showModal" class="modal-overlay" @click.self="showModal = false">
      <div class="modal">
        <h3>{{ isEdit ? '编辑会员卡' : '新增会员卡' }}</h3>
        <div class="form-group">
          <label>会员卡名称 <span class="required">*</span></label>
          <input v-model="form.memberCardName" placeholder="请输入会员卡名称" />
        </div>
        <div class="form-group">
          <label>会员卡类型 <span class="required">*</span></label>
          <select v-model="form.memberCardType" class="form-select">
            <option value="TIME_CARD">时长卡</option>
            <option value="COUNT_CARD">次卡</option>
            <option value="STORED_VALUE_CARD">储值卡</option>
          </select>
        </div>
        <div class="form-group">
          <label>价格 (元) <span class="required">*</span></label>
          <input v-model.number="form.memberCardPrice" type="number" step="0.01" min="0" placeholder="请输入价格" />
        </div>

        <!-- 时长卡字段 -->
        <div v-if="form.memberCardType === 'TIME_CARD'" class="form-group">
          <label>有效天数</label>
          <input v-model.number="form.memberCardValidityDays" type="number" min="1" placeholder="请输入有效天数" />
        </div>

        <!-- 次卡字段 -->
        <div v-if="form.memberCardType === 'COUNT_CARD'" class="form-group">
          <label>总次数</label>
          <input v-model.number="form.memberCardTotalTimes" type="number" min="1" placeholder="请输入总次数" />
        </div>

        <!-- 储值卡字段 -->
        <div v-if="form.memberCardType === 'STORED_VALUE_CARD'" class="form-group">
          <label>面额 (元)</label>
          <input v-model.number="form.memberCardAmount" type="number" step="0.01" min="0" placeholder="请输入面额" />
        </div>

        <div class="form-group">
          <label>状态</label>
          <select v-model.number="form.memberCardStatus" class="form-select">
            <option :value="1">已上架</option>
            <option :value="0">已下架</option>
          </select>
        </div>

        <div class="modal-actions">
          <button class="btn btn-outline" @click="showModal = false">取消</button>
          <button class="btn btn-primary" @click="handleSave" :disabled="saveLoading">
            <i v-if="saveLoading" class="fas fa-spinner fa-spin"></i>
            {{ saveLoading ? '保存中...' : '保存' }}
          </button>
        </div>
      </div>
    </div>

    <!-- 密码验证弹窗 -->
    <div v-if="showPasswordModal" class="modal-overlay" @click.self="showPasswordModal = false">
      <div class="modal modal-sm">
        <h3>
          <i class="fas fa-shield-alt" style="margin-right:8px;color:#4f7cff"></i>
          管理员身份验证
        </h3>
        <p class="modal-desc">
          即将删除会员卡，请输入管理员密码确认操作。
        </p>

        <div class="form-group">
          <label>管理员账号</label>
          <input :value="authStore.username" type="text" disabled class="input-disabled" />
        </div>
        <div class="form-group">
          <label>管理员密码 <span class="required">*</span></label>
          <input
            v-model="adminPassword"
            type="password"
            placeholder="请输入密码"
            @keyup.enter="handleVerifyPassword"
          />
        </div>
        <p v-if="passwordError" class="field-error">{{ passwordError }}</p>

        <div class="modal-actions">
          <button class="btn btn-outline" @click="showPasswordModal = false">取消</button>
          <button
            class="btn"
            style="background:#ef4444;border-color:#ef4444;color:white"
            @click="handleVerifyPassword"
            :disabled="verifying"
          >
            <i v-if="verifying" class="fas fa-spinner fa-spin"></i>
            {{ verifying ? '验证中...' : '确认删除' }}
          </button>
        </div>
      </div>
    </div>
  </AppLayout>
</template>

<style scoped>
.toolbar {
  margin-bottom: 20px;
}

.toolbar-row {
  display: flex;
  gap: 10px;
  align-items: center;
  flex-wrap: wrap;
}

.search-input {
  padding: 9px 16px;
  border-radius: 12px;
  border: 1px solid #e2e8f0;
  font-size: 14px;
  width: 260px;
  outline: none;
  transition: 0.15s;
}

.search-input:focus {
  border-color: #4f7cff;
  box-shadow: 0 0 0 3px rgba(79, 124, 255, 0.12);
}

.filter-select {
  padding: 9px 14px;
  border-radius: 12px;
  border: 1px solid #e2e8f0;
  font-size: 13px;
  color: #1e293b;
  background: white;
  outline: none;
  cursor: pointer;
  transition: 0.15s;
}

.btn {
  padding: 9px 20px;
  border-radius: 40px;
  border: 1px solid #e2e8f0;
  background: white;
  font-weight: 500;
  font-size: 13px;
  color: #1e293b;
  display: inline-flex;
  align-items: center;
  gap: 8px;
  cursor: pointer;
  transition: 0.15s;
}

.btn-primary {
  background: #4f7cff;
  border-color: #4f7cff;
  color: white;
  box-shadow: 0 4px 10px rgba(79, 124, 255, 0.25);
}

.btn-primary:hover:not(:disabled) {
  background: #3f6ae0;
}

.btn-primary:disabled {
  opacity: 0.6;
  cursor: not-allowed;
}

.btn-outline:hover {
  background: #f0f5ff;
}

.table-wrapper {
  background: white;
  border-radius: 20px;
  border: 1px solid #edf2f9;
  padding: 20px 24px 8px 24px;
}

.table-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 16px;
}

.table-header h3 {
  font-weight: 600;
  font-size: 16px;
  color: #0b1a33;
}

table {
  width: 100%;
  border-collapse: collapse;
  font-size: 14px;
}

th {
  text-align: left;
  padding: 12px 8px 12px 0;
  font-weight: 600;
  color: #4e627c;
  border-bottom: 1px solid #eef2f8;
}

td {
  padding: 14px 8px 14px 0;
  border-bottom: 1px solid #f1f5fa;
  color: #1e2f44;
}

tr:last-child td {
  border-bottom: none;
}

td.empty {
  text-align: center;
  padding: 40px;
  color: #8b9ab0;
}

.skeleton {
  background: linear-gradient(90deg, #eef2f8 25%, #e0e7f0 50%, #eef2f8 75%);
  background-size: 200% 100%;
  animation: shimmer 1.5s infinite;
  border-radius: 6px;
}

.sk-td {
  display: block;
  height: 16px;
  width: 80%;
}

@keyframes shimmer {
  0% {
    background-position: -200% 0;
  }
  100% {
    background-position: 200% 0;
  }
}

@keyframes fadeIn {
  from {
    opacity: 0;
    transform: translateY(6px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

tr {
  animation: fadeIn 0.35s ease;
}

.actions {
  white-space: nowrap;
}

.btn-sm {
  padding: 5px 12px;
  border-radius: 20px;
  border: 1px solid #e2e8f0;
  background: white;
  font-size: 12px;
  cursor: pointer;
  margin-right: 6px;
  transition: 0.15s;
}

.btn-sm:hover {
  background: #f0f5ff;
}

.btn-sm-danger {
  background: #fee2e2;
  color: #dc2626;
}

.btn-sm-danger:hover {
  background: #fecaca;
}

.pagination {
  display: flex;
  justify-content: center;
  align-items: center;
  gap: 16px;
  padding: 16px 0;
  font-size: 13px;
  color: #4e627c;
}

.pagination button {
  padding: 6px 16px;
  border-radius: 8px;
  border: 1px solid #e2e8f0;
  background: white;
  cursor: pointer;
  font-size: 13px;
  transition: 0.15s;
}

.pagination button:hover:not(:disabled) {
  background: #f0f5ff;
}

.pagination button:disabled {
  opacity: 0.4;
  cursor: not-allowed;
}

/* ---- modal ---- */
.modal-overlay {
  position: fixed;
  inset: 0;
  background: rgba(0, 0, 0, 0.3);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 200;
  animation: fadeIn 0.15s ease;
}

.modal {
  background: white;
  border-radius: 20px;
  padding: 28px;
  width: 560px;
  max-width: 92vw;
  max-height: 85vh;
  overflow-y: auto;
  box-shadow: 0 12px 40px rgba(0, 0, 0, 0.12);
  animation: fadeIn 0.2s ease;
}

.modal h3 {
  font-size: 18px;
  font-weight: 600;
  color: #0b1a33;
  margin-bottom: 20px;
}

.modal-sm { width: 420px; }

.modal-desc {
  font-size: 14px; color: #4e627c; margin-bottom: 16px; line-height: 1.6;
}

.input-disabled {
  background: #f1f5f9 !important; color: #64748b; cursor: not-allowed;
}

.field-error {
  color: #ef4444; font-size: 13px; margin: -6px 0 8px 0;
}

.form-group {
  margin-bottom: 14px;
}

.form-group label {
  display: block;
  font-size: 13px;
  font-weight: 600;
  color: #1e293b;
  margin-bottom: 4px;
}

.form-group input,
.form-group select {
  width: 100%;
  padding: 9px 12px;
  border-radius: 10px;
  border: 1px solid #e2e8f0;
  font-size: 14px;
  outline: none;
  transition: 0.15s;
  background: #f8fafd;
  font-family: inherit;
  box-sizing: border-box;
}

.form-group input:focus,
.form-group select:focus {
  border-color: #4f7cff;
  box-shadow: 0 0 0 3px rgba(79, 124, 255, 0.12);
}

.form-select {
  width: 100%;
}

.modal-actions {
  display: flex;
  justify-content: flex-end;
  gap: 10px;
  margin-top: 20px;
}

.badge-green {
  display: inline-block;
  padding: 2px 10px;
  border-radius: 20px;
  font-size: 12px;
  background: #e0f5ec;
  color: #0b8b5e;
  font-weight: 500;
}

.badge-gray {
  display: inline-block;
  padding: 2px 10px;
  border-radius: 20px;
  font-size: 12px;
  background: #f1f5f9;
  color: #64748b;
  font-weight: 500;
}

.required {
  color: #ef4444;
}
</style>
