'use client';

import * as React from 'react';
import { PersonaFeatureKey } from '@pac/types';
import { HoverCard, HoverCardTrigger, HoverCardContent } from '@/components/ui/hover-card';

/**
 * PersonaFeatureHover — 患者画像 4 个 feature 的算法说明 hover card。
 *
 * 数据来源:apps/pac-service/src/modules/persona/features/*.feature.ts 顶部 JSDoc。
 * 算法 doc 改动时同步这里(后续可考虑后端返回 description,前端零硬编码)。
 *
 * 触发器(children)在 feature 卡片右上角放一个 ? 图标。
 */
export function PersonaFeatureHover({
  featureKey,
  children,
}: {
  featureKey: string;
  children: React.ReactNode;
}) {
  const meta = ALGORITHMS[featureKey];
  if (!meta) return <>{children}</>;
  return (
    <HoverCard openDelay={150} closeDelay={80}>
      {/* 直接把 children 作为 trigger,radix 锚定 children 本身的位置(避免多包一层 0 尺寸 span)*/}
      <HoverCardTrigger asChild>{children}</HoverCardTrigger>
      <HoverCardContent align="end" sideOffset={6} className="w-80 p-3 text-[11.5px]">
        <div className="space-y-2">
          <div className="flex items-baseline justify-between border-b border-slate-200 pb-1.5">
            <span className="text-[13px] font-semibold text-slate-900">{meta.title}</span>
            <span className="text-[10.5px] text-slate-500">{meta.subtitle}</span>
          </div>
          {meta.formula && (
            <div className="rounded bg-slate-50 px-2 py-1.5 font-mono text-[10.5px] text-slate-700 leading-relaxed">
              {meta.formula}
            </div>
          )}
          <ul className="space-y-1 text-slate-600 leading-relaxed">
            {meta.rules.map((r, i) => (
              <li key={i} className="flex gap-2">
                <span className="text-slate-400 flex-none">·</span>
                <span>
                  {r.label && <strong className="text-slate-800 mr-1">{r.label}</strong>}
                  {r.body}
                </span>
              </li>
            ))}
          </ul>
          {meta.note && (
            <p className="border-t border-slate-100 pt-1.5 text-[10.5px] text-slate-500 leading-relaxed">
              {meta.note}
            </p>
          )}
        </div>
      </HoverCardContent>
    </HoverCard>
  );
}

interface AlgoMeta {
  title: string;
  subtitle: string;
  formula?: string;
  rules: { label?: string; body: string }[];
  note?: string;
}

const ALGORITHMS: Record<string, AlgoMeta> = {
  [PersonaFeatureKey.RFM]: {
    title: '价值分群 (RFM)',
    subtitle: 'R 最近 · F 频次 · M 金额 → 八象限',
    formula: 'R(就诊间隔)+ F(就诊次)+ M(净消费分位)各 1-5 分',
    rules: [
      { label: '重要价值', body: 'R≥4 F≥3 M≥4 — 近期高频高额' },
      { label: '重要保持/发展/挽留', body: '高额(M≥4)但 R 或 F 偏弱' },
      { label: '一般价值/保持/发展', body: '对应象限但 M<4(消费偏低)' },
      { label: '低活跃', body: 'R≤2 或各项普遍偏低' },
    ],
    note: 'M 分位按本租户群体算;另产 valueTier(¥档)+ 生命周期。喂优先级"意愿·RFM依从"',
  },
  [PersonaFeatureKey.AGE_BRACKET]: {
    title: '年龄段',
    subtitle: '从生日当下算(snapshot)',
    rules: [
      { body: '婴幼儿 0-2 / 学龄前 3-6 / 替牙期 7-11 / 青少年 12-17' },
      { body: '青年 18-25 / 中青年 26-30 / 中年 31-45 / 中老年 46-54 / 老年 ≥55' },
    ],
    note: '生日缺失或年龄越界(<0 / >120)→ 不打标签',
  },
  [PersonaFeatureKey.GENDER]: {
    title: '性别',
    subtitle: '影响话术与项目推荐',
    rules: [
      { label: '男性', body: 'gender = M / 男' },
      { label: '女性', body: 'gender = F / 女' },
      { label: '未知', body: '其他取值(始终打标签)' },
    ],
  },
  [PersonaFeatureKey.ACQUISITION_CHANNEL]: {
    title: '获客渠道',
    subtitle: '初诊来源(数仓 L2)',
    rules: [
      { body: '客户首次到诊的获客来源,数仓按初诊来源规则算好,一经判定不改' },
      { body: '一级 = PAC 标准枚举 / 二级 = host 原值' },
    ],
    note: '无渠道值(老数据/未摄入)→ 不打标签',
  },
  [PersonaFeatureKey.FAMILY_STRUCTURE]: {
    title: '家庭构成',
    subtitle: '直系亲属关系反推',
    rules: [
      { label: '多代之家', body: '有长辈(父母/祖辈)— 跨代优先' },
      { label: '多口之家', body: '有子女(含单亲)' },
      { label: '两口之家', body: '有配偶' },
      { label: '单身家庭', body: '仅非直系边(同辈/朋友)' },
    ],
    note: '无任何关系边 → 不打标签;依赖关系边覆盖,当前样本偏低',
  },
  [PersonaFeatureKey.REFERRAL_CHAMPION]: {
    title: '转介绍达人',
    subtitle: '老带新(有推荐且带来转化)',
    rules: [
      { label: '家庭型', body: '带家人:直系家庭关系 ≥3 人' },
      { label: '社交型', body: '推外人:非同手机号推荐 ≥3 人' },
      { body: 'v1 用 DW 预聚合:推荐人数 + 带来转化总额(>0)' },
    ],
    note: '推荐<3 或无转化额 → 不打标签。喂优先级"信任 +1"',
  },
  [PersonaFeatureKey.LIFECYCLE_STAGE]: {
    title: '生命周期',
    subtitle: '时间 + 消费规则',
    rules: [
      { label: '潜客', body: '0 就诊 + 有预约/咨询' },
      { label: '新客', body: '首诊 ≤180 天 且 就诊 ≤3 次' },
      { label: '成长客', body: '近1年消费 > 历史年均 ×1.5' },
      { label: '成熟客', body: '末诊 ≤540 且 年均就诊 ≥0.5(稳定)' },
      { label: '待激活 / 沉睡 / 流失', body: '末诊 180-540 / 540-730 / >730 天' },
    ],
    note: '喂优先级"意愿·信任基础"(成熟9 … 流失0)',
  },
  [PersonaFeatureKey.TREATMENT_HISTORY]: {
    title: '治疗史',
    subtitle: '读 treatment category(可多标签)',
    rules: [
      { label: '种植史', body: 'implant' },
      { label: '正畸史', body: 'orthodontic' },
      { label: '修复史', body: 'prosthodontic / cosmetic(冠桥/贴面/嵌体)' },
      { label: '牙周治疗史', body: 'periodontic' },
    ],
    note: '基础治疗(拔/补/根管)不计。喂优先级"信任·同类治疗史 +1"',
  },
  [PersonaFeatureKey.TIME_PREFERENCE]: {
    title: '时间偏好',
    subtitle: '预约时刻统计(可多标签)',
    rules: [
      { label: '工作日 / 周末', body: '工作日占比 ≥60% / 周末 ≥50%' },
      { label: '上午 / 下午 / 晚间', body: '8-12 / 12-18 / 18-21 时占比 ≥50%' },
    ],
    note: '近2年预约槽(北京时区),记录 <2 条 → 不打标签',
  },
  [PersonaFeatureKey.DISCOUNT_ANCHOR]: {
    title: '折扣锚点',
    subtitle: '历史最深折扣(价格底线)',
    formula: '折扣率 = 1 − 折扣额 / 应收',
    rules: [
      { body: '取真实治疗(原价 ≥¥500)上谈到的最深【部分】折扣 + 日期/项目' },
      { body: '排除免费洁牙/检查促销(全免 0 折)避免霸占锚点' },
    ],
    note: '无折扣记录 → 不打标签(业务:无锚点则换推权益,不直接降价)',
  },
  [PersonaFeatureKey.SPECIAL_ATTENTION]: {
    title: '特别关注',
    subtitle: '排班/触达需注意(可多标签)',
    rules: [
      { label: '屡次爽约', body: '近1年履约率 <50% 且决定数 ≥3' },
      { label: '经常迟到', body: '迟到(>15min)占比 ≥50% 且 ≥3 次' },
      { label: '免打扰', body: '主档标记不打扰' },
      { label: '不可等候', body: 'notes/标签/病历含 赶时间/不能等' },
    ],
  },
  [PersonaFeatureKey.TREATMENT_SENSITIVITY]: {
    title: '治疗敏感',
    subtitle: '病历关键词(可多标签)',
    rules: [
      { label: '看牙恐惧', body: '牙科恐惧/害怕看牙/牙科焦虑' },
      { label: '晕针 / 晕血', body: '晕针·害怕打针 / 晕血·见血不适' },
      { label: '密闭恐惧', body: '幽闭/密闭/长时间张口不适' },
    ],
    note: '关键词按真实数据精炼排假阳(不用裸"紧张/见血/张口受限")',
  },
  [PersonaFeatureKey.CONTRAINDICATION]: {
    title: '禁忌标签',
    subtitle: '治疗可行性 + 安全预警',
    rules: [
      { label: '种植禁忌', body: 'v1 仅:年龄 ≤18(骨骼发育未完全)' },
      { body: '其余(糖尿/高血压/过敏/抗凝/妊娠…)依赖既往史自由文本 → 留 Layer C(LLM)' },
    ],
    note: '年龄禁忌满 19 岁重算自动解除(validUntil 标到期日)',
  },
  [PersonaFeatureKey.URGENCY_LEVEL]: {
    title: '急迫等级',
    subtitle: '潜在治疗路径 × 末诊',
    rules: [
      { label: '紧急', body: '末诊 >90 天(有未满足需求且久未回诊)' },
      { label: '高', body: '末诊 30-90 天' },
      { label: '中', body: '末诊 <30 天 或 新发现' },
    ],
    note: '取所有潜在待转里最急的。喂优先级"急迫性 ×0.4"',
  },
  [PersonaFeatureKey.POTENTIAL_TREATMENT]: {
    title: '潜在治疗',
    subtitle: '诊断/建议了但没启动(可多标签)',
    rules: [
      { label: '种植 / 修复 / 拔牙', body: 'K08(>18岁) / K03 / K01·K03残根' },
      { label: '正畸 / 早矫', body: 'K07(>12岁) / K07(3-12岁)' },
      { label: '根管 / 牙周 / 补牙', body: 'K04 / K05·K06 / K02' },
    ],
    note: '与召回同源(共享 gap 核心)。喂优先级"价值性 ×0.3"',
  },
  [PersonaFeatureKey.ENTITLEMENT_STATUS]: {
    title: '权益身份',
    subtitle: '商保 / 医保结算史(事实投影,史+最近日期)',
    rules: [
      { label: '商保客户', body: '历史用商业保险结算过(channel=保险 或 有保司名),展示保司 + 最近一次日期' },
      { label: '医保结算', body: '用过社保医保结算(普惠,非高端 VIP 信号)' },
      { label: '不打标签', body: '无任何保险结算记录' },
    ],
    note: '商保强时效(雇主团险换工作即失效,DW 无保单有效期)→ 只陈述"曾经+最近日期",不断言"当前在保";新鲜度由人/打分器按最近日期判断',
  },
};
