<template>
  <div class="page ctms-page-shell page--flush">
    <div class="page-header unified-action-bar bar--flush">
      <div>
        <h1 class="page-title">{{ detail.subject_no || TEXT.modules.subjectManagement.screeningNo }}</h1>
        <p class="page-subtitle">{{ TEXT.modules.subjectManagement.screeningNo }}</p>
      </div>
      <div class="actions">
        <el-button
          v-if="subjectEditing"
          type="primary"
          :loading="subjectSaving"
          :disabled="isReadOnly"
          @click="saveSubjectEdit"
        >
          {{ TEXT.common.actions.save }}
        </el-button>
        <el-button v-if="subjectEditing" :disabled="isReadOnly" @click="cancelSubjectEdit">
          {{ TEXT.common.actions.cancel }}
        </el-button>
        <el-button v-else type="primary" :disabled="isReadOnly" @click="startSubjectEdit">
          {{ TEXT.common.actions.edit }}
        </el-button>
        <el-button @click="goBack">{{ TEXT.common.actions.back }}</el-button>
      </div>
    </div>

    <el-card class="unified-shell subject-shell" v-loading="loading">
      <el-descriptions class="subject-overview-descriptions" :column="2" border>
        <el-descriptions-item :label="TEXT.modules.subjectManagement.screeningNo">{{ detail.subject_no || TEXT.common.fallback }}</el-descriptions-item>
        <el-descriptions-item :label="TEXT.common.fields.site">{{ siteMap[detail.site_id] || TEXT.common.fallback }}</el-descriptions-item>
        <el-descriptions-item :label="TEXT.common.fields.status">
          <span>{{ displayEnum(TEXT.enums.subjectStatus, detail.status) }}</span>
        </el-descriptions-item>
        <el-descriptions-item :label="TEXT.common.fields.screeningDate">{{ displayDate(detail.screening_date) }}</el-descriptions-item>
        <el-descriptions-item :label="TEXT.common.fields.consentDate">
          <el-date-picker
            v-if="subjectEditing"
            v-model="subjectForm.consent_date"
            type="date"
            value-format="YYYY-MM-DD"
            size="small"
          />
          <span v-else>{{ displayDate(detail.consent_date) }}</span>
        </el-descriptions-item>
        <el-descriptions-item :label="TEXT.common.fields.enrollmentDate">
          <el-date-picker
            v-if="subjectEditing"
            v-model="subjectForm.enrollment_date"
            type="date"
            value-format="YYYY-MM-DD"
            size="small"
          />
          <span v-else>{{ displayDate(detail.enrollment_date) }}</span>
        </el-descriptions-item>
        <el-descriptions-item :label="TEXT.common.fields.baselineDate">
          <el-date-picker
            v-if="subjectEditing"
            v-model="subjectForm.baseline_date"
            type="date"
            value-format="YYYY-MM-DD"
            size="small"
          />
          <span v-else>{{ displayDate(detail.baseline_date) }}</span>
        </el-descriptions-item>
        <el-descriptions-item :label="TEXT.common.fields.completionDate">
          <el-date-picker
            v-if="subjectEditing"
            v-model="subjectForm.completion_date"
            type="date"
            value-format="YYYY-MM-DD"
            size="small"
          />
          <span v-else>{{ displayDate(detail.completion_date) }}</span>
        </el-descriptions-item>
        <el-descriptions-item :label="TEXT.common.fields.dropReason" :span="2">
          <el-input v-if="subjectEditing" v-model="subjectForm.drop_reason" type="textarea" :rows="2" />
          <span v-else>{{ detail.drop_reason || TEXT.common.fallback }}</span>
        </el-descriptions-item>
      </el-descriptions>
    </el-card>

    <el-card class="unified-shell subject-shell subject-tabs-shell">
      <div class="subject-tabs-action">
        <el-button type="primary" :loading="currentTabAction.loading" :disabled="isReadOnly" @click="currentTabAction.onClick">
          {{ currentTabAction.label }}
        </el-button>
        <el-button v-if="activeTab === 'visits'" type="warning" plain :disabled="isReadOnly" @click="openEarlyTerminationDialog">
          提前终止
        </el-button>
        <el-button v-if="adherenceEditing && activeTab === 'medicationAdherence'" :disabled="isReadOnly" @click="adherenceEditing = false">
          {{ TEXT.common.actions.cancel }}
        </el-button>
      </div>
      <el-tabs v-model="activeTab">
        <el-tab-pane :label="TEXT.modules.subjectDetail.tabs.history" name="history">
          <el-table :data="historyItems" v-loading="loadingHistory" style="width: 100%" class="subject-detail-table" table-layout="fixed">
            <el-table-column prop="record_date" :label="TEXT.common.fields.recordDate" show-overflow-tooltip>
              <template #default="scope">{{ displayDate(scope.row.record_date) }}</template>
            </el-table-column>
            <el-table-column prop="content" :label="TEXT.common.fields.content" show-overflow-tooltip />
            <el-table-column :label="TEXT.common.labels.actions" width="140">
              <template #default="scope">
                <el-button
                  link
                  type="primary"
                  size="small"
                  :disabled="isReadOnly"
                  @click="openHistoryDialog(scope.row)"
                >
                  {{ TEXT.common.actions.edit }}
                </el-button>
                <el-button
                  link
                  type="danger"
                  size="small"
                  :disabled="isReadOnly"
                  @click="removeHistory(scope.row)"
                >
                  {{ TEXT.common.actions.delete }}
                </el-button>
              </template>
            </el-table-column>
            <template #empty>
              <div v-if="!loadingHistory" class="table-empty">{{ TEXT.modules.subjectDetail.emptyHistory }}</div>
            </template>
          </el-table>
        </el-tab-pane>

        <el-tab-pane :label="TEXT.modules.subjectDetail.tabs.visits" name="visits">
          <el-table :data="visitItems" v-loading="loadingVisits" style="width: 100%" class="subject-detail-table" table-layout="fixed">
            <el-table-column prop="visit_code" :label="TEXT.common.fields.visitCode" show-overflow-tooltip />
            <el-table-column prop="planned_date" :label="TEXT.common.fields.plannedDate" show-overflow-tooltip>
              <template #default="scope">
                <div class="visit-planned-cell">
                  <span>{{ getVisitPlannedDateLabel(scope.row) }}</span>
                  <span v-if="getVisitWindowRangeLabel(scope.row)" class="visit-window-range">
                    {{ getVisitWindowRangeLabel(scope.row) }}
                  </span>
                </div>
              </template>
            </el-table-column>
            <el-table-column prop="actual_date" :label="TEXT.common.fields.actualDate" show-overflow-tooltip>
              <template #default="scope">
                <el-date-picker
                  v-if="visitEditingRowId === scope.row.id"
                  v-model="visitRowDraft.actual_date"
                  type="date"
                  value-format="YYYY-MM-DD"
                  size="small"
                />
                <span v-else>{{ displayDate(scope.row.actual_date) }}</span>
              </template>
            </el-table-column>
            <el-table-column prop="status" :label="TEXT.common.fields.status">
              <template #default="scope">
                <el-tag
                  :type="getVisitStatusTagType(getVisitStatus(scope.row, visitEditingRowId === scope.row.id ? visitRowDraft.actual_date : undefined))"
                  effect="light"
                >
                  {{ getVisitStatusLabel(scope.row, visitEditingRowId === scope.row.id ? visitRowDraft.actual_date : undefined) }}
                </el-tag>
              </template>
            </el-table-column>
            <el-table-column prop="notes" :label="TEXT.common.fields.notes" show-overflow-tooltip>
              <template #default="scope">
                <el-input
                  v-if="visitEditingRowId === scope.row.id"
                  v-model="visitRowDraft.notes"
                  size="small"
                  type="textarea"
                  :rows="1"
                />
                <span v-else>{{ scope.row.notes || TEXT.common.fallback }}</span>
              </template>
            </el-table-column>
            <el-table-column :label="TEXT.common.labels.actions" width="140">
              <template #default="scope">
                <template v-if="visitEditingRowId === scope.row.id">
                  <el-button link type="primary" size="small" :disabled="isReadOnly" @click="saveVisitRow(scope.row)">
                    {{ TEXT.common.actions.save }}
                  </el-button>
                  <el-button link size="small" :disabled="isReadOnly" @click="cancelVisitRow">
                    {{ TEXT.common.actions.cancel }}
                  </el-button>
                </template>
                <template v-else>
                  <el-button
                    link
                    type="primary"
                    size="small"
                    :disabled="isReadOnly"
                    @click="startVisitRowEdit(scope.row)"
                  >
                    {{ TEXT.common.actions.edit }}
                  </el-button>
                  <el-button
                    link
                    type="danger"
                    size="small"
                    :disabled="isReadOnly"
                    @click="removeVisit(scope.row)"
                  >
                    {{ TEXT.common.actions.delete }}
                  </el-button>
                </template>
              </template>
            </el-table-column>
            <template #empty>
              <div v-if="!loadingVisits" class="table-empty">{{ TEXT.modules.subjectDetail.emptyVisits }}</div>
            </template>
          </el-table>
        </el-tab-pane>

        <el-tab-pane label="用药依从性" name="medicationAdherence">
          <div class="adherence-panel">
            <el-descriptions :column="2" border>
              <el-descriptions-item label="开始用药日期">
                {{ displayDate(medicationStartDate) }}
              </el-descriptions-item>
              <el-descriptions-item label="结束用药日期">
                {{ displayDate(medicationEndDate) }}
              </el-descriptions-item>
              <el-descriptions-item label="结束日期来源">
                {{ medicationEndVisitLabel }}
              </el-descriptions-item>
              <el-descriptions-item label="理论用药次数">
                {{ expectedMedicationCountText }}
              </el-descriptions-item>
              <el-descriptions-item label="实际用药次数">
                <el-input-number
                  v-if="adherenceEditing"
                  v-model="adherenceForm.actual_medication_count"
                  :min="0"
                  :controls="false"
                  size="small"
                  class="adherence-count-input"
                  :disabled="isReadOnly"
                />
                <span v-else>{{ actualMedicationCountText }}</span>
              </el-descriptions-item>
              <el-descriptions-item label="用药依从性">
                <el-tag :type="adherenceRateTagType" effect="light">{{ medicationAdherenceRateText }}</el-tag>
              </el-descriptions-item>
            </el-descriptions>
            <div class="adherence-hint">
              用药依从性 = 实际用药次数 ÷ 理论用药次数 × 100%。实际用药次数为试验期间实际药物暴露次数；理论用药次数 =（结束用药日期 - 开始用药日期 + 1）× 1次/天。试验期间的用药依从性原则上要求在 75%~125% 范围内（包含边界值）。
            </div>
          </div>
        </el-tab-pane>

        <el-tab-pane :label="TEXT.modules.subjectDetail.tabs.ae" name="ae">
          <el-table :data="aeItems" v-loading="loadingAes" style="width: 100%" class="subject-detail-table" table-layout="fixed">
            <el-table-column prop="onset_date" :label="TEXT.common.fields.occurDate" show-overflow-tooltip>
              <template #default="scope">{{ displayDate(scope.row.onset_date) }}</template>
            </el-table-column>
            <el-table-column :label="TEXT.common.fields.aeType">
              <template #default="scope">
                <el-tag size="small" effect="light" :class="getAeTypeClass(scope.row)">
                  {{ getAeTypeLabel(scope.row) }}
                </el-tag>
              </template>
            </el-table-column>
            <el-table-column prop="term" :label="TEXT.common.fields.title" show-overflow-tooltip />
            <el-table-column prop="seriousness" :label="TEXT.common.fields.seriousness">
              <template #default="scope">
                {{ displayEnum(TEXT.enums.aeSeriousness, normalizeSeriousness(scope.row.seriousness)) }}
              </template>
            </el-table-column>
            <el-table-column prop="causality" :label="TEXT.common.fields.causality">
              <template #default="scope">{{ displayText(scope.row.causality, TEXT.enums.aeCausality) }}</template>
            </el-table-column>
            <el-table-column prop="outcome" :label="TEXT.common.fields.outcome">
              <template #default="scope">{{ displayText(scope.row.outcome, TEXT.enums.aeOutcome) }}</template>
            </el-table-column>
            <el-table-column prop="description" :label="TEXT.common.fields.remark" show-overflow-tooltip />
            <el-table-column :label="TEXT.common.labels.actions" width="140">
              <template #default="scope">
                <el-button
                  link
                  type="primary"
                  size="small"
                  :disabled="isReadOnly"
                  @click="openAeDialog(scope.row)"
                >
                  {{ TEXT.common.actions.edit }}
                </el-button>
                <el-button
                  link
                  type="danger"
                  size="small"
                  :disabled="isReadOnly"
                  @click="removeAe(scope.row)"
                >
                  {{ TEXT.common.actions.delete }}
                </el-button>
              </template>
            </el-table-column>
            <template #empty>
              <div v-if="!loadingAes" class="table-empty">{{ TEXT.modules.subjectDetail.emptyAe }}</div>
            </template>
          </el-table>
        </el-tab-pane>

        <el-tab-pane :label="TEXT.modules.subjectDetail.tabs.pd" name="pd">
          <el-table :data="pdItems" v-loading="loadingPds" style="width: 100%" class="subject-detail-table" table-layout="fixed">
            <el-table-column prop="pd_no" :label="TEXT.common.fields.pdNo" show-overflow-tooltip />
            <el-table-column prop="pd_type" :label="TEXT.common.fields.pdType" show-overflow-tooltip />
            <el-table-column prop="pd_level" :label="TEXT.common.fields.pdLevel">
              <template #default="scope">{{ displayEnum(TEXT.enums.pdLevel, scope.row.pd_level) }}</template>
            </el-table-column>
            <el-table-column prop="description" :label="TEXT.common.fields.pdDescription" show-overflow-tooltip>
              <template #default="scope">{{ scope.row.description || TEXT.common.fallback }}</template>
            </el-table-column>
            <el-table-column prop="status" :label="TEXT.common.fields.status">
              <template #default="scope">{{ displayEnum(TEXT.enums.pdStatus, scope.row.status) }}</template>
            </el-table-column>
            <el-table-column :label="TEXT.common.labels.actions" width="140">
              <template #default="scope">
                <el-button
                  link
                  type="primary"
                  size="small"
                  :disabled="isReadOnly"
                  @click="openPdDialog(scope.row)"
                >
                  {{ TEXT.common.actions.edit }}
                </el-button>
                <el-button
                  link
                  type="danger"
                  size="small"
                  :disabled="isReadOnly"
                  @click="removePd(scope.row)"
                >
                  {{ TEXT.common.actions.delete }}
                </el-button>
              </template>
            </el-table-column>
            <template #empty>
              <div v-if="!loadingPds" class="table-empty">{{ TEXT.modules.subjectDetail.emptyPd }}</div>
            </template>
          </el-table>
        </el-tab-pane>
      </el-tabs>
    </el-card>

    <el-dialog v-if="historyDialogVisible" append-to=".layout-main .content-wrapper" v-model="historyDialogVisible" :title="TEXT.modules.subjectDetail.dialogHistory" width="520px">
      <el-form :model="historyForm" label-width="90px">
        <el-form-item :label="TEXT.common.fields.recordDate">
          <el-date-picker v-model="historyForm.record_date" type="date" value-format="YYYY-MM-DD" />
        </el-form-item>
        <el-form-item :label="TEXT.common.fields.content" required>
          <el-input v-model="historyForm.content" type="textarea" :rows="3" />
        </el-form-item>
      </el-form>
      <template #footer>
        <el-button @click="historyDialogVisible = false">{{ TEXT.common.actions.cancel }}</el-button>
        <el-button type="primary" :disabled="isReadOnly" @click="saveHistory">{{ TEXT.common.actions.save }}</el-button>
      </template>
    </el-dialog>

    <el-dialog v-if="visitDialogVisible" append-to=".layout-main .content-wrapper" v-model="visitDialogVisible" :title="TEXT.modules.subjectDetail.dialogVisit" width="560px">
      <el-form :model="visitForm" label-width="100px">
        <template v-if="!visitEditingId">
          <el-form-item :label="TEXT.common.fields.visitCode" required>
            <el-input v-model="visitForm.visit_code" disabled />
          </el-form-item>
          <el-form-item :label="TEXT.common.fields.plannedDate" :required="isFirstVisit">
            <el-date-picker v-model="visitForm.planned_date" type="date" value-format="YYYY-MM-DD" />
          </el-form-item>
          <el-form-item :label="TEXT.common.fields.windowStart">
            <el-date-picker v-model="visitForm.window_start" type="date" value-format="YYYY-MM-DD" />
          </el-form-item>
          <el-form-item :label="TEXT.common.fields.windowEnd">
            <el-date-picker v-model="visitForm.window_end" type="date" value-format="YYYY-MM-DD" />
          </el-form-item>
        </template>
        <template v-else>
          <el-form-item :label="TEXT.common.fields.actualDate">
            <el-date-picker v-model="visitForm.actual_date" type="date" value-format="YYYY-MM-DD" />
          </el-form-item>
          <el-form-item :label="TEXT.common.fields.remark">
            <el-input v-model="visitForm.notes" type="textarea" :rows="3" />
          </el-form-item>
        </template>
      </el-form>
      <template #footer>
        <el-button @click="visitDialogVisible = false">{{ TEXT.common.actions.cancel }}</el-button>
        <el-button type="primary" :disabled="isReadOnly" @click="saveVisit">{{ TEXT.common.actions.save }}</el-button>
      </template>
    </el-dialog>

    <el-dialog
      v-if="earlyTerminationDialogVisible"
      append-to=".layout-main .content-wrapper"
      v-model="earlyTerminationDialogVisible"
      title="提前终止"
      width="560px"
    >
      <el-form :model="earlyTerminationForm" label-width="110px">
        <el-form-item label="提前终止日期" required>
          <el-date-picker v-model="earlyTerminationForm.termination_date" type="date" value-format="YYYY-MM-DD" />
        </el-form-item>
        <el-form-item label="提前终止原因" required>
          <el-input v-model="earlyTerminationForm.reason" type="textarea" :rows="2" />
        </el-form-item>
        <el-form-item :label="TEXT.common.fields.remark">
          <el-input v-model="earlyTerminationForm.notes" type="textarea" :rows="3" />
        </el-form-item>
      </el-form>
      <div class="early-termination-hint">
        提前终止表示受试者在方案最后一个计划访视窗口期前停止治疗；日期进入最后访视窗口期后，应录入正常终止治疗访视。
      </div>
      <template #footer>
        <el-button @click="earlyTerminationDialogVisible = false">{{ TEXT.common.actions.cancel }}</el-button>
        <el-button type="primary" :loading="earlyTerminationSaving" :disabled="isReadOnly" @click="saveEarlyTermination">
          {{ TEXT.common.actions.save }}
        </el-button>
      </template>
    </el-dialog>

    <el-dialog v-if="aeDialogVisible" append-to=".layout-main .content-wrapper" v-model="aeDialogVisible" :title="TEXT.modules.subjectDetail.dialogAe" width="560px">
      <el-form :model="aeForm" label-width="100px">
        <el-form-item :label="TEXT.common.fields.title" required>
          <el-input v-model="aeForm.term" />
        </el-form-item>
        <el-form-item :label="TEXT.common.fields.occurDate">
          <el-date-picker v-model="aeForm.onset_date" type="date" value-format="YYYY-MM-DD" />
        </el-form-item>
        <el-form-item :label="TEXT.common.fields.seriousness" required>
          <el-select v-model="aeForm.seriousness">
            <el-option v-for="option in aeSeriousnessOptions" :key="option.value" :label="option.label" :value="option.value" />
          </el-select>
        </el-form-item>
        <el-form-item :label="TEXT.common.fields.isSae">
          <el-switch v-model="aeForm.is_sae" @change="onSaeChanged" />
        </el-form-item>
        <el-form-item :label="TEXT.common.fields.isSusar">
          <el-switch v-model="aeForm.is_susar" @change="onSusarChanged" />
        </el-form-item>
        <el-form-item :label="TEXT.common.fields.causality">
          <el-select v-model="aeForm.causality" clearable>
            <el-option v-for="option in aeCausalityOptions" :key="option.value" :label="option.label" :value="option.value" />
          </el-select>
        </el-form-item>
        <el-form-item :label="TEXT.common.fields.outcome">
          <el-select v-model="aeForm.outcome" clearable>
            <el-option v-for="option in aeOutcomeOptions" :key="option.value" :label="option.label" :value="option.value" />
          </el-select>
        </el-form-item>
        <el-form-item :label="TEXT.common.fields.remark">
          <el-input v-model="aeForm.description" type="textarea" :rows="3" />
        </el-form-item>
      </el-form>
      <template #footer>
        <el-button @click="aeDialogVisible = false">{{ TEXT.common.actions.cancel }}</el-button>
        <el-button type="primary" :disabled="isReadOnly" @click="saveAe">{{ TEXT.common.actions.save }}</el-button>
      </template>
    </el-dialog>

    <el-dialog v-if="pdDialogVisible" append-to=".layout-main .content-wrapper" v-model="pdDialogVisible" :title="TEXT.modules.subjectDetail.dialogPd" width="560px">
      <el-form :model="pdForm" label-width="100px">
        <el-form-item :label="TEXT.common.fields.pdNo">
          <el-input v-model="pdForm.pd_no" disabled :placeholder="TEXT.modules.subjectDetail.pdNoAuto" />
        </el-form-item>
        <el-form-item :label="TEXT.common.fields.pdType" required>
          <el-select v-model="pdForm.pd_type" filterable allow-create default-first-option clearable>
            <el-option v-for="item in pdTypeOptions" :key="item" :label="item" :value="item" />
          </el-select>
        </el-form-item>
        <el-form-item :label="TEXT.common.fields.pdLevel" required>
          <el-select v-model="pdForm.pd_level">
            <el-option v-for="option in pdLevelOptions" :key="option.value" :label="option.label" :value="option.value" />
          </el-select>
        </el-form-item>
        <el-form-item :label="TEXT.common.fields.status" required>
          <el-select v-model="pdForm.status">
            <el-option v-for="option in pdStatusOptions" :key="option.value" :label="option.label" :value="option.value" />
          </el-select>
        </el-form-item>
        <el-form-item :label="TEXT.common.fields.pdDescription">
          <el-input v-model="pdForm.description" type="textarea" :rows="3" />
        </el-form-item>
      </el-form>
      <template #footer>
        <el-button @click="pdDialogVisible = false">{{ TEXT.common.actions.cancel }}</el-button>
        <el-button type="primary" :disabled="isReadOnly" @click="savePd">{{ TEXT.common.actions.save }}</el-button>
      </template>
    </el-dialog>
  </div>
</template>

<script setup lang="ts">
import { computed, onMounted, reactive, ref, watch } from "vue";
import { useRoute, useRouter } from "vue-router";
import { ElMessage, ElMessageBox } from "element-plus";
import { useStudyStore } from "../../store/study";
import { getSubject, updateSubject } from "../../api/subjects";
import { fetchSites } from "../../api/sites";
import { listSubjectHistories, createSubjectHistory, updateSubjectHistory, deleteSubjectHistory } from "../../api/subjectHistories";
import { fetchVisits, createEarlyTerminationVisit, createVisit, updateVisit, deleteVisit } from "../../api/visits";
import { fetchAes, createAe, updateAe, deleteAe } from "../../api/aes";
import { listSubjectPds, createSubjectPd, updateSubjectPd, deleteSubjectPd } from "../../api/subjectPds";
import { displayDate, displayEnum, displayText } from "../../utils/display";
import { TEXT } from "../../locales";

const route = useRoute();
const router = useRouter();
const study = useStudyStore();
const subjectId = route.params.subjectId as string;
const studyId = study.currentStudy?.id || "";
const resolveTabFromQuery = () => {
  const tab = typeof route.query.tab === "string" ? route.query.tab : "";
  return ["history", "visits", "medicationAdherence", "ae", "pd"].includes(tab) ? tab : "history";
};

const loading = ref(false);
const detail = reactive<any>({
  subject_no: "",
  site_id: "",
  status: "",
  screening_date: "",
  consent_date: "",
  enrollment_date: "",
  baseline_date: "",
  completion_date: "",
  actual_medication_count: null as number | null,
  drop_reason: "",
});

const subjectEditing = ref(false);
const subjectSaving = ref(false);
const subjectForm = reactive({
  enrollment_date: "",
  baseline_date: "",
  consent_date: "",
  completion_date: "",
  drop_reason: "",
});

const siteMap = ref<Record<string, string>>({});
const siteActiveMap = ref<Record<string, boolean>>({});
const isReadOnly = computed(() => !!detail.site_id && siteActiveMap.value[detail.site_id] === false);
const activeTab = ref(resolveTabFromQuery());

const historyItems = ref<any[]>([]);
const loadingHistory = ref(false);
const historyDialogVisible = ref(false);
const historyEditingId = ref<string | null>(null);
const historyForm = reactive({
  record_date: "",
  content: "",
});

const visitItems = ref<any[]>([]);
const loadingVisits = ref(false);
const visitDialogVisible = ref(false);
const earlyTerminationDialogVisible = ref(false);
const earlyTerminationSaving = ref(false);
const visitEditingId = ref<string | null>(null);
const visitEditingRowId = ref<string | null>(null);
const visitRowDraft = reactive({
  actual_date: "",
  notes: "",
});
const visitForm = reactive<any>({
  visit_code: "",
  planned_date: "",
  window_start: "",
  window_end: "",
  actual_date: "",
  notes: "",
});
const earlyTerminationForm = reactive({
  termination_date: "",
  reason: "",
  notes: "",
});
const isFirstVisit = computed(() => visitForm.visit_code === "V1");
const adherenceEditing = ref(false);
const adherenceSaving = ref(false);
const adherenceForm = reactive({
  actual_medication_count: null as number | null,
});

const aeItems = ref<any[]>([]);
const loadingAes = ref(false);
const aeDialogVisible = ref(false);
const aeEditingId = ref<string | null>(null);
const aeCausalityOptions = [
  { value: "肯定有关", label: TEXT.enums.aeCausality["肯定有关"] },
  { value: "很可能有关", label: TEXT.enums.aeCausality["很可能有关"] },
  { value: "可能有关", label: TEXT.enums.aeCausality["可能有关"] },
  { value: "可能无关", label: TEXT.enums.aeCausality["可能无关"] },
  { value: "无关", label: TEXT.enums.aeCausality["无关"] },
  { value: "待评估", label: TEXT.enums.aeCausality["待评估"] },
];
const aeOutcomeOptions = [
  { value: "痊愈", label: TEXT.enums.aeOutcome["痊愈"] },
  { value: "好转", label: TEXT.enums.aeOutcome["好转"] },
  { value: "持续", label: TEXT.enums.aeOutcome["持续"] },
  { value: "恶化", label: TEXT.enums.aeOutcome["恶化"] },
  { value: "死亡", label: TEXT.enums.aeOutcome["死亡"] },
  { value: "失访", label: TEXT.enums.aeOutcome["失访"] },
];
const aeForm = reactive({
  term: "",
  onset_date: "",
  seriousness: "I",
  is_sae: false,
  is_susar: false,
  causality: "",
  outcome: "",
  description: "",
});
const aeSeriousnessOptions = [
  { value: "I", label: TEXT.enums.aeSeriousness.I },
  { value: "II", label: TEXT.enums.aeSeriousness.II },
  { value: "III", label: TEXT.enums.aeSeriousness.III },
  { value: "IV", label: TEXT.enums.aeSeriousness.IV },
  { value: "V", label: TEXT.enums.aeSeriousness.V },
];

const pdItems = ref<any[]>([]);
const loadingPds = ref(false);
const pdDialogVisible = ref(false);
const pdEditingId = ref<string | null>(null);
const pdTypeOptions = ["知情同意", "排除标准", "药物使用", "入排标准", "访视流程", "检验检查", "其他"];
const pdLevelOptions = Object.entries(TEXT.enums.pdLevel).map(([value, label]) => ({ value, label }));
const pdStatusOptions = Object.entries(TEXT.enums.pdStatus).map(([value, label]) => ({ value, label }));
const pdForm = reactive({
  pd_no: "",
  pd_type: "",
  pd_level: "GENERAL",
  description: "",
  status: "OPEN",
});

const normalizeSeriousness = (value?: string | null) => {
  if (!value) return "I";
  const normalized = String(value).trim().toUpperCase();
  const digitMap: Record<string, string> = {
    "1": "I",
    "2": "II",
    "3": "III",
    "4": "IV",
    "5": "V",
  };
  const legacyMap: Record<string, string> = {
    SERIOUS: "IV",
    NON_SERIOUS: "II",
  };
  if (digitMap[normalized]) return digitMap[normalized];
  if (legacyMap[normalized]) return legacyMap[normalized];
  if (["I", "II", "III", "IV", "V"].includes(normalized)) return normalized;
  return "I";
};

const getErrorMessage = (error: any, fallback: string) => {
  const detail = error?.response?.data?.detail;
  if (typeof error?.response?.data?.message === "string") return error.response.data.message;
  if (typeof detail === "string") return detail;
  if (typeof detail?.message === "string") return detail.message;
  return fallback;
};

const loadSites = async () => {
  if (!studyId) return;
  try {
    const { data } = await fetchSites(studyId, { limit: 500 });
    const list = Array.isArray(data) ? data : data.items || [];
    siteMap.value = list.reduce((acc: Record<string, string>, site: any) => {
      acc[site.id] = site.name;
      return acc;
    }, {});
    siteActiveMap.value = list.reduce((acc: Record<string, boolean>, site: any) => {
      acc[site.id] = !!site.is_active;
      return acc;
    }, {});
  } catch {
    siteMap.value = {};
    siteActiveMap.value = {};
  }
};

const loadSubject = async () => {
  if (!studyId || !subjectId) return;
  loading.value = true;
  try {
    const { data } = await getSubject(studyId, subjectId);
    Object.assign(detail, data);
  } catch (e: any) {
    ElMessage.error(e?.response?.data?.message || TEXT.common.messages.loadFailed);
  } finally {
    loading.value = false;
  }
};

const startSubjectEdit = () => {
  if (isReadOnly.value) {
    ElMessage.warning("中心已停用");
    return;
  }
  subjectForm.consent_date = detail.consent_date || "";
  subjectForm.enrollment_date = detail.enrollment_date || "";
  subjectForm.baseline_date = detail.baseline_date || "";
  subjectForm.completion_date = detail.completion_date || "";
  subjectForm.drop_reason = detail.drop_reason || "";
  subjectEditing.value = true;
};

const cancelSubjectEdit = () => {
  subjectEditing.value = false;
};

const saveSubjectEdit = async () => {
  if (isReadOnly.value) {
    ElMessage.warning("中心已停用");
    return;
  }
  if (!studyId || !subjectId) return;
  subjectSaving.value = true;
  try {
    const payload = {
      consent_date: subjectForm.consent_date || null,
      enrollment_date: subjectForm.enrollment_date || null,
      baseline_date: subjectForm.baseline_date || null,
      completion_date: subjectForm.completion_date || null,
      drop_reason: subjectForm.drop_reason || null,
    };
    await updateSubject(studyId, subjectId, payload);
    ElMessage.success(TEXT.common.messages.saveSuccess);
    subjectEditing.value = false;
    await loadSubject();
    await loadVisits();
  } catch (e: any) {
    ElMessage.error(e?.response?.data?.message || TEXT.common.messages.saveFailed);
  } finally {
    subjectSaving.value = false;
  }
};

const loadHistories = async () => {
  if (!studyId || !subjectId) return;
  loadingHistory.value = true;
  try {
    const { data } = (await listSubjectHistories(studyId, subjectId)) as any;
    historyItems.value = Array.isArray(data) ? data : data.items || [];
  } catch (e: any) {
    ElMessage.error(e?.response?.data?.message || TEXT.common.messages.loadFailed);
  } finally {
    loadingHistory.value = false;
  }
};

const openHistoryDialog = (row?: any) => {
  if (isReadOnly.value) {
    ElMessage.warning("中心已停用");
    return;
  }
  historyEditingId.value = row?.id || null;
  historyForm.record_date = row?.record_date || "";
  historyForm.content = row?.content || "";
  historyDialogVisible.value = true;
};

const saveHistory = async () => {
  if (isReadOnly.value) {
    ElMessage.warning("中心已停用");
    return;
  }
  if (!studyId || !subjectId) return;
  try {
    const payload = {
      subject_id: subjectId,
      record_date: historyForm.record_date || null,
      content: historyForm.content,
    };
    if (historyEditingId.value) {
      await updateSubjectHistory(studyId, subjectId, historyEditingId.value, payload);
    } else {
      await createSubjectHistory(studyId, subjectId, payload);
    }
    historyDialogVisible.value = false;
    loadHistories();
  } catch (e: any) {
    ElMessage.error(e?.response?.data?.message || TEXT.common.messages.saveFailed);
  }
};

const removeHistory = async (row: any) => {
  if (isReadOnly.value) {
    ElMessage.warning("中心已停用");
    return;
  }
  if (!studyId || !subjectId) return;
  const ok = await ElMessageBox.confirm(TEXT.common.confirm.delete, TEXT.common.labels.tips).catch(() => null);
  if (!ok) return;
  try {
    await deleteSubjectHistory(studyId, subjectId, row.id);
    loadHistories();
  } catch (e: any) {
    ElMessage.error(e?.response?.data?.message || TEXT.common.messages.deleteFailed);
  }
};

const loadVisits = async () => {
  if (!studyId || !subjectId) return;
  loadingVisits.value = true;
  try {
    const { data } = (await fetchVisits(studyId, subjectId)) as any;
    const items = Array.isArray(data) ? data : data.items || [];
    visitItems.value = items;
  } catch (e: any) {
    ElMessage.error(e?.response?.data?.message || TEXT.common.messages.loadFailed);
  } finally {
    loadingVisits.value = false;
  }
};

const getNextVisitCode = () => {
  const used = new Set<number>();
  visitItems.value.forEach((item) => {
    const code = String(item?.visit_code || "");
    if (!code.startsWith("V")) return;
    const num = Number(code.slice(1));
    if (Number.isFinite(num) && num > 0) {
      used.add(num);
    }
  });
  let next = 1;
  while (used.has(next)) next += 1;
  return `V${next}`;
};

const openVisitDialog = (row?: any) => {
  if (isReadOnly.value) {
    ElMessage.warning("中心已停用");
    return;
  }
  visitEditingId.value = row?.id || null;
  if (row) {
    visitForm.actual_date = row.actual_date || "";
    visitForm.notes = row.notes || "";
  } else {
    visitForm.visit_code = getNextVisitCode();
    visitForm.planned_date = "";
    visitForm.window_start = "";
    visitForm.window_end = "";
    visitForm.actual_date = "";
    visitForm.notes = "";
  }
  visitDialogVisible.value = true;
};

const openEarlyTerminationDialog = () => {
  if (isReadOnly.value) {
    ElMessage.warning("中心已停用");
    return;
  }
  earlyTerminationForm.termination_date = "";
  earlyTerminationForm.reason = "";
  earlyTerminationForm.notes = "";
  earlyTerminationDialogVisible.value = true;
};

const startVisitRowEdit = (row: any) => {
  if (isReadOnly.value) {
    ElMessage.warning("中心已停用");
    return;
  }
  visitEditingRowId.value = row?.id || null;
  visitRowDraft.actual_date = row?.actual_date || "";
  visitRowDraft.notes = row?.notes || "";
};

const cancelVisitRow = () => {
  visitEditingRowId.value = null;
};

const saveVisitRow = async (row: any) => {
  if (isReadOnly.value) {
    ElMessage.warning("中心已停用");
    return;
  }
  if (!studyId || !subjectId || !row?.id) return;
  try {
    const payload = {
      actual_date: visitRowDraft.actual_date || null,
      notes: visitRowDraft.notes || null,
    };
    await updateVisit(studyId, subjectId, row.id, payload);
    visitEditingRowId.value = null;
    loadVisits();
  } catch (e: any) {
    ElMessage.error(e?.response?.data?.message || TEXT.common.messages.saveFailed);
  }
};

const parseDate = (value?: string | null) => {
  if (!value) return null;
  const date = new Date(value);
  if (isNaN(date.getTime())) return null;
  return date;
};

const parseDateAtNoon = (value?: string | null) => {
  if (!value) return null;
  const date = new Date(`${value}T12:00:00`);
  if (isNaN(date.getTime())) return null;
  return date;
};

const getVisitWindowStartDateText = (row: any) => row?.window_start || row?.planned_date || "";

const getVisitPlannedDateLabel = (row: any) => {
  if (String(row?.visit_code || "").trim() === "提前终止") return "不适用";
  return displayDate(row?.planned_date);
};

const getVisitWindowRangeLabel = (row: any) => {
  if (String(row?.visit_code || "").trim() === "提前终止") return "";
  if (!row?.window_start || !row?.window_end) return "";
  if (row.window_start === row.planned_date && row.window_end === row.planned_date) return "";
  return `${displayDate(row.window_start)} ～ ${displayDate(row.window_end)}`;
};

const lastPlannedVisitWindowStartText = computed(() => {
  const excludedCodes = new Set(["筛选访视", "基线访视", "提前终止"]);
  const candidates = visitItems.value
    .filter((item) => !excludedCodes.has(String(item?.visit_code || "").trim()))
    .map((item) => getVisitWindowStartDateText(item))
    .filter(Boolean)
    .sort();
  return candidates[candidates.length - 1] || "";
});

const validateEarlyTerminationDateInput = () => {
  const boundary = lastPlannedVisitWindowStartText.value;
  if (!boundary || !earlyTerminationForm.termination_date) return true;
  if (earlyTerminationForm.termination_date >= boundary) {
    ElMessage.error(`提前终止日期必须早于最后计划访视窗口期开始日（${boundary}）`);
    return false;
  }
  return true;
};

const formatCount = (value: number | null | undefined) => (value === null || value === undefined ? TEXT.common.fallback : String(value));
const medicationStartDate = computed(() => detail.baseline_date || "");
const medicationEndVisit = computed(() => {
  const targetLabels = new Set(["终止治疗", "提前终止"]);
  return (
    visitItems.value.find((item) => targetLabels.has(String(item?.visit_code || "").trim()) && item?.actual_date) || null
  );
});
const medicationEndDate = computed(() => medicationEndVisit.value?.actual_date || "");
const medicationEndVisitLabel = computed(() => medicationEndVisit.value?.visit_code || "未记录终止治疗/提前终止实际日期");
const expectedMedicationCount = computed(() => {
  const start = parseDateAtNoon(medicationStartDate.value);
  const end = parseDateAtNoon(medicationEndDate.value);
  if (!start || !end || end < start) return null;
  return Math.floor((end.getTime() - start.getTime()) / 86400000) + 1;
});
const expectedMedicationCountText = computed(() => formatCount(expectedMedicationCount.value));
const actualMedicationCount = computed(() => detail.actual_medication_count ?? null);
const actualMedicationCountText = computed(() => formatCount(actualMedicationCount.value));
const medicationAdherenceRate = computed(() => {
  const expected = expectedMedicationCount.value;
  const actual = actualMedicationCount.value;
  if (!expected || actual === null || actual === undefined) return null;
  return (actual / expected) * 100;
});
const medicationAdherenceRateText = computed(() => {
  const rate = medicationAdherenceRate.value;
  if (rate === null) return "无法计算";
  return `${rate.toFixed(1)}%`;
});
const adherenceRateTagType = computed(() => {
  const rate = medicationAdherenceRate.value;
  if (rate === null) return "info";
  if (rate < 75 || rate > 125) return "danger";
  return "success";
});

const getVisitStatus = (row: any, actualDateOverride?: string) => {
  if (row?.status === "CANCELLED") return "CANCELLED";
  const actualDate = parseDate(actualDateOverride ?? row?.actual_date);
  const windowStart = parseDate(row?.window_start);
  const windowEnd = parseDate(row?.window_end);
  const plannedDate = parseDate(row?.planned_date);

  if (actualDate) {
    if ((windowStart && actualDate < windowStart) || (windowEnd && actualDate > windowEnd)) {
      return "OVERDUE";
    }
    return "DONE";
  }

  const today = new Date();
  const deadline = windowEnd || plannedDate;
  if (deadline && today > deadline) {
    return "LOST";
  }
  return "PLANNED";
};

const getVisitStatusTagType = (status: string) => {
  switch (status) {
    case "DONE":
      return "success";
    case "OVERDUE":
      return "warning";
    case "LOST":
      return "danger";
    case "CANCELLED":
      return "info";
    default:
      return "info";
  }
};

const getVisitStatusLabel = (row: any, actualDateOverride?: string) => {
  const status = getVisitStatus(row, actualDateOverride);
  if (status === "CANCELLED" && String(row?.notes || "").includes("提前终止")) {
    return "不适用";
  }
  return displayEnum(TEXT.enums.visitStatus, status);
};

const getAeTypeKey = (row: any) => {
  if (row?.is_susar) return "susar";
  if (row?.is_sae) return "sae";
  return "ae";
};

const getAeTypeLabel = (row: any) => TEXT.modules.subjectDetail.aeType[getAeTypeKey(row)];

const getAeTypeClass = (row: any) => `ae-type-tag ae-type-${getAeTypeKey(row)}`;

const onSaeChanged = (value: boolean) => {
  if (!value) {
    aeForm.is_susar = false;
  }
};

const onSusarChanged = (value: boolean) => {
  if (value) {
    aeForm.is_sae = true;
  }
};

const saveVisit = async () => {
  if (isReadOnly.value) {
    ElMessage.warning("中心已停用");
    return;
  }
  if (!studyId || !subjectId) return;
  try {
    if (visitEditingId.value) {
      const payload = {
        actual_date: visitForm.actual_date || null,
        notes: visitForm.notes || null,
      };
      await updateVisit(studyId, subjectId, visitEditingId.value, payload);
    } else {
      if (visitForm.visit_code === "V1" && !visitForm.planned_date) {
        ElMessage.error("首次新增访视必须填写计划访视日期");
        return;
      }
      const payload = {
        subject_id: subjectId,
        visit_code: visitForm.visit_code,
        planned_date: visitForm.planned_date || null,
        window_start: visitForm.window_start || null,
        window_end: visitForm.window_end || null,
      };
      await createVisit(studyId, subjectId, payload);
    }
    visitDialogVisible.value = false;
    loadVisits();
  } catch (e: any) {
    ElMessage.error(e?.response?.data?.message || TEXT.common.messages.saveFailed);
  }
};

const saveEarlyTermination = async () => {
  if (isReadOnly.value) {
    ElMessage.warning("中心已停用");
    return;
  }
  if (!studyId || !subjectId) return;
  if (!earlyTerminationForm.termination_date) {
    ElMessage.error("请填写提前终止日期");
    return;
  }
  if (!earlyTerminationForm.reason.trim()) {
    ElMessage.error("请填写提前终止原因");
    return;
  }
  if (!validateEarlyTerminationDateInput()) return;
  earlyTerminationSaving.value = true;
  try {
    await createEarlyTerminationVisit(studyId, subjectId, {
      termination_date: earlyTerminationForm.termination_date,
      reason: earlyTerminationForm.reason.trim(),
      notes: earlyTerminationForm.notes || null,
    }, {
      suppressErrorMessage: true,
    });
    earlyTerminationDialogVisible.value = false;
    ElMessage.success(TEXT.common.messages.saveSuccess);
  } catch (e: any) {
    ElMessage.error(getErrorMessage(e, TEXT.common.messages.saveFailed));
    earlyTerminationSaving.value = false;
    return;
  }
  try {
    await Promise.all([loadSubject(), loadVisits()]);
  } catch {
    ElMessage.warning("提前终止已保存，刷新数据失败，请手动刷新页面");
  } finally {
    earlyTerminationSaving.value = false;
  }
};

const removeVisit = async (row: any) => {
  if (isReadOnly.value) {
    ElMessage.warning("中心已停用");
    return;
  }
  if (!studyId || !subjectId) return;
  const ok = await ElMessageBox.confirm(TEXT.common.confirm.delete, TEXT.common.labels.tips).catch(() => null);
  if (!ok) return;
  try {
    await deleteVisit(studyId, subjectId, row.id);
    loadVisits();
  } catch (e: any) {
    ElMessage.error(e?.response?.data?.message || TEXT.common.messages.deleteFailed);
  }
};

const loadAes = async () => {
  if (!studyId || !subjectId) return;
  loadingAes.value = true;
  try {
    const { data } = (await fetchAes(studyId, { subject_id: subjectId })) as any;
    aeItems.value = Array.isArray(data) ? data : data.items || [];
  } catch (e: any) {
    ElMessage.error(e?.response?.data?.message || TEXT.common.messages.loadFailed);
  } finally {
    loadingAes.value = false;
  }
};

const openAeDialog = (row?: any) => {
  if (isReadOnly.value) {
    ElMessage.warning("中心已停用");
    return;
  }
  aeEditingId.value = row?.id || null;
  Object.assign(aeForm, {
    term: row?.term || "",
    onset_date: row?.onset_date || "",
    seriousness: normalizeSeriousness(row?.seriousness),
    is_sae: !!row?.is_sae || !!row?.is_susar,
    is_susar: !!row?.is_susar,
    causality: row?.causality || "",
    outcome: row?.outcome || "",
    description: row?.description || "",
  });
  aeDialogVisible.value = true;
};

const saveAe = async () => {
  if (isReadOnly.value) {
    ElMessage.warning("中心已停用");
    return;
  }
  if (!studyId || !subjectId) return;
  try {
    const payload = {
      subject_id: subjectId,
      site_id: detail.site_id || null,
      term: aeForm.term,
      onset_date: aeForm.onset_date || null,
      seriousness: aeForm.seriousness,
      is_sae: !!aeForm.is_sae || !!aeForm.is_susar,
      is_susar: !!aeForm.is_susar,
      causality: aeForm.causality || null,
      outcome: aeForm.outcome || null,
      description: aeForm.description || null,
    };
    if (aeEditingId.value) {
      await updateAe(studyId, aeEditingId.value, payload);
    } else {
      await createAe(studyId, payload);
    }
    aeDialogVisible.value = false;
    loadAes();
  } catch (e: any) {
    ElMessage.error(e?.response?.data?.message || TEXT.common.messages.saveFailed);
  }
};

const removeAe = async (row: any) => {
  if (isReadOnly.value) {
    ElMessage.warning("中心已停用");
    return;
  }
  if (!studyId) return;
  const ok = await ElMessageBox.confirm(TEXT.common.confirm.delete, TEXT.common.labels.tips).catch(() => null);
  if (!ok) return;
  try {
    await deleteAe(studyId, row.id);
    loadAes();
  } catch (e: any) {
    ElMessage.error(e?.response?.data?.message || TEXT.common.messages.deleteFailed);
  }
};

const loadPds = async () => {
  if (!studyId || !subjectId) return;
  loadingPds.value = true;
  try {
    const { data } = (await listSubjectPds(studyId, subjectId)) as any;
    const list = Array.isArray(data) ? data : data.items || [];
    const getPdSeq = (pdNo: string) => {
      const text = String(pdNo || "");
      const matched = text.match(/^PD(\d+)$/i);
      if (!matched) return Number.POSITIVE_INFINITY;
      const num = Number(matched[1]);
      return Number.isFinite(num) ? num : Number.POSITIVE_INFINITY;
    };
    pdItems.value = list.sort((a: any, b: any) => getPdSeq(a?.pd_no) - getPdSeq(b?.pd_no));
  } catch (e: any) {
    ElMessage.error(e?.response?.data?.message || TEXT.common.messages.loadFailed);
  } finally {
    loadingPds.value = false;
  }
};

const openPdDialog = (row?: any) => {
  if (isReadOnly.value) {
    ElMessage.warning("中心已停用");
    return;
  }
  pdEditingId.value = row?.id || null;
  Object.assign(pdForm, {
    pd_no: row?.pd_no || "",
    pd_type: row?.pd_type || "",
    pd_level: row?.pd_level || "GENERAL",
    description: row?.description || "",
    status: row?.status || "OPEN",
  });
  pdDialogVisible.value = true;
};

const currentTabAction = computed(() => {
  switch (activeTab.value) {
    case "visits":
      return { label: TEXT.common.actions.newVisit, onClick: () => openVisitDialog() };
    case "medicationAdherence":
      if (adherenceEditing.value) {
        return { label: "保存用药次数", loading: adherenceSaving.value, onClick: () => saveMedicationAdherence() };
      }
      return { label: "编辑", loading: false, onClick: () => startMedicationAdherenceEdit() };
    case "ae":
      return { label: TEXT.common.actions.newAe, onClick: () => openAeDialog() };
    case "pd":
      return { label: TEXT.modules.subjectDetail.newPd, onClick: () => openPdDialog() };
    case "history":
    default:
      return { label: TEXT.common.actions.newHistory, onClick: () => openHistoryDialog() };
  }
});

const startMedicationAdherenceEdit = () => {
  if (isReadOnly.value) {
    ElMessage.warning("中心已停用");
    return;
  }
  adherenceForm.actual_medication_count = detail.actual_medication_count ?? null;
  adherenceEditing.value = true;
};

const saveMedicationAdherence = async () => {
  if (isReadOnly.value) {
    ElMessage.warning("中心已停用");
    return;
  }
  if (!studyId || !subjectId) return;
  adherenceSaving.value = true;
  try {
    await updateSubject(studyId, subjectId, {
      actual_medication_count: adherenceForm.actual_medication_count ?? null,
    });
    adherenceEditing.value = false;
    ElMessage.success(TEXT.common.messages.saveSuccess);
    await loadSubject();
  } catch (e: any) {
    ElMessage.error(e?.response?.data?.message || TEXT.common.messages.saveFailed);
  } finally {
    adherenceSaving.value = false;
  }
};

const savePd = async () => {
  if (isReadOnly.value) {
    ElMessage.warning("中心已停用");
    return;
  }
  if (!studyId || !subjectId) return;
  if (!pdForm.pd_type?.trim()) {
    ElMessage.error(TEXT.common.messages.required);
    return;
  }
  try {
    const basePayload = {
      pd_type: pdForm.pd_type.trim(),
      pd_level: pdForm.pd_level,
      description: pdForm.description?.trim() || null,
      status: pdForm.status,
    };
    if (pdEditingId.value) {
      await updateSubjectPd(studyId, subjectId, pdEditingId.value, basePayload);
    } else {
      await createSubjectPd(studyId, subjectId, { subject_id: subjectId, ...basePayload });
    }
    pdDialogVisible.value = false;
    loadPds();
  } catch (e: any) {
    ElMessage.error(e?.response?.data?.message || TEXT.common.messages.saveFailed);
  }
};

const removePd = async (row: any) => {
  if (isReadOnly.value) {
    ElMessage.warning("中心已停用");
    return;
  }
  if (!studyId || !subjectId) return;
  const ok = await ElMessageBox.confirm(TEXT.common.confirm.delete, TEXT.common.labels.tips).catch(() => null);
  if (!ok) return;
  try {
    await deleteSubjectPd(studyId, subjectId, row.id);
    loadPds();
  } catch (e: any) {
    ElMessage.error(e?.response?.data?.message || TEXT.common.messages.deleteFailed);
  }
};

const goBack = () => router.push("/subjects");

watch(
  () => route.query.tab,
  () => {
    activeTab.value = resolveTabFromQuery();
  }
);

onMounted(async () => {
  await loadSites();
  await loadSubject();
  loadHistories();
  loadVisits();
  loadAes();
  loadPds();
});
</script>

<style scoped>
.page {
  display: flex;
  flex-direction: column;
  gap: 0;
}

.page-header {
  display: flex;
  justify-content: space-between;
  align-items: flex-end;
}

.subject-shell {
  border: 0;
  border-radius: 0;
  box-shadow: none;
}

.subject-shell :deep(.el-card__body) {
  padding: 0;
}

.subject-tabs-shell {
  margin-top: 12px;
  border-top: 8px solid #f3f6fb;
}

.subject-tabs-shell {
  position: relative;
}

.subject-tabs-shell :deep(.el-tabs__header) {
  margin: 0;
  padding: 0 160px 0 0;
  background: #ffffff;
  border-top: 1px solid #e5edf6;
  border-bottom: 1px solid #e5edf6;
}

.subject-tabs-shell :deep(.el-tabs__nav-wrap) {
  padding-left: 0;
}

.subject-tabs-shell :deep(.el-tabs__item) {
  height: 48px;
  line-height: 48px;
  font-weight: 700;
}

.subject-tabs-shell :deep(.el-tabs__content) {
  padding-top: 0;
  background: #ffffff;
}

.subject-tabs-action {
  position: absolute;
  top: 8px;
  right: 0;
  z-index: 2;
  display: flex;
  align-items: center;
  gap: 8px;
}

.subject-overview-descriptions :deep(.el-descriptions__table) {
  table-layout: fixed;
}

.visit-planned-cell {
  display: flex;
  min-width: 0;
  flex-direction: column;
  gap: 2px;
  line-height: 1.35;
}

.visit-window-range {
  color: #8a97ab;
  font-size: 12px;
}

.adherence-panel {
  padding: 16px 0 0;
}

.adherence-count-input {
  width: 160px;
}

.adherence-hint {
  margin-top: 12px;
  color: #6b778c;
  font-size: 13px;
}

.early-termination-hint {
  margin-top: 10px;
  color: #6b778c;
  font-size: 13px;
  line-height: 1.6;
}

.subject-overview-descriptions :deep(.el-descriptions__label) {
  width: 140px;
  min-width: 140px;
  color: #344258;
  font-weight: 700;
}

.subject-overview-descriptions :deep(.el-descriptions__content) {
  width: calc(50% - 140px);
  min-width: 0;
}

.subject-overview-descriptions :deep(.el-descriptions__cell) {
  height: 42px;
  vertical-align: middle;
}

.page-title {
  margin: 0;
  font-size: 22px;
  font-weight: 600;
}

.page-subtitle {
  margin: 6px 0 0;
  font-size: 13px;
  color: var(--ctms-text-secondary);
}

.actions {
  display: flex;
  gap: 8px;
}

.subject-detail-table :deep(.el-table__inner-wrapper::before) {
  display: none;
}

.ae-type-tag {
  border: none;
}

.ae-type-ae {
  color: #ffffff;
  background-color: #3b82f6;
}

.ae-type-sae {
  color: #ffffff;
  background-color: #ef4444;
}

.ae-type-susar {
  color: #ffffff;
  background-color: #8b5cf6;
}
.table-empty {
  min-height: 220px;
  display: flex;
  align-items: center;
  justify-content: center;
  color: #8a97ab;
  font-size: 14px;
  font-weight: 500;
  letter-spacing: 0.02em;
}
</style>
