<script setup lang="ts">
import { computed, onMounted, reactive, ref } from 'vue'
import { Check, Close, Plus, RefreshRight, Stamp } from '@element-plus/icons-vue'
import http, { apiErrorMessage } from '../api/http'
import { useAuthStore } from '../stores/auth'

type ChangeState =
  | 'Submitted'
  | 'CounselorApproved'
  | 'CollegeApproved'
  | 'Approved'
  | 'Rejected'
  | 'Cancelled'

const auth = useAuthStore()
const isStudent = computed(() => auth.user?.roles.includes('Student') ?? false)
const changes = ref<any[]>([])
const options = ref<any | null>(null)
const loading = ref(false)
const applyDialog = ref(false)
const reviewDialog = ref(false)
const selected = ref<any | null>(null)
const reviewApproved = ref(true)
const applyForm = reactive({ type: '', reason: '' })
const reviewForm = reactive({ comment: '' })
const page = ref(1)
const total = ref(0)
const actionableTotal = ref(0)
const finishedTotal = ref(0)
const pageSize = 20

const typeLabels: Record<string, string> = {
  Suspension: '休学',
  Resumption: '复学',
  Withdrawal: '退学',
}
const statusLabels: Record<string, string> = {
  Active: '在籍',
  Suspended: '休学',
  Withdrawn: '退学',
  Graduated: '毕业',
}
const stateLabels: Record<ChangeState, string> = {
  Submitted: '待辅导员审核',
  CounselorApproved: '待学院审核',
  CollegeApproved: '待校级审核',
  Approved: '已批准',
  Rejected: '已驳回',
  Cancelled: '已撤回',
}
const steps = [
  { label: '辅导员审核', state: 'Submitted' },
  { label: '学院审核', state: 'CounselorApproved' },
  { label: '校级审批', state: 'CollegeApproved' },
]
function dateText(value?: string) {
  if (!value) return '—'
  return new Intl.DateTimeFormat('zh-CN', {
    year: 'numeric', month: '2-digit', day: '2-digit',
    hour: '2-digit', minute: '2-digit', hour12: false,
  }).format(new Date(value))
}
function stageIndex(state: ChangeState) {
  if (state === 'Submitted') return 0
  if (state === 'CounselorApproved') return 1
  if (state === 'CollegeApproved') return 2
  if (state === 'Approved') return 3
  return -1
}
function stepClass(change: any, index: number) {
  const current = stageIndex(change.state)
  return {
    done: change.state === 'Approved' || current > index,
    active: current === index,
    stopped: ['Rejected', 'Cancelled'].includes(change.state) && index === Math.max(current, 0),
  }
}
function canReview(change: any) {
  const roles = auth.user?.roles ?? []
  return (
    (change.state === 'Submitted' && roles.includes('Counselor')) ||
    (change.state === 'CounselorApproved' && roles.includes('CollegeAdmin')) ||
    (change.state === 'CollegeApproved' &&
      roles.some((role) => ['AcademicAdmin', 'SuperAdmin'].includes(role)))
  )
}
function stateTagType(state: ChangeState) {
  if (state === 'Approved') return 'success'
  if (state === 'Rejected') return 'danger'
  if (state === 'Cancelled') return 'info'
  return 'warning'
}

async function load(resetPage = false) {
  if (resetPage) page.value = 1
  loading.value = true
  try {
    const requests = [http.get('/student-status-changes', {
      params: { page: page.value, pageSize },
    })]
    if (isStudent.value) requests.push(http.get('/student-status-changes/options'))
    const [changeResponse, optionResponse] = await Promise.all(requests)
    changes.value = changeResponse.data.items
    total.value = changeResponse.data.total
    actionableTotal.value = changeResponse.data.actionableTotal
    finishedTotal.value = changeResponse.data.finishedTotal
    if (optionResponse) options.value = optionResponse.data
    if (changes.value.length === 0 && page.value > 1) {
      page.value--
      await load()
    }
  } catch (error) {
    ElMessage.error(apiErrorMessage(error))
  } finally {
    loading.value = false
  }
}
function openApply() {
  applyForm.type = options.value?.types?.[0] ?? ''
  applyForm.reason = ''
  applyDialog.value = true
}
async function submitApply() {
  if (!applyForm.type || applyForm.reason.trim().length < 10) {
    ElMessage.warning('请选择异动类型，并填写至少 10 个字的申请说明。')
    return
  }
  try {
    await http.post('/student-status-changes', applyForm)
    applyDialog.value = false
    ElMessage.success('申请已提交，等待辅导员审核。')
    await load(true)
  } catch (error) {
    ElMessage.error(apiErrorMessage(error))
  }
}
async function cancel(change: any) {
  try {
    await ElMessageBox.confirm('撤回后本次申请将结束，需要时可重新提交。', '撤回申请', {
      type: 'warning', confirmButtonText: '确认撤回',
    })
    await http.post(`/student-status-changes/${change.id}/cancel`)
    ElMessage.success('申请已撤回。')
    await load()
  } catch (error: any) {
    if (error !== 'cancel' && error !== 'close') ElMessage.error(apiErrorMessage(error))
  }
}
function openReview(change: any, approved: boolean) {
  selected.value = change
  reviewApproved.value = approved
  reviewForm.comment = ''
  reviewDialog.value = true
}
async function submitReview() {
  if (!reviewApproved.value && !reviewForm.comment.trim()) {
    ElMessage.warning('驳回申请时必须填写审核意见。')
    return
  }
  try {
    await http.post(`/student-status-changes/${selected.value.id}/review`, {
      approved: reviewApproved.value,
      comment: reviewForm.comment,
    })
    reviewDialog.value = false
    ElMessage.success(reviewApproved.value ? '审核已通过，申请进入下一环节。' : '申请已驳回。')
    await load()
  } catch (error) {
    ElMessage.error(apiErrorMessage(error))
  }
}

onMounted(load)
</script>

<template>
  <div class="page-stack status-change-page">
    <section class="page-intro">
      <div>
        <span class="section-kicker">STUDENT RECORD TRANSFER</span>
        <h2>{{ isStudent ? '学籍异动申请' : '学籍异动审核' }}</h2>
        <p>{{ isStudent ? '在线办理休学、复学或退学申请，清晰跟踪每一级审核进度。' : '按辅导员、学院、学校三级权限逐级审核，最终结果同步学生学籍。' }}</p>
      </div>
      <el-button
        v-if="isStudent"
        type="primary"
        :icon="Plus"
        :disabled="options?.hasPending || !options?.types?.length"
        @click="openApply"
      >发起申请</el-button>
      <el-button v-else :icon="RefreshRight" @click="() => load()">刷新队列</el-button>
    </section>

    <section v-if="isStudent && options" class="status-identity">
      <div>
        <span>CURRENT STUDENT STATUS</span>
        <b>{{ statusLabels[options.status] }}</b>
        <p>{{ options.hasPending ? '当前有申请正在流转，请等待处理。' : '当前可以提交新的学籍异动申请。' }}</p>
      </div>
      <div class="status-available">
        <span>可申请业务</span>
        <strong v-for="type in options.types" :key="type">{{ typeLabels[type] }}</strong>
        <em v-if="!options.types.length">当前状态无可申请业务</em>
      </div>
    </section>

    <section v-if="!isStudent" class="status-review-summary">
      <div><span>当前待我审核</span><b>{{ actionableTotal }}</b><small>件</small></div>
      <div><span>辖区申请总数</span><b>{{ total }}</b><small>件</small></div>
      <div><span>已结束</span><b>{{ finishedTotal }}</b><small>件</small></div>
      <p>系统仅开放当前审核层级的操作，所有越级请求都会由服务端拒绝。</p>
    </section>

    <section class="status-folio-list" v-loading="loading">
      <article v-for="change in changes" :key="change.id" :class="{ actionable: canReview(change) }">
        <header>
          <div class="folio-number">
            <span>APPLICATION FOLIO</span>
            <b>{{ change.studentNumber }}</b>
          </div>
          <div class="folio-person">
            <span>{{ change.collegeName }} · {{ change.className }}</span>
            <h3>{{ change.name }} · {{ typeLabels[change.type] }}申请</h3>
            <p>{{ statusLabels[change.originalStatus] }} → {{ statusLabels[change.targetStatus] }} · 提交于 {{ dateText(change.submittedAt) }}</p>
          </div>
          <el-tag :type="stateTagType(change.state)" effect="plain">{{ stateLabels[change.state as ChangeState] }}</el-tag>
        </header>

        <div class="folio-reason">
          <span>申请说明</span>
          <p>{{ change.reason }}</p>
        </div>

        <div class="approval-track">
          <div v-for="(step, index) in steps" :key="step.state" :class="stepClass(change, index)">
            <i><el-icon v-if="stepClass(change, index).done"><Check /></el-icon><span v-else>{{ index + 1 }}</span></i>
            <b>{{ step.label }}</b>
            <small>{{ stepClass(change, index).done ? '已通过' : stepClass(change, index).active ? '处理中' : '待流转' }}</small>
          </div>
        </div>

        <footer>
          <div v-if="change.reviewComment" class="review-comment">
            <span>最近审核意见</span><b>{{ change.reviewComment }}</b>
          </div>
          <div v-else class="review-comment"><span>流程编号</span><b>{{ change.id.slice(0, 8).toUpperCase() }}</b></div>
          <div class="folio-actions">
            <el-button v-if="isStudent && change.state === 'Submitted'" type="danger" plain @click="cancel(change)">撤回申请</el-button>
            <template v-if="canReview(change)">
              <el-button :icon="Close" type="danger" plain @click="openReview(change, false)">驳回</el-button>
              <el-button :icon="Stamp" type="primary" @click="openReview(change, true)">审核通过</el-button>
            </template>
          </div>
        </footer>
      </article>
      <el-empty v-if="!changes.length && !loading" :description="isStudent ? '尚未提交学籍异动申请' : '当前辖区暂无学籍异动申请'" />
      <el-pagination
        v-if="total > pageSize"
        v-model:current-page="page"
        :page-size="pageSize"
        :total="total"
        layout="total, prev, pager, next"
        class="table-pagination"
        @current-change="() => load()"
      />
    </section>

    <el-dialog v-model="applyDialog" title="发起学籍异动申请" width="620px">
      <el-form label-position="top">
        <el-form-item label="申请类型">
          <el-radio-group v-model="applyForm.type">
            <el-radio-button v-for="type in options?.types" :key="type" :value="type">{{ typeLabels[type] }}</el-radio-button>
          </el-radio-group>
        </el-form-item>
        <el-form-item label="申请说明">
          <el-input v-model="applyForm.reason" type="textarea" :rows="6" maxlength="1000" show-word-limit placeholder="请说明申请原因、预计时间以及需要学校了解的情况（至少 10 个字）" />
        </el-form-item>
      </el-form>
      <template #footer>
        <el-button @click="applyDialog = false">取消</el-button>
        <el-button type="primary" @click="submitApply">提交申请</el-button>
      </template>
    </el-dialog>

    <el-dialog v-model="reviewDialog" :title="reviewApproved ? '审核通过' : '驳回申请'" width="600px">
      <div v-if="selected" class="review-target">
        <span>{{ selected.studentNumber }}</span>
        <b>{{ selected.name }} · {{ typeLabels[selected.type] }}申请</b>
        <p>{{ selected.collegeName }} · {{ selected.className }}</p>
      </div>
      <el-form label-position="top">
        <el-form-item :label="reviewApproved ? '审核意见（选填）' : '驳回原因（必填）'">
          <el-input v-model="reviewForm.comment" type="textarea" :rows="4" maxlength="500" show-word-limit />
        </el-form-item>
      </el-form>
      <template #footer>
        <el-button @click="reviewDialog = false">取消</el-button>
        <el-button :type="reviewApproved ? 'primary' : 'danger'" @click="submitReview">{{ reviewApproved ? '确认通过' : '确认驳回' }}</el-button>
      </template>
    </el-dialog>
  </div>
</template>
