<script setup lang="ts">
import { computed, onMounted, reactive, ref, watch } from 'vue'
import { Calendar, Document, Download, Key, Plus, Refresh, Search, Upload } from '@element-plus/icons-vue'
import { useRoute, useRouter } from 'vue-router'
import http, { apiErrorMessage } from '../api/http'
import { downloadApiFile, importExcel } from '../api/excel'
import { useAuthStore } from '../stores/auth'

type Registry = 'teachers' | 'students'
interface PageResult {
  items: any[]
  total: number
  page: number
  pageSize: number
}

const auth = useAuthStore()
const route = useRoute()
const router = useRouter()
const active = computed<Registry>(() =>
  route.meta.registry === 'students' ? 'students' : 'teachers',
)
const loading = ref(false)
const importing = ref(false)
const fileInput = ref<HTMLInputElement>()
const rows = ref<any[]>([])
const total = ref(0)
const dialogVisible = ref(false)
const activationDialog = ref(false)
const activationLoading = ref(false)
const activatingTeacher = ref<any | null>(null)
const editingId = ref('')
const colleges = ref<any[]>([])
const majors = ref<any[]>([])
const classes = ref<any[]>([])
const query = reactive({
  page: 1,
  pageSize: 20,
  keyword: '',
  collegeId: undefined as string | undefined,
  majorId: undefined as string | undefined,
  classId: undefined as string | undefined,
  enrollmentYear: undefined as number | undefined,
  status: undefined as string | undefined,
})
const form = reactive<Record<string, any>>({})
const activationForm = reactive({
  password: '',
  confirmPassword: '',
})

const canManage = computed(() =>
  auth.user?.roles.some((role) =>
    ['SuperAdmin', 'AcademicAdmin', 'CollegeAdmin'].includes(role),
  ) ?? false,
)
const scopedCollegeId = computed(() =>
  auth.user?.roles.some((role) => ['CollegeAdmin', 'Counselor'].includes(role))
    ? auth.user.collegeId
    : undefined,
)
const availableColleges = computed(() =>
  scopedCollegeId.value
    ? colleges.value.filter((item) => item.id === scopedCollegeId.value)
    : colleges.value,
)
const availableMajors = computed(() =>
  scopedCollegeId.value
    ? majors.value.filter((item) => item.collegeId === scopedCollegeId.value)
    : majors.value,
)
const availableClasses = computed(() => {
  const majorIds = new Set(availableMajors.value.map((item) => item.id))
  return classes.value.filter((item) => majorIds.has(item.majorId))
})
const pageTitle = computed(() => active.value === 'teachers' ? '教师档案' : '学生档案')
const numberLabel = computed(() => active.value === 'teachers' ? '工号' : '学号')
const filteredMajors = computed(() =>
  query.collegeId
    ? availableMajors.value.filter((item) => item.collegeId === query.collegeId)
    : availableMajors.value,
)
const filteredClasses = computed(() => {
  if (query.majorId) {
    return availableClasses.value.filter((item) => item.majorId === query.majorId)
  }
  if (query.collegeId) {
    const majorIds = new Set(
      availableMajors.value
        .filter((item) => item.collegeId === query.collegeId)
        .map((item) => item.id),
    )
    return availableClasses.value.filter((item) => majorIds.has(item.majorId))
  }
  return availableClasses.value
})
const formClasses = computed(() => availableClasses.value)

const genderLabels: Record<string, string> = {
  Unknown: '未设置', Male: '男', Female: '女',
}
const teacherStatusLabels: Record<string, string> = {
  Active: '在职', OnLeave: '离岗', Retired: '退休', Departed: '离职',
}
const studentStatusLabels: Record<string, string> = {
  Active: '在籍', Suspended: '休学', Graduated: '毕业', Withdrawn: '退学',
}

function resetForm(row?: any) {
  Object.keys(form).forEach((key) => delete form[key])
  if (active.value === 'teachers') {
    Object.assign(form, {
      teacherNumber: '',
      name: '',
      gender: 'Unknown',
      collegeId: scopedCollegeId.value,
      title: '',
      status: 'Active',
      hireDate: '',
      isExternal: false,
      phone: '',
      email: '',
      notes: '',
    }, row ?? {})
  } else {
    const currentYear = new Date().getFullYear()
    Object.assign(form, {
      studentNumber: '',
      name: '',
      gender: 'Unknown',
      administrativeClassId: undefined,
      enrollmentYear: currentYear,
      enrollmentDate: `${currentYear}-09-01`,
      status: 'Active',
      dateOfBirth: '',
      phone: '',
      email: '',
      notes: '',
    }, row ?? {})
  }
}

async function load() {
  loading.value = true
  try {
    const params: Record<string, any> = {
      page: query.page,
      pageSize: query.pageSize,
      keyword: query.keyword || undefined,
      collegeId: query.collegeId,
    }
    if (active.value === 'teachers') {
      params.teacherStatus = query.status
    } else {
      Object.assign(params, {
        majorId: query.majorId,
        classId: query.classId,
        enrollmentYear: query.enrollmentYear,
        studentStatus: query.status,
      })
    }
    const { data } = await http.get<PageResult>(`/personnel/${active.value}`, { params })
    rows.value = data.items
    total.value = data.total
  } catch (error) {
    ElMessage.error(apiErrorMessage(error))
  } finally {
    loading.value = false
  }
}

async function loadReferences() {
  const [collegeRes, majorRes, classRes] = await Promise.all([
    http.get('/base-data/colleges'),
    http.get('/base-data/majors'),
    http.get('/base-data/classes'),
  ])
  colleges.value = collegeRes.data
  majors.value = majorRes.data
  classes.value = classRes.data
  if (scopedCollegeId.value) query.collegeId = scopedCollegeId.value
}

function resetFilters() {
  Object.assign(query, {
    page: 1,
    keyword: '',
    collegeId: scopedCollegeId.value,
    majorId: undefined,
    classId: undefined,
    enrollmentYear: undefined,
    status: undefined,
  })
  load()
}

function exportParams() {
  const params: Record<string, any> = {
    keyword: query.keyword || undefined,
    collegeId: query.collegeId,
  }
  if (active.value === 'teachers') params.teacherStatus = query.status
  else {
    Object.assign(params, {
      majorId: query.majorId,
      classId: query.classId,
      enrollmentYear: query.enrollmentYear,
      studentStatus: query.status,
    })
  }
  return params
}

async function downloadTemplate() {
  try {
    await downloadApiFile(
      `/personnel/${active.value}/template`,
      `${pageTitle.value}导入模板.xlsx`,
    )
  } catch (error) {
    ElMessage.error(apiErrorMessage(error))
  }
}

async function exportRows() {
  try {
    await downloadApiFile(
      `/personnel/${active.value}/export`,
      `${pageTitle.value}.xlsx`,
      { params: exportParams() },
    )
    ElMessage.success(`${pageTitle.value}已导出`)
  } catch (error) {
    ElMessage.error(apiErrorMessage(error))
  }
}

function chooseImportFile() {
  fileInput.value?.click()
}

async function handleImport(event: Event) {
  const input = event.target as HTMLInputElement
  const file = input.files?.[0]
  input.value = ''
  if (!file) return
  importing.value = true
  try {
    const { data } = await importExcel(`/personnel/${active.value}/import`, file)
    ElMessage.success(`导入完成：新增 ${data.created} 条，更新 ${data.updated} 条`)
    await load()
  } catch (error) {
    ElMessage.error(apiErrorMessage(error))
  } finally {
    importing.value = false
  }
}

function openCreate() {
  editingId.value = ''
  resetForm()
  dialogVisible.value = true
}

function openEdit(row: any) {
  editingId.value = row.id
  resetForm(row)
  dialogVisible.value = true
}

async function save() {
  const number = active.value === 'teachers' ? form.teacherNumber : form.studentNumber
  if (!number?.trim() || !form.name?.trim()) {
    ElMessage.warning(`请填写${numberLabel.value}和姓名。`)
    return
  }
  try {
    const path = `/personnel/${active.value}`
    if (editingId.value) await http.put(`${path}/${editingId.value}`, form)
    else await http.post(path, form)
    ElMessage.success(editingId.value ? '档案已更新' : '档案已建立')
    dialogVisible.value = false
    await load()
  } catch (error) {
    ElMessage.error(apiErrorMessage(error))
  }
}

async function remove(row: any) {
  try {
    await ElMessageBox.confirm(
      `确定删除“${row.name}”的${pageTitle.value}吗？`,
      '删除档案',
      { type: 'warning', confirmButtonText: '删除', cancelButtonText: '取消' },
    )
    await http.delete(`/personnel/${active.value}/${row.id}`)
    ElMessage.success('档案已删除')
    await load()
  } catch (error: any) {
    if (error !== 'cancel' && error !== 'close') ElMessage.error(apiErrorMessage(error))
  }
}

function openActivation(row: any) {
  activatingTeacher.value = row
  activationForm.password = ''
  activationForm.confirmPassword = ''
  activationDialog.value = true
}

async function activateTeacherAccount() {
  if (!activationForm.password) {
    ElMessage.warning('请设置教师的初始密码。')
    return
  }
  if (activationForm.password.length < 8 ||
      !/[a-z]/.test(activationForm.password) ||
      !/[A-Z]/.test(activationForm.password) ||
      !/\d/.test(activationForm.password) ||
      !/[^A-Za-z0-9]/.test(activationForm.password)) {
    ElMessage.warning('密码至少 8 位，并包含大写字母、小写字母、数字和特殊字符。')
    return
  }
  if (activationForm.password !== activationForm.confirmPassword) {
    ElMessage.warning('两次输入的密码不一致。')
    return
  }

  activationLoading.value = true
  try {
    const { data } = await http.post(
      `/personnel/teachers/${activatingTeacher.value.id}/activate-account`,
      { password: activationForm.password },
    )
    activationDialog.value = false
    ElMessage.success(`教师账号 ${data.userName} 已激活`)
    await load()
  } catch (error) {
    ElMessage.error(apiErrorMessage(error))
  } finally {
    activationLoading.value = false
  }
}

function viewTimetable(teacher: any) {
  router.push({ name: 'teacher-timetable', params: { teacherId: teacher.id } })
}

onMounted(async () => {
  await Promise.all([loadReferences(), load()])
})

watch(active, async () => {
  resetFilters()
})
</script>

<template>
  <div class="page-stack">
    <section class="page-intro registry-intro">
      <div>
        <span class="section-kicker">
          {{ active === 'teachers' ? 'TEACHING STAFF' : 'STUDENT ROLL' }}
        </span>
        <h2>{{ pageTitle }}</h2>
        <p>
          {{ active === 'teachers'
            ? '以工号维护教师归属、职称、任职状态与联系信息。'
            : '以学号维护学生班级归属、入学信息与学籍状态。' }}
        </p>
      </div>
      <el-button v-if="canManage" type="primary" :icon="Plus" @click="openCreate">
        新增{{ pageTitle }}
      </el-button>
    </section>

    <section class="registry-banner" :class="{ student: active === 'students' }">
      <div>
        <span>{{ active === 'teachers' ? 'STAFF DIRECTORY' : 'STUDENT DIRECTORY' }}</span>
        <b>{{ active === 'teachers' ? '工号是教师身份与教学任务的唯一索引' : '学号贯穿学籍、选课、成绩与毕业业务' }}</b>
        <small>当前筛选结果会原样用于 Excel 导出</small>
      </div>
      <div class="registry-total">
        <span>当前结果</span>
        <strong>{{ total }}</strong>
        <small>条档案</small>
      </div>
    </section>

    <section class="data-card">
      <div class="filter-bar">
        <el-input
          v-model="query.keyword"
          :prefix-icon="Search"
          clearable
          :placeholder="`搜索${numberLabel}、姓名${active === 'teachers' ? '或职称' : ''}`"
          @keyup.enter="query.page = 1; load()"
        />
        <el-select v-model="query.collegeId" clearable placeholder="全部学院">
          <el-option v-for="item in availableColleges" :key="item.id" :label="item.name" :value="item.id" />
        </el-select>
        <template v-if="active === 'students'">
          <el-select v-model="query.majorId" clearable filterable placeholder="全部专业">
            <el-option v-for="item in filteredMajors" :key="item.id" :label="item.name" :value="item.id" />
          </el-select>
          <el-select v-model="query.classId" clearable filterable placeholder="全部班级">
            <el-option v-for="item in filteredClasses" :key="item.id" :label="item.name" :value="item.id" />
          </el-select>
        </template>
        <el-select v-model="query.status" clearable placeholder="全部状态">
          <el-option
            v-for="(label, value) in active === 'teachers' ? teacherStatusLabels : studentStatusLabels"
            :key="value"
            :label="label"
            :value="value"
          />
        </el-select>
        <el-button type="primary" @click="query.page = 1; load()">查询</el-button>
        <el-button :icon="Refresh" @click="resetFilters">重置</el-button>
        <template v-if="canManage">
          <el-button :icon="Document" @click="downloadTemplate">下载模板</el-button>
          <el-button :icon="Upload" :loading="importing" @click="chooseImportFile">Excel 导入</el-button>
          <input
            ref="fileInput"
            class="visually-hidden"
            type="file"
            accept=".xlsx"
            @change="handleImport"
          />
        </template>
        <el-button :icon="Download" @click="exportRows">导出结果</el-button>
      </div>

      <el-table v-loading="loading" :data="rows" class="data-table registry-table">
        <el-table-column :label="numberLabel" width="135">
          <template #default="{ row }"><span class="registry-number">{{ active === 'teachers' ? row.teacherNumber : row.studentNumber }}</span></template>
        </el-table-column>
        <el-table-column label="姓名" min-width="120">
          <template #default="{ row }">
            <div class="record-name">
              <b>{{ row.name }}</b>
              <span>{{ genderLabels[row.gender] }}</span>
            </div>
          </template>
        </el-table-column>
        <el-table-column v-if="active === 'teachers'" prop="collegeName" label="所属学院" min-width="150" />
        <el-table-column v-if="active === 'teachers'" prop="title" label="职称" width="110">
          <template #default="{ row }">{{ row.title || '—' }}</template>
        </el-table-column>
        <el-table-column v-if="active === 'teachers'" label="教师类别" width="105">
          <template #default="{ row }">{{ row.isExternal ? '外聘' : '校内' }}</template>
        </el-table-column>
        <el-table-column v-if="active === 'students'" prop="className" label="行政班" min-width="155" />
        <el-table-column v-if="active === 'students'" prop="majorName" label="专业" min-width="170" />
        <el-table-column v-if="active === 'students'" prop="enrollmentYear" label="入学年级" width="105" />
        <el-table-column label="状态" width="95">
          <template #default="{ row }">
            <span class="table-status" :class="{ off: row.status !== 'Active' }">
              {{ (active === 'teachers' ? teacherStatusLabels : studentStatusLabels)[row.status] }}
            </span>
          </template>
        </el-table-column>
        <el-table-column label="登录账号" width="105">
          <template #default="{ row }">
            <span class="table-status" :class="{ off: !row.userId }">
              {{ row.userId ? '已激活' : '未激活' }}
            </span>
          </template>
        </el-table-column>
        <el-table-column label="联系方式" min-width="170">
          <template #default="{ row }">{{ row.phone || row.email || '—' }}</template>
        </el-table-column>
        <el-table-column
          v-if="canManage"
          label="操作"
          :width="active === 'teachers' ? 280 : 145"
          fixed="right"
        >
          <template #default="{ row }">
            <el-button
              v-if="active === 'teachers' && !row.userId"
              link
              type="success"
              :icon="Key"
              :disabled="row.status !== 'Active'"
              @click="openActivation(row)"
            >
              激活账号
            </el-button>
            <el-button
              v-if="active === 'teachers'"
              link
              type="warning"
              :icon="Calendar"
              :disabled="row.status !== 'Active'"
              @click="viewTimetable(row)"
            >
              课表
            </el-button>
            <el-button link type="primary" @click="openEdit(row)">编辑</el-button>
            <el-button link type="danger" @click="remove(row)">删除</el-button>
          </template>
        </el-table-column>
        <template #empty><el-empty description="没有符合条件的档案" /></template>
      </el-table>

      <div class="pagination-bar">
        <span>共 {{ total }} 条</span>
        <el-pagination
          v-model:current-page="query.page"
          :page-size="query.pageSize"
          :total="total"
          layout="prev, pager, next"
          @current-change="load"
        />
      </div>
    </section>

    <el-dialog v-model="dialogVisible" :title="`${editingId ? '编辑' : '新增'}${pageTitle}`" width="620px">
      <el-form label-position="top" class="entity-form">
        <template v-if="active === 'teachers'">
          <div class="form-grid">
            <el-form-item label="工号" required><el-input v-model="form.teacherNumber" /></el-form-item>
            <el-form-item label="姓名" required><el-input v-model="form.name" /></el-form-item>
          </div>
          <div class="form-grid">
            <el-form-item label="所属学院" required>
              <el-select v-model="form.collegeId">
                <el-option v-for="item in availableColleges" :key="item.id" :label="item.name" :value="item.id" />
              </el-select>
            </el-form-item>
            <el-form-item label="职称"><el-input v-model="form.title" placeholder="教授、副教授、讲师等" /></el-form-item>
          </div>
          <div class="form-grid">
            <el-form-item label="性别">
              <el-select v-model="form.gender">
                <el-option v-for="(label, value) in genderLabels" :key="value" :label="label" :value="value" />
              </el-select>
            </el-form-item>
            <el-form-item label="任职状态">
              <el-select v-model="form.status">
                <el-option v-for="(label, value) in teacherStatusLabels" :key="value" :label="label" :value="value" />
              </el-select>
            </el-form-item>
          </div>
          <div class="form-grid">
            <el-form-item label="入职日期"><el-date-picker v-model="form.hireDate" value-format="YYYY-MM-DD" /></el-form-item>
            <el-form-item label="教师类别"><el-switch v-model="form.isExternal" active-text="外聘" inactive-text="校内" /></el-form-item>
          </div>
        </template>
        <template v-else>
          <div class="form-grid">
            <el-form-item label="学号" required><el-input v-model="form.studentNumber" /></el-form-item>
            <el-form-item label="姓名" required><el-input v-model="form.name" /></el-form-item>
          </div>
          <el-form-item label="行政班" required>
            <el-select v-model="form.administrativeClassId" filterable>
              <el-option
                v-for="item in formClasses"
                :key="item.id"
                :label="`${item.collegeName} · ${item.majorName} · ${item.name}`"
                :value="item.id"
              />
            </el-select>
          </el-form-item>
          <div class="form-grid">
            <el-form-item label="入学年级"><el-input-number v-model="form.enrollmentYear" :min="2000" :max="2200" /></el-form-item>
            <el-form-item label="入学日期"><el-date-picker v-model="form.enrollmentDate" value-format="YYYY-MM-DD" /></el-form-item>
          </div>
          <div class="form-grid">
            <el-form-item label="性别">
              <el-select v-model="form.gender">
                <el-option v-for="(label, value) in genderLabels" :key="value" :label="label" :value="value" />
              </el-select>
            </el-form-item>
            <el-form-item label="学籍状态">
              <el-select v-model="form.status">
                <el-option v-for="(label, value) in studentStatusLabels" :key="value" :label="label" :value="value" />
              </el-select>
            </el-form-item>
          </div>
          <el-form-item label="出生日期"><el-date-picker v-model="form.dateOfBirth" value-format="YYYY-MM-DD" /></el-form-item>
        </template>
        <div class="form-grid">
          <el-form-item label="联系电话"><el-input v-model="form.phone" /></el-form-item>
          <el-form-item label="电子邮箱"><el-input v-model="form.email" /></el-form-item>
        </div>
        <el-form-item label="备注"><el-input v-model="form.notes" type="textarea" :rows="3" /></el-form-item>
      </el-form>
      <template #footer>
        <el-button @click="dialogVisible = false">取消</el-button>
        <el-button type="primary" @click="save">保存档案</el-button>
      </template>
    </el-dialog>

    <el-dialog
      v-model="activationDialog"
      title="激活教师账号"
      width="520px"
      @closed="activatingTeacher = null"
    >
      <el-alert
        title="账号激活后，教师可使用工号和初始密码登录。请通过安全方式将密码交给教师。"
        type="info"
        :closable="false"
        show-icon
      />
      <el-form v-if="activatingTeacher" label-position="top" class="entity-form activation-account-form">
        <div class="form-grid">
          <el-form-item label="教师">
            <el-input :model-value="activatingTeacher.name" disabled />
          </el-form-item>
          <el-form-item label="登录账号">
            <el-input :model-value="activatingTeacher.teacherNumber" disabled />
          </el-form-item>
        </div>
        <el-form-item label="初始密码" required>
          <el-input
            v-model="activationForm.password"
            type="password"
            show-password
            autocomplete="new-password"
            placeholder="至少 8 位，含大小写字母、数字和特殊字符"
          />
        </el-form-item>
        <el-form-item label="确认初始密码" required>
          <el-input
            v-model="activationForm.confirmPassword"
            type="password"
            show-password
            autocomplete="new-password"
            @keyup.enter="activateTeacherAccount"
          />
        </el-form-item>
      </el-form>
      <template #footer>
        <el-button @click="activationDialog = false">取消</el-button>
        <el-button
          type="primary"
          :loading="activationLoading"
          @click="activateTeacherAccount"
        >
          确认激活
        </el-button>
      </template>
    </el-dialog>
  </div>
</template>

<style scoped>
.activation-account-form {
  margin-top: 20px;
}
</style>
