<script lang="ts" setup>
/**
 * PC 接诊：AI 辅助出方
 * 主抽屉：历史列表 + 详情对照 + 确认导入
 * 二级弹窗：紧凑可编辑病历预览 → 生成处方（编辑同步回病历面板）
 */
import { computed, ref } from 'vue';

import { useVbenDrawer, useVbenModal } from '@vben/common-ui';
import { Button, Checkbox, Descriptions, Input, Radio, Spin, Switch, Tag, message } from 'ant-design-vue';

import {
  aiGeneratePrescriptionApi,
  aiListGenerationsApi,
  aiMatchPrescriptionDrugsApi,
  aiSavePrescriptionDrugSelectionApi,
  getProcessRuleList,
} from '../api';
import AiDisclaimerBanner from '#/views/doctor/components/AiDisclaimerBanner.vue';
import { ensureAiFeatureConsent } from '#/views/doctor/utils/aiFeatureGate';
import PrescriptionLoading from '#/components/loading/PrescriptionLoading.vue';

/** 本地「正在生成中」占位 id，不与真实 generation_id 冲突 */
const PENDING_GEN_ID = -1;

/** 二级弹窗通栏字段（Descriptions span=2） */
const FULL_SPAN_KEYS = new Set([
  'chief_complaint',
  'present_illness',
  'tcm_case',
  'treatment_advice',
  'doctor_order',
  'auxiliary_exam',
  'physical_exam',
]);

/** 二级弹窗可编辑的病历字段（主诉单独置顶） */
const MR_EDIT_FIELDS: Array<{ key: string; label: string }> = [
  { key: 'present_illness', label: '现病史' },
  { key: 'tongue', label: '舌象' },
  { key: 'pulse', label: '脉象' },
  { key: 'tcm_case', label: '中医病案' },
  { key: 'tcm_disease', label: '中医疾病' },
  { key: 'tcm_syndrome', label: '中医证候' },
  { key: 'tcm_method', label: '中医治法' },
  { key: 'diagnosis', label: '临床诊断' },
  { key: 'treatment_advice', label: '治疗意见' },
  { key: 'doctor_order', label: '医嘱' },
  { key: 'allergy_history', label: '过敏史' },
  { key: 'past_history', label: '既往史' },
  { key: 'family_history', label: '家族史' },
  { key: 'epidemic_history', label: '流行病学史' },
  { key: 'personal_history', label: '个人史' },
  { key: 'menstrual_history', label: '月经史' },
  { key: 'marital_history', label: '婚育史' },
  { key: 'physical_exam', label: '体征检查' },
  { key: 'auxiliary_exam', label: '辅助检查' },
];

const emit = defineEmits<{
  (
    e: 'import',
    payload: {
      rows: Array<Record<string, any>>;
      dosage?: number;
      day_dosage?: number;
      process_rule_id?: number;
      child_process_rule_id?: number;
      process_rule_note_id?: number;
      rule_type?: number;
      /** P4：本次导入来源的 AI 生成记录 ID，随开方提交回传做采纳率统计 */
      generation_id?: number;
    },
  ): void;
  (e: 'search-drug', keyword: string): void;
  /** 预览里改病历字段时回写父页病历面板 */
  (e: 'sync-medical-record', payload: Record<string, any>): void;
}>();

const registerId = ref(0);
const storeId = ref(0);
const prescriptionType = ref(0);
const patientName = ref('');
const patientSex = ref(0);
const patientAge = ref(0);
const chiefComplaint = ref('');
const medicalRecord = ref<Record<string, any>>({});
const histLoading = ref(false);
const generating = ref(false);
const matchLoading = ref(false);
const historyList = ref<any[]>([]);
const activeId = ref(0);
const matchedList = ref<any[]>([]);
const unmatchedList = ref<any[]>([]);
const conflictMessages = ref<string[]>([]);
/**
 * P2 安全校验提示（后端 safety_flags）：
 * 十八反/孕妇禁忌/剂量超限逐条标红展示，医生自行决断（只提示不拦截）
 */
const safetyFlags = ref<
  Array<{ drug?: string; level: string; message: string; ref?: string; type: string }>
>([]);
const rxDosage = ref(0);
const rxDayDosage = ref(0);
const rxReason = ref('');
const rxBasis = ref('');
const rxPrescriptionName = ref('');
/** 最近一次生成耗时（毫秒） */
const lastDurationMs = ref(0);
/** AI 返回的委托调剂制剂信息（导入时传给开方区） */
const rxProcessRuleId = ref(0);
const rxChildProcessRuleId = ref(0);
const rxProcessRuleNoteId = ref(0);
const rxProcessRuleName = ref('');
const rxChildProcessRuleName = ref('');
const rxProcessRuleNote = ref('');
/** 生成弹窗：中药委托调剂选项（本地记忆） */
const AI_RX_ENTRUSTED_STORAGE_KEY = 'xk_ai_rx_use_entrusted_process';
const useEntrustedProcess = ref(false);
const genProcessRuleId = ref<number | undefined>(undefined);
const processRuleOptions = ref<Array<{ label: string; value: number }>>([]);
const processRuleLoading = ref(false);
/** 委托时是否出推荐剂数/每日几次/详细制剂规则（本地记忆） */
const AI_RX_DETAIL_STORAGE_KEY = 'xk_ai_rx_return_dosage_process_detail';
const returnDosageProcessDetail = ref(true);
/** 制剂要求 id 本地记忆 */
const AI_RX_PROCESS_RULE_STORAGE_KEY = 'xk_ai_rx_process_rule_id';
/** 二级弹窗：当前正在编辑的字段 key，空表示浏览态 */
const editingKey = ref('');
/** 醒目提示文案（系统配置 / 门闸下发） */
const disclaimerText = ref('');

const sexLabel = computed(() => {
  const s = Number(patientSex.value);
  if (s === 1) return '男';
  if (s === 2) return '女';
  return '未知';
});

const typeLabel = computed(() => {
  const t = Number(prescriptionType.value);
  if (t === 1) return '中药';
  if (t === 2) return '西（中成）药';
  return `类型 ${t || '—'}`;
});

const isTcmRx = computed(() => Number(prescriptionType.value) === 1);

/** 二级弹窗紧凑展示：有内容的字段 + 主诉 */
const genPreviewRows = computed(() => {
  const mr = medicalRecord.value || {};
  const rows: Array<{ key: string; label: string; value: string }> = [
    {
      key: 'chief_complaint',
      label: '主诉',
      value: String(chiefComplaint.value || mr.chief_complaint || '').trim(),
    },
  ];
  for (const f of MR_EDIT_FIELDS) {
    const val = String(mr[f.key] ?? '').trim();
    if (val) rows.push({ key: f.key, label: f.label, value: val });
  }
  return rows;
});

const [Drawer, drawerApi] = useVbenDrawer({
  title: 'AI辅助出方',
  class: 'w-[920px]',
  // 按钮放内容区，关掉默认 footer，避免底部留白占高
  footer: false,
  showCancelButton: false,
  showConfirmButton: false,
  // 内容区改 flex 铺满，由内部滚动，避免双重裁切
  contentClass: '!flex !flex-col !overflow-hidden',
  async onOpenChange(isOpen) {
    if (!isOpen) {
      resetState();
      return;
    }
    const data = drawerApi.getData<{
      registerId: number;
      storeId?: number;
      prescriptionType: number;
      patientName?: string;
      patientSex?: number;
      patientAge?: number;
      chiefComplaint?: string;
      medicalRecord?: Record<string, any>;
    }>();
    registerId.value = Number(data?.registerId || 0);
    storeId.value = Number(data?.storeId || 0);
    prescriptionType.value = Number(data?.prescriptionType || 0);
    patientName.value = String(data?.patientName || '');
    patientSex.value = Number(data?.patientSex || 0);
    patientAge.value = Number(data?.patientAge || 0);
    chiefComplaint.value = String(data?.chiefComplaint || '');
    medicalRecord.value =
      data?.medicalRecord && typeof data.medicalRecord === 'object'
        ? { ...data.medicalRecord }
        : {};
    resetPreview();
    // 首次使用对应 VIP 功能需签署知情同意；拒绝则关闭抽屉
    try {
      const gate = await ensureAiFeatureConsent({
        featureCode: 'ai_prescription',
        storeId: storeId.value || undefined,
      });
      if (!gate) {
        drawerApi.close();
        return;
      }
      disclaimerText.value = gate.disclaimer_text || '';
    } catch (e: any) {
      message.error(e?.message || e?.msg || '无法校验 AI 使用规范');
      drawerApi.close();
      return;
    }
    void bootstrapHistory();
  },
});

const [GenModal, genModalApi] = useVbenModal({
  title: '生成处方',
  class: 'w-[920px]',
  confirmText: '开始生成',
  cancelText: '取消',
  // 校验失败不关；通过后立刻关弹窗，生成在抽屉内进行
  onConfirm: async () => confirmGenerateAndClose(),
});

function resetPreview() {
  matchedList.value = [];
  unmatchedList.value = [];
  conflictMessages.value = [];
  safetyFlags.value = [];
  rxDosage.value = 0;
  rxDayDosage.value = 0;
  rxReason.value = '';
  rxBasis.value = '';
  rxPrescriptionName.value = '';
  lastDurationMs.value = 0;
  rxProcessRuleId.value = 0;
  rxChildProcessRuleId.value = 0;
  rxProcessRuleNoteId.value = 0;
  rxProcessRuleName.value = '';
  rxChildProcessRuleName.value = '';
  rxProcessRuleNote.value = '';
  activeId.value = 0;
  editingKey.value = '';
}

function resetState() {
  generating.value = false;
  matchLoading.value = false;
  histLoading.value = false;
  historyList.value = [];
  medicalRecord.value = {};
  chiefComplaint.value = '';
  disclaimerText.value = '';
  genProcessRuleId.value = undefined;
  processRuleOptions.value = [];
  resetPreview();
  genModalApi.close();
}

function formatTime(ts: number) {
  const n = Number(ts || 0);
  if (!n) return '—';
  const d = new Date(n * 1000);
  const pad = (x: number) => (x < 10 ? `0${x}` : `${x}`);
  return `${pad(d.getMonth() + 1)}-${pad(d.getDate())} ${pad(d.getHours())}:${pad(d.getMinutes())}`;
}

/** 毫秒转可读耗时（850ms / 1.2s） */
function formatDurationMs(ms: number | undefined | null) {
  const n = Number(ms || 0);
  if (!n) return '';
  if (n < 1000) return `${Math.round(n)}ms`;
  const sec = n / 1000;
  return sec >= 10 ? `${Math.round(sec)}s` : `${sec.toFixed(1)}s`;
}

function typeLabelOf(t: number | string) {
  const n = Number(t || 0);
  if (n === 1) return '中药';
  if (n === 2) return '西药（中成药）';
  return n ? `类型 ${n}` : '—';
}

function applyRxMeta(data: any) {
  // 中药剂数/每日次数缺省时用处方页默认，避免预览「—」和导入丢空
  const dosage = Number(data?.dosage || 0);
  const dayDosage = Number(data?.day_dosage || 0);
  rxDosage.value = dosage > 0 ? dosage : isTcmRx.value ? 7 : 0;
  rxDayDosage.value = dayDosage > 0 ? dayDosage : isTcmRx.value ? 2 : 0;
  rxReason.value = String(data?.reason || '').trim();
  rxBasis.value = String(data?.basis || '').trim();
  rxPrescriptionName.value = String(data?.prescription_name || '').trim();
  if (data?.duration_ms != null) {
    lastDurationMs.value = Number(data.duration_ms || 0);
  }
  rxProcessRuleId.value = Number(data?.process_rule_id || 0);
  rxChildProcessRuleId.value = Number(data?.child_process_rule_id || 0);
  rxProcessRuleNoteId.value = Number(data?.process_rule_note_id || 0);
  rxProcessRuleName.value = String(data?.process_rule_name || '').trim();
  rxChildProcessRuleName.value = String(data?.child_process_rule_name || '').trim();
  rxProcessRuleNote.value = String(data?.process_rule_note || '').trim();
}

/** 加载制剂要求列表（pid=0），供生成前委托调剂选择 */
async function loadTopProcessRules() {
  if (!isTcmRx.value) return;
  processRuleLoading.value = true;
  try {
    const list = await getProcessRuleList({ pid: 0 });
    const arr = Array.isArray(list) ? list : [];
    processRuleOptions.value = arr.map((item: any) => ({
      label: String(item.name || item.title || `#${item.id}`),
      value: Number(item.id),
    }));
    applyProcessRulePrefFromStorage();
  } catch {
    processRuleOptions.value = [];
  } finally {
    processRuleLoading.value = false;
  }
}

function onEntrustedToggle(checked: boolean) {
  useEntrustedProcess.value = !!checked;
  persistUseEntrustedProcessPref(!!checked);
  if (checked) {
    if (!processRuleOptions.value.length) {
      void loadTopProcessRules();
    } else {
      applyProcessRulePrefFromStorage();
    }
  } else {
    genProcessRuleId.value = undefined;
  }
}

/** 标签单选制剂要求：点选写入并记本地 */
function onProcessRuleTagClick(id: number) {
  genProcessRuleId.value = Number(id) || undefined;
  persistProcessRuleIdPref(genProcessRuleId.value);
}

/** 读取本地：是否勾选委托调剂（未存过默认不勾选） */
function loadUseEntrustedProcessPref() {
  try {
    return localStorage.getItem(AI_RX_ENTRUSTED_STORAGE_KEY) === '1';
  } catch {
    return false;
  }
}

function persistUseEntrustedProcessPref(v: boolean) {
  try {
    localStorage.setItem(AI_RX_ENTRUSTED_STORAGE_KEY, v ? '1' : '0');
  } catch {
    /* ignore */
  }
}

/** 读取本地：制剂要求 id */
function loadProcessRuleIdPref() {
  try {
    const id = Number(localStorage.getItem(AI_RX_PROCESS_RULE_STORAGE_KEY) || 0);
    return id > 0 ? id : 0;
  } catch {
    return 0;
  }
}

function persistProcessRuleIdPref(id?: number) {
  try {
    const n = Number(id || 0);
    if (n > 0) {
      localStorage.setItem(AI_RX_PROCESS_RULE_STORAGE_KEY, String(n));
    } else {
      localStorage.removeItem(AI_RX_PROCESS_RULE_STORAGE_KEY);
    }
  } catch {
    /* ignore */
  }
}

/** 列表加载后回填本地记忆的制剂要求（须仍在可选列表中） */
function applyProcessRulePrefFromStorage() {
  const prefId = loadProcessRuleIdPref();
  if (prefId <= 0) return;
  if (processRuleOptions.value.some((o) => Number(o.value) === prefId)) {
    genProcessRuleId.value = prefId;
  }
}

/** 读取本地：委托时是否出剂数/每日/详细规则 */
function loadReturnDosageProcessDetailPref() {
  try {
    const raw = localStorage.getItem(AI_RX_DETAIL_STORAGE_KEY);
    // 未存过默认「需要」；显式存 0 才为不需要
    return raw === null || raw === '' || raw === '1';
  } catch {
    return true;
  }
}

function persistReturnDosageProcessDetailPref(v: boolean) {
  try {
    localStorage.setItem(AI_RX_DETAIL_STORAGE_KEY, v ? '1' : '0');
  } catch {
    /* ignore */
  }
}

function onReturnDosageProcessDetailChange(v: boolean) {
  returnDosageProcessDetail.value = !!v;
  persistReturnDosageProcessDetailPref(!!v);
}

function applyConflict(conflict: any) {
  const msgs = Array.isArray(conflict?.messages) ? conflict.messages : [];
  conflictMessages.value = msgs
    .map((m: any) => String(m || '').trim())
    .filter(Boolean);
}

/**
 * 解析后端 safety_flags 结构 { has_risk, flags: [{type, level, drug, message, ref}] }
 * 有 safety_flags 时优先展示统一安全块（含十八反），老记录没有该字段则回落旧配伍提示条
 */
function applySafetyFlags(safety: any) {
  const flags = Array.isArray(safety?.flags) ? safety.flags : [];
  safetyFlags.value = flags
    .map((f: any) => ({
      type: String(f?.type || ''),
      level: String(f?.level || 'info'),
      drug: String(f?.drug || ''),
      message: String(f?.message || '').trim(),
      ref: String(f?.ref || '').trim(),
    }))
    .filter((f: any) => f.message);
}

/** 安全提示分级样式（error红/warning橙/info灰，主题变量适配暗色） */
function safetyLevelClass(level: string) {
  if (level === 'error') return 'text-red-500';
  if (level === 'warning') return 'text-orange-500';
  return 'text-muted-foreground';
}

/** 安全提示分级标签文本 */
function safetyLevelLabel(level: string) {
  if (level === 'error') return '禁忌';
  if (level === 'warning') return '警示';
  return '参考';
}

function applyMatch(match: any) {
  const matched = Array.isArray(match?.matched) ? match.matched : [];
  matchedList.value = matched.map((m: any) => ({
    ...m,
    _import: true,
  }));
  unmatchedList.value = Array.isArray(match?.unmatched) ? match.unmatched : [];
}

async function loadHistory() {
  histLoading.value = true;
  try {
    const list = await aiListGenerationsApi({
      register_id: registerId.value,
      scene: 'prescription',
      limit: 30,
    });
    historyList.value = Array.isArray(list) ? list : [];
  } catch (e: any) {
    historyList.value = [];
    message.error(e?.message || e?.msg || '加载历史失败');
  } finally {
    histLoading.value = false;
  }
}

/** 打开抽屉后加载历史；有则选最新，无则自动打开生成框 */
async function bootstrapHistory() {
  if (!registerId.value) return;
  await loadHistory();
  if (historyList.value.length) {
    await onSelectHistory(historyList.value[0]);
  } else {
    openGenerateModal();
  }
}

function openGenerateModal() {
  if (!prescriptionType.value) {
    message.warning('请先选择处方类型');
    return;
  }
  editingKey.value = '';
  useEntrustedProcess.value = loadUseEntrustedProcessPref();
  returnDosageProcessDetail.value = loadReturnDosageProcessDetailPref();
  if (isTcmRx.value && useEntrustedProcess.value) {
    if (!processRuleOptions.value.length) {
      void loadTopProcessRules();
    } else {
      applyProcessRulePrefFromStorage();
    }
  } else {
    genProcessRuleId.value = undefined;
  }
  genModalApi.open();
}

/**
 * 点字段进入编辑；改完 blur 后同步病历
 */
function startEdit(key: string) {
  editingKey.value = key;
}

function fieldValue(key: string) {
  if (key === 'chief_complaint') return chiefComplaint.value;
  return String(medicalRecord.value?.[key] ?? '');
}

function onFieldInput(key: string, val: string) {
  if (key === 'chief_complaint') {
    chiefComplaint.value = val;
    medicalRecord.value = {
      ...(medicalRecord.value || {}),
      chief_complaint: val,
    };
  } else {
    medicalRecord.value = {
      ...(medicalRecord.value || {}),
      [key]: val,
    };
  }
  emit('sync-medical-record', { [key]: val });
}

function endEdit() {
  editingKey.value = '';
}

/**
 * 开始生成：取消旧选中、清空对照预览，历史顶部插入「正在生成中」占位
 */
function beginGeneratingPlaceholder() {
  resetPreview();
  activeId.value = PENDING_GEN_ID;
  const rest = (historyList.value || []).filter(
    (r) => Number(r?.id) !== PENDING_GEN_ID && !r?._pending,
  );
  historyList.value = [
    {
      id: PENDING_GEN_ID,
      name: '正在生成中…',
      prescription_name: '正在生成中…',
      prescription_type: prescriptionType.value,
      prescription_type_label: typeLabel.value,
      item_count: 0,
      created_at: Math.floor(Date.now() / 1000),
      _pending: true,
    },
    ...rest,
  ];
}

/** 生成结束：去掉本地占位 */
function endGeneratingPlaceholder() {
  historyList.value = (historyList.value || []).filter(
    (r) => Number(r?.id) !== PENDING_GEN_ID && !r?._pending,
  );
  if (Number(activeId.value) === PENDING_GEN_ID) {
    activeId.value = 0;
  }
}

/**
 * 二级弹窗点「开始生成」：先关弹窗，回抽屉等待 AI
 */
async function confirmGenerateAndClose(): Promise<boolean> {
  if (generating.value) return false;
  const chief = String(chiefComplaint.value || '').trim();
  if (!chief) {
    message.warning('请先填写主诉后再生成');
    return false;
  }
  if (!prescriptionType.value) {
    message.warning('请先选择处方类型');
    return false;
  }
  if (!registerId.value) {
    message.warning('挂号无效');
    return false;
  }
  if (isTcmRx.value && useEntrustedProcess.value && !genProcessRuleId.value) {
    message.warning('请选择制剂要求');
    return false;
  }
  // 先关模态，在抽屉内展示「AI 处理中」
  genModalApi.close();
  void runGenerateInDrawer(chief);
  return true;
}

async function runGenerateInDrawer(chief: string) {
  beginGeneratingPlaceholder();
  generating.value = true;
  try {
    const req: Record<string, any> = {
      register_id: registerId.value,
      store_id: storeId.value || undefined,
      prescription_type: prescriptionType.value,
      chief_complaint: chief,
      medical_record: {
        ...(medicalRecord.value || {}),
        chief_complaint: chief,
      },
    };
    // 中药委托调剂：传制剂要求；可选是否出剂数/每日/详细规则
    if (isTcmRx.value && useEntrustedProcess.value && genProcessRuleId.value) {
      req.use_entrusted_process = 1;
      req.process_rule_id = genProcessRuleId.value;
      req.return_dosage_process_detail = returnDosageProcessDetail.value ? 1 : 0;
    }
    const data = await aiGeneratePrescriptionApi(req);
    const durationText = formatDurationMs(data?.duration_ms);
    // 业务软失败：HTTP 成功但 ok=false，警告提示而非 error
    if (data?.ok === false) {
      endGeneratingPlaceholder();
      resetPreview();
      if (data?.generation_id) {
        await loadHistory();
        activeId.value = Number(data.generation_id);
      }
      message.warning(String(data?.message || '生成未成功'));
      return;
    }
    await loadHistory();
    activeId.value = Number(data?.generation_id || 0);
    applyMatch(data?.match || null);
    applyConflict(data?.conflict || null);
    applySafetyFlags(data?.safety_flags || null);
    applyRxMeta(data);
    message.success(
      durationText ? `已生成（耗时 ${durationText}）` : '已生成，请确认导入',
    );
  } catch (e: any) {
    endGeneratingPlaceholder();
    resetPreview();
    message.error(e?.message || e?.msg || '生成失败');
  } finally {
    generating.value = false;
  }
}

async function onSelectHistory(row: any) {
  if (!row?.id || Number(row.id) === PENDING_GEN_ID || row._pending) return;
  activeId.value = Number(row.id);
  matchLoading.value = true;
  try {
    const data = await aiMatchPrescriptionDrugsApi({
      generation_id: Number(row.id),
      register_id: registerId.value,
      store_id: storeId.value || undefined,
      prescription_type: Number(
        prescriptionType.value || row.prescription_type || 0,
      ),
    });
    applyMatch(data);
    applyConflict(data?.conflict || null);
    applySafetyFlags(data?.safety_flags || null);
    applyRxMeta({
      ...data,
      duration_ms: row.duration_ms,
      prescription_name:
        data?.prescription_name || row?.name || row?.prescription_name || '',
    });
  } catch (e: any) {
    matchedList.value = [];
    unmatchedList.value = [];
    conflictMessages.value = [];
    safetyFlags.value = [];
    message.error(e?.message || e?.msg || '对照失败');
  } finally {
    matchLoading.value = false;
  }
}

/**
 * 医生点选对照候选药：本地更新 + 同步写回 aijson（result_json）
 * @param mi matchedList 下标
 * @param candidate 候选药品
 */
async function onPickCandidate(mi: number, candidate: any) {
  const row = matchedList.value[mi];
  if (!row || !candidate) return;
  const drugId = Number(candidate.drug_id || 0);
  if (!drugId) return;
  if (Number(row.selected_drug_id) === drugId) return;
  const prevId = Number(row.selected_drug_id || 0);
  const prevModified = Number(row.is_modified || 0);
  row.selected_drug_id = drugId;
  row.is_modified = 1;
  const generationId = Number(activeId.value || 0);
  const itemIndex = Number(
    row.item_index !== undefined && row.item_index !== null
      ? row.item_index
      : mi,
  );
  if (generationId <= 0) {
    message.warning('请先生成或选择历史处方后再改选');
    return;
  }
  try {
    await aiSavePrescriptionDrugSelectionApi({
      generation_id: generationId,
      item_index: itemIndex,
      selected_drug_id: drugId,
      selected_drug_name: String(candidate.drug_name || ''),
    });
  } catch (e: any) {
    // 回滚本地，避免 UI 与库不一致
    row.selected_drug_id = prevId;
    row.is_modified = prevModified;
    message.error(e?.message || e?.msg || '改选保存失败');
  }
}

function onConfirmImport() {
  const drugs: any[] = [];
  for (const m of matchedList.value) {
    if (!m || m._import === false) continue;
    const sid = Number(m.selected_drug_id || 0);
    if (!sid) continue;
    const picked = (m.candidates || []).find(
      (c: any) => Number(c.drug_id) === sid,
    );
    if (!picked) continue;
    drugs.push({
      candidate: picked,
      dose: m.dose || '',
      unit: m.unit || '',
      usage: m.usage || '',
      ai_name: m.ai_name || '',
    });
  }
  if (!drugs.length) {
    message.warning('请先勾选已对照药品');
    return;
  }
  const importPayload: {
    rows: typeof drugs;
    dosage?: number;
    day_dosage?: number;
    rule_type?: number;
    process_rule_id?: number;
    child_process_rule_id?: number;
    process_rule_note_id?: number;
    generation_id?: number;
  } = {
    rows: drugs,
  };
  // P4：带上生成记录 ID，父页开方提交时透传给后端做采纳率/修改率统计
  if (activeId.value > 0) {
    importPayload.generation_id = activeId.value;
  }
  // 中药导入必须带剂数/每日次数，缺省用处方页默认 7/2
  if (isTcmRx.value) {
    importPayload.dosage = rxDosage.value > 0 ? rxDosage.value : 7;
    importPayload.day_dosage = rxDayDosage.value > 0 ? rxDayDosage.value : 2;
  } else {
    if (rxDosage.value > 0) importPayload.dosage = rxDosage.value;
    if (rxDayDosage.value > 0) importPayload.day_dosage = rxDayDosage.value;
  }
  if (rxProcessRuleId.value > 0) {
    importPayload.rule_type = 2;
    importPayload.process_rule_id = rxProcessRuleId.value;
    if (rxChildProcessRuleId.value > 0) {
      importPayload.child_process_rule_id = rxChildProcessRuleId.value;
    }
    if (rxProcessRuleNoteId.value > 0) {
      importPayload.process_rule_note_id = rxProcessRuleNoteId.value;
    }
  }
  emit('import', importPayload);
  drawerApi.close();
}

defineExpose({
  open(payload: {
    registerId: number;
    storeId?: number;
    prescriptionType: number;
    patientName?: string;
    patientSex?: number;
    patientAge?: number;
    chiefComplaint?: string;
    medicalRecord?: Record<string, any>;
  }) {
    drawerApi.setData(payload);
    drawerApi.open();
  },
});
</script>

<template>
  <Drawer>
    <!-- 铺满抽屉内容区：头部/禁忌/按钮固定，中间历史+对照可滚动 -->
    <div class="flex min-h-0 flex-1 flex-col gap-2 overflow-hidden text-foreground">
      <div class="shrink-0 text-sm text-muted-foreground">
        {{ patientName || '—' }} · {{ sexLabel }} · {{ patientAge || '—' }}岁 ·
        {{ typeLabel }}
      </div>
      <AiDisclaimerBanner class="shrink-0" :text="disclaimerText" />
      <!-- P2 安全校验统一提示块：十八反/孕妇禁忌/剂量超限逐条分级标红（只提示，医生决断） -->
      <div
        v-if="safetyFlags.length"
        class="shrink-0 rounded-lg border border-red-500/35 bg-red-500/5 px-3 py-2 text-xs"
      >
        <div class="mb-1 font-medium text-red-500">安全校验提示（请人工核对）</div>
        <div v-for="(f, i) in safetyFlags" :key="i" class="flex items-start gap-1.5 leading-5">
          <span
            class="shrink-0 font-medium"
            :class="safetyLevelClass(f.level)"
          >[{{ safetyLevelLabel(f.level) }}]</span>
          <span :class="f.level === 'info' ? 'text-muted-foreground' : ''">
            {{ f.message }}
            <span v-if="f.ref" class="text-muted-foreground">（依据：{{ f.ref }}）</span>
          </span>
        </div>
      </div>
      <!-- 老记录（未落 safety_flags 字段）回落旧配伍提示条 -->
      <div
        v-else-if="conflictMessages.length"
        class="shrink-0 rounded-lg border border-orange-500/35 bg-orange-500/10 px-3 py-2 text-xs"
      >
        <div class="mb-1 font-medium">配伍禁忌提示</div>
        <div v-for="(line, i) in conflictMessages" :key="i" class="text-muted-foreground">
          · {{ line }}
        </div>
      </div>
      <div class="flex min-h-0 flex-1 gap-3 overflow-hidden">
        <div class="w-44 shrink-0 overflow-y-auto border-r border-border pr-2">
          <div class="mb-2 text-sm font-medium">历史记录</div>
          <div v-if="histLoading" class="text-xs text-muted-foreground">加载中…</div>
          <div v-else-if="!historyList.length" class="text-xs text-muted-foreground">
            暂无记录，可点击下方「生成处方」
          </div>
          <div
            v-for="row in historyList"
            :key="row.id"
            class="mb-1 cursor-pointer rounded-md px-2 py-1.5 text-xs transition-colors hover:bg-accent"
            :class="{
              'bg-primary/10 ring-1 ring-primary/20': activeId === Number(row.id),
              'cursor-default border border-dashed border-primary/40 bg-primary/5':
                Number(row.id) === PENDING_GEN_ID || row._pending,
            }"
            @click="onSelectHistory(row)"
          >
            <div class="truncate font-medium">
              {{
                Number(row.id) === PENDING_GEN_ID || row._pending
                  ? '正在生成中…'
                  : row.name || row.prescription_name || `方案 #${row.id}`
              }}
            </div>
            <div class="mt-0.5 text-muted-foreground">
              <template v-if="Number(row.id) === PENDING_GEN_ID || row._pending">
                请稍候，右侧为生成进度
              </template>
              <template v-else>
                {{ row.prescription_type_label || typeLabelOf(row.prescription_type) }}
                · {{ row.item_count || 0 }}味 · {{ formatTime(row.created_at) }}
                <span v-if="row.duration_ms"> · {{ formatDurationMs(row.duration_ms) }}</span>
              </template>
            </div>
          </div>
        </div>
        <div class="min-h-0 min-w-0 flex-1 overflow-y-auto pl-1 pb-2">
          <!-- AI 专属动画：仅真正调用生成接口时展示；历史/对照加载用普通 Spin -->
          <div
            v-if="generating"
            class="flex h-full min-h-[260px] items-center justify-center"
          >
            <PrescriptionLoading
              type="prescription"
              text="AI正在生成处方"
              class="h-[280px] w-full max-w-[420px]"
            />
          </div>
          <div
            v-else-if="matchLoading"
            class="flex h-full min-h-[200px] flex-col items-center justify-center gap-2 text-muted-foreground"
          >
            <Spin />
            <span class="text-sm">加载历史处方…</span>
          </div>
          <template v-else>
            <div
              v-if="!matchedList.length && !unmatchedList.length && !lastDurationMs"
              class="py-8 text-center text-muted-foreground"
            >
              请选择左侧历史，或点击「生成处方」
            </div>
            <div
              v-else-if="!matchedList.length && !unmatchedList.length && lastDurationMs"
              class="py-8 text-center text-muted-foreground"
            >
              本次生成未产出对照结果
              <span v-if="formatDurationMs(lastDurationMs)">
                （耗时 {{ formatDurationMs(lastDurationMs) }}）
              </span>
            </div>
            <template v-else>
              <div class="mb-1.5 text-xs font-medium text-muted-foreground">
                已对照（{{ matchedList.length }}）
              </div>
              <!-- 中药：一行多味网格；西药：仍用较完整卡片 -->
              <div
                v-if="isTcmRx"
                class="grid grid-cols-2 gap-1.5 xl:grid-cols-3"
              >
                <div
                  v-for="(m, mi) in matchedList"
                  :key="mi"
                  class="rounded border border-border bg-card px-1.5 py-1"
                >
                  <div class="flex items-start gap-1">
                    <div class="min-w-0 flex-1">
                      <div class="truncate text-xs font-medium">
                        {{ m.ai_name }}
                        <Tag
                          v-if="Number(m.is_modified) === 1"
                          color="orange"
                          class="!m-0 !ml-1 !px-1 !text-[10px] !leading-4"
                        >
                          已改
                        </Tag>
                      </div>
                      <div class="text-[11px] text-muted-foreground">
                        {{ m.dose }}{{ m.unit }}{{ m.usage ? `·${m.usage}` : '' }}
                      </div>
                    </div>
                    <Switch v-model:checked="m._import" size="small" />
                  </div>
                  <div class="mt-1 flex flex-wrap gap-0.5">
                    <Tag
                      v-for="c in m.candidates || []"
                      :key="c.drug_id"
                      class="cursor-pointer !m-0 !px-1 !text-[10px] !leading-4"
                      :color="
                        Number(m.selected_drug_id) === Number(c.drug_id)
                          ? 'success'
                          : undefined
                      "
                      @click="onPickCandidate(mi, c)"
                    >
                      {{ c.drug_name }}
                    </Tag>
                  </div>
                </div>
              </div>
              <div v-else class="space-y-2">
                <div
                  v-for="(m, mi) in matchedList"
                  :key="mi"
                  class="rounded-lg border border-border bg-card p-2.5"
                >
                  <div class="flex items-center gap-2">
                    <span class="min-w-0 flex-1 truncate font-medium">
                      {{ m.ai_name }}
                      <Tag
                        v-if="Number(m.is_modified) === 1"
                        color="orange"
                        class="!m-0 !ml-1 !text-[10px]"
                      >
                        已改
                      </Tag>
                    </span>
                    <span class="text-xs text-muted-foreground">
                      {{ m.dose }}{{ m.unit }}{{ m.usage ? `·${m.usage}` : '' }}
                    </span>
                    <Switch v-model:checked="m._import" size="small" />
                  </div>
                  <div class="mt-1 flex flex-wrap gap-1">
                    <Tag
                      v-for="c in m.candidates || []"
                      :key="c.drug_id"
                      class="cursor-pointer !m-0 !text-[11px]"
                      :color="
                        Number(m.selected_drug_id) === Number(c.drug_id)
                          ? 'success'
                          : undefined
                      "
                      @click="onPickCandidate(mi, c)"
                    >
                      {{ c.drug_name }} ￥{{ Number(c.price || 0).toFixed(2) }}
                    </Tag>
                  </div>
                </div>
              </div>
              <div
                v-if="unmatchedList.length"
                class="mb-1.5 mt-3 text-xs font-medium text-muted-foreground"
              >
                未对照（{{ unmatchedList.length }}）
              </div>
              <div
                v-for="(u, ui) in unmatchedList"
                :key="ui"
                class="mb-1.5 rounded border border-orange-500/30 bg-orange-500/10 px-2 py-1.5 text-sm"
              >
                <div class="font-medium">{{ u.ai_name }}</div>
                <Button
                  type="link"
                  size="small"
                  class="!h-auto !px-0"
                  @click="
                    emit('search-drug', u.ai_name || '');
                    drawerApi.close();
                  "
                >
                  去手动搜索
                </Button>
              </div>
              <!-- 药方摘要：Descriptions 双列展示名称/剂数/出方理由 -->
              <Descriptions
                v-if="
                  rxPrescriptionName ||
                  rxReason ||
                  rxBasis ||
                  rxDosage ||
                  rxDayDosage ||
                  lastDurationMs ||
                  rxProcessRuleName
                "
                :column="2"
                bordered
                size="small"
                class="ai-rx-meta-desc mt-3"
                title="出方说明"
              >
                <Descriptions.Item label="药方名" :span="2">
                  {{ rxPrescriptionName || '未命名药方' }}
                </Descriptions.Item>
                <Descriptions.Item label="推荐剂数">
                  {{ rxDosage || '—' }}剂
                </Descriptions.Item>
                <Descriptions.Item label="每天几次">
                  {{ rxDayDosage || '—' }}次
                </Descriptions.Item>
                <Descriptions.Item v-if="lastDurationMs" label="生成耗时">
                  {{ formatDurationMs(lastDurationMs) }}
                </Descriptions.Item>
                <Descriptions.Item
                  v-if="rxProcessRuleName"
                  label="制剂要求"
                  :span="2"
                >
                  {{ rxProcessRuleName }}
                  <span v-if="rxChildProcessRuleName"> · {{ rxChildProcessRuleName }}</span>
                  <span v-if="rxProcessRuleNote"> · {{ rxProcessRuleNote }}</span>
                </Descriptions.Item>
                <Descriptions.Item
                  v-if="rxReason"
                  label="为什么出这个方"
                  :span="2"
                >
                  <div class="max-h-28 overflow-y-auto whitespace-pre-wrap leading-relaxed">
                    {{ rxReason }}
                  </div>
                </Descriptions.Item>
                <Descriptions.Item
                  v-if="rxBasis"
                  label="根据哪些"
                  :span="2"
                >
                  <div class="max-h-28 overflow-y-auto whitespace-pre-wrap leading-relaxed">
                    {{ rxBasis }}
                  </div>
                </Descriptions.Item>
              </Descriptions>
            </template>
          </template>
        </div>
      </div>
      <div class="flex shrink-0 justify-end gap-2 border-t border-border pt-3">
        <Button @click="drawerApi.close()">关闭</Button>
        <Button type="default" @click="openGenerateModal">生成处方</Button>
        <Button
          type="primary"
          :disabled="generating || matchLoading || !matchedList.length"
          @click="onConfirmImport"
        >
          确认导入
        </Button>
      </div>
    </div>
  </Drawer>

  <!-- 二级：病历预览（可点改）+ 生成；Descriptions 双列 -->
  <GenModal>
    <div class="space-y-2 text-sm text-foreground">
      <AiDisclaimerBanner :text="disclaimerText" />
      <div class="text-xs text-muted-foreground">
        {{ patientName || '—' }} · {{ sexLabel }} · {{ patientAge || '—' }}岁 ·
        {{ typeLabel }} · 点击文字可编辑，将同步到病历
      </div>
      <div class="max-h-[58vh] overflow-y-auto">
        <Descriptions
          v-if="genPreviewRows.length"
          :column="2"
          bordered
          size="small"
          class="ai-rx-gen-desc"
        >
          <Descriptions.Item
            v-for="row in genPreviewRows"
            :key="row.key"
            :label="row.label"
            :span="FULL_SPAN_KEYS.has(row.key) ? 2 : 1"
          >
            <Input.TextArea
              v-if="editingKey === row.key"
              :value="fieldValue(row.key)"
              :rows="row.key === 'chief_complaint' ? 3 : 2"
              autofocus
              @update:value="(v) => onFieldInput(row.key, String(v ?? ''))"
              @blur="endEdit"
            />
            <div
              v-else
              class="max-h-24 cursor-text overflow-y-auto whitespace-pre-wrap leading-relaxed"
              title="点击编辑"
              @click="startEdit(row.key)"
            >
              {{ fieldValue(row.key) || '（空，点击填写）' }}
            </div>
          </Descriptions.Item>
        </Descriptions>
        <div
          v-if="genPreviewRows.length <= 1"
          class="px-2 py-3 text-center text-xs text-muted-foreground"
        >
          仅有主诉。建议先在病历区补充现病史、舌脉等，再生成。
        </div>
      </div>
      <!-- 中药：生成前可选委托调剂 + 制剂要求 -->
      <div
        v-if="isTcmRx"
        class="rounded-lg border border-border bg-muted/30 p-3"
      >
        <Checkbox
          v-model:checked="useEntrustedProcess"
          @update:checked="onEntrustedToggle"
        >
          委托调剂
        </Checkbox>
        <div v-if="useEntrustedProcess" class="mt-2 space-y-3">
          <div>
            <div class="mb-1 text-xs text-muted-foreground">制剂要求</div>
            <div v-if="processRuleLoading" class="text-xs text-muted-foreground">加载中…</div>
            <div v-else class="ai-process-pill-group">
              <span
                v-for="opt in processRuleOptions"
                :key="opt.value"
                class="ai-process-pill"
                :class="{ active: genProcessRuleId === opt.value }"
                @click="onProcessRuleTagClick(opt.value)"
              >{{ opt.label }}</span>
            </div>
            <div
              v-if="!processRuleLoading && !processRuleOptions.length"
              class="mt-1 text-xs text-muted-foreground"
            >
              暂无制剂要求可选
            </div>
          </div>
          <div>
            <div class="mb-1 text-xs text-muted-foreground">
              是否出详细制剂规则（二级煎法/备注）
            </div>
            <Radio.Group
              :value="returnDosageProcessDetail"
              @update:value="onReturnDosageProcessDetailChange"
            >
              <Radio :value="true">需要</Radio>
              <Radio :value="false">不需要</Radio>
            </Radio.Group>
            <div class="mt-1 text-xs text-muted-foreground">
              需要：额外返回二级制剂说明；不需要：仅按一级制剂限定组方，剂数/每日次数仍返回（默认 7 剂 / 2 次）
            </div>
          </div>
        </div>
      </div>
    </div>
  </GenModal>
</template>

<style scoped>
.ai-rx-gen-desc :deep(.ant-descriptions-item-label),
.ai-rx-meta-desc :deep(.ant-descriptions-item-label) {
  width: 110px;
  white-space: nowrap;
}
.ai-rx-gen-desc :deep(.ant-descriptions-item-content),
.ai-rx-meta-desc :deep(.ant-descriptions-item-content) {
  font-size: 12px;
}
.ai-process-pill-group {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}
.ai-process-pill {
  padding: 4px 16px;
  background-color: #f4f6f8;
  color: #6c7380;
  border-radius: 20px;
  font-size: 13px;
  cursor: pointer;
  border: 1px solid transparent;
  user-select: none;
  transition: all 0.2s;
}
.ai-process-pill.active {
  background-color: #e8f6f4;
  color: #00a88a;
  border-color: #00a88a;
  font-weight: 600;
}
/* 暗色模式：与处方页制剂标签一致 */
.dark .ai-process-pill {
  background-color: #2a2a2a;
  color: #a3a3a3;
  border-color: #404040;
}
.dark .ai-process-pill.active {
  background-color: rgba(0, 168, 138, 0.15);
  color: #3dd6b5;
  border-color: #00a88a;
}
</style>
