<script setup lang="ts">
import PageTitle from '@/components/PageTitle.vue'
import { computed, ref, watch } from 'vue'
import { usePageLoad } from '@/composables/usePageLoad'
import { fetchDictByCode } from '@/api/admin/dict'
import { createDemand } from '@/api/admin/demands'
import TeacherDetailDialog from '@/views/teachers/components/TeacherDetailDialog.vue'
import TeacherPaperDialog from '@/components/TeacherPaperDialog.vue'
import { fetchAdminUsers } from '@/api/admin/users'
import type { DictItemBrief } from '@/api/admin/teachers'
import {
  batchUpdateTeacherStar,
  createTeacher,
  createTeacherFollowRecord,
  createUniversity,
  fetchTeacherFilterOptions,
  fetchTeacherFollowRecords,
  fetchTeachersList,
  fetchTeacherStats,
  fetchUniversities,
  type FollowRecordRow,
  type TeacherRow,
  type TeacherStats,
} from '@/api/admin/teachers'
import { followRuleHint, previewNextFollowDate } from '@/utils/teacherFollowRule'
import { starDisplay, sourceTagType, statusTagType, urgencyTagType } from '@/utils/teacherStar'
import { useAuthStore } from '@/stores/auth'
import { ElMessage } from 'element-plus'

const auth = useAuthStore()
const isGridMember = computed(() => auth.isGridMember)

function defaultFollowAdminUserId() {
  const currentId = auth.user?.id
  if (currentId != null && adminOptions.value.some((a) => a.id === currentId)) {
    return currentId
  }
  return adminOptions.value[0]?.id
}

const loading = ref(false)
const detailVisible = ref(false)
const detailTeacherId = ref<number | null>(null)
const items = ref<TeacherRow[]>([])
const meta = ref({ current_page: 1, per_page: 20, total: 0 })
const page = ref(1)
const stats = ref<TeacherStats>({ month_pending: 0, month_followed: 0, overdue: 0, partners: 0 })

const keyword = ref('')
const filterSource = ref<number | ''>('')
const filterStar = ref<number | ''>('')
const filterStatus = ref<number | ''>('')
const filterUniversity = ref<number | ''>('')
const filterDirection = ref<number | ''>('')
const statBucket = ref('')

const sourceOptions = ref<DictItemBrief[]>([])
const starOptions = ref<DictItemBrief[]>([])
const statusOptions = ref<DictItemBrief[]>([])
const methodOptions = ref<DictItemBrief[]>([])
const urgencyOptions = ref<DictItemBrief[]>([])
const universityOptions = ref<{ id: number; name: string; city?: string | null }[]>([])
const directionOptions = ref<{ id: number; name: string }[]>([])
const adminOptions = ref<{ id: number; label: string }[]>([])
const demandTypeOptions = ref<DictItemBrief[]>([])

const selectedRows = ref<TeacherRow[]>([])
const selectedIds = computed(() => selectedRows.value.map((r) => r.id))
const selectedNamesText = computed(() => selectedRows.value.map((r) => r.name).join('、'))

const createDialog = ref(false)
const createForm = ref({
  name: '',
  university_id: undefined as number | undefined,
  city: '',
  title: '',
  department: '',
  bio: '',
  research_direction_values: [] as Array<number | string>,
  phone: '',
  email: '',
  source_dict_item_id: undefined as number | undefined,
  star_level_dict_item_id: undefined as number | undefined,
  status_dict_item_id: undefined as number | undefined,
})

const universityDialog = ref(false)
const universitySaving = ref(false)
const universityForm = ref({
  name: '',
  city: '',
  province: '',
  longitude: '',
  latitude: '',
})

const batchDialog = ref(false)
const batchStarId = ref<number | undefined>()
const batchStarRule = computed(() => {
  const item = starOptions.value.find((s) => s.id === batchStarId.value)
  return followRuleHint(item?.value)
})

const followDialog = ref(false)
const followTeacher = ref<TeacherRow | null>(null)
const followNextDateRule = computed(() => followRuleHint(followTeacher.value?.star_level_item?.value))
const followForm = ref({
  subject: '',
  content: '',
  followed_at: new Date().toISOString().slice(0, 10),
  follow_method_dict_item_id: undefined as number | undefined,
  urgency_dict_item_id: undefined as number | undefined,
  admin_user_id: undefined as number | undefined,
  next_follow_subject: '',
  next_follow_date: '',
})

const recordsDialog = ref(false)
const recordsTeacher = ref<TeacherRow | null>(null)
const records = ref<FollowRecordRow[]>([])

const paperDialog = ref(false)
const paperTeacher = ref<TeacherRow | null>(null)

const demandDialog = ref(false)
const demandTeacher = ref<TeacherRow | null>(null)
const demandForm = ref({
  type_dict_item_id: undefined as number | undefined,
  title: '',
  content: '',
})

const manualSourceId = computed(() => sourceOptions.value.find((o) => o.value === 'manual')?.id)
const pendingStarId = computed(() => starOptions.value.find((s) => s.value === 'pending')?.id)

function onUniversityPick(id: number | undefined) {
  if (!id) return
  const u = universityOptions.value.find((x) => x.id === id)
  if (u?.city && !createForm.value.city) {
    createForm.value.city = u.city
  }
}

watch(
  () => createForm.value.university_id,
  (id) => onUniversityPick(id),
)

async function loadDicts() {
  const [source, star, status, method, urgency, demandType, uni, admins, filters] = await Promise.all([
    fetchDictByCode('teacher_source'),
    fetchDictByCode('teacher_level'),
    fetchDictByCode('teacher_status'),
    fetchDictByCode('follow_method'),
    fetchDictByCode('follow_urgency'),
    fetchDictByCode('demand_type'),
    fetchUniversities({ page: 1, page_size: 200 }),
    fetchAdminUsers({ page: 1, page_size: 200, status: 1 }),
    fetchTeacherFilterOptions(),
  ])
  sourceOptions.value = source.items
  starOptions.value = star.items
  statusOptions.value = status.items
  methodOptions.value = method.items
  urgencyOptions.value = urgency.items
  demandTypeOptions.value = demandType.items
  const scopeIds = auth.user?.grid_scope?.university_ids
  universityOptions.value = scopeIds?.length
    ? uni.items.filter((u) => scopeIds.includes(u.id))
    : uni.items
  const scopeDirIds = auth.user?.grid_scope?.research_direction_ids
  directionOptions.value = scopeDirIds?.length
    ? filters.research_directions.filter((d) => scopeDirIds.includes(d.id))
    : filters.research_directions
  adminOptions.value = admins.items.map((u) => ({
    id: u.id,
    label: u.real_name || u.username,
  }))
}

async function loadStats() {
  stats.value = await fetchTeacherStats()
}

async function load() {
  loading.value = true
  try {
    const params: Record<string, unknown> = {
      page: page.value,
      page_size: meta.value.per_page,
    }
    if (keyword.value) params.keyword = keyword.value
    if (filterSource.value !== '') params.source_dict_item_id = filterSource.value
    if (filterStar.value !== '') params.star_level_dict_item_id = filterStar.value
    if (filterStatus.value !== '') params.status_dict_item_id = filterStatus.value
    if (filterUniversity.value !== '') params.university_id = filterUniversity.value
    if (filterDirection.value !== '') params.research_direction_id = filterDirection.value
    if (statBucket.value) params.stat_bucket = statBucket.value
    const res = await fetchTeachersList(params)
    items.value = res.items
    meta.value = res.meta
    selectedRows.value = []
    const dirs = await fetchTeacherFilterOptions()
    directionOptions.value = dirs.research_directions
  } finally {
    loading.value = false
  }
}

function resetFilters() {
  keyword.value = ''
  filterSource.value = ''
  filterStar.value = ''
  filterStatus.value = ''
  filterUniversity.value = ''
  filterDirection.value = ''
  statBucket.value = ''
  page.value = 1
  load()
}

function searchTeachers() {
  page.value = 1
  load()
}

function pickStat(bucket: string) {
  statBucket.value = statBucket.value === bucket ? '' : bucket
  page.value = 1
  load()
}

function goDetail(row: TeacherRow) {
  detailTeacherId.value = row.id
  detailVisible.value = true
}

async function refreshDirectionOptions() {
  const filters = await fetchTeacherFilterOptions()
  directionOptions.value = filters.research_directions
}

function openUniversityCreate() {
  universityForm.value = {
    name: '',
    city: createForm.value.city || '',
    province: '',
    longitude: '',
    latitude: '',
  }
  universityDialog.value = true
}

async function saveUniversityCreate() {
  const f = universityForm.value
  if (!f.name.trim()) {
    ElMessage.warning('请填写高校名称')
    return
  }
  if (!f.longitude.trim() || !f.latitude.trim()) {
    ElMessage.warning('请填写经度与纬度')
    return
  }
  const longitude = Number(f.longitude)
  const latitude = Number(f.latitude)
  if (Number.isNaN(longitude) || Number.isNaN(latitude)) {
    ElMessage.warning('经纬度须为有效数字')
    return
  }
  universitySaving.value = true
  try {
    const u = await createUniversity({
      name: f.name.trim(),
      city: f.city.trim() || null,
      province: f.province.trim() || null,
      longitude,
      latitude,
    })
    if (!universityOptions.value.some((x) => x.id === u.id)) {
      universityOptions.value.push(u)
    }
    createForm.value.university_id = u.id
    if (u.city) {
      createForm.value.city = u.city
    }
    universityDialog.value = false
    ElMessage.success('高校已创建')
  } finally {
    universitySaving.value = false
  }
}

function splitDirectionValues(values: Array<number | string>) {
  const ids: number[] = []
  const names: string[] = []
  for (const value of values) {
    if (typeof value === 'number') {
      ids.push(value)
      continue
    }
    const name = String(value).trim()
    if (name) names.push(name)
  }
  return { ids, names }
}

async function openCreate() {
  createForm.value = {
    name: '',
    university_id: undefined,
    city: '',
    title: '',
    department: '',
    bio: '',
    research_direction_values: [],
    phone: '',
    email: '',
    source_dict_item_id: manualSourceId.value,
    star_level_dict_item_id: pendingStarId.value,
    status_dict_item_id: statusOptions.value.find((s) => s.value === 'active')?.id,
  }
  await refreshDirectionOptions()
  createDialog.value = true
}

async function saveCreate() {
  const f = createForm.value
  if (!f.name.trim()) {
    ElMessage.warning('请填写姓名')
    return
  }
  const directions = splitDirectionValues(f.research_direction_values)
  if (!directions.ids.length && !directions.names.length) {
    ElMessage.warning('请至少选择一个或新增研究方向')
    return
  }
  if (!f.city.trim()) {
    ElMessage.warning('请填写城市')
    return
  }
  if (!f.title.trim()) {
    ElMessage.warning('请填写职称')
    return
  }
  if (!f.status_dict_item_id) {
    ElMessage.warning('请选择状态')
    return
  }

  if (!f.university_id) {
    ElMessage.warning('请选择高校，或点击「新建高校」')
    return
  }

  await createTeacher({
    name: f.name.trim(),
    university_id: f.university_id,
    city: f.city.trim(),
    title: f.title.trim(),
    department: f.department.trim() || null,
    bio: f.bio.trim() || null,
    research_direction_ids: directions.ids,
    new_research_directions: directions.names,
    phone: f.phone || null,
    email: f.email || null,
    source_dict_item_id: f.source_dict_item_id ?? manualSourceId.value,
    star_level_dict_item_id: f.star_level_dict_item_id ?? pendingStarId.value,
    status_dict_item_id: f.status_dict_item_id,
    recalc_next_follow_date: true,
  })
  ElMessage.success('已录入')
  createDialog.value = false
  await Promise.all([load(), loadStats()])
}

function openBatch() {
  if (!selectedRows.value.length) {
    ElMessage.warning('请先在列表中勾选需要改星的老师')
    return
  }
  batchStarId.value = undefined
  batchDialog.value = true
}

async function saveBatch() {
  if (!batchStarId.value) {
    ElMessage.warning('请选择目标星级')
    return
  }
  await batchUpdateTeacherStar({
    ids: selectedIds.value,
    star_level_dict_item_id: batchStarId.value,
    recalc_next_follow_date: true,
  })
  ElMessage.success('已批量更新')
  batchDialog.value = false
  await Promise.all([load(), loadStats()])
}

function openFollow(row: TeacherRow) {
  followTeacher.value = row
  followForm.value = {
    subject: '',
    content: '',
    followed_at: new Date().toISOString().slice(0, 10),
    follow_method_dict_item_id: methodOptions.value[0]?.id,
    urgency_dict_item_id: urgencyOptions.value.find((u) => u.value === 'normal')?.id,
    admin_user_id: defaultFollowAdminUserId(),
    next_follow_subject: '',
    next_follow_date: previewNextFollowDate(row.star_level_item?.value) || '',
  }
  followDialog.value = true
}

async function saveFollow() {
  const f = followForm.value
  if (!followTeacher.value) return
  if (!f.subject.trim() || !f.next_follow_subject.trim() || !f.next_follow_date) {
    ElMessage.warning('请填写必填项')
    return
  }
  if (!f.follow_method_dict_item_id || !f.urgency_dict_item_id || !f.admin_user_id) {
    ElMessage.warning('请填写跟进方式、紧急程度与跟进人员')
    return
  }
  await createTeacherFollowRecord(followTeacher.value.id, { ...f })
  ElMessage.success('已保存跟进')
  followDialog.value = false
  await Promise.all([load(), loadStats()])
}

async function openRecords(row: TeacherRow) {
  recordsTeacher.value = row
  records.value = await fetchTeacherFollowRecords(row.id)
  recordsDialog.value = true
}

function openPaper(row: TeacherRow) {
  paperTeacher.value = row
  paperDialog.value = true
}

function openDemand(row: TeacherRow) {
  demandTeacher.value = row
  demandForm.value = { type_dict_item_id: undefined, title: '', content: '' }
  demandDialog.value = true
}

async function saveDemand() {
  if (!demandTeacher.value) return
  if (!demandForm.value.type_dict_item_id || !demandForm.value.title.trim() || !demandForm.value.content.trim()) {
    ElMessage.warning('请填写需求类型、标题与详细描述')
    return
  }
  await createDemand({
    teacher_id: demandTeacher.value.id,
    type_dict_item_id: demandForm.value.type_dict_item_id,
    title: demandForm.value.title.trim(),
    content: demandForm.value.content.trim(),
  })
  ElMessage.success('已发布需求')
  demandDialog.value = false
}

usePageLoad(async () => {
  await loadDicts()
  await Promise.all([loadStats(), load()])
})
</script>

<template>
  <div class="list-page teachers-page">
    <div class="page-header">
      <PageTitle />
      <div class="page-header-actions">
        <el-button class="btn-action-secondary" size="small" @click="openBatch">批量改星</el-button>
        <el-button
          v-if="!isGridMember"
          type="primary"
          size="small"
          class="teachers-primary-btn"
          @click="openCreate"
        >
          手动录入
        </el-button>
      </div>
    </div>

    <div class="talent-stat-grid">
        <button
          type="button"
          class="talent-stat-card"
          :class="{ 'is-active': statBucket === 'month_pending' }"
          @click="pickStat('month_pending')"
        >
          <div class="talent-stat-label">本月待跟进数量</div>
          <div class="talent-stat-value">{{ stats.month_pending }}</div>
        </button>
        <button
          type="button"
          class="talent-stat-card"
          :class="{ 'is-active': statBucket === 'month_followed' }"
          @click="pickStat('month_followed')"
        >
          <div class="talent-stat-label">本月已跟进</div>
          <div class="talent-stat-value is-dark">{{ stats.month_followed }}</div>
        </button>
        <button
          type="button"
          class="talent-stat-card"
          :class="{ 'is-active': statBucket === 'overdue' }"
          @click="pickStat('overdue')"
        >
          <div class="talent-stat-label">已逾期</div>
          <div class="talent-stat-value is-danger">{{ stats.overdue }}</div>
        </button>
        <button
          type="button"
          class="talent-stat-card"
          :class="{ 'is-active': statBucket === 'partner' }"
          @click="pickStat('partner')"
        >
          <div class="talent-stat-label">入孵用户数量</div>
          <div class="talent-stat-value is-success">{{ stats.partners }}</div>
        </button>
      </div>

    <el-card shadow="never" class="admin-list-card teachers-list-card">
      <div class="list-filter-bar">
        <el-input
          v-model="keyword"
          class="filter-search teachers-filter-search"
          placeholder="搜索姓名、高校、学院、简介、研究方向…"
          clearable
          @keyup.enter="searchTeachers"
        />
        <el-select v-model="filterSource" class="filter-source" placeholder="来源" clearable>
          <el-option v-for="o in sourceOptions" :key="o.id" :label="o.label" :value="o.id" />
        </el-select>
        <el-select v-model="filterStar" class="filter-stars" placeholder="星级" clearable>
          <el-option v-for="o in starOptions" :key="o.id" :label="o.label" :value="o.id" />
        </el-select>
        <el-select v-model="filterStatus" class="filter-status" placeholder="状态" clearable>
          <el-option v-for="o in statusOptions" :key="o.id" :label="o.label" :value="o.id" />
        </el-select>
        <el-select
          v-model="filterUniversity"
          class="filter-school"
          placeholder="学校"
          clearable
          filterable
        >
          <el-option v-for="u in universityOptions" :key="u.id" :label="u.name" :value="u.id" />
        </el-select>
        <el-select
          v-model="filterDirection"
          class="filter-direction"
          placeholder="研究方向"
          clearable
          filterable
        >
          <el-option v-for="d in directionOptions" :key="d.id" :label="d.name" :value="d.id" />
        </el-select>
        <el-button type="primary" @click="searchTeachers">搜索</el-button>
        <el-button @click="resetFilters">重置</el-button>
      </div>

      <el-table
        v-loading="loading"
        :data="items"
        row-key="id"
        @selection-change="(rows: TeacherRow[]) => (selectedRows = rows)"
      >
        <el-table-column type="selection" width="44" />
        <el-table-column prop="name" label="姓名" width="108">
          <template #default="{ row }">
            <a class="name-link" href="#" @click.prevent="goDetail(row)">{{ row.name }}</a>
            <el-tag v-if="row.is_overdue" type="danger" size="small" class="tag-overdue">逾期</el-tag>
          </template>
        </el-table-column>
        <el-table-column prop="university_name" label="高校" min-width="130" />
        <el-table-column prop="department" label="所属学院" min-width="120" show-overflow-tooltip />
        <el-table-column prop="title" label="职称" width="96" />
        <el-table-column label="研究方向" min-width="160">
          <template #default="{ row }">
            <template v-if="row.research_directions?.length">
              <el-tag
                v-for="d in row.research_directions"
                :key="d.id"
                size="small"
                type="info"
                style="margin: 2px 4px 2px 0"
              >
                {{ d.name }}
              </el-tag>
            </template>
            <span v-else class="text-muted">—</span>
          </template>
        </el-table-column>
        <el-table-column label="来源" width="108" align="center">
          <template #default="{ row }">
            <el-tag
              :type="sourceTagType(row.source_item?.value)"
              size="small"
              effect="dark"
              class="source-tag"
              :class="{ 'source-tag-manual': row.source_item?.value === 'manual' }"
            >
              {{ row.source_item?.label || '—' }}
            </el-tag>
          </template>
        </el-table-column>
        <el-table-column label="星级" width="108">
          <template #default="{ row }">
            <span class="star-text" :title="row.star_level_item?.label || ''">
              {{ starDisplay(row.star_level_item?.value, row.star_level_item?.label) }}
            </span>
          </template>
        </el-table-column>
        <el-table-column label="状态" width="100">
          <template #default="{ row }">
            <el-tag :type="statusTagType(row.status_item?.value)" size="small" effect="dark">
              {{ row.status_item?.label || '—' }}
            </el-tag>
          </template>
        </el-table-column>
        <el-table-column label="跟进记录" width="96" align="center">
          <template #default="{ row }">
            <el-button size="small" class="btn-action-secondary teachers-table-btn" @click="openRecords(row)">
              {{ row.follow_records_count || 0 }}条记录
            </el-button>
          </template>
        </el-table-column>
        <el-table-column label="操作" width="176" fixed="right">
          <template #default="{ row }">
            <div class="table-row-actions teachers-table-actions">
              <el-button size="small" class="btn-action-info teachers-table-btn" @click="openFollow(row)">
                跟进
              </el-button>
              <el-button size="small" class="btn-action-primary teachers-table-btn" @click="openPaper(row)">
                论文
              </el-button>
              <el-button
                v-if="row.is_partner || row.status_item?.value === 'partner'"
                type="primary"
                size="small"
                class="teachers-primary-btn teachers-table-btn"
                @click="openDemand(row)"
              >
                需求
              </el-button>
              <el-button size="small" class="btn-action-primary teachers-table-btn" @click="goDetail(row)">
                编辑
              </el-button>
            </div>
          </template>
        </el-table-column>
      </el-table>

      <div class="list-pager">
        <el-pagination
          v-model:current-page="page"
          :page-size="meta.per_page"
          :total="meta.total"
          layout="total, prev, pager, next"
          @current-change="load"
        />
      </div>
    </el-card>

    <!-- 手动录入：对齐 createTeacherModal -->
    <el-dialog v-model="createDialog" title="手动录入老师" width="960px" destroy-on-close>
      <el-form label-position="top" class="form-small">
        <el-row :gutter="12">
          <el-col :xs="24" :md="4">
            <el-form-item label="姓名" required>
              <el-input v-model="createForm.name" />
            </el-form-item>
          </el-col>
          <el-col :xs="24" :md="8">
            <el-form-item label="高校" required>
              <div class="uni-row">
                <el-select
                  v-model="createForm.university_id"
                  filterable
                  placeholder="选择高校"
                  style="flex: 1"
                >
                  <el-option v-for="u in universityOptions" :key="u.id" :label="u.name" :value="u.id" />
                </el-select>
                <el-button
                  v-if="!isGridMember"
                  type="primary"
                  size="small"
                  class="btn-create teachers-primary-btn"
                  @click="openUniversityCreate"
                >
                  新建高校
                </el-button>
              </div>
            </el-form-item>
          </el-col>
          <el-col :xs="24" :md="4">
            <el-form-item label="城市" required>
              <el-input v-model="createForm.city" />
            </el-form-item>
          </el-col>
          <el-col :xs="24" :md="8">
            <el-form-item label="职称" required>
              <el-input v-model="createForm.title" />
            </el-form-item>
          </el-col>
          <el-col :xs="24" :md="8">
            <el-form-item label="所属学院">
              <el-input v-model="createForm.department" placeholder="如：计算机科学与技术学院" />
            </el-form-item>
          </el-col>
          <el-col :xs="24" :md="16">
            <el-form-item label="个人简介">
              <el-input v-model="createForm.bio" type="textarea" :rows="3" placeholder="老师个人简介" />
            </el-form-item>
          </el-col>
          <el-col :xs="24" :md="8">
            <el-form-item label="研究方向" required>
              <el-select
                v-model="createForm.research_direction_values"
                multiple
                filterable
                allow-create
                default-first-option
                collapse-tags
                collapse-tags-tooltip
                placeholder="选择或输入研究方向"
                style="width: 100%"
              >
                <el-option v-for="d in directionOptions" :key="d.id" :label="d.name" :value="d.id" />
              </el-select>
            </el-form-item>
          </el-col>
          <el-col :xs="24" :md="6">
            <el-form-item label="电话">
              <el-input v-model="createForm.phone" />
            </el-form-item>
          </el-col>
          <el-col :xs="24" :md="6">
            <el-form-item label="邮箱">
              <el-input v-model="createForm.email" type="email" />
            </el-form-item>
          </el-col>
          <el-col :xs="24" :md="4">
            <el-form-item label="星级">
              <el-select v-model="createForm.star_level_dict_item_id" style="width: 100%">
                <el-option v-for="o in starOptions" :key="o.id" :label="o.label" :value="o.id" />
              </el-select>
            </el-form-item>
          </el-col>
          <el-col :xs="24" :md="6">
            <el-form-item label="状态" required>
              <el-select v-model="createForm.status_dict_item_id" placeholder="请选择状态" style="width: 100%">
                <el-option v-for="o in statusOptions" :key="o.id" :label="o.label" :value="o.id" />
              </el-select>
            </el-form-item>
          </el-col>
        </el-row>
      </el-form>
      <template #footer>
        <el-button @click="createDialog = false">取消</el-button>
        <el-button type="primary" @click="saveCreate">保存</el-button>
      </template>
    </el-dialog>

    <el-dialog
      v-model="universityDialog"
      title="新建高校"
      width="480px"
      append-to-body
      destroy-on-close
    >
      <el-form label-position="top" class="form-small">
        <el-form-item label="高校名称" required>
          <el-input v-model="universityForm.name" placeholder="如：复旦大学" />
        </el-form-item>
        <el-row :gutter="12">
          <el-col :span="12">
            <el-form-item label="经度" required>
              <el-input v-model="universityForm.longitude" placeholder="如：121.5031" />
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="纬度" required>
              <el-input v-model="universityForm.latitude" placeholder="如：31.2970" />
            </el-form-item>
          </el-col>
        </el-row>
        <el-row :gutter="12">
          <el-col :span="12">
            <el-form-item label="省份">
              <el-input v-model="universityForm.province" placeholder="如：上海市" />
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="城市">
              <el-input v-model="universityForm.city" placeholder="如：上海" />
            </el-form-item>
          </el-col>
        </el-row>
      </el-form>
      <template #footer>
        <el-button @click="universityDialog = false">取消</el-button>
        <el-button type="primary" :loading="universitySaving" @click="saveUniversityCreate">保存</el-button>
      </template>
    </el-dialog>

    <!-- 批量改星 -->
    <el-dialog v-model="batchDialog" title="批量修改星级" width="480px">
      <el-alert
        v-if="!selectedRows.length"
        type="warning"
        :closable="false"
        title="请先在列表中勾选需要改星的老师。"
        show-icon
      />
      <template v-else>
        <div class="follow-teacher-summary">
          已选择 <span class="text-brand">{{ selectedRows.length }}</span> 位老师
          <span v-if="selectedNamesText" class="names-muted">{{ selectedNamesText }}</span>
        </div>
        <el-form label-position="top" style="margin-top: 12px">
          <el-form-item label="目标星级" required>
            <el-select v-model="batchStarId" placeholder="请选择目标星级" style="width: 100%">
              <el-option v-for="o in starOptions" :key="o.id" :label="o.label" :value="o.id" />
            </el-select>
          </el-form-item>
          <p class="batch-rule">{{ batchStarRule }}</p>
        </el-form>
      </template>
      <template #footer>
        <el-button @click="batchDialog = false">取消</el-button>
        <el-button type="primary" :disabled="!selectedRows.length" @click="saveBatch">
          保存并重算跟进日
        </el-button>
      </template>
    </el-dialog>

    <!-- 新增跟进 -->
    <el-dialog v-model="followDialog" title="新增跟进" width="720px" destroy-on-close>
      <div v-if="followTeacher" class="follow-teacher-summary">
        {{ followTeacher.name }} · {{ followTeacher.university_name }} · {{ followTeacher.title }}
      </div>
      <el-form label-position="top" class="form-small" style="margin-top: 12px">
        <el-row :gutter="12">
          <el-col :span="10">
            <el-form-item label="跟进主题" required>
              <el-input v-model="followForm.subject" placeholder="请输入跟进主题" />
            </el-form-item>
          </el-col>
          <el-col :span="6">
            <el-form-item label="跟进日期" required>
              <el-date-picker
                v-model="followForm.followed_at"
                type="date"
                value-format="YYYY-MM-DD"
                style="width: 100%"
              />
            </el-form-item>
          </el-col>
          <el-col :span="4">
            <el-form-item label="跟进方式" required>
              <el-select v-model="followForm.follow_method_dict_item_id" style="width: 100%">
                <el-option v-for="o in methodOptions" :key="o.id" :label="o.label" :value="o.id" />
              </el-select>
            </el-form-item>
          </el-col>
          <el-col :span="4">
            <el-form-item label="跟进人员" required>
              <el-select v-model="followForm.admin_user_id" style="width: 100%">
                <el-option v-for="a in adminOptions" :key="a.id" :label="a.label" :value="a.id" />
              </el-select>
            </el-form-item>
          </el-col>
          <el-col :span="24">
            <el-form-item label="跟进记录">
              <el-input
                v-model="followForm.content"
                type="textarea"
                :rows="4"
                placeholder="请输入跟进内容"
              />
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="下次跟进主题" required>
              <el-input v-model="followForm.next_follow_subject" placeholder="请输入下次跟进主题" />
            </el-form-item>
          </el-col>
          <el-col :span="6">
            <el-form-item label="下次跟进日期" required>
              <el-date-picker
                v-model="followForm.next_follow_date"
                type="date"
                value-format="YYYY-MM-DD"
                style="width: 100%"
              />
              <p v-if="followNextDateRule" class="follow-date-rule">{{ followNextDateRule }}</p>
            </el-form-item>
          </el-col>
          <el-col :span="6">
            <el-form-item label="紧急程度" required>
              <el-select v-model="followForm.urgency_dict_item_id" placeholder="请选择紧急程度" style="width: 100%">
                <el-option v-for="o in urgencyOptions" :key="o.id" :label="o.label" :value="o.id" />
              </el-select>
            </el-form-item>
          </el-col>
        </el-row>
      </el-form>
      <template #footer>
        <el-button @click="followDialog = false">取消</el-button>
        <el-button type="primary" @click="saveFollow">保存</el-button>
      </template>
    </el-dialog>

    <!-- 跟进记录时间线 -->
    <el-dialog v-model="recordsDialog" title="跟进记录" width="960px">
      <div v-if="recordsTeacher" class="follow-teacher-summary">
        <span>{{ recordsTeacher.name }}</span>
        <span class="dot">·</span>
        <span>{{ recordsTeacher.university_name }}</span>
        <span class="dot">·</span>
        <span>{{ recordsTeacher.title }}</span>
        <span class="dot">·</span>
        <span class="star-text">
          {{ starDisplay(recordsTeacher.star_level_item?.value, recordsTeacher.star_level_item?.label) }}
        </span>
      </div>
      <div class="follow-history-list">
        <div v-for="r in records" :key="r.id" class="follow-history-card">
          <div class="follow-history-head">
            <div>
              <span class="follow-history-title">{{ r.subject }}</span>
              <span class="follow-history-date">{{ r.followed_at }}</span>
            </div>
            <el-tag
              v-if="r.urgency_item"
              :type="urgencyTagType((r.urgency_item as { value?: string }).value)"
              size="small"
            >
              {{ r.urgency_item.label }}
            </el-tag>
          </div>
          <div class="follow-history-body">
            <div class="follow-history-row">
              <span>跟进主题：</span>
              <div>{{ r.subject }}</div>
            </div>
            <div class="follow-history-row">
              <span>跟进方式：</span>
              <div>{{ r.follow_method_item?.label || '—' }}</div>
            </div>
            <div class="follow-history-row">
              <span>跟进记录：</span>
              <div>{{ r.content || '—' }}</div>
            </div>
            <div class="follow-history-row">
              <span>下次跟进：</span>
              <div>主题：{{ r.next_follow_subject }}<br />日期：{{ r.next_follow_date }}</div>
            </div>
          </div>
          <div class="follow-history-footer">跟进人：{{ r.operator_name || '—' }}</div>
        </div>
        <el-empty v-if="!records.length" description="暂无跟进记录" />
      </div>
      <template #footer>
        <el-button @click="recordsDialog = false">关闭</el-button>
      </template>
    </el-dialog>

    <TeacherPaperDialog
      v-model="paperDialog"
      :teacher-id="paperTeacher?.id ?? null"
      :default-authors="paperTeacher?.name"
      :default-school-name="paperTeacher?.university_name || ''"
      @saved="load"
    />

    <!-- 发布需求（伙伴老师，需求模块待接） -->
    <el-dialog v-model="demandDialog" title="发布需求" width="640px" destroy-on-close>
      <el-form label-position="top" class="form-small">
        <el-row :gutter="12">
          <el-col :span="12">
            <el-form-item label="关联老师">
              <el-input :model-value="demandTeacher?.name || ''" readonly />
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="需求类型" required>
              <el-select v-model="demandForm.type_dict_item_id" placeholder="请选择需求类型" style="width: 100%">
                <el-option v-for="o in demandTypeOptions" :key="o.id" :label="o.label" :value="o.id" />
              </el-select>
            </el-form-item>
          </el-col>
          <el-col :span="24">
            <el-form-item label="标题" required>
              <el-input v-model="demandForm.title" placeholder="请输入需求标题" />
            </el-form-item>
          </el-col>
          <el-col :span="24">
            <el-form-item label="详细描述" required>
              <el-input
                v-model="demandForm.content"
                type="textarea"
                :rows="5"
                placeholder="请描述需求背景、目标、期望资源或合作方式"
              />
            </el-form-item>
          </el-col>
        </el-row>
      </el-form>
      <template #footer>
        <el-button @click="demandDialog = false">取消</el-button>
        <el-button type="primary" @click="saveDemand">发布</el-button>
      </template>
    </el-dialog>

    <TeacherDetailDialog v-model="detailVisible" :teacher-id="detailTeacherId" @saved="load" />
  </div>
</template>

<style scoped>
.teachers-page {
  --brand-primary: #244e98;
  --brand-primary-hover: #8b1519;
  --brand-bg-soft: #fdf3f3;
  display: flex;
  flex-direction: column;
  gap: 12px;
}
.talent-stat-grid {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 14px;
}
.teachers-list-card {
  margin-top: 0;
}
.teachers-filter-search {
  width: 180px;
}
.talent-stat-card {
  min-height: 68px;
  padding: 10px 16px;
  border: 1px solid #d8dde4;
  border-radius: 8px;
  background: #fff;
  box-shadow: 0 2px 10px rgba(15, 23, 42, 0.08);
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  justify-content: center;
  gap: 6px;
  text-align: left;
  position: relative;
  cursor: pointer;
  font: inherit;
}
.talent-stat-card:hover,
.talent-stat-card.is-active {
  border-color: var(--brand-primary);
}
.talent-stat-card.is-active::before {
  content: '';
  position: absolute;
  left: 0;
  top: 0;
  bottom: 0;
  width: 4px;
  background: var(--brand-primary);
}
.talent-stat-label {
  color: #6b7280;
  font-size: 14px;
}
.talent-stat-value {
  color: var(--brand-primary);
  font-size: 24px;
  line-height: 1.1;
  font-weight: 600;
}
.talent-stat-value.is-dark {
  color: #111827;
}
.talent-stat-value.is-danger {
  color: var(--el-color-danger);
}
.talent-stat-value.is-success {
  color: var(--el-color-success);
}
.filter-source {
  width: 132px;
}
.filter-stars {
  width: 100px;
}
.filter-status {
  width: 112px;
}
.filter-school {
  width: 184px;
}
.filter-direction {
  width: 146px;
}
.name-link {
  color: inherit;
  text-decoration: none;
}
.name-link:hover {
  color: var(--brand-primary);
}
.tag-overdue {
  margin-left: 4px;
  vertical-align: middle;
}
.star-text {
  color: #e6a23c;
  letter-spacing: 1px;
}
.source-tag {
  border: none;
  font-weight: 500;
}
.source-tag-manual {
  --el-tag-bg-color: #6c757d;
  --el-tag-border-color: #6c757d;
  --el-tag-text-color: #fff;
}
.teachers-table-actions {
  flex-wrap: nowrap;
  gap: 4px;
}
.teachers-table-btn {
  padding: 2px 6px !important;
  min-height: 22px;
  font-size: 12px;
}
.follow-teacher-summary {
  padding: 10px 12px;
  border-left: 4px solid var(--brand-primary);
  background: var(--brand-bg-soft);
  border-radius: 6px;
  font-size: 14px;
}
.text-brand {
  color: var(--brand-primary);
  font-weight: 600;
}
.names-muted {
  margin-left: 8px;
  color: #6b7280;
  font-size: 13px;
}
.batch-rule {
  font-size: 12px;
  color: #6b7280;
  margin: 0;
}
.follow-date-rule {
  margin: 6px 0 0;
  font-size: 12px;
  line-height: 1.45;
  color: #6b7280;
}
.follow-history-list {
  display: grid;
  gap: 14px;
  margin-top: 12px;
  max-height: 60vh;
  overflow: auto;
}
.follow-history-card {
  border: 1px solid #dfe4eb;
  border-left: 4px solid var(--brand-primary);
  border-radius: 6px;
  background: #fff;
}
.follow-history-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 12px 14px;
  border-bottom: 1px solid #e6eaf1;
}
.follow-history-title {
  color: var(--brand-primary);
  font-weight: 600;
}
.follow-history-date {
  margin-left: 14px;
  color: #6b7280;
  font-size: 13px;
}
.follow-history-body {
  padding: 14px;
  font-size: 13px;
}
.follow-history-row {
  display: grid;
  grid-template-columns: 96px 1fr;
  gap: 14px;
  margin-bottom: 10px;
}
.follow-history-row > span {
  color: #6b7280;
}
.follow-history-footer {
  padding: 0 14px 14px;
  color: #6b7280;
  font-size: 13px;
}
.dot {
  margin: 0 6px;
  color: #9ca3af;
}
.uni-row {
  display: flex;
  align-items: center;
  gap: 8px;
  width: 100%;
}
:global(.teachers-primary-btn.el-button--primary) {
  --el-button-text-color: #fff;
  --el-button-bg-color: #244e98;
  --el-button-border-color: #244e98;
  --el-button-hover-text-color: #fff;
  --el-button-hover-bg-color: #8b1519;
  --el-button-hover-border-color: #8b1519;
  --el-button-active-text-color: #fff;
  --el-button-active-bg-color: #8b1519;
  --el-button-active-border-color: #8b1519;
}
.form-small :deep(.el-form-item__label) {
  font-size: 13px;
  padding-bottom: 4px;
}
@media (max-width: 992px) {
  .talent-stat-grid {
    grid-template-columns: 1fr 1fr;
  }
}
</style>
