'use client';

import { useCallback, useEffect, useRef, useState } from 'react';
import { usePlanSyncStore } from '@/stores/plan-sync-store';
import { emitPetEvent, onPetEvent, type DirectorScript } from '@/lib/pet-events';

/** 身体能演的姿态(基线姿态 + 一次性演出共用同一词表)。 */
export type PetPose =
  | 'idle'
  | 'think'
  | 'celebrate'
  | 'sleep'
  | 'floss'
  | 'shine'
  | 'chomp'
  | 'vet_exam'
  | 'vet_scale'
  | 'vet_fill'
  | 'vet_polish'
  | 'vet_fluoride'
  | 'absorb';

/** gesture → 一次性姿态映射(greet/think 只有台词/基线,没有专属一次性姿态)。 */
const ONE_SHOT_POSE: Partial<Record<string, PetPose>> = {
  celebrate: 'celebrate',
  sleep: 'sleep',
  floss: 'floss',
  shine: 'shine',
  chomp: 'chomp',
  vet_exam: 'vet_exam',
  vet_scale: 'vet_scale',
  vet_fill: 'vet_fill',
  vet_polish: 'vet_polish',
  vet_fluoride: 'vet_fluoride',
  absorb: 'absorb',
};

const SLEEP_AFTER_MS = 300_000; // 无操作 5 分钟 → 打盹
const GLANCE_MIN_MS = 7_000; // idle 小动作(随机张望)间隔
const GLANCE_MAX_MS = 16_000;

/**
 * 宠物大脑 — 反射层(纯规则,毫秒级,永远在线)。
 *
 * 基线姿态按优先级推导:AI 生成中 think > 用户久未操作 sleep > idle;
 * 一次性演出(celebrate/气泡)由 play(DirectorScript) 叠加,ttl 到点复位回基线。
 * play 是唯一指令入口 —— 将来 LLM 导演的输出也走这里,断了就只是"不说话",宠物照活。
 */
export function usePetBrain(opts: { calm?: boolean } = {}) {
  // calm 模式(助手的脸):不打盹、不跑 idle 小动作轮盘 —— 只在"有意义时刻"
  //   (AI 思考/说话、成约庆祝、切患者打招呼)动,平时安静待命。
  const calm = !!opts.calm;
  const [pose, setPose] = useState<PetPose>('idle');
  const [bubble, setBubble] = useState<string | null>(null);
  /** 自增信号:身体收到后做一次随机张望(idle 防机械感)。 */
  const [glanceSeq, setGlanceSeq] = useState(0);

  const thinking = useRef(false);
  const voiceThinking = useRef(false); // LLM 已发起、第一个词还没到 → 思考脸
  const voiceTalking = useRef(false); // 流式吐字中 → 嘴动(复用 chomp)
  const lastActiveAt = useRef(Date.now());
  const gestureTimer = useRef<ReturnType<typeof setTimeout> | null>(null);
  const bubbleTimer = useRef<ReturnType<typeof setTimeout> | null>(null);

  /** 没有一次性演出时应处的基线姿态。 */
  const basePose = useCallback((): PetPose => {
    if (voiceThinking.current) return 'think'; // 说话前先思考(等第一个词)
    if (voiceTalking.current) return 'chomp'; // 说话中嘴一张一合
    if (thinking.current) return 'think';
    if (!calm && Date.now() - lastActiveAt.current > SLEEP_AFTER_MS) return 'sleep';
    return 'idle';
  }, [calm]);

  /** 演出脚本唯一入口(规则导演现在用,LLM 导演将来同入口)。 */
  const play = useCallback(
    (script: DirectorScript) => {
      const ttl = script.ttlMs ?? 3_000;
      if (script.gesture === 'none') {
        // 显式打断:立即清掉一次性演出,复位基线(组合动作中途被打断用)
        if (gestureTimer.current) {
          clearTimeout(gestureTimer.current);
          gestureTimer.current = null;
        }
        setPose(basePose());
      } else if (script.gesture) {
        const oneShot = ONE_SHOT_POSE[script.gesture] ?? null;
        if (oneShot) {
          if (gestureTimer.current) clearTimeout(gestureTimer.current);
          setPose(oneShot);
          gestureTimer.current = setTimeout(() => {
            gestureTimer.current = null;
            setPose(basePose());
          }, ttl);
        }
      }
      if (script.bubble) {
        if (bubbleTimer.current) clearTimeout(bubbleTimer.current);
        setBubble(script.bubble);
        bubbleTimer.current = setTimeout(() => {
          bubbleTimer.current = null;
          setBubble(null);
        }, ttl);
      }
    },
    [basePose],
  );

  /** 回到基线(若没有一次性演出占着)。 */
  const settle = useCallback(() => {
    if (!gestureTimer.current) setPose(basePose());
  }, [basePose]);

  // ── 感知:AI 生成中(use-assistant-chat 发事件)+ director 脚本直达 ──
  useEffect(
    () =>
      onPetEvent((e) => {
        if (e.type === 'director') {
          play(e.script);
          return;
        }
        if (e.type === 'pet_voice') {
          // think → talk → end:驱动基线姿态(思考脸 / 嘴动 / 复位),气泡走 director
          voiceThinking.current = e.phase === 'think';
          voiceTalking.current = e.phase === 'talk';
          // 清掉残留的一次性 gesture(如刚才的咬合操),让说话姿态立即生效
          if (e.phase !== 'end' && gestureTimer.current) {
            clearTimeout(gestureTimer.current);
            gestureTimer.current = null;
          }
          setPose(basePose());
          return;
        }
        if (e.type === 'cohort_handoff') {
          // ⭐ **这里是唯一决定「怎么演」的地方**(三层架构的大脑层)。
          //   业务侧只发语义事件,换演法只改这一处。
          const { count, treatment, temperature } = e.payload;
          // 从矩阵点进来会带温度档,气泡就说得更具体一点(「正在挑 44 位种植治疗·热…」);
          // 从列表侧「移交助手」进来没有温度,退回到只说治疗项。⛔ 别在这里编一个默认档位。
          const what = treatment
            ? temperature
              ? `${treatment}·${temperature}`
              : treatment
            : '';
          play({
            gesture: 'absorb',
            bubble: what ? `正在挑 ${count} 位${what}…` : `正在挑 ${count} 位…`,
            ttlMs: 2400,
          });
          return;
        }
        if (e.type === 'ai_thinking_start') thinking.current = true;
        if (e.type === 'ai_thinking_end') thinking.current = false;
        settle();
      }),
    [settle, play, basePose],
  );

  // ── 感知:业务事件(直接订阅工作台同步 store,业务代码零改动)──
  // 注:除 LLM 语音外,所有动作都不带说话框 —— 成约只演庆祝动作,切患者只抬头看一眼。
  useEffect(() => {
    let prevSeq = usePlanSyncStore.getState().seq;
    let prevPlanId = usePlanSyncStore.getState().current?.planId ?? null;
    return usePlanSyncStore.subscribe((s) => {
      // 成约 → 庆祝动作(无气泡)
      if (s.seq !== prevSeq) {
        prevSeq = s.seq;
        if (s.status === 'completed') play({ gesture: 'celebrate', ttlMs: 3_600 });
      }
      // 切患者 → 抬头看一眼 + 打招呼气泡(此动作保留说话框)
      const planId = s.current?.planId ?? null;
      if (planId && planId !== prevPlanId) {
        prevPlanId = planId;
        if (s.current?.patientName) {
          setGlanceSeq((g) => g + 1);
          play({ gesture: 'greet', bubble: `开始跟进「${s.current.patientName}」`, ttlMs: 2_600 });
        }
      }
    });
  }, [play]);

  // ── 感知:用户活跃度(打盹/唤醒)+ 周期对账基线姿态 ──
  useEffect(() => {
    const onActivity = () => {
      lastActiveAt.current = Date.now();
      // 在睡 → 立即醒(不等 tick)
      if (!gestureTimer.current) setPose((p) => (p === 'sleep' ? basePose() : p));
    };
    window.addEventListener('pointermove', onActivity, { passive: true });
    window.addEventListener('keydown', onActivity, { passive: true });
    window.addEventListener('wheel', onActivity, { passive: true });
    const tick = setInterval(settle, 5_000);
    return () => {
      window.removeEventListener('pointermove', onActivity);
      window.removeEventListener('keydown', onActivity);
      window.removeEventListener('wheel', onActivity);
      clearInterval(tick);
    };
  }, [basePose, settle]);

  // ── idle 小动作轮盘:张望 / 牙线自理 / 闪亮微笑 / 咬合操(防机械循环)──
  //   calm 模式(助手的脸)关掉整个轮盘:工作区里安静待命,不做环境娱乐动作。
  useEffect(() => {
    if (calm || pose !== 'idle') return;
    let timer: ReturnType<typeof setTimeout>;
    const schedule = () => {
      timer = setTimeout(() => {
        const r = Math.random();
        if (r < 0.4) setGlanceSeq((s) => s + 1);
        else if (r < 0.56) play({ gesture: 'floss', ttlMs: 3_000 });
        else if (r < 0.71) play({ gesture: 'shine', ttlMs: 1_800 });
        else if (r < 0.84) play({ gesture: 'chomp', ttlMs: 2_400 });
        else emitPetEvent({ type: 'vet_combo' }); // ~16%:交给 widget 跑牙医诊疗组合
        schedule();
      }, GLANCE_MIN_MS + Math.random() * (GLANCE_MAX_MS - GLANCE_MIN_MS));
    };
    schedule();
    return () => clearTimeout(timer);
  }, [calm, pose, play]);

  // 卸载清理
  useEffect(
    () => () => {
      if (gestureTimer.current) clearTimeout(gestureTimer.current);
      if (bubbleTimer.current) clearTimeout(bubbleTimer.current);
    },
    [],
  );

  return { pose, bubble, glanceSeq };
}
