<script setup lang="ts">
import { ref, onMounted, computed } from 'vue'
import {
  getCourseList,
  cancelCourse,
  type GroupCourse,
} from '@/api/groupCourse'
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 allCourses = ref<GroupCourse[]>([])
const loading = ref(false)
const cancelLoading = ref(false)

// 多选
const selectedIds = ref<Set<number>>(new Set())
const selectAll = ref(false)

// 密码验证
const showPasswordModal = ref(false)
const adminPassword = ref('')
const passwordError = ref('')
const verifying = ref(false)

// 搜索
const keyword = ref('')

const cancellableCourses = computed(() => {
  const list = allCourses.value.filter((c) => c.status != null && Number(c.status) === 0)
  if (!keyword.value.trim()) return list
  const kw = keyword.value.trim().toLowerCase()
  return list.filter(
    (c) =>
      c.courseName.toLowerCase().includes(kw) ||
      String(c.id).includes(kw) ||
      (c.location && c.location.toLowerCase().includes(kw)),
  )
})

const hasSelection = computed(() => selectedIds.value.size > 0)

async function fetchCourses() {
  loading.value = true
  try {
    const data = await getCourseList()
    allCourses.value = data
  } catch {
    allCourses.value = []
  } finally {
    loading.value = false
  }
}

function toggleSelect(id: number) {
  const next = new Set(selectedIds.value)
  if (next.has(id)) {
    next.delete(id)
  } else {
    next.add(id)
  }
  selectedIds.value = next
  selectAll.value = next.size === cancellableCourses.value.length && next.size > 0
}

function toggleSelectAll() {
  if (selectAll.value) {
    selectedIds.value = new Set()
    selectAll.value = false
  } else {
    selectedIds.value = new Set(cancellableCourses.value.map((c) => c.id))
    selectAll.value = true
  }
}

function openCancelDialog() {
  if (!hasSelection.value) {
    toast.error('请先选择要取消的团课')
    return
  }
  adminPassword.value = ''
  passwordError.value = ''
  showPasswordModal.value = true
}

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

async function executeBatchCancel() {
  cancelLoading.value = true
  const ids = Array.from(selectedIds.value)
  let successCount = 0
  let failCount = 0
  let firstError = ''

  for (const id of ids) {
    try {
      await cancelCourse(id)
      successCount++
    } catch (e: any) {
      failCount++
      if (!firstError) {
        firstError =
          e?.response?.data?.message ||
          e?.message ||
          `课程 id=${id} 取消失败`
      }
    }
  }

  selectedIds.value = new Set()
  selectAll.value = false

  if (failCount === 0) {
    toast.success(`已成功取消 ${successCount} 个团课`)
  } else {
    toast.error(firstError || `成功 ${successCount} 个，失败 ${failCount} 个`)
  }

  cancelLoading.value = false
  fetchCourses()
}

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

onMounted(fetchCourses)
</script>

<template>
  <AppLayout>
    <div class="toolbar">
      <div class="search-row">
        <input
          v-model="keyword"
          type="text"
          placeholder="搜索课程名称、ID 或地点..."
          class="search-input"
        />
        <span class="count-badge">
          可取消: <strong>{{ cancellableCourses.length }}</strong> 个
        </span>
      </div>
      <div class="action-row">
        <span v-if="hasSelection" class="selection-info">
          已选择 <strong>{{ selectedIds.size }}</strong> 个团课
        </span>
        <button
          class="btn btn-danger"
          :disabled="!hasSelection || cancelLoading"
          @click="openCancelDialog"
        >
          <i v-if="cancelLoading" class="fas fa-spinner fa-spin"></i>
          <i v-else class="fas fa-ban"></i>
          {{ cancelLoading ? '取消中...' : `批量取消 (${selectedIds.size})` }}
        </button>
      </div>
    </div>

    <div class="table-wrapper">
      <div class="table-header">
        <h3>可取消团课列表</h3>
      </div>

      <!-- skeleton -->
      <table v-if="loading">
        <thead>
          <tr>
            <th style="width:40px"></th>
            <th>ID</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 style="width:40px">
              <input
                type="checkbox"
                :checked="selectAll"
                @change="toggleSelectAll"
                :disabled="cancellableCourses.length === 0"
              />
            </th>
            <th>ID</th><th>课程名称</th><th>开始时间</th><th>结束时间</th>
            <th>人数</th><th>地点</th><th>状态</th>
          </tr>
        </thead>
        <tbody>
          <tr
            v-for="c in cancellableCourses"
            :key="c.id"
            :class="{ 'row-selected': selectedIds.has(c.id) }"
            @click="toggleSelect(c.id)"
          >
            <td @click.stop>
              <input
                type="checkbox"
                :checked="selectedIds.has(c.id)"
                @change="toggleSelect(c.id)"
              />
            </td>
            <td>{{ c.id }}</td>
            <td class="course-name">{{ c.courseName }}</td>
            <td>{{ formatTime(c.startTime) }}</td>
            <td>{{ formatTime(c.endTime) }}</td>
            <td>{{ c.currentMembers }}/{{ c.maxMembers }}</td>
            <td>{{ c.location }}</td>
            <td>
              <span class="status-badge green">正常</span>
            </td>
          </tr>
          <tr v-if="cancellableCourses.length === 0">
            <td colspan="8" class="empty">
              {{ keyword ? '未找到匹配的团课' : '暂无可取消的团课' }}
            </td>
          </tr>
        </tbody>
      </table>
    </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">
          即将取消 <strong>{{ selectedIds.size }}</strong> 个团课，请输入管理员密码确认操作。
        </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>
          <div class="input-wrapper">
            <i class="fas fa-lock"></i>
            <input
              v-model="adminPassword"
              type="password"
              placeholder="请输入密码"
              @keyup.enter="handleVerify"
              ref="passwordInput"
            />
          </div>
        </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 btn-danger" @click="handleVerify" :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;
  display: flex;
  flex-direction: column;
  gap: 12px;
}

.search-row {
  display: flex;
  gap: 12px;
  align-items: center;
}

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

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

.count-badge {
  font-size: 13px;
  color: #6b7d94;
  background: #f8fafd;
  padding: 6px 14px;
  border-radius: 20px;
  border: 1px solid #edf2f9;
}

.action-row {
  display: flex;
  gap: 12px;
  align-items: center;
}

.selection-info {
  font-size: 13px;
  color: #4f7cff;
  background: #eff6ff;
  padding: 6px 14px;
  border-radius: 20px;
  border: 1px solid #bfdbfe;
}

.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-danger {
  background: #ef4444;
  border-color: #ef4444;
  color: white;
  box-shadow: 0 4px 10px rgba(239,68,68,0.25);
}

.btn-danger:hover:not(:disabled) { background: #dc2626; }
.btn-danger:disabled { opacity: 0.5; 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;
}

tr {
  cursor: pointer;
  transition: background 0.1s;
  animation: fadeIn 0.35s ease;
}

tr:hover {
  background: #f8fafd;
}

tr.row-selected {
  background: #eff6ff;
}

tr.row-selected:hover {
  background: #dbeafe;
}

input[type='checkbox'] {
  width: 16px;
  height: 16px;
  accent-color: #4f7cff;
  cursor: pointer;
}

.course-name {
  font-weight: 500;
}

/* ---- skeleton ---- */
.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%; }

/* ---- badge ---- */
.status-badge {
  padding: 4px 12px;
  border-radius: 40px;
  font-size: 12px;
  font-weight: 500;
  display: inline-block;
  background: #e0f5ec;
  color: #0b8b5e;
}

/* ---- 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;
  box-shadow: 0 12px 40px rgba(0,0,0,0.12);
  animation: fadeIn 0.2s ease;
}

.modal-sm {
  width: 440px;
}

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

.modal-desc {
  font-size: 14px;
  color: #6b7d94;
  margin-bottom: 20px;
  line-height: 1.5;
}

.modal-desc strong {
  color: #ef4444;
}

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

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

.form-group .required { color: #ef4444; }

.input-disabled {
  width: 100%;
  padding: 9px 12px;
  border-radius: 10px;
  border: 1px solid #e2e8f0;
  font-size: 14px;
  background: #f1f5f9;
  color: #94a3b8;
  cursor: not-allowed;
}

.input-wrapper {
  display: flex;
  align-items: center;
  gap: 10px;
  background: #f8fafd;
  border: 1px solid #e2e8f0;
  border-radius: 12px;
  padding: 8px 14px;
  transition: 0.15s;
}

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

.input-wrapper i {
  color: #8b9ab0;
  font-size: 14px;
  width: 16px;
}

.input-wrapper input {
  border: none;
  outline: none;
  background: transparent;
  flex: 1;
  font-size: 14px;
  color: #1e293b;
}

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

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

/* ---- animations ---- */
@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); }
}
</style>
