'use client';

import {
  subLabelZh,
  triggerTypeLabelZh,
  diagnosisCodeNameZh,
  treatmentCategoryNameZhFor,
  recommendedCategoriesForAge,
  refineCategoriesForDiagnosis,
} from '@pac/types';
import { formatToothPosition, formatDaysReadable } from '@/lib/utils';

/**
 * ReasonLine — 召回理由富文本渲染。
 *
 * 数据契约:后端只回原始 enum / canonical code(reason.signals JSON),
 * 前端用 @pac/types 字典翻译 + 富文本组合(加粗 + 玫红高亮,色彩克制)。
 *
 * 同源:列表页 PatientPlanCard + 详情页 WhyCard 共用。
 *
 * 老数据/异常兜底:signals 缺失时落回 reason 文本。
 */
export interface ReasonLineInput {
  scenario: string;
  reason: string;
  signals?: {
    subKey: string;
    triggers: Array<{ type: string; code?: string | null }>;
    toothPosition?: string | null;
    daysSince: number;
    expectedCategories: string[];
    /** 按年龄适配后的建议治疗主类目;旧 plan 无此字段 → 回落 expectedCategories[0] */
    focusCategory?: string | null;
    /** plan 生成时的年龄快照(无生日 → null);展示按此措辞 */
    patientAge?: number | null;
    /** 触发诊断原文词快照(如「乳牙早失」);K00 细分用,旧 plan 无 → 回落原顺序 */
    dxNameZh?: string | null;
  } | null;
}

export function ReasonLine({ reason }: { reason: ReasonLineInput }) {
  if (!reason.signals) return <span>{reason.reason}</span>;
  const s = reason.signals;
  const trig = s.triggers[0]; // 第一个 trigger 给 code 展示(后端把 diagnosis 排前)
  // 多 trigger 合并显示 source:cluster 同时含诊断+建议两种 sig → "(诊断+医生建议)"
  const typeSet = new Set(s.triggers.map((t) => t.type));
  const sourceLabel =
    typeSet.size > 1
      ? [...typeSet].map(triggerTypeLabelZh).join('+')
      : trig
        ? triggerTypeLabelZh(trig.type)
        : '';
  // 标签分流(triggers 已按 诊断>建议>影像 排序,triggers[0]=最高优先源):
  //   triggers[0]=建议 ⟹ 该 gap 只有医生建议、无诊断 → 主标签用建议名(如"建议种植"),
  //     不再套子场景的诊断词"缺失牙"(否则把"建议拔除同期种植"误说成缺失牙)。
  //   triggers[0]=诊断/影像 ⟹ 有诊断(影像AI 也是 K 诊断)→ 仍用病种名,以诊断为准。
  const isRecLead = trig?.type === 'recommendation';
  const subLabel =
    isRecLead && trig?.code ? diagnosisCodeNameZh(trig.code) : subLabelZh(reason.scenario, s.subKey);
  // 建议治疗:走**源头**的两道重排(与后端同一对函数,保证「目标 · X」与本行首项一致):
  //   ① refineCategoriesForDiagnosis —— K00 按诊断词定方向(早失→正畸、滞留→外科…);
  //   ② recommendedCategoriesForAge —— >70 岁缺牙义齿前置、<18 岁种植降末位(均并行保留);
  //   乳牙 restorative → 「充填」(去嵌体);≤12 岁 orthodontic → 「早期矫治」。
  //   旧 plan 无 patientAge / dxNameZh → 原顺序,行为不变。
  const cats = recommendedCategoriesForAge(
    refineCategoriesForDiagnosis(trig?.code, s.dxNameZh, s.expectedCategories),
    s.patientAge ?? null,
  )
    .map((c) => treatmentCategoryNameZhFor(c, s.toothPosition, s.patientAge ?? null))
    .join(' / ');
  return (
    <span>
      <strong className="text-slate-900">{subLabel}</strong>
      {s.toothPosition && ` · 牙位 ${formatToothPosition(s.toothPosition)}`}
      {/* 建议为首时主标签已是建议名,不再重复追加 code 名 */}
      {!isRecLead && trig?.code && ` — ${diagnosisCodeNameZh(trig.code)}`}
      {sourceLabel && `(${sourceLabel})`}{' '}
      <strong className="text-rose-600 tabular-nums">{formatDaysReadable(s.daysSince)}前</strong>
      {cats && `,未启动 ${cats}`}
    </span>
  );
}
