'use client';

import { type ReactNode } from 'react';
import { cn } from '@/lib/utils';
import { Chip } from './shared';
import { ChainDetailView } from './chain-viz';
import { EmrSoapView } from './emr-soap-view';
import { FactsTimeline } from './facts-timeline';
import { ToothTimeline } from './tooth-timeline';
import { PersonaDetailList } from './persona-detail-list';
import type { Chain, PersonaFeature, PlanReason } from './mock-data';
import type { AdaptedFact } from './adapt-data';
import type { ReturnVisitItem } from './plan-detail-app';

export type DrawerKind = 'chain-detail' | 'medical' | 'image' | 'facts' | 'treatments' | 'teeth' | 'persona' | 'return-visits' | null;

export function Drawer({
  open,
  onClose,
  kind,
  chains,
  persona,
  summaries,
  reason,
  reasons,
  facts,
  fmtRel,
  returnVisits,
  summaryOverride,
  summaryStreaming,
  onRegenerateSummary,
}: {
  open: boolean;
  onClose: () => void;
  kind: DrawerKind;
  chains: Chain[];
  persona: { computedAt: Date; refreshedAt: Date; features: PersonaFeature[] };
  summaries: {
    medical_record: { content: string; generatedAt: Date };
    treatment_chain: { content: string; generatedAt: Date };
  };
  reason: PlanReason;
  /// 生产召回结果全量(plan.reasons)— ToothTimeline 对账用
  reasons: PlanReason[];
  /// v2.1:所有 active fact(FactsTimeline + ImageDrawer 用)
  facts: AdaptedFact[];
  fmtRel: (d: Date) => string;
  /// 历史联系(诊所回访)结构化记录 — 「历史联系」卡片「详情」抽屉用
  returnVisits: ReturnVisitItem[];
  /** AI 流式重生成结果(部分或完成);存在时覆盖 mock summaries 显示 */
  summaryOverride?: {
    medicalRecord?: string;
    treatmentChain?: string;
  };
  /** 是否正在流式生成中(显示 "AI 正在生成" 指示) */
  summaryStreaming?: boolean;
  /** 触发重新生成(plan-detail-app 传入,绑了 planId) */
  onRegenerateSummary?: () => void;
}) {
  if (!open || !kind) return null;

  const medicalText = summaryOverride?.medicalRecord ?? summaries.medical_record.content;
  const chainText = summaryOverride?.treatmentChain ?? summaries.treatment_chain.content;

  let title = '';
  let subtitle = '';
  let body: ReactNode = null;
  let width = 'w-[540px]';

  if (kind === 'chain-detail') {
    title = '治疗链全景';
    subtitle = `${chains.length} 条治疗链 · 含本次召回目标 + 历史信任锚`;
    // AI 跨链叙述移除 — 5 阶段 timeline 已表达全部事实(具体动作 / 关键事实 / 医生 / 时间 / 建议下一步),
    // AI 文本再叠加是冗余;后续若客服真有"自然语言摘要"需求,可在病历快读里加而非这里。
    body = <ChainDetailView chains={chains} />;
    width = 'w-[760px]';
  } else if (kind === 'medical') {
    // 病历快读改为 PAC 事实驱动 + SOAP 结构化展示(W3 末从 AI 文本改造)
    // 数据源:emr_record + 同 source_encounter 的 diagnosis_record / treatment_record / image_record
    const emrCount = facts.filter((f) => f.type === 'emr_record').length;
    title = '病历快读';
    subtitle = `${emrCount} 次接诊病历`;
    body = <EmrSoapView facts={facts} />;
    width = 'w-[700px]';
  } else if (kind === 'image') {
    const imageFacts = facts.filter((f) => f.type === 'image_record');
    title = `影像资料(${imageFacts.length})`;
    subtitle = imageFacts.length > 0
      ? `最早 ${imageFacts[imageFacts.length - 1]?.occurredAt?.slice(0, 10) ?? '—'} ~ 最近 ${imageFacts[0]?.occurredAt?.slice(0, 10) ?? '—'}`
      : '无影像 fact';
    body = <ImageFactsView facts={imageFacts} />;
    width = 'w-[640px]';
  } else if (kind === 'facts') {
    title = `患者事实时间轴(${facts.length})`;
    subtitle = '按时间倒序';
    body = <FactsTimeline facts={facts} />;
    width = 'w-[640px]';
  } else if (kind === 'treatments') {
    // 治疗历史卡「详情」:同 facts 时间轴,默认只勾选治疗(可在 chip 里再放开看其余)
    const txCount = facts.filter((f) => f.type === 'treatment_record').length;
    title = `治疗时间轴(${txCount})`;
    subtitle = '仅治疗 · 时间倒序(治疗计划可在上方筛选打开)';
    body = <FactsTimeline facts={facts} initialTypes={['treatment_record']} />;
    width = 'w-[640px]';
  } else if (kind === 'return-visits') {
    title = `历史联系(${returnVisits.length})`;
    subtitle = '诊所回访记录 · 时间倒序';
    body = <ReturnVisitsList visits={returnVisits} />;
    width = 'w-[520px]';
  } else if (kind === 'teeth') {
    title = '牙位事实';
    subtitle = '每颗牙 / 全口治疗线 · 时间倒序';
    body = <ToothTimeline facts={facts} />;
    width = 'w-[560px]';
  } else if (kind === 'persona') {
    title = '画像标签';
    // 「更新于」用 refreshedAt(内容真实新鲜度):只有天数漂移时后端就地刷新、不升版本,
    // computedAt 会停在版本创建那刻,拿它显示会让客服以为数据比实际更旧。
    subtitle = `更新于 ${fmtRel(persona.refreshedAt)} · ${persona.features.length} 项画像`;
    body = <PersonaDetailList features={persona.features} facts={facts} />;
  }

  return (
    <div className="fixed inset-0 z-[60] flex" onClick={onClose}>
      <div className="flex-1 bg-slate-900/30" />
      <aside
        className={cn('max-w-[92vw] bg-white shadow-2xl border-l border-slate-100 flex flex-col', width)}
        onClick={(e) => e.stopPropagation()}
      >
        <header className="px-5 py-3.5 border-b border-slate-100 flex items-center justify-between flex-none">
          <div>
            <h3 className="text-[14px] font-semibold text-slate-900">{title}</h3>
            <p className="text-[11px] text-slate-500 mt-0.5">{subtitle}</p>
          </div>
          <button
            onClick={onClose}
            className="w-7 h-7 rounded-md hover:bg-slate-100 flex items-center justify-center text-slate-500"
          >
            <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" className="w-4 h-4">
              <path d="M6 6l12 12M18 6L6 18" strokeLinecap="round" />
            </svg>
          </button>
        </header>
        <div className="flex-1 overflow-y-auto p-5">{body}</div>
      </aside>
    </div>
  );
}

// ──────────────────────────────────────────
// 重新生成摘要按钮 + 流式中提示
// ──────────────────────────────────────────
function RegenSummaryBtn({
  streaming,
  onClick,
}: {
  streaming: boolean;
  onClick?: () => void;
}) {
  if (!onClick) return null;
  return (
    <button
      onClick={onClick}
      disabled={streaming}
      title={streaming ? 'AI 正在生成中…' : '重新生成此摘要(同时刷新另外 2 段)'}
      className={cn(
        'inline-flex items-center gap-1 px-2 py-0.5 rounded text-[10.5px] transition-colors',
        streaming
          ? 'text-slate-400 bg-slate-100 cursor-not-allowed'
          : 'text-slate-500 hover:text-indigo-700 hover:bg-indigo-50',
      )}
    >
      <svg
        viewBox="0 0 24 24"
        fill="none"
        stroke="currentColor"
        strokeWidth="1.8"
        strokeLinecap="round"
        strokeLinejoin="round"
        className={cn('w-3 h-3', streaming && 'animate-spin')}
      >
        <path d="M23 4v6h-6M1 20v-6h6" />
        <path d="M3.51 9a9 9 0 0 1 14.85-3.36L23 10M1 14l4.64 4.36A9 9 0 0 0 20.49 15" />
      </svg>
      {streaming ? 'AI 生成中' : '重新生成'}
    </button>
  );
}

function StreamingHint() {
  return (
    <div className="text-[11px] text-indigo-600 font-mono mb-2 inline-flex items-center gap-1">
      <span className="inline-flex items-center gap-[2px]">
        <span className="w-1 h-1 rounded-full bg-indigo-500 animate-[pulse_1.2s_ease-in-out_infinite]" />
        <span className="w-1 h-1 rounded-full bg-indigo-500 animate-[pulse_1.2s_ease-in-out_0.2s_infinite]" />
        <span className="w-1 h-1 rounded-full bg-indigo-500 animate-[pulse_1.2s_ease-in-out_0.4s_infinite]" />
      </span>
      AI 正在生成 · 流式输出中
    </div>
  );
}

// ──────────────────────────────────────────
// ImageFactsView — image_record fact 列表(真实数据)
// 影像原图走宿主系统(actionUrls.VIEW_IMAGE);此处只展示 metadata + finding
// ──────────────────────────────────────────
function ImageFactsView({ facts }: { facts: AdaptedFact[] }) {
  if (facts.length === 0) {
    return (
      <div className="text-center py-12 text-sm text-slate-400">
        无影像 fact
        <div className="text-[10.5px] mt-1.5">
          (DW 给的是 metadata + URL,原图走宿主影像系统跳转)
        </div>
      </div>
    );
  }
  return (
    <div className="space-y-2.5">
      {facts.map((f) => {
        const c = (f.content ?? {}) as Record<string, unknown>;
        const modality = (c.modality as string | undefined) ?? 'image';
        const finding = (c.finding as string | undefined) ?? null;
        const tooths = Array.isArray(c.tooth_positions)
          ? (c.tooth_positions as string[]).join(' / ')
          : ((c.tooth_position as string | undefined) ?? null);
        const encId = c.encounter_external_id as string | undefined;
        return (
          <div key={f.id} className="rounded-md border border-slate-100 p-3">
            <div className="flex items-center justify-between mb-1.5">
              <div className="flex items-center gap-2">
                <Chip tone="violet" size="xs">
                  {modality.toUpperCase()}
                </Chip>
                {tooths && (
                  <span className="text-[11px] text-slate-600 font-mono tabular-nums">
                    牙位 {tooths}
                  </span>
                )}
              </div>
              <span className="text-[10.5px] text-slate-400 tabular-nums font-mono">
                {f.occurredAt?.slice(0, 10) ?? '—'}
              </span>
            </div>
            {finding ? (
              <div className="text-[12px] text-slate-700 leading-relaxed">{finding}</div>
            ) : (
              <div className="text-[11px] text-slate-400 italic">(无 finding 备注)</div>
            )}
            {encId && (
              <div className="mt-1.5 text-[10px] text-slate-400 font-mono">
                source encounter: {encId}
              </div>
            )}
          </div>
        );
      })}
      <div className="text-[10.5px] text-slate-400 pt-2 border-t border-slate-100">
        如需查看原始 DICOM,请跳转宿主影像系统(deep-link 待 host actionUrls 接入)
      </div>
    </div>
  );
}

// ──────────────────────────────────────────
// CBCT Image View(mock placeholder)— deprecated,留作 fallback
// ──────────────────────────────────────────
function CBCTImageView() {
  return (
    <div className="space-y-3">
      <div className="aspect-[4/3] rounded-lg border border-slate-100 bg-slate-900 relative overflow-hidden">
        <div
          className="absolute inset-0"
          style={{ backgroundImage: 'radial-gradient(circle at 50% 60%, #475569 0%, #0f172a 50%, #000 100%)' }}
        />
        <svg viewBox="0 0 400 300" className="absolute inset-0 w-full h-full opacity-70">
          <path d="M80 180 Q200 80 320 180" stroke="#64748b" strokeWidth="2" fill="none" opacity="0.6" />
          {[100, 130, 160, 190, 220, 250, 280, 300].map((x, i) => (
            <rect
              key={i}
              x={x}
              y={150 + Math.abs(i - 4) * 8}
              width="18"
              height="32"
              rx="3"
              fill="#94a3b8"
              opacity="0.7"
            />
          ))}
          <rect x="139" y="170" width="18" height="32" rx="3" fill="none" stroke="#f43f5e" strokeWidth="2" strokeDasharray="4 3" />
          <line x1="148" y1="170" x2="148" y2="130" stroke="#f43f5e" strokeWidth="1.5" />
          <circle cx="148" cy="125" r="3" fill="#f43f5e" />
        </svg>
        <div className="absolute top-3 left-3 px-2 py-1 rounded bg-black/60 text-white text-[10px] font-mono">
          CBCT · 36 区骨量评估
        </div>
        <div className="absolute top-3 right-3 px-2 py-1 rounded bg-rose-600 text-white text-[10px] font-medium">
          医生标注 · 牙缺失
        </div>
        <div className="absolute bottom-3 left-3 text-white/70 text-[10px] font-mono">
          2025.12.10 · 医生 李**军
        </div>
        <div className="absolute bottom-3 right-3 text-white/70 text-[10px] font-mono tabular-nums">骨量 11.2mm</div>
      </div>
      <div className="text-[11.5px] text-slate-500 leading-relaxed">
        如需重新加载原始 DICOM,请跳转宿主影像系统。诊断结论与医嘱详见「病历快读」。
      </div>
    </div>
  );
}

/**
 * 历史联系(诊所回访)结构化列表 — 「历史联系」卡片「详情」抽屉内容。
 *
 * 「最近一次」单独标出来:客服接手第一个问题就是"上次联系聊到哪儿了",而列表按日期倒序时
 * 头部很可能是**还没到日子的排程**,肉眼分不出哪条才是真发生过的最后一次。
 * 判定口径与后端摘要一致(taskDate ≤ 今天 的第一条),两处说法不会打架。
 *
 * ⚠️ 宿主回访表只有**事由标签 + 结果标签**,没有逐字沟通内容。空着不如明说"未留结果",
 * 免得客服以为是 PAC 没展示(2026-07 可用性测试的原始反馈就是这个误会)。
 */
function ReturnVisitsList({ visits }: { visits: ReturnVisitItem[] }) {
  if (visits.length === 0) {
    return <div className="text-center py-12 text-sm text-slate-400">无历史联系记录</div>;
  }
  const today = new Date().toISOString().slice(0, 10);
  const latestPast = visits.findIndex((v) => v.taskDate != null && v.taskDate <= today);
  return (
    <div className="space-y-2">
      {visits.map((v, i) => {
        const done = v.status === '已回访' || v.taskStatus === '已完成';
        const future = v.taskDate != null && v.taskDate > today;
        const latest = i === latestPast;
        return (
          <div
            key={i}
            className={cn(
              'flex items-start gap-2.5 text-[12.5px] py-1 border-b border-slate-50 last:border-0',
              latest && 'bg-teal-50/50 -mx-2 px-2 rounded',
            )}
          >
            <span className={cn('flex-none mt-[5px] w-1.5 h-1.5 rounded-full', done ? 'bg-teal-400' : 'bg-slate-300')} />
            <div className="flex-1 min-w-0">
              <div className="flex items-center gap-1.5 flex-wrap">
                {latest && (
                  <span className="flex-none rounded bg-teal-600 px-1 py-px text-[10px] font-medium text-white">
                    最近一次
                  </span>
                )}
                {future && (
                  <span className="flex-none rounded bg-slate-100 px-1 py-px text-[10px] text-slate-500">未到期</span>
                )}
                <span className="font-medium text-slate-700">{v.type ?? '回访'}</span>
                {v.status && <span className="text-slate-400">· {v.status}</span>}
                {v.taskDate && <span className="text-slate-400 tabular-nums">{v.taskDate}</span>}
                {v.treatmentItems && <span className="text-teal-700/70">· {v.treatmentItems}</span>}
              </div>
              {v.followContent && (
                <div className="text-slate-600 leading-snug break-words mt-0.5">{v.followContent}</div>
              )}
              {v.result ? (
                <div className="text-slate-400 leading-snug break-words mt-0.5">结果:{v.result}</div>
              ) : (
                latest && <div className="text-slate-400 leading-snug mt-0.5">结果:宿主未记录</div>
              )}
            </div>
          </div>
        );
      })}
    </div>
  );
}

