<template>
  <div class="patients-container">
    <el-card class="panel-card">
      <div class="header-actions">
        <el-form :inline="true" :model="searchForm" class="search-form">
          <el-form-item label="目标医院" v-if="isSystemAdmin">
            <el-select
              v-model="searchForm.hospitalId"
              placeholder="系统管理员必须选择医院"
              clearable
              filterable
              style="width: 240px"
              @change="handleSearchHospitalChange"
            >
              <el-option
                v-for="hospital in hospitals"
                :key="hospital.id"
                :label="hospital.name"
                :value="hospital.id"
              />
            </el-select>
          </el-form-item>
          <el-form-item label="患者关键词">
            <el-input
              v-model="searchForm.keyword"
              placeholder="姓名 / 住院号 / 手机号 / 手术名称"
              clearable
            />
          </el-form-item>
          <el-form-item>
            <el-button type="primary" @click="handleSearch" icon="Search">
              查询
            </el-button>
            <el-button @click="resetSearch" icon="Refresh">重置</el-button>
            <el-button type="success" @click="openCreateDialog" icon="Plus">
              新增患者
            </el-button>
          </el-form-item>
        </el-form>
      </div>

      <el-alert
        v-if="searchForm.doctorId"
        type="info"
        :closable="false"
        style="margin-bottom: 16px"
      >
        <template #title>
          当前正在查看{{ searchForm.doctorName || '指定医生' }}的患者与手术记录
          <el-button link type="primary" @click="clearDoctorFilter">
            清除筛选
          </el-button>
        </template>
      </el-alert>

      <el-alert
        v-if="isSystemAdmin && !searchForm.hospitalId"
        type="warning"
        :closable="false"
        title="系统管理员查询或新增患者前必须先选择医院。"
        style="margin-bottom: 16px"
      />

      <el-table
        :data="tableData"
        v-loading="loading"
        border
        stripe
        style="width: 100%"
      >
        <el-table-column prop="id" label="ID" width="78" align="center" />
        <el-table-column prop="name" label="姓名" min-width="120" />
        <el-table-column prop="inpatientNo" label="住院号" min-width="150" />
        <el-table-column label="手术名称" min-width="180">
          <template #default="{ row }">
            {{ row.latestSurgery?.surgeryName || '-' }}
          </template>
        </el-table-column>
        <el-table-column prop="phone" label="联系电话" min-width="140" />
        <el-table-column prop="idCard" label="身份证号" min-width="200" />
        <el-table-column
          v-if="canViewHospitalInfo"
          label="归属医院"
          min-width="150"
        >
          <template #default="{ row }">
            {{ row.hospital?.name || '-' }}
          </template>
        </el-table-column>
        <el-table-column label="归属医生" min-width="140">
          <template #default="{ row }">
            {{ row.doctor?.name || '-' }}
          </template>
        </el-table-column>
        <el-table-column label="操作" width="440" fixed="right" align="center">
          <template #default="{ row }">
            <el-button
              v-if="canPublishAdjustTask"
              size="small"
              type="warning"
              plain
              @click="openPatientAdjustDialog(row)"
            >
              调压
            </el-button>
            <el-button
              size="small"
              type="primary"
              @click="openDetailDialog(row)"
            >
              详情
            </el-button>
            <el-button
              v-if="row.latestSurgery?.id"
              size="small"
              @click="
                row.shuntSurgeryCount > 1
                  ? openSurgeriesTab(row)
                  : openSurgeryDialog(row, row.latestSurgery.id)
              "
            >
              {{ row.shuntSurgeryCount > 1 ? '选择手术' : '编辑手术' }}
            </el-button>
            <el-button
              size="small"
              type="success"
              @click="openSurgeryDialog(row)"
            >
              追加手术
            </el-button>
            <el-button size="small" @click="openEditDialog(row)"
              >编辑</el-button
            >
            <el-button size="small" type="danger" @click="handleDelete(row)">
              删除
            </el-button>
          </template>
        </el-table-column>
      </el-table>

      <div class="pagination-container">
        <el-pagination
          v-model:current-page="page"
          v-model:page-size="pageSize"
          :page-sizes="[10, 20, 50, 100]"
          :total="total"
          background
          layout="total, sizes, prev, pager, next, jumper"
          @size-change="fetchData"
          @current-change="fetchData"
        />
      </div>
    </el-card>

    <el-dialog
      :title="isEdit ? '编辑患者档案' : '新增患者档案'"
      v-model="dialogVisible"
      width="1020px"
      top="4vh"
      destroy-on-close
      @close="resetPatientForm"
    >
      <div class="dialog-scroll">
        <el-form
          :model="patientForm"
          :rules="patientRules"
          ref="patientFormRef"
          label-width="110px"
        >
          <div class="section-card">
            <div class="section-card-head">
              <div>
                <div class="section-card-title">基础档案</div>
                <div class="section-card-subtitle">
                  先录基础信息，再决定是否同步录入首台手术
                </div>
              </div>
            </div>

            <el-row :gutter="16">
              <el-col :xs="24" :md="12">
                <el-form-item label="患者姓名" prop="name">
                  <el-input
                    v-model="patientForm.name"
                    placeholder="请输入患者姓名"
                  />
                </el-form-item>
              </el-col>
              <el-col :xs="24" :md="12">
                <el-form-item label="住院号">
                  <el-input
                    v-model="patientForm.inpatientNo"
                    placeholder="请输入住院号"
                  />
                </el-form-item>
              </el-col>
              <el-col :xs="24" :md="12">
                <el-form-item label="联系电话" prop="phone">
                  <el-input
                    v-model="patientForm.phone"
                    placeholder="请输入手机号"
                  />
                </el-form-item>
              </el-col>
              <el-col :xs="24" :md="12">
                <el-form-item label="身份证号" prop="idCard">
                  <el-input
                    v-model="patientForm.idCard"
                    placeholder="请输入身份证号"
                  />
                </el-form-item>
              </el-col>
              <el-col :xs="24" :md="12">
                <el-form-item label="归属医生" prop="doctorId">
                  <el-tree-select
                    v-model="patientForm.doctorId"
                    :data="doctorTreeOptions"
                    :props="doctorTreeProps"
                    filterable
                    clearable
                    placeholder="请选择归属医生（按科室/小组）"
                    style="width: 100%"
                  />
                </el-form-item>
              </el-col>
            </el-row>
          </div>

          <div class="section-card" v-if="!isEdit">
            <div class="section-card-head">
              <div>
                <div class="section-card-title">首台手术</div>
                <div class="section-card-subtitle">
                  建议创建患者时同步录入，后续二次手术可在列表中追加
                </div>
              </div>
              <el-switch
                v-model="includeInitialSurgery"
                active-text="同步录入"
                inactive-text="稍后录入"
              />
            </div>

            <SurgeryFormSection
              v-if="includeInitialSurgery"
              :form="initialSurgeryForm"
              :catalog-options="implantCatalogOptions"
              :surgeon-label="resolveSurgerySurgeonLabel(patientForm.doctorId)"
              :dictionary-options="medicalDictionaryOptions"
              :upload-hospital-id="resolveCurrentHospitalId()"
              title="首术信息"
              description="选择型号后会自动联动厂家和名称，可一次录入多台设备。"
            />
          </div>
        </el-form>
      </div>

      <template #footer>
        <div class="dialog-footer">
          <el-button @click="dialogVisible = false">取消</el-button>
          <el-button
            type="primary"
            :loading="submitLoading"
            @click="handleSubmitPatient"
          >
            {{ isEdit ? '保存修改' : '创建患者' }}
          </el-button>
        </div>
      </template>
    </el-dialog>

    <el-dialog
      :title="isSurgeryEditMode ? '编辑手术' : '追加手术'"
      v-model="surgeryDialogVisible"
      width="1120px"
      top="3vh"
      destroy-on-close
      @close="resetSurgeryDialog"
    >
      <div class="dialog-scroll">
        <el-alert
          v-if="surgeryPatientContext"
          type="info"
          :closable="false"
          class="context-alert"
        >
          <template #title>
            <template v-if="isSurgeryEditMode">
              正在编辑患者「{{ surgeryPatientContext.name }}」的手术记录
              <span v-if="surgeryPatientContext.editingSurgery">
                ：{{ surgeryPatientContext.editingSurgery.surgeryName }} （{{
                  formatDateTime(
                    surgeryPatientContext.editingSurgery.surgeryDate,
                  )
                }}）
              </span>
            </template>
            <template v-else>
              为患者「{{ surgeryPatientContext.name }}」追加手术
              <span v-if="surgeryPatientContext.latestSurgery">
                ，上次手术：
                {{ surgeryPatientContext.latestSurgery.surgeryName }}
                （{{
                  formatDateTime(
                    surgeryPatientContext.latestSurgery.surgeryDate,
                  )
                }}）
              </span>
            </template>
          </template>
        </el-alert>

        <SurgeryFormSection
          v-if="surgeryPatientContext"
          :form="appendSurgeryForm"
          :catalog-options="implantCatalogOptions"
          :surgeon-label="surgeryPatientContext.surgeonLabel"
          :dictionary-options="medicalDictionaryOptions"
          :upload-hospital-id="surgeryPatientContext.hospitalId"
          :abandonable-devices="surgeryPatientContext.activeDevices"
          :show-abandon-selector="!isSurgeryEditMode"
          :allow-device-structure-edit="!isSurgeryEditMode"
          :title="isSurgeryEditMode ? '编辑手术内容' : '手术录入'"
          :description="
            isSurgeryEditMode
              ? '可修改本次手术及已有植入设备信息；如需调整历史弃用设备，请通过追加手术处理。'
              : '若本次手术后需要停用旧设备，可在上方直接勾选弃用。'
          "
        />
      </div>

      <template #footer>
        <div class="dialog-footer">
          <el-button @click="surgeryDialogVisible = false">取消</el-button>
          <el-button
            type="primary"
            :loading="surgerySubmitLoading"
            @click="handleSubmitSurgery"
          >
            {{ isSurgeryEditMode ? '保存修改' : '保存手术' }}
          </el-button>
        </div>
      </template>
    </el-dialog>

    <el-dialog
      title="发布调压任务"
      v-model="adjustDialogVisible"
      width="560px"
      destroy-on-close
      @close="resetAdjustDialog"
    >
      <div v-if="currentAdjustPatient" class="adjust-dialog-body">
        <el-alert
          type="info"
          :closable="false"
          class="context-alert"
          title="这里只选择目标挡位；发布后由本院工程师接收，当前压力会在任务完成后自动刷新。"
        />

        <el-descriptions :column="1" border size="small">
          <el-descriptions-item label="患者">
            {{ formatPatientLabel(currentAdjustPatient) }}
          </el-descriptions-item>
          <el-descriptions-item label="设备">
            {{
              currentAdjustDevice?.implantName ||
              currentAdjustDevice?.implantModel ||
              '未命名设备'
            }}
          </el-descriptions-item>
          <el-descriptions-item label="当前压力">
            {{ formatValue(currentAdjustDevice?.currentPressure) }}
          </el-descriptions-item>
        </el-descriptions>

        <el-form label-width="100px" class="adjust-form">
          <el-form-item label="调压设备">
            <el-select
              v-model="adjustForm.deviceId"
              placeholder="请选择设备"
              style="width: 100%"
              @change="handleAdjustDeviceChange"
            >
              <el-option
                v-for="device in currentAdjustDevices"
                :key="device.id"
                :label="formatAdjustDeviceLabel(device)"
                :value="device.id"
              />
            </el-select>
          </el-form-item>
          <el-form-item label="目标挡位">
            <el-select
              v-model="adjustForm.targetPressure"
              placeholder="请选择下一次压力值"
              style="width: 100%"
              :disabled="!currentAdjustDevice"
            >
              <el-option
                v-for="level in resolveAdjustTargetOptions(currentAdjustDevice)"
                :key="`${currentAdjustDevice?.id}-${level}`"
                :label="String(level)"
                :value="level"
              />
            </el-select>
          </el-form-item>
        </el-form>
      </div>

      <template #footer>
        <div class="dialog-footer">
          <el-button @click="adjustDialogVisible = false">取消</el-button>
          <el-button
            type="primary"
            :loading="adjustSubmitLoading"
            @click="handleSubmitAdjustTask"
          >
            创建调压任务
          </el-button>
        </div>
      </template>
    </el-dialog>

    <el-dialog
      title="患者详情"
      v-model="detailDialogVisible"
      width="1180px"
      top="3vh"
      destroy-on-close
    >
      <div class="dialog-scroll" v-loading="detailLoading">
        <template v-if="detailPatient">
          <el-tabs v-model="detailTab">
            <el-tab-pane label="基础档案" name="profile">
              <div class="detail-profile">
                <el-descriptions :column="3" border>
                  <el-descriptions-item label="患者姓名">
                    {{ detailPatient.name || '-' }}
                  </el-descriptions-item>
                  <el-descriptions-item label="住院号">
                    {{ detailPatient.inpatientNo || '-' }}
                  </el-descriptions-item>
                  <el-descriptions-item label="联系电话">
                    {{ detailPatient.phone || '-' }}
                  </el-descriptions-item>
                  <el-descriptions-item label="身份证号">
                    {{ detailPatient.idCard || '-' }}
                  </el-descriptions-item>
                  <el-descriptions-item label="归属医生">
                    {{ detailPatient.doctor?.name || '-' }}
                  </el-descriptions-item>
                  <el-descriptions-item label="创建人">
                    {{ detailPatient.creator?.name || '-' }}
                  </el-descriptions-item>
                  <el-descriptions-item
                    v-if="canViewHospitalInfo"
                    label="归属医院"
                  >
                    {{ detailPatient.hospital?.name || '-' }}
                  </el-descriptions-item>
                  <el-descriptions-item label="建档时间">
                    {{ formatDateTime(detailPatient.createdAt) }}
                  </el-descriptions-item>
                  <el-descriptions-item label="分流手术次数">
                    {{ detailPatient.shuntSurgeryCount || 0 }}
                  </el-descriptions-item>
                  <el-descriptions-item label="当前在用设备">
                    {{ detailPatient.activeDeviceCount || 0 }}
                  </el-descriptions-item>
                </el-descriptions>
              </div>
            </el-tab-pane>

            <el-tab-pane label="手术记录" name="surgeries">
              <div
                v-if="detailPatient.surgeries?.length"
                class="surgery-card-list"
              >
                <el-card
                  v-for="surgery in detailPatient.surgeries"
                  :key="surgery.id"
                  shadow="never"
                  class="surgery-card"
                >
                  <template #header>
                    <div class="surgery-card-head">
                      <div>
                        <div class="surgery-card-title">
                          {{ surgery.surgeryName }}
                        </div>
                        <div class="surgery-card-meta">
                          {{ formatDateTime(surgery.surgeryDate) }} · 主刀
                          {{ surgery.surgeonName || '-' }}
                        </div>
                      </div>
                      <div class="surgery-card-tags">
                        <el-button
                          size="small"
                          type="primary"
                          plain
                          @click="openSurgeryEditFromDetail(surgery)"
                        >
                          编辑手术
                        </el-button>
                        <el-tag type="primary">
                          第 {{ surgery.shuntSurgeryCount || '-' }} 次分流手术
                        </el-tag>
                        <el-tag type="success">
                          在用 {{ surgery.activeDeviceCount || 0 }} 台
                        </el-tag>
                        <el-tag
                          v-if="surgery.abandonedDeviceCount"
                          type="warning"
                        >
                          弃用 {{ surgery.abandonedDeviceCount }} 台
                        </el-tag>
                      </div>
                    </div>
                  </template>

                  <el-descriptions :column="4" border class="surgery-desc">
                    <el-descriptions-item label="原发病">
                      {{ surgery.primaryDisease || '-' }}
                    </el-descriptions-item>
                    <el-descriptions-item label="脑积水类型">
                      {{ formatList(surgery.hydrocephalusTypes) }}
                    </el-descriptions-item>
                    <el-descriptions-item label="术前测压">
                      {{ formatValue(surgery.preOpPressure) }}
                    </el-descriptions-item>
                    <el-descriptions-item label="上次分流时间">
                      {{ formatDateTime(surgery.previousShuntSurgeryDate) }}
                    </el-descriptions-item>
                    <el-descriptions-item label="手术备注" :span="2">
                      {{ surgery.notes || '-' }}
                    </el-descriptions-item>
                    <el-descriptions-item label="术前资料" :span="2">
                      <div
                        v-if="
                          Array.isArray(surgery.preOpMaterials) &&
                          surgery.preOpMaterials.length
                        "
                        class="material-preview-list"
                      >
                        <div
                          v-for="(material, index) in surgery.preOpMaterials"
                          :key="`${surgery.id}-material-${index}`"
                          class="material-preview-card"
                        >
                          <div class="material-preview-name">
                            {{
                              material.name ||
                              material.type ||
                              `资料${index + 1}`
                            }}
                          </div>
                          <el-image
                            v-if="material.type === 'IMAGE'"
                            :src="material.url"
                            fit="contain"
                            class="material-preview-image"
                            :preview-src-list="[material.url]"
                            preview-teleported
                          />
                          <video
                            v-else-if="material.type === 'VIDEO'"
                            :src="material.url"
                            controls
                            class="material-preview-video"
                          />
                          <el-link
                            v-else
                            :href="material.url"
                            target="_blank"
                            type="primary"
                          >
                            打开文件
                          </el-link>
                        </div>
                      </div>
                      <span v-else>-</span>
                    </el-descriptions-item>
                  </el-descriptions>

                  <div class="device-grid">
                    <el-card
                      v-for="device in surgery.devices || []"
                      :key="device.id"
                      shadow="hover"
                      class="device-detail-card"
                    >
                      <div class="device-detail-head">
                        <div>
                          <div class="device-detail-title">
                            {{
                              device.implantName ||
                              device.implantModel ||
                              '未命名设备'
                            }}
                          </div>
                          <div class="device-detail-subtitle">
                            {{ device.implantManufacturer || '-' }} ·
                            {{ device.implantModel || '-' }}
                          </div>
                        </div>
                        <div class="device-detail-tags">
                          <el-tag
                            :type="
                              device.isValve === false ? 'info' : 'success'
                            "
                          >
                            {{ device.isValve === false ? '管子' : '阀门' }}
                          </el-tag>
                          <el-tag
                            v-if="device.isPressureAdjustable !== false"
                            type="success"
                          >
                            调压设备
                          </el-tag>
                          <el-tag
                            :type="device.isAbandoned ? 'warning' : 'primary'"
                          >
                            {{ device.isAbandoned ? '已弃用' : '在用' }}
                          </el-tag>
                          <el-button
                            v-if="canAdjustDevice(device)"
                            size="small"
                            type="warning"
                            plain
                            @click="openAdjustDialog(device)"
                          >
                            调压
                          </el-button>
                        </div>
                      </div>

                      <el-descriptions :column="2" border size="small">
                        <el-descriptions-item label="分流方式">
                          {{ device.shuntMode || '-' }}
                        </el-descriptions-item>
                        <el-descriptions-item label="远端方向">
                          {{ device.distalShuntDirection || '-' }}
                        </el-descriptions-item>
                        <el-descriptions-item label="近端穿刺区域">
                          {{ formatList(device.proximalPunctureAreas) }}
                        </el-descriptions-item>
                        <el-descriptions-item label="阀门植入部位">
                          {{
                            device.isValve === false
                              ? '-'
                              : formatList(device.valvePlacementSites)
                          }}
                        </el-descriptions-item>
                        <el-descriptions-item label="初始压力">
                          {{
                            device.isValve === false
                              ? '-'
                              : formatValue(device.initialPressure)
                          }}
                        </el-descriptions-item>
                        <el-descriptions-item label="当前压力">
                          {{
                            device.isValve === false
                              ? '-'
                              : formatValue(device.currentPressure)
                          }}
                        </el-descriptions-item>
                        <el-descriptions-item label="植入物备注" :span="2">
                          {{ device.implantNotes || '-' }}
                        </el-descriptions-item>
                        <el-descriptions-item label="植入物标签" :span="2">
                          <el-image
                            v-if="device.labelImageUrl"
                            :src="device.labelImageUrl"
                            fit="contain"
                            class="device-label-preview"
                            :preview-src-list="[device.labelImageUrl]"
                            preview-teleported
                          />
                          <span v-else>-</span>
                        </el-descriptions-item>
                      </el-descriptions>
                    </el-card>
                  </div>
                </el-card>
              </div>

              <el-empty v-else description="当前患者尚未录入手术信息" />
            </el-tab-pane>

            <el-tab-pane label="调压记录" name="adjustments">
              <div class="adjust-records-panel">
                <div
                  v-if="detailAdjustDeviceOptions.length > 1"
                  class="adjust-records-toolbar"
                >
                  <div class="adjust-records-toolbar-title">
                    当前患者有多台可调压设备，请切换设备分别查看调压记录
                  </div>
                  <el-select
                    v-model="detailAdjustDeviceId"
                    placeholder="请选择调压设备"
                    class="adjust-records-filter"
                  >
                    <el-option
                      v-for="device in detailAdjustDeviceOptions"
                      :key="device.id"
                      :label="device.label"
                      :value="device.id"
                    />
                  </el-select>
                </div>

                <el-table
                  :data="detailAdjustRecords"
                  border
                  stripe
                  max-height="520"
                  empty-text="暂无调压记录"
                >
                  <el-table-column label="时间" width="180">
                    <template #default="{ row }">
                      {{ formatDateTime(row.occurredAt) }}
                    </template>
                  </el-table-column>
                  <el-table-column label="调压设备" min-width="260">
                    <template #default="{ row }">
                      <div>
                        {{
                          row.device?.implantName ||
                          row.device?.implantModel ||
                          '未命名设备'
                        }}
                      </div>
                      <div class="sub-text">
                        {{ row.device?.implantModel || '-' }}
                      </div>
                    </template>
                  </el-table-column>
                  <el-table-column
                    label="压力变化"
                    min-width="160"
                    align="center"
                  >
                    <template #default="{ row }">
                      {{ formatAdjustRecordPressureChange(row) }}
                    </template>
                  </el-table-column>
                  <el-table-column label="任务状态" width="120" align="center">
                    <template #default="{ row }">
                      <el-tag :type="getTaskStatusTagType(row.task?.status)">
                        {{ getTaskStatusLabel(row.task?.status) }}
                      </el-tag>
                    </template>
                  </el-table-column>
                  <el-table-column label="关联手术" min-width="180">
                    <template #default="{ row }">
                      {{ row.surgery?.surgeryName || '-' }}
                    </template>
                  </el-table-column>
                  <el-table-column
                    v-if="canViewHospitalInfo"
                    label="医院"
                    min-width="150"
                  >
                    <template #default="{ row }">
                      {{ row.hospital?.name || '-' }}
                    </template>
                  </el-table-column>
                </el-table>
              </div>
            </el-tab-pane>
          </el-tabs>
        </template>
      </div>

      <template #footer>
        <div class="dialog-footer">
          <el-button @click="detailDialogVisible = false">关闭</el-button>
          <el-button
            v-if="detailPatient"
            type="primary"
            @click="openSurgeryFromDetail"
          >
            追加手术
          </el-button>
        </div>
      </template>
    </el-dialog>
  </div>
</template>

<script setup>
import { computed, onMounted, reactive, ref } from 'vue';
import { useRoute, useRouter } from 'vue-router';
import { ElMessage, ElMessageBox } from 'element-plus';
import {
  createPatient,
  createPatientSurgery,
  deletePatient,
  getPatientById,
  getPatientDoctors,
  getPatientLifecycle,
  getPatients,
  updatePatient,
  updatePatientSurgery,
} from '../../api/patients';
import { getImplantCatalogs } from '../../api/devices';
import { getDictionaries } from '../../api/dictionaries';
import { publishTask } from '../../api/tasks';
import {
  getDepartments,
  getGroups,
  getHospitals,
} from '../../api/organization';
import {
  createEmptyMedicalDictionaryOptions,
  groupMedicalDictionaryItems,
} from '../../constants/medical-dictionaries';
import { useUserStore } from '../../store/user';
import SurgeryFormSection from './components/SurgeryFormSection.vue';

const userStore = useUserStore();
const route = useRoute();
const router = useRouter();

const roleMap = {
  DIRECTOR: '科室主任',
  LEADER: '小组组长',
  DOCTOR: '医生',
};

const doctorTreeProps = {
  value: 'value',
  label: 'label',
  children: 'children',
  disabled: 'disabled',
};

const isSystemAdmin = computed(() => userStore.role === 'SYSTEM_ADMIN');
const canViewHospitalInfo = computed(() =>
  ['SYSTEM_ADMIN', 'HOSPITAL_ADMIN'].includes(userStore.role),
);
const canPublishAdjustTask = computed(() =>
  ['SYSTEM_ADMIN', 'HOSPITAL_ADMIN', 'DOCTOR', 'DIRECTOR', 'LEADER'].includes(
    userStore.role,
  ),
);

const loading = ref(false);
const submitLoading = ref(false);
const surgerySubmitLoading = ref(false);
const detailLoading = ref(false);

const tableData = ref([]);
const total = ref(0);
const page = ref(1);
const pageSize = ref(10);

const hospitals = ref([]);
const departments = ref([]);
const groups = ref([]);
const doctorOptions = ref([]);
const implantCatalogOptions = ref([]);
const medicalDictionaryOptions = ref(createEmptyMedicalDictionaryOptions());

const searchForm = reactive({
  keyword: '',
  hospitalId: null,
  doctorId: null,
  doctorName: '',
});

const dialogVisible = ref(false);
const isEdit = ref(false);
const patientFormRef = ref(null);
const currentEditId = ref(null);

const surgeryDialogVisible = ref(false);
const surgeryPatientContext = ref(null);
const surgeryDialogMode = ref('create');
const currentEditSurgeryId = ref(null);
const reopenDetailAfterSurgerySubmit = ref(false);
const adjustDialogVisible = ref(false);
const adjustSubmitLoading = ref(false);
const currentAdjustPatient = ref(null);

const detailDialogVisible = ref(false);
const detailTab = ref('profile');
const detailPatient = ref(null);
const detailLifecycle = ref([]);
const detailAdjustDeviceId = ref(null);

const patientForm = reactive({
  name: '',
  inpatientNo: '',
  phone: '',
  idCard: '',
  doctorId: null,
});

const includeInitialSurgery = ref(true);
const initialSurgeryForm = ref(createSurgeryForm());
const appendSurgeryForm = ref(createSurgeryForm());
const adjustForm = reactive({
  deviceId: null,
  targetPressure: null,
});

const currentAdjustDevices = computed(() => {
  if (!Array.isArray(currentAdjustPatient.value?.devices)) {
    return [];
  }

  return currentAdjustPatient.value.devices.filter((device) =>
    isAdjustableDeviceAvailable(device),
  );
});
const isSurgeryEditMode = computed(() => surgeryDialogMode.value === 'edit');

const currentAdjustDevice = computed(() => {
  return (
    currentAdjustDevices.value.find(
      (device) => device.id === adjustForm.deviceId,
    ) || null
  );
});

const TASK_STATUS_LABELS = {
  PENDING: '待接收',
  ACCEPTED: '已接收',
  COMPLETED: '已完成',
  CANCELLED: '已取消',
};

const TASK_STATUS_TAG_TYPES = {
  PENDING: 'warning',
  ACCEPTED: 'primary',
  COMPLETED: 'success',
  CANCELLED: 'info',
};

const detailAdjustDeviceOptions = computed(() => {
  return buildDetailAdjustDeviceOptions(
    detailPatient.value,
    detailLifecycle.value,
  );
});

const detailAdjustRecords = computed(() => {
  const records = Array.isArray(detailLifecycle.value)
    ? detailLifecycle.value
    : [];
  const adjustmentRecords = records.filter(
    (item) => item.eventType === 'TASK_PRESSURE_ADJUSTMENT',
  );

  if (!detailAdjustDeviceId.value) {
    return adjustmentRecords;
  }

  return adjustmentRecords.filter(
    (item) => item.device?.id === detailAdjustDeviceId.value,
  );
});

const patientRules = {
  name: [{ required: true, message: '请输入患者姓名', trigger: 'blur' }],
  phone: [
    { required: true, message: '请输入手机号', trigger: 'blur' },
    { pattern: /^1\d{10}$/, message: '请输入正确的手机号', trigger: 'blur' },
  ],
  idCard: [{ required: true, message: '请输入身份证号', trigger: 'blur' }],
  doctorId: [{ required: true, message: '请选择归属医生', trigger: 'change' }],
};

function createSurgeryForm() {
  return {
    surgeryDate: getNowDateTimeValue(),
    surgeryName: '',
    preOpPressure: null,
    primaryDisease: '',
    hydrocephalusTypes: [],
    previousShuntSurgeryDate: '',
    notes: '',
    preOpMaterials: [],
    devices: [createDeviceFormItem()],
    abandonedDeviceIds: [],
  };
}

function createMaterialFormItem(overrides = {}) {
  return {
    type: 'IMAGE',
    name: '',
    url: '',
    ...overrides,
  };
}

function createDeviceFormItem(overrides = {}) {
  return {
    id: null,
    implantCatalogId: null,
    shuntMode: '',
    proximalPunctureAreas: [],
    valvePlacementSites: [],
    distalShuntDirection: '',
    initialPressure: '',
    implantNotes: '',
    labelImageUrl: '',
    ...overrides,
  };
}

function getNowDateTimeValue() {
  return toDateTimeFormValue(new Date());
}

function toDateTimeFormValue(value) {
  if (!value) {
    return '';
  }

  const date = value instanceof Date ? value : new Date(value);
  if (Number.isNaN(date.getTime())) {
    return '';
  }

  const pad = (num) => String(num).padStart(2, '0');
  return `${date.getFullYear()}-${pad(date.getMonth() + 1)}-${pad(
    date.getDate(),
  )}T${pad(date.getHours())}:${pad(date.getMinutes())}:${pad(
    date.getSeconds(),
  )}`;
}

function normalizeOptionalString(value) {
  const normalized = String(value ?? '').trim();
  return normalized || undefined;
}

function normalizePressureLabel(value) {
  const raw = String(value ?? '').trim();
  if (!raw) {
    return '';
  }
  if (!/^\d+(\.\d+)?$/.test(raw)) {
    return '';
  }

  const [integerPart, fractionPart = ''] = raw.split('.');
  const normalizedInteger = integerPart.replace(/^0+(?=\d)/, '') || '0';
  const normalizedFraction = fractionPart.replace(/0+$/, '');

  return normalizedFraction
    ? `${normalizedInteger}.${normalizedFraction}`
    : normalizedInteger;
}

function normalizeStringArray(list, max = Infinity) {
  if (!Array.isArray(list)) {
    return [];
  }

  return Array.from(
    new Set(
      list
        .map((item) => String(item ?? '').trim())
        .filter(Boolean)
        .slice(0, max),
    ),
  );
}

function resolveCatalog(catalogId) {
  return (
    implantCatalogOptions.value.find((item) => item.id === catalogId) || null
  );
}

function resolveCatalogPressureLevels(catalogId) {
  const pressureLevels = resolveCatalog(catalogId)?.pressureLevels;
  return Array.isArray(pressureLevels) ? pressureLevels : [];
}

function validateSurgeryForm(form) {
  if (!form.surgeryDate) {
    return '请选择手术日期';
  }
  if (!String(form.surgeryName || '').trim()) {
    return '请输入手术名称';
  }
  if (!String(form.primaryDisease || '').trim()) {
    return '请选择原发病';
  }
  if (!normalizeStringArray(form.hydrocephalusTypes).length) {
    return '请至少选择一个脑积水类型';
  }
  if (!Array.isArray(form.devices) || form.devices.length === 0) {
    return '至少录入一台植入设备';
  }

  for (const [index, material] of (form.preOpMaterials || []).entries()) {
    const url = normalizeOptionalString(material.url);
    const name = normalizeOptionalString(material.name);
    if ((url && !material.type) || (!url && name)) {
      return `术前资料第 ${index + 1} 项请补全类型和地址`;
    }
    if (!url && !name) {
      continue;
    }
    if (!url) {
      return `术前资料第 ${index + 1} 项缺少地址`;
    }
  }

  for (const [index, device] of form.devices.entries()) {
    const catalog = resolveCatalog(device.implantCatalogId);
    if (!device.implantCatalogId || !catalog) {
      return `设备 ${index + 1} 请选择植入物型号`;
    }
    if (!String(device.shuntMode || '').trim()) {
      return `设备 ${index + 1} 请选择分流方式`;
    }
    if (!normalizeStringArray(device.proximalPunctureAreas, 2).length) {
      return `设备 ${index + 1} 请填写近端穿刺区域`;
    }
    if (
      catalog.isValve !== false &&
      !normalizeStringArray(device.valvePlacementSites, 2).length
    ) {
      return `设备 ${index + 1} 请填写阀门植入部位`;
    }
    if (!String(device.distalShuntDirection || '').trim()) {
      return `设备 ${index + 1} 请选择远端分流方向`;
    }
    if (
      catalog.isValve !== false &&
      catalog.isPressureAdjustable &&
      resolveCatalogPressureLevels(device.implantCatalogId).length > 0
    ) {
      const pressureLevels = resolveCatalogPressureLevels(
        device.implantCatalogId,
      );
      const normalizedInitialPressure = normalizePressureLabel(
        device.initialPressure,
      );
      if (
        normalizedInitialPressure &&
        !pressureLevels.includes(normalizedInitialPressure)
      ) {
        return `设备 ${index + 1} 初始压力不在该植入物挡位范围内`;
      }
    } else if (
      normalizeOptionalString(device.initialPressure) &&
      !normalizePressureLabel(device.initialPressure)
    ) {
      return `设备 ${index + 1} 初始压力格式不合法`;
    }
  }

  return '';
}

function buildSurgeryPayload(form, options = {}) {
  const includeAbandonedDeviceIds = options.includeAbandonedDeviceIds !== false;

  const payload = {
    surgeryDate: new Date(form.surgeryDate).toISOString(),
    surgeryName: String(form.surgeryName || '').trim(),
    preOpPressure:
      typeof form.preOpPressure === 'number' ? form.preOpPressure : undefined,
    primaryDisease: String(form.primaryDisease || '').trim(),
    hydrocephalusTypes: normalizeStringArray(form.hydrocephalusTypes),
    previousShuntSurgeryDate: form.previousShuntSurgeryDate
      ? new Date(form.previousShuntSurgeryDate).toISOString()
      : undefined,
    notes: normalizeOptionalString(form.notes),
    preOpMaterials: (form.preOpMaterials || [])
      .map((material) => ({
        type: material.type,
        name: normalizeOptionalString(material.name),
        url: normalizeOptionalString(material.url),
      }))
      .filter((material) => material.url),
    devices: (form.devices || []).map((device) => {
      const payloadDevice = {
        implantCatalogId: device.implantCatalogId,
        shuntMode: String(device.shuntMode || '').trim(),
        proximalPunctureAreas: normalizeStringArray(
          device.proximalPunctureAreas,
          2,
        ),
        valvePlacementSites: normalizeStringArray(device.valvePlacementSites, 2)
          .length
          ? normalizeStringArray(device.valvePlacementSites, 2)
          : undefined,
        distalShuntDirection: String(device.distalShuntDirection || '').trim(),
        initialPressure:
          resolveCatalog(device.implantCatalogId)?.isValve === false
            ? undefined
            : normalizePressureLabel(device.initialPressure) || undefined,
        implantNotes: normalizeOptionalString(device.implantNotes),
        labelImageUrl: normalizeOptionalString(device.labelImageUrl),
      };

      if (Number.isInteger(Number(device.id)) && Number(device.id) > 0) {
        payloadDevice.id = Number(device.id);
      }

      return payloadDevice;
    }),
  };

  if (includeAbandonedDeviceIds) {
    payload.abandonedDeviceIds = normalizeStringArray(
      form.abandonedDeviceIds,
    ).map(Number);
  }

  return payload;
}

function mapSurgeryToForm(surgery) {
  return {
    surgeryDate: toDateTimeFormValue(surgery?.surgeryDate),
    surgeryName: surgery?.surgeryName || '',
    preOpPressure:
      typeof surgery?.preOpPressure === 'number' ? surgery.preOpPressure : null,
    primaryDisease: surgery?.primaryDisease || '',
    hydrocephalusTypes: Array.isArray(surgery?.hydrocephalusTypes)
      ? [...surgery.hydrocephalusTypes]
      : [],
    previousShuntSurgeryDate: toDateTimeFormValue(
      surgery?.previousShuntSurgeryDate,
    ),
    notes: surgery?.notes || '',
    preOpMaterials: Array.isArray(surgery?.preOpMaterials)
      ? surgery.preOpMaterials.map((material) =>
          createMaterialFormItem({
            type: material?.type || 'IMAGE',
            name: material?.name || '',
            url: material?.url || '',
          }),
        )
      : [],
    devices:
      Array.isArray(surgery?.devices) && surgery.devices.length > 0
        ? surgery.devices.map((device) =>
            createDeviceFormItem({
              id: device.id,
              implantCatalogId: device.implantCatalogId ?? null,
              shuntMode: device.shuntMode || '',
              proximalPunctureAreas: Array.isArray(device.proximalPunctureAreas)
                ? [...device.proximalPunctureAreas]
                : [],
              valvePlacementSites: Array.isArray(device.valvePlacementSites)
                ? [...device.valvePlacementSites]
                : [],
              distalShuntDirection: device.distalShuntDirection || '',
              initialPressure: device.initialPressure || '',
              implantNotes: device.implantNotes || '',
              labelImageUrl: device.labelImageUrl || '',
            }),
          )
        : [createDeviceFormItem()],
    abandonedDeviceIds: [],
  };
}

const departmentNameMap = computed(() => {
  return Object.fromEntries(
    (departments.value || []).map((item) => [item.id, item.name]),
  );
});

const groupNameMap = computed(() => {
  return Object.fromEntries(
    (groups.value || []).map((item) => [item.id, item.name]),
  );
});

const doctorTreeOptions = computed(() => {
  const options = Array.isArray(doctorOptions.value) ? doctorOptions.value : [];
  const deptMap = new Map();

  options.forEach((doctor) => {
    const deptId = doctor.departmentId ?? 0;
    const groupId = doctor.groupId ?? 0;
    const deptKey = `dept_${deptId}`;
    const groupKey = `group_${groupId}`;

    if (!deptMap.has(deptKey)) {
      const deptLabel = deptId
        ? departmentNameMap.value[deptId] || `科室#${deptId}`
        : '未分配科室';
      deptMap.set(deptKey, {
        value: deptKey,
        label: deptLabel,
        disabled: true,
        children: [],
      });
    }

    const deptNode = deptMap.get(deptKey);

    if (groupId) {
      let groupNode = deptNode.children.find((item) => item.value === groupKey);
      if (!groupNode) {
        groupNode = {
          value: groupKey,
          label: groupNameMap.value[groupId] || `小组#${groupId}`,
          disabled: true,
          children: [],
        };
        deptNode.children.push(groupNode);
      }

      groupNode.children.push({
        value: doctor.id,
        label: formatDoctorOptionLabel(doctor),
      });
      return;
    }

    deptNode.children.push({
      value: doctor.id,
      label: formatDoctorOptionLabel(doctor),
    });
  });

  return Array.from(deptMap.values()).sort((a, b) =>
    String(a.label).localeCompare(String(b.label), 'zh-Hans-CN'),
  );
});

function resolveCurrentHospitalId() {
  return isSystemAdmin.value
    ? searchForm.hospitalId
    : userStore.userInfo?.hospitalId;
}

function formatDoctorOptionLabel(doctor) {
  if (!doctor?.name) {
    return '';
  }

  const meta = [roleMap[doctor.role] || doctor.role, doctor.phone]
    .filter(Boolean)
    .join(' / ');

  return meta ? `${doctor.name}（${meta}）` : doctor.name;
}

function resolveSurgerySurgeonLabel(doctorId) {
  const doctor =
    doctorOptions.value.find((item) => item.id === doctorId) || null;
  return formatDoctorOptionLabel(doctor);
}

function formatPatientLabel(patient) {
  return [
    patient.name,
    patient.inpatientNo ? `住院号 ${patient.inpatientNo}` : null,
    patient.phone,
  ]
    .filter(Boolean)
    .join(' ｜ ');
}

function formatAdjustDeviceLabel(device) {
  const placementLabel = formatList(device.valvePlacementSites);
  return [
    device.implantName || device.implantModel || '未命名设备',
    `部位 ${placementLabel}`,
    `当前压力 ${formatValue(device.currentPressure)}`,
  ].join(' ｜ ');
}

function formatDateTime(value) {
  if (!value) {
    return '-';
  }

  const date = new Date(value);
  if (Number.isNaN(date.getTime())) {
    return '-';
  }

  return date.toLocaleString('zh-CN', { hour12: false });
}

function formatList(value) {
  return Array.isArray(value) && value.length ? value.join('、') : '-';
}

function formatValue(value) {
  return value == null || value === '' ? '-' : value;
}

function getTaskStatusLabel(status) {
  return TASK_STATUS_LABELS[status] || status || '-';
}

function getTaskStatusTagType(status) {
  return TASK_STATUS_TAG_TYPES[status] || 'info';
}

function formatAdjustRecordPressureChange(event) {
  return `${event.taskItem?.oldPressure ?? '-'} -> ${
    event.taskItem?.targetPressure ?? '-'
  }`;
}

function applyFiltersAndPagination() {
  page.value = Math.max(1, Number(page.value) || 1);
}

function syncDoctorFilterFromRoute() {
  const doctorId = Number(route.query.doctorId);
  searchForm.doctorId =
    Number.isInteger(doctorId) && doctorId > 0 ? doctorId : null;
  searchForm.doctorName = String(route.query.doctorName || '').trim();
}

async function fetchHospitalsForAdmin() {
  if (!isSystemAdmin.value) {
    return;
  }

  const res = await getHospitals({ page: 1, pageSize: 100 });
  hospitals.value = res.list || [];
  if (!searchForm.hospitalId && hospitals.value.length > 0) {
    searchForm.hospitalId = hospitals.value[0].id;
  }
}

async function fetchDoctorOptions(hospitalId = resolveCurrentHospitalId()) {
  const params = {};
  if (isSystemAdmin.value) {
    if (!hospitalId) {
      doctorOptions.value = [];
      return;
    }
    params.hospitalId = hospitalId;
  }
  const res = await getPatientDoctors(params);
  doctorOptions.value = Array.isArray(res) ? res : [];
}

async function fetchOrgNodesForDoctorTree(
  hospitalId = resolveCurrentHospitalId(),
) {
  const params = { pageSize: 100 };
  if (isSystemAdmin.value) {
    if (!hospitalId) {
      departments.value = [];
      groups.value = [];
      return;
    }
    params.hospitalId = hospitalId;
  }

  const [deptRes, groupRes] = await Promise.all([
    getDepartments(params),
    getGroups(params),
  ]);
  departments.value = Array.isArray(deptRes?.list) ? deptRes.list : [];
  groups.value = Array.isArray(groupRes?.list) ? groupRes.list : [];
}

async function fetchImplantCatalogOptions() {
  const res = await getImplantCatalogs();
  implantCatalogOptions.value = Array.isArray(res) ? res : [];
}

async function fetchMedicalDictionaryOptions() {
  const res = await getDictionaries();
  medicalDictionaryOptions.value = groupMedicalDictionaryItems(res);
}

async function fetchData() {
  if (isSystemAdmin.value && !searchForm.hospitalId) {
    tableData.value = [];
    total.value = 0;
    return;
  }

  loading.value = true;
  try {
    const params = {
      page: page.value,
      pageSize: pageSize.value,
    };
    if (isSystemAdmin.value) {
      params.hospitalId = searchForm.hospitalId;
    }
    if (searchForm.keyword) {
      params.keyword = searchForm.keyword;
    }
    if (searchForm.doctorId) {
      params.doctorId = searchForm.doctorId;
    }

    const res = await getPatients(params);
    tableData.value = Array.isArray(res?.list) ? res.list : [];
    total.value = Number(res?.total || 0);
  } finally {
    loading.value = false;
  }
}

async function handleSearchHospitalChange() {
  page.value = 1;
  searchForm.doctorId = null;
  searchForm.doctorName = '';
  await Promise.all([
    fetchOrgNodesForDoctorTree(searchForm.hospitalId),
    fetchDoctorOptions(searchForm.hospitalId),
  ]);
  await fetchData();
}

async function handleSearch() {
  page.value = 1;
  await fetchData();
}

async function resetSearch() {
  searchForm.keyword = '';
  page.value = 1;
  await fetchData();
}

async function clearDoctorFilter() {
  searchForm.doctorId = null;
  searchForm.doctorName = '';
  await router.replace({ path: '/patients' });
  page.value = 1;
  await fetchData();
}

function resetPatientForm() {
  patientFormRef.value?.clearValidate?.();
  patientForm.name = '';
  patientForm.inpatientNo = '';
  patientForm.phone = '';
  patientForm.idCard = '';
  patientForm.doctorId = null;
  includeInitialSurgery.value = true;
  initialSurgeryForm.value = createSurgeryForm();
  currentEditId.value = null;
}

function resetSurgeryDialog() {
  appendSurgeryForm.value = createSurgeryForm();
  surgeryPatientContext.value = null;
  surgeryDialogMode.value = 'create';
  currentEditSurgeryId.value = null;
  reopenDetailAfterSurgerySubmit.value = false;
}

async function ensureCreateContext() {
  const hospitalId = resolveCurrentHospitalId();
  if (isSystemAdmin.value && !hospitalId) {
    ElMessage.warning('请先选择医院，再新增患者');
    return false;
  }

  await Promise.all([
    fetchOrgNodesForDoctorTree(hospitalId),
    fetchDoctorOptions(hospitalId),
    fetchImplantCatalogOptions(),
  ]);
  return true;
}

async function openCreateDialog() {
  const ready = await ensureCreateContext();
  if (!ready) {
    return;
  }

  isEdit.value = false;
  resetPatientForm();

  dialogVisible.value = true;
}

async function openEditDialog(row) {
  const hospitalId =
    row.hospital?.id || row.hospitalId || resolveCurrentHospitalId();
  await Promise.all([
    fetchOrgNodesForDoctorTree(hospitalId),
    fetchDoctorOptions(hospitalId),
  ]);

  const detail = await getPatientById(row.id);
  isEdit.value = true;
  includeInitialSurgery.value = false;
  currentEditId.value = detail.id;
  patientForm.name = detail.name || '';
  patientForm.inpatientNo = detail.inpatientNo || '';
  patientForm.phone = detail.phone || '';
  patientForm.idCard = detail.idCard || '';
  patientForm.doctorId = detail.doctorId || null;
  dialogVisible.value = true;
}

async function handleSubmitPatient() {
  if (!patientFormRef.value) {
    return;
  }

  try {
    await patientFormRef.value.validate();
  } catch {
    return;
  }

  if (!isEdit.value && includeInitialSurgery.value) {
    const errorMessage = validateSurgeryForm(initialSurgeryForm.value);
    if (errorMessage) {
      ElMessage.warning(errorMessage);
      return;
    }
  }

  submitLoading.value = true;
  try {
    const payload = {
      name: patientForm.name,
      inpatientNo: patientForm.inpatientNo,
      phone: patientForm.phone,
      idCard: patientForm.idCard,
      doctorId: patientForm.doctorId,
    };

    if (!isEdit.value && includeInitialSurgery.value) {
      payload.initialSurgery = buildSurgeryPayload(initialSurgeryForm.value);
    }

    if (isEdit.value) {
      await updatePatient(currentEditId.value, payload);
      ElMessage.success('患者档案已更新');
    } else {
      await createPatient(payload);
      ElMessage.success('患者档案已创建');
    }

    dialogVisible.value = false;
    await fetchData();
  } finally {
    submitLoading.value = false;
  }
}

async function openSurgeryDialog(row, surgeryId = null) {
  const detail = await getPatientById(row.id);
  const hospitalId = detail.hospital?.id || detail.hospitalId;

  await Promise.all([
    fetchImplantCatalogOptions(),
    fetchDoctorOptions(hospitalId),
  ]);

  const normalizedSurgeryId = Number(surgeryId);
  const editingSurgery =
    Number.isInteger(normalizedSurgeryId) && normalizedSurgeryId > 0
      ? (detail.surgeries || []).find(
          (item) => item.id === normalizedSurgeryId,
        ) || null
      : null;

  if (surgeryId != null && !editingSurgery) {
    ElMessage.warning('未找到要编辑的手术记录');
    return;
  }

  surgeryDialogMode.value = editingSurgery ? 'edit' : 'create';
  currentEditSurgeryId.value = editingSurgery?.id || null;
  appendSurgeryForm.value = editingSurgery
    ? mapSurgeryToForm(editingSurgery)
    : createSurgeryForm();

  if (!editingSurgery) {
    appendSurgeryForm.value.previousShuntSurgeryDate = toDateTimeFormValue(
      detail.latestSurgery?.surgeryDate || detail.surgeries?.[0]?.surgeryDate,
    );
  }

  surgeryPatientContext.value = {
    id: detail.id,
    name: detail.name,
    hospitalId,
    latestSurgery: detail.latestSurgery || detail.surgeries?.[0] || null,
    editingSurgery,
    surgeonLabel:
      formatDoctorOptionLabel(detail.doctor) ||
      resolveSurgerySurgeonLabel(detail.doctorId),
    activeDevices: Array.isArray(detail.devices)
      ? detail.devices.filter((device) => !device.isAbandoned)
      : [],
  };

  surgeryDialogVisible.value = true;
}

async function handleSubmitSurgery() {
  if (!surgeryPatientContext.value) {
    return;
  }

  const errorMessage = validateSurgeryForm(appendSurgeryForm.value);
  if (errorMessage) {
    ElMessage.warning(errorMessage);
    return;
  }

  surgerySubmitLoading.value = true;
  try {
    const patientId = surgeryPatientContext.value.id;
    const payload = buildSurgeryPayload(appendSurgeryForm.value, {
      includeAbandonedDeviceIds: !isSurgeryEditMode.value,
    });

    if (isSurgeryEditMode.value) {
      await updatePatientSurgery(
        patientId,
        currentEditSurgeryId.value,
        payload,
      );
      ElMessage.success('手术记录已更新');
    } else {
      await createPatientSurgery(patientId, payload);
      ElMessage.success('手术记录已保存');
    }

    surgeryDialogVisible.value = false;
    await fetchData();

    if (
      (detailDialogVisible.value || reopenDetailAfterSurgerySubmit.value) &&
      detailPatient.value?.id === patientId
    ) {
      await openDetailDialog({ ...detailPatient.value });
      detailTab.value = 'surgeries';
    }

    reopenDetailAfterSurgerySubmit.value = false;
  } finally {
    surgerySubmitLoading.value = false;
  }
}

function openSurgeryFromDetail() {
  if (!detailPatient.value) {
    return;
  }
  reopenDetailAfterSurgerySubmit.value = true;
  detailDialogVisible.value = false;
  openSurgeryDialog(detailPatient.value);
}

async function openSurgeriesTab(row) {
  await openDetailDialog(row);
  detailTab.value = 'surgeries';
}

function openSurgeryEditFromDetail(surgery) {
  if (!detailPatient.value || !surgery?.id) {
    return;
  }

  reopenDetailAfterSurgerySubmit.value = true;
  detailDialogVisible.value = false;
  openSurgeryDialog(detailPatient.value, surgery.id);
}

function resolveDevicePressureLevels(device) {
  const pressureLevels = device?.implantCatalog?.pressureLevels;
  return Array.isArray(pressureLevels) ? pressureLevels : [];
}

function resolveAdjustTargetOptions(device) {
  const pressureLevels = resolveDevicePressureLevels(device);
  if (!pressureLevels.length) {
    return [];
  }

  const currentPressure = normalizePressureLabel(device?.currentPressure);
  if (!currentPressure) {
    return pressureLevels;
  }

  return pressureLevels.filter((level) => level !== currentPressure);
}

function isAdjustableDeviceAvailable(device) {
  return (
    device?.isPressureAdjustable !== false &&
    device?.status === 'ACTIVE' &&
    !device?.isAbandoned &&
    resolveAdjustTargetOptions(device).length > 0
  );
}

function canAdjustDevice(device) {
  return canPublishAdjustTask.value && isAdjustableDeviceAvailable(device);
}

function buildDetailAdjustDeviceOptions(patient, lifecycle) {
  const adjustableRecords = Array.isArray(lifecycle)
    ? lifecycle.filter((item) => item.eventType === 'TASK_PRESSURE_ADJUSTMENT')
    : [];
  const recordDeviceIds = new Set(
    adjustableRecords.map((item) => item.device?.id).filter(Boolean),
  );
  const patientDevices = Array.isArray(patient?.devices) ? patient.devices : [];
  const options = patientDevices
    .filter(
      (device) =>
        device?.isPressureAdjustable !== false &&
        (device?.status === 'ACTIVE' || recordDeviceIds.has(device.id)),
    )
    .map((device) => ({
      id: device.id,
      label: formatAdjustDeviceLabel(device),
    }));

  if (options.length > 0) {
    return options;
  }

  return adjustableRecords
    .map((item) => item.device)
    .filter(Boolean)
    .filter(
      (device, index, list) =>
        list.findIndex((item) => item?.id === device?.id) === index,
    )
    .map((device) => ({
      id: device.id,
      label: formatAdjustDeviceLabel(device),
    }));
}

function resetAdjustDialog() {
  currentAdjustPatient.value = null;
  adjustForm.deviceId = null;
  adjustForm.targetPressure = null;
}

function handleAdjustDeviceChange(deviceId) {
  const nextDevice =
    currentAdjustDevices.value.find((device) => device.id === deviceId) || null;
  const targetOptions = resolveAdjustTargetOptions(nextDevice);
  adjustForm.targetPressure = targetOptions[0] ?? null;
}

async function openPatientAdjustDialog(row) {
  if (!row) {
    return;
  }

  const detail =
    detailPatient.value?.id === row.id
      ? detailPatient.value
      : await getPatientById(row.id);
  const adjustableDevices = Array.isArray(detail?.devices)
    ? detail.devices.filter((device) => isAdjustableDeviceAvailable(device))
    : [];

  if (!adjustableDevices.length) {
    ElMessage.warning('该患者当前没有可发布调压任务的在用调压设备');
    return;
  }

  currentAdjustPatient.value = detail;
  adjustForm.deviceId = adjustableDevices[0].id;
  handleAdjustDeviceChange(adjustForm.deviceId);
  adjustDialogVisible.value = true;
}

async function openAdjustDialog(device) {
  const patient = detailPatient.value;
  if (!patient) {
    return;
  }

  currentAdjustPatient.value = patient;
  adjustForm.deviceId = device.id;
  handleAdjustDeviceChange(device.id);
  adjustDialogVisible.value = true;
}

async function handleSubmitAdjustTask() {
  if (!currentAdjustDevice.value) {
    ElMessage.warning('请选择调压设备和目标挡位');
    return;
  }

  if (adjustForm.targetPressure == null) {
    ElMessage.warning('请选择调压设备和目标挡位');
    return;
  }

  adjustSubmitLoading.value = true;
  try {
    await publishTask({
      items: [
        {
          deviceId: adjustForm.deviceId,
          targetPressure: adjustForm.targetPressure,
        },
      ],
    });

    ElMessage.success('调压任务已发布，待本院工程师接收');
    adjustDialogVisible.value = false;

    if (detailPatient.value?.id === currentAdjustPatient.value?.id) {
      await openDetailDialog({
        id: detailPatient.value.id,
        phone: detailPatient.value.phone,
        idCard: detailPatient.value.idCard,
      });
      detailTab.value = 'adjustments';
    }
  } finally {
    adjustSubmitLoading.value = false;
  }
}

function handleDelete(row) {
  ElMessageBox.confirm(`确定要删除患者 "${row.name}" 吗？`, '警告', {
    confirmButtonText: '确定',
    cancelButtonText: '取消',
    type: 'warning',
  })
    .then(async () => {
      await deletePatient(row.id);
      ElMessage.success('删除成功');
      await fetchData();
    })
    .catch(() => {});
}

async function openDetailDialog(row) {
  detailDialogVisible.value = true;
  detailLoading.value = true;
  detailTab.value = 'profile';
  detailPatient.value = null;
  detailLifecycle.value = [];
  detailAdjustDeviceId.value = null;

  try {
    const detailPromise = getPatientById(row.id);
    const lifecyclePromise = getPatientLifecycle(row.id);

    const [detail, lifecycle] = await Promise.all([
      detailPromise,
      lifecyclePromise.catch((error) => {
        ElMessage.error(error?.response?.data?.msg || '患者生命周期加载失败');
        return { lifecycle: [] };
      }),
    ]);

    detailPatient.value = detail;
    const fullLifecycle = Array.isArray(lifecycle?.lifecycle)
      ? lifecycle.lifecycle
      : [];
    detailLifecycle.value = fullLifecycle.filter(
      (item) => item.patient?.id === detail.id,
    );
    const deviceOptions = buildDetailAdjustDeviceOptions(
      detail,
      detailLifecycle.value,
    );
    detailAdjustDeviceId.value = deviceOptions[0]?.id || null;
  } finally {
    detailLoading.value = false;
  }
}

onMounted(async () => {
  syncDoctorFilterFromRoute();
  await fetchHospitalsForAdmin();
  await fetchMedicalDictionaryOptions();
  await Promise.all([
    fetchOrgNodesForDoctorTree(),
    fetchDoctorOptions(),
    fetchData(),
  ]);
});
</script>

<style scoped>
.patients-container {
  padding: 0;
}

.panel-card {
  border-radius: 20px;
  border: none;
  background:
    radial-gradient(
      circle at top right,
      rgba(18, 99, 167, 0.09),
      transparent 22%
    ),
    linear-gradient(180deg, #ffffff 0%, #f6f9fd 100%);
}

.header-actions {
  margin-bottom: 20px;
}

.pagination-container {
  margin-top: 20px;
  display: flex;
  justify-content: flex-end;
}

.dialog-scroll {
  max-height: 72vh;
  overflow: auto;
  padding-right: 4px;
}

.section-card {
  padding: 18px 18px 8px;
  border: 1px solid #d8e5f3;
  border-radius: 18px;
  background: linear-gradient(180deg, #ffffff 0%, #f8fbff 100%);
}

.section-card + .section-card {
  margin-top: 16px;
}

.section-card-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  margin-bottom: 16px;
}

.section-card-title {
  font-size: 16px;
  font-weight: 600;
  color: #16324f;
}

.section-card-subtitle {
  margin-top: 4px;
  font-size: 12px;
  color: #64748b;
}

.dialog-footer {
  display: flex;
  justify-content: flex-end;
  gap: 12px;
}

.context-alert {
  margin-bottom: 16px;
}

.detail-profile {
  padding-top: 6px;
}

.surgery-card-list {
  display: grid;
  gap: 16px;
}

.surgery-card {
  border-radius: 18px;
  border-color: #d7e6f5;
  background:
    radial-gradient(
      circle at top right,
      rgba(0, 109, 119, 0.08),
      transparent 26%
    ),
    linear-gradient(180deg, #ffffff 0%, #f7fbff 100%);
}

.surgery-card-head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 16px;
}

.surgery-card-title {
  font-size: 16px;
  font-weight: 600;
  color: #16324f;
}

.surgery-card-meta {
  margin-top: 4px;
  color: #64748b;
  font-size: 13px;
}

.surgery-card-tags {
  display: flex;
  flex-wrap: wrap;
  justify-content: flex-end;
  gap: 8px;
}

.surgery-desc {
  margin-bottom: 16px;
}

.link-list {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
}

.material-preview-list {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
  gap: 12px;
}

.material-preview-card {
  padding: 12px;
  border: 1px solid #d7e6f5;
  border-radius: 14px;
  background: #fff;
}

.material-preview-name {
  margin-bottom: 8px;
  font-size: 13px;
  font-weight: 600;
  color: #16324f;
  word-break: break-all;
}

.material-preview-image,
.material-preview-video {
  width: 100%;
  height: 160px;
  border-radius: 12px;
  overflow: hidden;
}

.material-preview-image {
  display: block;
  background: #edf4fb;
}

.material-preview-image :deep(.el-image__inner) {
  object-fit: contain;
}

.material-preview-video {
  object-fit: contain;
  background: #0f172a;
}

.device-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
  gap: 14px;
}

.device-detail-card {
  border-radius: 16px;
  border-color: #d7e6f5;
  background: #fff;
}

.device-detail-head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 12px;
  margin-bottom: 12px;
}

.device-detail-title {
  font-size: 14px;
  font-weight: 600;
  color: #16324f;
}

.device-detail-subtitle {
  margin-top: 4px;
  font-size: 12px;
  color: #64748b;
}

.device-detail-tags {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}

.device-label-preview {
  width: 200px;
  height: 130px;
  border-radius: 12px;
  overflow: hidden;
  display: block;
  background: #edf4fb;
}

.device-label-preview :deep(.el-image__inner) {
  object-fit: contain;
}

.adjust-records-panel {
  display: grid;
  gap: 14px;
}

.adjust-records-toolbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  padding: 14px 16px;
  border: 1px solid #d7e6f5;
  border-radius: 16px;
  background: linear-gradient(180deg, #ffffff 0%, #f8fbff 100%);
}

.adjust-records-toolbar-title {
  color: #64748b;
  font-size: 13px;
}

.adjust-records-filter {
  width: 360px;
  max-width: 100%;
}

.adjust-dialog-body {
  display: grid;
  gap: 16px;
}

.adjust-form {
  padding-top: 4px;
}

@media (max-width: 768px) {
  .section-card-head,
  .surgery-card-head,
  .device-detail-head,
  .adjust-records-toolbar {
    flex-direction: column;
    align-items: flex-start;
  }

  .surgery-card-tags {
    justify-content: flex-start;
  }

  .adjust-records-filter {
    width: 100%;
  }
}
</style>
