<template>
  <ContentWrap>
    <!-- 页面标题 -->
    <div class="page-title">项目列表</div>

    <!-- 会议摘要信息 -->
    <div class="meeting-summary-bar">
      <span class="summary-label">所属会议：</span>
      <span class="summary-meeting-name">{{ meetingInfo.name || '-' }}</span>
      <span class="summary-sep">|</span>
      <span class="summary-label">会议时间：</span>
      <span class="summary-value">
        {{ meetingInfo.startTime ? formatDate(meetingInfo.startTime, 'YYYY-MM-DD HH:mm') : '-' }}
        &nbsp;~&nbsp;
        {{ meetingInfo.endTime ? formatDate(meetingInfo.endTime, 'YYYY-MM-DD HH:mm') : '-' }}
      </span>
      <span class="summary-sep">|</span>
      <span class="summary-label">会议地点：</span>
      <span class="summary-value">{{ meetingInfo.location || '-' }}</span>
      <span class="summary-sep">|</span>
      <span class="summary-label">状态：</span>
      <span :class="`status-text status-${meetingInfo.status}`">{{ STATUS_LABEL[meetingInfo.status] }}</span>
    </div>

    <!-- 搜索栏 -->
    <div class="search-bar">
      <el-input
        v-model="queryParams.projectTitle"
        placeholder="项目标题"
        clearable
        class="search-input"
        @keyup.enter="handleQuery"
      />
      <el-input
        v-model="queryParams.reporter"
        placeholder="报告人"
        clearable
        class="search-input"
        @keyup.enter="handleQuery"
      />
      <el-select v-model="queryParams.agendaCategory" placeholder="议程分类" clearable class="search-input">
        <el-option v-for="item in REVIEW_AGENDA_CATEGORY_OPTIONS" :key="item" :label="item" :value="item" />
      </el-select>
      <button class="btn-reset" @click="resetQuery">重置</button>
      <button class="btn-search" @click="handleQuery">查询</button>
    </div>

    <!-- 操作按钮 -->
    <div class="toolbar">
      <button class="btn-default" @click="openForm('create')">
        <span class="btn-icon">+</span> 新增评审项目
      </button>
      <button class="btn-default btn-danger" :disabled="selectedIds.length === 0" @click="handleDelete()">
        批量删除
      </button>
    </div>

    <!-- 列表 -->
    <el-table
      ref="tableRef"
      v-loading="loading || sortLoading"
      :data="list"
      row-key="id"
      size="small"
      border
      class="review-table"
      @selection-change="handleSelectionChange"
    >
      <el-table-column type="selection" width="46" align="center" />
      <el-table-column label="拖拽" width="54" align="center">
        <template #default>
          <span class="drag-handle" title="拖拽排序">⋮⋮</span>
        </template>
      </el-table-column>
      <el-table-column label="立项编号" prop="id" width="72" align="center" />
      <el-table-column label="会中序号" prop="seqNo" width="72" align="center" />
      <el-table-column label="起止时间" width="236" align="center">
        <template #default="{ row }">
          <div class="inline-time-range">
            <el-time-picker
              v-model="row.startTime"
              class="inline-time"
              size="small"
              format="HH:mm"
              value-format="HH:mm"
              placeholder="开始"
              @change="saveInlineRow(row)"
            />
            <span class="inline-time-sep">-</span>
            <el-time-picker
              v-model="row.endTime"
              class="inline-time"
              size="small"
              format="HH:mm"
              value-format="HH:mm"
              placeholder="结束"
              @change="saveInlineRow(row)"
            />
          </div>
        </template>
      </el-table-column>
      <el-table-column label="议程分类" width="130">
        <template #default="{ row }">
          <el-select
            v-model="row.agendaCategory"
            class="inline-field"
            size="small"
            placeholder="议程分类"
            @change="saveInlineRow(row, { reload: true })"
          >
            <el-option v-for="item in REVIEW_AGENDA_CATEGORY_OPTIONS" :key="item" :label="item" :value="item" />
          </el-select>
        </template>
      </el-table-column>
      <el-table-column label="项目名称" prop="projectTitle" min-width="220">
        <template #default="{ row }">
          <el-input
            v-model="row.projectTitle"
            class="inline-field"
            size="small"
            placeholder="项目名称"
            @blur="saveInlineRow(row)"
          />
        </template>
      </el-table-column>
      <el-table-column label="报告人" width="120">
        <template #default="{ row }">
          <el-input
            v-model="row.reporter"
            class="inline-field"
            size="small"
            placeholder="报告人"
            @blur="saveInlineRow(row)"
          />
        </template>
      </el-table-column>
      <el-table-column label="报告单位" min-width="180">
        <template #default="{ row }">
          <el-input
            v-model="row.reporterUnit"
            class="inline-field"
            size="small"
            placeholder="报告单位"
            @blur="saveInlineRow(row)"
          />
        </template>
      </el-table-column>
      <el-table-column label="评审日期" width="142" align="center">
        <template #default="{ row }">
          <el-date-picker
            v-model="row.reviewDate"
            class="inline-field"
            size="small"
            type="date"
            value-format="YYYY-MM-DD"
            placeholder="评审日期"
            @change="saveInlineRow(row)"
          />
        </template>
      </el-table-column>
      <el-table-column label="会前资料齐全" width="110" align="center">
        <template #default="{ row }">
          <span :class="getMaterialCompleteClass(row.preMeetingMaterialsComplete)">
            {{ row.preMeetingMaterialsComplete ? '✓' : '✗' }}
          </span>
        </template>
      </el-table-column>
      <el-table-column label="会后资料齐全" width="110" align="center">
        <template #default="{ row }">
          <span :class="getMaterialCompleteClass(row.postMeetingMaterialsComplete)">
            {{ row.postMeetingMaterialsComplete ? '✓' : '✗' }}
          </span>
        </template>
      </el-table-column>
      <el-table-column label="评审结果" width="120" align="center">
        <template #default="{ row }">
          <el-select
            v-model="row.reviewResult"
            class="inline-field"
            size="small"
            placeholder="评审结果"
            clearable
            @change="saveInlineRow(row)"
          >
            <el-option label="通过" value="PASS" />
            <el-option label="不通过" value="REJECT" />
          </el-select>
        </template>
      </el-table-column>
      <el-table-column label="操作" width="154" align="center" fixed="right">
        <template #default="{ row }">
          <a class="op-link" @click="goToDetail(row)">上传项目资料</a>
          <a class="op-link op-danger" @click="handleDelete(row.id)">删除</a>
        </template>
      </el-table-column>
    </el-table>

    <!-- 编辑/新增项目弹窗 -->
    <el-dialog v-model="formVisible" :title="formType === 'create' ? '新增评审项目' : '编辑评审项目'" width="550px">
      <el-form ref="formRef" :model="formData" :rules="formRules" label-width="100px">
        <el-form-item label="序号" prop="seqNo">
          <el-input-number v-model="formData.seqNo" :min="1" />
        </el-form-item>
        <el-form-item label="时间范围">
          <div style="display: flex; gap: 10px; width: 100%;">
            <el-time-picker v-model="formData.startTime" format="HH:mm" value-format="HH:mm" placeholder="开始时间" style="flex: 1" />
            <span>-</span>
            <el-time-picker v-model="formData.endTime" format="HH:mm" value-format="HH:mm" placeholder="结束时间" style="flex: 1" />
          </div>
        </el-form-item>
        <el-form-item label="议程分类" prop="agendaCategory">
          <el-select v-model="formData.agendaCategory" placeholder="请选择议程分类" style="width: 100%">
            <el-option v-for="item in REVIEW_AGENDA_CATEGORY_OPTIONS" :key="item" :label="item" :value="item" />
          </el-select>
        </el-form-item>
        <el-form-item label="项目标题" prop="projectTitle">
          <el-input v-model="formData.projectTitle" placeholder="请输入项目标题" />
        </el-form-item>
        <el-form-item label="汇报人" prop="reporter">
          <el-input v-model="formData.reporter" placeholder="请输入汇报人" />
        </el-form-item>
        <el-form-item label="报告单位" prop="reporterUnit">
          <el-input v-model="formData.reporterUnit" placeholder="请输入报告单位" />
        </el-form-item>
        <el-form-item label="评审日期" prop="reviewDate">
          <el-date-picker v-model="formData.reviewDate" type="date" value-format="YYYY-MM-DD" placeholder="请选择评审日期" style="width: 100%" />
        </el-form-item>
        <el-form-item label="评审结果" prop="reviewResult">
          <el-select v-model="formData.reviewResult" placeholder="请选择评审结果" clearable style="width: 100%">
            <el-option label="通过" value="PASS" />
            <el-option label="不通过" value="REJECT" />
          </el-select>
        </el-form-item>
      </el-form>
      <template #footer>
        <el-button @click="formVisible = false">取 消</el-button>
        <el-button type="primary" :loading="formLoading" @click="submitForm">确 定</el-button>
      </template>
    </el-dialog>

    <!-- 分页 -->
    <Pagination :total="total" v-model:page="queryParams.pageNo" v-model:limit="queryParams.pageSize" @pagination="getList" />
  </ContentWrap>
</template>

<script setup lang="ts">
import { ref, reactive, onMounted, onBeforeUnmount, nextTick } from 'vue'
import { useRoute, useRouter } from 'vue-router'
import { ElMessage, ElMessageBox } from 'element-plus'
import Sortable from 'sortablejs'
import { getReviewMeeting } from '@/api/review/meeting'
import {
  REVIEW_AGENDA_CATEGORY_OPTIONS,
  getReviewProjectPage,
  updateReviewProject,
  updateReviewProjectSeqBatch,
  createReviewProject,
  deleteReviewProject,
  type ReviewMeetingProjectRespVO
} from '@/api/review/project'
import { formatDate } from '@/utils/formatTime'

defineOptions({ name: 'ReviewMeetingProject' })

const route = useRoute()
const router = useRouter()
const reviewMeetingId = Number(route.params.meetingId)

const loading = ref(false)
const sortLoading = ref(false)
const list = ref<ReviewMeetingProjectRespVO[]>([])
const total = ref(0)
const meetingInfo = ref<any>({})
const tableRef = ref()
let sortableInstance: Sortable | null = null

const STATUS_LABEL: Record<number, string> = { 0: '待召开', 1: '正在召开', 2: '已结束', 3: '已取消' }
const getMaterialCompleteClass = (complete?: boolean) => {
  if (complete) return 'material-complete'
  return 'material-incomplete'
}
type InlineEditableFields = {
  seqNo?: number
  startTime?: string
  endTime?: string
  agendaCategory?: string
  projectTitle?: string
  reporter?: string
  reporterUnit?: string
  reviewDate?: string
  reviewResult?: 'PASS' | 'REJECT'
}
const inlineSnapshotMap = ref<Record<number, InlineEditableFields>>({})

const queryParams = reactive({
  pageNo: 1,
  pageSize: 10,
  reviewMeetingId,
  projectTitle: undefined as string | undefined,
  agendaCategory: undefined as string | undefined,
  reporter: undefined as string | undefined
})

const getList = async () => {
  loading.value = true
  try {
    const data = await getReviewProjectPage(queryParams)
    list.value = data.list
    total.value = data.total
    syncInlineSnapshots(data.list || [])
  } finally {
    loading.value = false
    await nextTick()
    initSortable()
  }
}

const buildInlineFields = (row: ReviewMeetingProjectRespVO): InlineEditableFields => ({
  seqNo: row.seqNo,
  startTime: row.startTime,
  endTime: row.endTime,
  agendaCategory: row.agendaCategory,
  projectTitle: row.projectTitle,
  reporter: row.reporter,
  reporterUnit: row.reporterUnit,
  reviewDate: row.reviewDate,
  reviewResult: row.reviewResult
})

const syncInlineSnapshots = (rows: ReviewMeetingProjectRespVO[]) => {
  const snapshot: Record<number, InlineEditableFields> = {}
  rows.forEach((row) => {
    snapshot[row.id] = buildInlineFields(row)
  })
  inlineSnapshotMap.value = snapshot
}

const isInlineChanged = (current: InlineEditableFields, snapshot: InlineEditableFields) => {
  const normalize = (value: unknown) => (value ?? '') as string | number
  return normalize(current.seqNo) !== normalize(snapshot.seqNo)
    || normalize(current.startTime) !== normalize(snapshot.startTime)
    || normalize(current.endTime) !== normalize(snapshot.endTime)
    || normalize(current.agendaCategory) !== normalize(snapshot.agendaCategory)
    || normalize(current.projectTitle) !== normalize(snapshot.projectTitle)
    || normalize(current.reporter) !== normalize(snapshot.reporter)
    || normalize(current.reporterUnit) !== normalize(snapshot.reporterUnit)
    || normalize(current.reviewDate) !== normalize(snapshot.reviewDate)
    || normalize(current.reviewResult) !== normalize(snapshot.reviewResult)
}

const saveInlineRow = async (row: ReviewMeetingProjectRespVO, options: { reload?: boolean } = {}) => {
  const snapshot = inlineSnapshotMap.value[row.id]
  if (!snapshot) return
  row.projectTitle = row.projectTitle?.trim()
  if (!row.agendaCategory) {
    ElMessage.warning('议程分类不能为空')
    Object.assign(row, snapshot)
    return
  }
  if (!row.projectTitle) {
    ElMessage.warning('项目名称不能为空')
    Object.assign(row, snapshot)
    return
  }
  const current = buildInlineFields(row)
  if (!isInlineChanged(current, snapshot)) return
  try {
    await updateReviewProject({
      id: row.id,
      ...current
    })
    inlineSnapshotMap.value[row.id] = buildInlineFields(row)
    if (options.reload) {
      await getList()
    }
  } catch {
    Object.assign(row, snapshot)
    ElMessage.error('保存失败，已恢复')
  }
}

const initSortable = () => {
  if (!tableRef.value?.$el) return
  const tbody = tableRef.value.$el.querySelector('.el-table__body-wrapper tbody')
  if (!tbody) return
  sortableInstance?.destroy()
  sortableInstance = Sortable.create(tbody, {
    animation: 150,
    handle: '.drag-handle',
    ghostClass: 'drag-ghost',
    chosenClass: 'drag-chosen',
    onEnd: ({ oldIndex, newIndex }) => {
      if (oldIndex === undefined || newIndex === undefined || oldIndex === newIndex) return
      handleSortEnd(oldIndex, newIndex)
    }
  })
}

const handleSortEnd = async (oldIndex: number, newIndex: number) => {
  if (queryParams.projectTitle || queryParams.agendaCategory || queryParams.reporter) {
    ElMessage.warning('请先清空筛选条件后再拖拽排序')
    await getList()
    return
  }
  const moved = list.value.splice(oldIndex, 1)[0]
  if (!moved) return
  list.value.splice(newIndex, 0, moved)
  list.value = [...list.value]

  sortLoading.value = true
  try {
    const pageStart = (queryParams.pageNo - 1) * queryParams.pageSize
    const allData = await getReviewProjectPage({
      reviewMeetingId,
      pageNo: 1,
      pageSize: Math.max(total.value || 0, queryParams.pageSize, 200)
    })
    const fullList = [...(allData.list || [])]
    list.value.forEach((item, index) => {
      fullList[pageStart + index] = item
    })

    const changedRows: ReviewMeetingProjectRespVO[] = []
    fullList.forEach((item, index) => {
      const nextSeq = index + 1
      if (item.seqNo !== nextSeq) {
        item.seqNo = nextSeq
        changedRows.push(item)
      }
    })
    if (changedRows.length === 0) return

    list.value = fullList.slice(pageStart, pageStart + queryParams.pageSize)
    await updateReviewProjectSeqBatch(
      changedRows.map((row) => ({
        id: row.id,
        seqNo: row.seqNo
      }))
    )
    ElMessage.success('排序已更新')
  } catch {
    ElMessage.error('排序保存失败，已恢复原列表')
    await getList()
  } finally {
    sortLoading.value = false
  }
}

const handleQuery = () => { queryParams.pageNo = 1; getList() }
const resetQuery = () => {
  queryParams.projectTitle = undefined
  queryParams.agendaCategory = undefined
  queryParams.reporter = undefined
  handleQuery()
}

const selectedIds = ref<number[]>([])
const handleSelectionChange = (val: ReviewMeetingProjectRespVO[]) => {
  selectedIds.value = val.map(v => v.id)
}

const handleDelete = async (id?: number) => {
  const ids = id ? [id] : selectedIds.value
  if (ids.length === 0) return
  await ElMessageBox.confirm(`确认删除选中的 ${ids.length} 个项目吗？`, '警告', { type: 'warning' })
  await deleteReviewProject(ids)
  ElMessage.success('删除成功')
  getList()
}

const formVisible = ref(false)
const formType = ref<'create' | 'update'>('create')
const formLoading = ref(false)
const formRef = ref()
const formData = reactive<Partial<ReviewMeetingProjectRespVO>>({})
const formRules = {
  agendaCategory: [{ required: true, message: '请选择议程分类', trigger: 'change' }],
  projectTitle: [{ required: true, message: '项目标题不能为空', trigger: 'blur' }]
}

const openForm = (type: 'create' | 'update', row?: ReviewMeetingProjectRespVO) => {
  formType.value = type
  if (type === 'create') {
    Object.keys(formData).forEach(key => delete formData[key as keyof ReviewMeetingProjectRespVO])
    formData.reviewMeetingId = reviewMeetingId
  } else if (row) {
    Object.assign(formData, row)
  }
  formVisible.value = true
}

const submitForm = async () => {
  const valid = await formRef.value?.validate()
  if (!valid) return
  formLoading.value = true
  try {
    if (formType.value === 'create') {
      await createReviewProject(formData)
      ElMessage.success('新增成功')
    } else {
      await updateReviewProject(formData)
      ElMessage.success('修改成功')
    }
    formVisible.value = false
    getList()
  } finally {
    formLoading.value = false
  }
}

const goToDetail = (row: ReviewMeetingProjectRespVO) => {
  router.push({
    name: 'ReviewProjectDetail',
    params: { meetingId: reviewMeetingId, projectId: row.id },
    state: {
      projectTitle: row.projectTitle,
      seqNo: row.seqNo,
      startTime: row.startTime,
      endTime: row.endTime,
      agendaCategory: row.agendaCategory,
      reporter: row.reporter,
      reporterUnit: row.reporterUnit,
      meetingHost: meetingInfo.value?.host,
      meetingName: meetingInfo.value?.name
    }
  })
}

onMounted(async () => {
  meetingInfo.value = await getReviewMeeting(reviewMeetingId)
  await getList()
})

onBeforeUnmount(() => {
  sortableInstance?.destroy()
  sortableInstance = null
})
</script>

<style scoped>
/* ── 页面标题 ── */
.page-title {
  font-size: 22px;
  font-weight: 600;
  color: #333;
  margin-bottom: 16px;
  padding-bottom: 14px;
  border-bottom: 1px solid #e1e7f0;
}

/* ── 会议摘要栏 ── */
.meeting-summary-bar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 6px;
  padding: 10px 14px;
  background-color: rgba(41, 90, 188, 0.05);
  border: 1px solid rgba(41, 90, 188, 0.12);
  border-radius: 6px;
  margin-bottom: 16px;
  font-size: 14px;
  color: #333;
}
.summary-label {
  color: #666;
}
.summary-meeting-name {
  color: #295abc;
  font-weight: 500;
}
.summary-value {
  color: #333;
}
.summary-sep {
  color: #ddd;
  margin: 0 4px;
}

/* ── 状态文字 ── */
.status-text { font-size: 14px; font-weight: 500; }
.status-0 { color: #ecae4b; }
.status-1 { color: #73c047; }
.status-2 { color: #999; }
.status-3 { color: #999; }

.review-result-pass {
  color: #67c23a;
  font-weight: 500;
}
.review-result-reject {
  color: #f56c6c;
  font-weight: 500;
}
.material-complete {
  color: #67c23a !important;
  font-weight: 600;
  font-size: 16px;
}
.material-incomplete {
  color: #f56c6c !important;
  font-weight: 600;
  font-size: 16px;
}

/* ── 搜索栏 ── */
.search-bar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 12px;
  margin-bottom: 14px;
}
.search-input {
  width: 180px;
}
:deep(.search-input .el-input__wrapper) {
  height: 40px;
  border-radius: 6px;
  border-color: #dcdedf;
}
:deep(.search-input .el-input__inner) {
  font-size: 15px;
  color: #333;
}

.btn-search {
  height: 40px;
  padding: 0 22px;
  background-color: #295abc;
  color: #fff;
  border: none;
  border-radius: 6px;
  font-size: 15px;
  cursor: pointer;
  transition: background-color 0.2s;
}
.btn-search:hover { background-color: rgba(41, 90, 188, 0.88); }

.btn-reset {
  height: 40px;
  padding: 0 8px;
  background: none;
  border: none;
  color: #295abc;
  font-size: 15px;
  cursor: pointer;
}
.btn-reset:hover { opacity: 0.8; }

/* ── 工具栏 ── */
.toolbar {
  display: flex;
  gap: 10px;
  margin-bottom: 12px;
}
.btn-default {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  height: 36px;
  padding: 0 16px;
  background-color: #fff;
  border: 1px solid #d5d5d5;
  border-radius: 6px;
  font-size: 14px;
  color: #333;
  cursor: pointer;
  transition: all 0.2s;
}
.btn-default:hover {
  background-color: rgba(41, 90, 188, 0.08);
  border-color: #295abc;
  color: #295abc;
}
.btn-default:disabled {
  opacity: 0.45;
  cursor: not-allowed;
}
.btn-danger {
  border-color: #fc4f54;
  color: #fc4f54;
}
.btn-danger:hover {
  background-color: rgba(252, 79, 84, 0.08);
  border-color: #fc4f54;
  color: #fc4f54;
}
.btn-icon {
  font-size: 16px;
  line-height: 1;
}

/* ── 项目名称 ── */
.project-name-text {
  color: #295abc;
  font-size: 14px;
}

.inline-time-range {
  display: flex;
  align-items: center;
  gap: 6px;
}
.inline-time-sep {
  color: #999;
}
.inline-time {
  width: 92px;
}
.inline-field {
  width: 100%;
}
:deep(.inline-field .el-input__wrapper),
:deep(.inline-field .el-select__wrapper),
:deep(.inline-time .el-input__wrapper) {
  border-radius: 6px;
  border: 1px solid transparent;
  box-shadow: none;
  background-color: #f8fafc;
  transition: border-color 0.2s, background-color 0.2s;
}
:deep(.review-table .el-table__body tr:hover .inline-field .el-input__wrapper),
:deep(.review-table .el-table__body tr:hover .inline-field .el-select__wrapper),
:deep(.review-table .el-table__body tr:hover .inline-time .el-input__wrapper) {
  border-color: #d8e0ec;
  background-color: #fff;
}
:deep(.inline-field .el-input__wrapper.is-focus),
:deep(.inline-field .el-select__wrapper.is-focused),
:deep(.inline-time .el-input__wrapper.is-focus) {
  border-color: #295abc;
  background-color: #fff;
}

/* ── 操作链接 ── */
.op-link {
  display: inline-block;
  color: #295abc;
  font-size: 13px;
  cursor: pointer;
  margin: 0 4px;
  transition: opacity 0.2s;
}
.op-link:hover { opacity: 0.8; text-decoration: underline; }
.op-danger { color: #fc4f54; }

/* ── 表格 ── */
:deep(.review-table .el-table__header-wrapper th) {
  background-color: #eef2fb;
  color: #333;
  font-weight: 600;
  font-size: 14px;
  border-color: #e1e7f0;
}
:deep(.review-table .el-table__body td) {
  font-size: 14px;
  color: #333;
  border-color: #e1e7f0;
  padding-top: 10px;
  padding-bottom: 10px;
}
:deep(.review-table .el-table__body tr:hover > td) {
  background-color: rgba(41, 90, 188, 0.04);
}

.drag-handle {
  display: inline-block;
  color: #7a869a;
  font-size: 16px;
  line-height: 1;
  cursor: grab;
  user-select: none;
}
.drag-handle:active {
  cursor: grabbing;
}
:deep(.drag-ghost > td) {
  background-color: rgba(41, 90, 188, 0.1) !important;
}
:deep(.drag-chosen > td) {
  background-color: rgba(41, 90, 188, 0.06);
}
</style>
