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

const auth = useAuthStore()
const loading = ref(false)
const rows = ref<any[]>([])
const total = ref(0)
const colleges = ref<any[]>([])
const categories = ref<any[]>([])
const courseOptions = ref<any[]>([])
const dialogVisible = ref(false)
const editingId = ref('')
const importing = ref(false)
const importInput = ref<HTMLInputElement>()
const query = reactive({
  page: 1,
  pageSize: 20,
  keyword: '',
  collegeId: undefined as string | undefined,
  categoryId: undefined as string | undefined,
  nature: undefined as string | undefined,
  isEnabled: undefined as boolean | undefined,
})
const form = reactive<Record<string, any>>({})

const canManage = computed(() =>
  auth.user?.roles.some((role) =>
    ['SuperAdmin', 'AcademicAdmin', 'CollegeAdmin'].includes(role),
  ) ?? false,
)
const isCollegeAdmin = computed(() => auth.user?.roles.includes('CollegeAdmin') ?? false)
const formColleges = computed(() =>
  auth.user?.roles.includes('CollegeAdmin') && auth.user.collegeId
    ? colleges.value.filter((item) => item.id === auth.user!.collegeId)
    : colleges.value,
)
const natureLabels: Record<string, string> = {
  GeneralRequired: '通识必修',
  MajorRequired: '专业必修',
  MajorElective: '专业选修',
  GeneralElective: '通识选修',
  Practice: '实践课程',
}
const assessmentLabels: Record<string, string> = {
  Examination: '考试',
  Assessment: '考查',
}
const collegeNatureLabels = computed(() => {
  if (!isCollegeAdmin.value) return natureLabels
  return Object.fromEntries(
    Object.entries(natureLabels).filter(([value]) =>
      ['MajorRequired', 'MajorElective', 'Practice'].includes(value),
    ),
  )
})
const maintenanceScope = computed(() =>
  isCollegeAdmin.value
    ? `${formColleges.value[0]?.name ?? '所属学院'} · 专业课与实践课`
    : '全校课程 · 全性质',
)
const prerequisiteOptions = computed(() =>
  courseOptions.value.filter((item) => item.id !== editingId.value),
)

function canManageRow(row: any) {
  return row.canManage === true
}

function resetForm(row?: any) {
  Object.keys(form).forEach((key) => delete form[key])
  Object.assign(form, {
    code: '',
    name: '',
    englishName: '',
    collegeId: auth.user?.roles.includes('CollegeAdmin') ? auth.user.collegeId : undefined,
    courseCategoryId: categories.value.find((item) => item.isEnabled)?.id,
    credits: 2,
    totalHours: 32,
    lectureHours: 24,
    practiceHours: 8,
    nature: isCollegeAdmin.value ? 'MajorRequired' : 'GeneralRequired',
    assessmentMethod: 'Examination',
    description: '',
    prerequisiteCourseIds: [],
    isEnabled: true,
    sortOrder: 0,
  }, row ?? {})
}

async function load() {
  loading.value = true
  try {
    const { data } = await http.get('/courses', {
      params: {
        page: query.page,
        pageSize: query.pageSize,
        keyword: query.keyword || undefined,
        collegeId: query.collegeId,
        categoryId: query.categoryId,
        nature: query.nature,
        isEnabled: query.isEnabled,
      },
    })
    rows.value = data.items
    total.value = data.total
  } catch (error) {
    ElMessage.error(apiErrorMessage(error))
  } finally {
    loading.value = false
  }
}

async function resetFilters() {
  Object.assign(query, {
    page: 1,
    keyword: '',
    collegeId: undefined,
    categoryId: undefined,
    nature: undefined,
    isEnabled: undefined,
  })
  await load()
}

function exportParams() {
  return {
    keyword: query.keyword || undefined,
    collegeId: query.collegeId,
    categoryId: query.categoryId,
    nature: query.nature,
    isEnabled: query.isEnabled,
  }
}

async function downloadTemplate() {
  try {
    await downloadApiFile('/courses/template', '课程库导入模板.xlsx')
  } catch (error) {
    ElMessage.error(apiErrorMessage(error))
  }
}

async function exportRows() {
  try {
    await downloadApiFile(
      '/courses/export',
      '课程库.xlsx',
      { params: exportParams() },
    )
  } catch (error) {
    ElMessage.error(apiErrorMessage(error))
  }
}

function chooseImportFile() {
  importInput.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('/courses/import', file)
    ElMessage.success(
      `导入完成：新增 ${data.created} 门，更新 ${data.updated} 门，共处理 ${data.total} 门。`,
    )
    query.page = 1
    await load()
    courseOptions.value = (await http.get('/courses/options')).data
  } 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() {
  if (!form.code?.trim() || !form.name?.trim() ||
      !form.collegeId || !form.courseCategoryId) {
    ElMessage.warning('请填写课程编码、名称、开课学院和课程分类。')
    return
  }
  if (form.lectureHours + form.practiceHours > form.totalHours) {
    ElMessage.warning('讲授学时与实践学时之和不能超过总学时。')
    return
  }
  try {
    if (editingId.value) await http.put(`/courses/${editingId.value}`, form)
    else await http.post('/courses', form)
    ElMessage.success(editingId.value ? '课程已更新' : '课程已加入课程库')
    dialogVisible.value = false
    await load()
    courseOptions.value = (await http.get('/courses/options')).data
  } catch (error) {
    ElMessage.error(apiErrorMessage(error))
  }
}

async function remove(row: any) {
  try {
    await ElMessageBox.confirm(
      `确定删除课程“${row.name}”吗？已进入培养方案的课程将无法删除。`,
      '删除课程',
      { type: 'warning', confirmButtonText: '删除', cancelButtonText: '取消' },
    )
    await http.delete(`/courses/${row.id}`)
    ElMessage.success('课程已删除')
    await load()
  } catch (error: any) {
    if (error !== 'cancel' && error !== 'close') ElMessage.error(apiErrorMessage(error))
  }
}

onMounted(async () => {
  const [collegeRes, categoryRes, courseRes] = await Promise.all([
    http.get('/base-data/colleges'),
    http.get('/base-data/course-categories'),
    http.get('/courses/options'),
  ])
  colleges.value = collegeRes.data
  categories.value = categoryRes.data
  courseOptions.value = courseRes.data
  await load()
})
</script>

<template>
  <div class="page-stack">
    <section class="page-intro">
      <div>
        <span class="section-kicker">COURSE CATALOGUE</span>
        <h2>课程库</h2>
        <p>通识课程由校级统筹，专业课与实践课由开课学院维护，统一供培养方案与教学任务引用。</p>
      </div>
      <div class="page-actions">
        <el-button :icon="Download" @click="exportRows">导出结果</el-button>
        <el-button v-if="canManage" type="primary" :icon="Plus" @click="openCreate">新增课程</el-button>
      </div>
    </section>

    <section class="course-ledger">
      <div class="ledger-label">
        <span>当前可见</span>
        <b>{{ total }}</b>
        <small>门课程</small>
      </div>
      <div class="ledger-rule">
        <span>维护范围</span>
        <b>{{ maintenanceScope }}</b>
        <small>{{ isCollegeAdmin ? '通识课程可查看、可引用' : '负责跨学院标准统筹' }}</small>
      </div>
    </section>

    <section class="data-card">
      <div class="filter-bar">
        <el-input
          v-model="query.keyword"
          :prefix-icon="Search"
          clearable
          placeholder="搜索课程编码、中英文名称"
          @keyup.enter="query.page = 1; load()"
        />
        <el-select v-model="query.collegeId" clearable placeholder="全部开课学院">
          <el-option v-for="item in colleges" :key="item.id" :label="item.name" :value="item.id" />
        </el-select>
        <el-select v-model="query.categoryId" clearable placeholder="全部课程分类">
          <el-option v-for="item in categories" :key="item.id" :label="item.name" :value="item.id" />
        </el-select>
        <el-select v-model="query.nature" clearable placeholder="全部课程性质">
          <el-option v-for="(label, value) in natureLabels" :key="value" :label="label" :value="value" />
        </el-select>
        <el-select v-model="query.isEnabled" clearable placeholder="全部状态">
          <el-option label="启用" :value="true" />
          <el-option label="停用" :value="false" />
        </el-select>
        <el-button type="primary" @click="query.page = 1; load()">查询</el-button>
        <el-button :icon="Refresh" @click="resetFilters">重置</el-button>
      </div>
      <div class="table-toolbar">
        <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="importInput"
            class="visually-hidden"
            type="file"
            accept=".xlsx"
            @change="handleImport"
          />
        </template>
        <span>当前筛选条件会原样用于 Excel 导出 · 共 {{ total }} 门</span>
      </div>

      <el-table v-loading="loading" :data="rows" class="data-table course-table">
        <el-table-column label="课程编码" width="130">
          <template #default="{ row }"><span class="course-code">{{ row.code }}</span></template>
        </el-table-column>
        <el-table-column label="课程名称" min-width="210">
          <template #default="{ row }">
            <div class="course-name">
              <b>{{ row.name }}</b>
              <span>{{ row.englishName || '—' }}</span>
            </div>
          </template>
        </el-table-column>
        <el-table-column prop="collegeName" label="开课学院" min-width="145" />
        <el-table-column label="课程分类" width="105">
          <template #default="{ row }">
            <span class="course-category">{{ row.categoryName || '未分类' }}</span>
          </template>
        </el-table-column>
        <el-table-column label="性质" width="105">
          <template #default="{ row }">{{ natureLabels[row.nature] }}</template>
        </el-table-column>
        <el-table-column label="学分/学时" width="120">
          <template #default="{ row }"><b>{{ row.credits }}</b> 学分 · {{ row.totalHours }} 学时</template>
        </el-table-column>
        <el-table-column label="学时构成" width="135">
          <template #default="{ row }">讲授 {{ row.lectureHours }} / 实践 {{ row.practiceHours }}</template>
        </el-table-column>
        <el-table-column label="考核" width="80">
          <template #default="{ row }">{{ assessmentLabels[row.assessmentMethod] }}</template>
        </el-table-column>
        <el-table-column label="先修课程" min-width="180">
          <template #default="{ row }">
            <span v-if="row.prerequisites?.length" class="prerequisite-list">
              {{ row.prerequisites.map((item: any) => item.code).join('、') }}
            </span>
            <span v-else>—</span>
          </template>
        </el-table-column>
        <el-table-column label="状态" width="85">
          <template #default="{ row }">
            <span class="table-status" :class="{ off: !row.isEnabled }">{{ row.isEnabled ? '启用' : '停用' }}</span>
          </template>
        </el-table-column>
        <el-table-column v-if="canManage" label="操作" width="145" fixed="right">
          <template #default="{ row }">
            <template v-if="canManageRow(row)">
              <el-button link type="primary" @click="openEdit(row)">编辑</el-button>
              <el-button link type="danger" @click="remove(row)">删除</el-button>
            </template>
            <span v-else class="muted-action">校级维护</span>
          </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 ? '编辑' : '新增'}课程`" width="660px">
      <el-form label-position="top" class="entity-form">
        <div class="form-grid">
          <el-form-item label="课程编码" required><el-input v-model="form.code" placeholder="全校唯一" /></el-form-item>
          <el-form-item label="课程名称" required><el-input v-model="form.name" /></el-form-item>
        </div>
        <el-form-item label="英文名称"><el-input v-model="form.englishName" /></el-form-item>
        <div class="form-grid">
          <el-form-item label="开课学院" required>
            <el-select v-model="form.collegeId">
              <el-option v-for="item in formColleges" :key="item.id" :label="item.name" :value="item.id" />
            </el-select>
          </el-form-item>
          <el-form-item label="课程分类" required>
            <el-select v-model="form.courseCategoryId" filterable>
              <el-option
                v-for="item in categories.filter((category) => category.isEnabled)"
                :key="item.id"
                :label="item.name"
                :value="item.id"
              />
            </el-select>
          </el-form-item>
        </div>
        <div class="form-grid">
          <el-form-item label="课程性质">
            <el-select v-model="form.nature">
              <el-option v-for="(label, value) in collegeNatureLabels" :key="value" :label="label" :value="value" />
            </el-select>
          </el-form-item>
          <div class="taxonomy-note">
            <b>两个维度</b>
            <span>分类表示教学领域，性质决定课程在培养方案中的管理方式。</span>
          </div>
        </div>
        <div class="form-grid three">
          <el-form-item label="学分"><el-input-number v-model="form.credits" :min="0.1" :max="99" :step="0.5" /></el-form-item>
          <el-form-item label="总学时"><el-input-number v-model="form.totalHours" :min="1" /></el-form-item>
          <el-form-item label="考核方式">
            <el-select v-model="form.assessmentMethod">
              <el-option v-for="(label, value) in assessmentLabels" :key="value" :label="label" :value="value" />
            </el-select>
          </el-form-item>
        </div>
        <div class="form-grid">
          <el-form-item label="讲授学时"><el-input-number v-model="form.lectureHours" :min="0" /></el-form-item>
          <el-form-item label="实践学时"><el-input-number v-model="form.practiceHours" :min="0" /></el-form-item>
        </div>
        <el-form-item label="先修课程">
          <el-select
            v-model="form.prerequisiteCourseIds"
            multiple
            filterable
            collapse-tags
            collapse-tags-tooltip
            placeholder="选择修读本课程前必须通过的课程"
          >
            <el-option
              v-for="item in prerequisiteOptions"
              :key="item.id"
              :label="`${item.code} · ${item.name}`"
              :value="item.id"
            />
          </el-select>
          <span class="field-hint">学生规划时会检查这些课程是否已经通过，或安排在更早的模拟学期。</span>
        </el-form-item>
        <el-form-item label="课程简介"><el-input v-model="form.description" type="textarea" :rows="3" /></el-form-item>
        <div class="form-grid compact">
          <el-form-item label="排序"><el-input-number v-model="form.sortOrder" :min="0" /></el-form-item>
          <el-form-item label="状态"><el-switch v-model="form.isEnabled" active-text="启用" inactive-text="停用" /></el-form-item>
        </div>
      </el-form>
      <template #footer>
        <el-button @click="dialogVisible = false">取消</el-button>
        <el-button type="primary" @click="save">保存课程</el-button>
      </template>
    </el-dialog>
  </div>
</template>
