'use client';

import { useEffect, useRef, useState } from 'react';
import { Bot } from 'lucide-react';
import { Permission } from '@pac/types';
import { cn } from '@/lib/utils';
import { useHasPermission } from '@/hooks/use-permission';
import { usePlanSyncStore } from '@/stores/plan-sync-store';
import { AssistantChat } from './assistant-chat';

/**
 * AssistantWidget — 详情页右下角吸附助手(与 /assistant 同一能力,复用 AssistantChat)。
 *
 * 收起 = 右下角圆形悬浮钮;展开 = 400×~75vh 吸附小窗。
 * 关键:收起用 CSS 隐藏而非卸载 → 对话/工具步骤/听写状态全保留;
 * 挂在 plans/layout(路由段之上)→ 切患者对话也不丢。
 * 权限同 /assistant 页(AGENT_INVOKE),无权限不渲染。
 */
export function AssistantWidget() {
  const allowed = useHasPermission(Permission.AGENT_INVOKE);
  const [open, setOpen] = useState(false);
  // 窗口落点:打开瞬间按"钮的当前位置"计算(拖钮的意义所在),并夹紧在视窗内
  const [winPos, setWinPos] = useState<{ x: number; y: number } | null>(null);

  const openAt = (fab: DOMRect) => {
    const W = Math.min(400, window.innerWidth - 16);
    const H = Math.min(620, Math.round(window.innerHeight * 0.78));
    // 水平:钮在屏幕右半 → 窗口右缘对齐钮右缘;左半 → 左缘对齐
    let x = fab.left + fab.width / 2 > window.innerWidth / 2 ? fab.right - W : fab.left;
    // 垂直:优先弹在钮上方,放不下弹下方
    let y = fab.top - H - 8;
    if (y < 8) y = fab.bottom + 8;
    x = Math.min(Math.max(x, 8), window.innerWidth - W - 8);
    y = Math.min(Math.max(y, 8), window.innerHeight - H - 8);
    setWinPos({ x, y });
    setOpen(true);
  };
  // 场景化开场建议(规则,非 AI):有当前患者 → 围绕该患者;否则兜底通用
  const current = usePlanSyncStore((s) => s.current);
  const examples = current?.patientName
    ? [
        `${current.patientName}为什么被召回?帮我捋一下关键事实`,
        `查一下${current.patientName}的画像和潜在治疗`,
        `这通电话怎么开口比较好?给我两句开场`,
      ]
    : ['现在召回池里优先级最高的是谁?', '帮我准备一下今天要跟进的召回工作'];

  if (!allowed) return null;

  return (
    <>
      {/* 吸附窗:常驻挂载,关着时 invisible(状态不丢) */}
      <div
        style={winPos ? { left: winPos.x, top: winPos.y } : undefined}
        className={cn(
          'fixed z-[60] flex flex-col overflow-hidden rounded-xl border border-slate-100 shadow-2xl',
          !winPos && 'bottom-4 right-4',
          'h-[620px] max-h-[78vh] w-[400px] max-w-[calc(100vw-2rem)]',
          'transition-[opacity,transform] duration-150',
          open ? 'translate-y-0 opacity-100' : 'pointer-events-none invisible translate-y-2 opacity-0',
        )}
      >
        <AssistantChat variant="widget" onClose={() => setOpen(false)} examples={examples} />
      </div>
      {/* 悬浮开关钮(可拖移:位移 >4px 判定为拖,松手即记忆位置;否则当点击打开) */}
      {!open && <DraggableFab onOpen={openAt} />}
    </>
  );
}


const FAB_POS_KEY = 'pac-assistant-fab-pos';

/** 可拖移悬浮钮:pointer 事件拖动(阈值 4px 区分点击),位置 localStorage 记忆并随窗口缩放夹紧。 */
function DraggableFab({ onOpen }: { onOpen: (fabRect: DOMRect) => void }) {
  const [pos, setPos] = useState<{ x: number; y: number } | null>(null); // null = 默认右下角
  const drag = useRef<{ startX: number; startY: number; baseX: number; baseY: number; moved: boolean } | null>(null);
  const btnRef = useRef<HTMLButtonElement>(null);

  useEffect(() => {
    try {
      const raw = localStorage.getItem(FAB_POS_KEY);
      if (raw) setPos(clampPos(JSON.parse(raw) as { x: number; y: number }));
    } catch {
      /* 忽略坏数据 */
    }
  }, []);

  const onPointerDown = (e: React.PointerEvent) => {
    const r = btnRef.current!.getBoundingClientRect();
    drag.current = { startX: e.clientX, startY: e.clientY, baseX: r.left, baseY: r.top, moved: false };
    btnRef.current!.setPointerCapture(e.pointerId);
  };
  const onPointerMove = (e: React.PointerEvent) => {
    const d = drag.current;
    if (!d) return;
    const dx = e.clientX - d.startX;
    const dy = e.clientY - d.startY;
    if (!d.moved && Math.hypot(dx, dy) < 4) return;
    d.moved = true;
    setPos(clampPos({ x: d.baseX + dx, y: d.baseY + dy }));
  };
  const onPointerUp = () => {
    const d = drag.current;
    drag.current = null;
    if (!d) return;
    if (d.moved) {
      setPos((p) => {
        if (p) localStorage.setItem(FAB_POS_KEY, JSON.stringify(p));
        return p;
      });
    } else {
      const r = btnRef.current?.getBoundingClientRect();
      if (r) onOpen(r);
    }
  };

  return (
    <button
      ref={btnRef}
      type="button"
      title="打开助手(可拖动)"
      onPointerDown={onPointerDown}
      onPointerMove={onPointerMove}
      onPointerUp={onPointerUp}
      style={pos ? { left: pos.x, top: pos.y } : undefined}
      className={cn(
        'fixed z-[60] inline-flex h-12 w-12 touch-none items-center justify-center rounded-full bg-teal-600 text-white shadow-lg hover:bg-teal-700',
        !pos && 'bottom-4 right-4',
      )}
    >
      <Bot className="h-5 w-5" />
    </button>
  );
}

function clampPos(p: { x: number; y: number }): { x: number; y: number } {
  const size = 48; // h-12 w-12
  return {
    x: Math.min(Math.max(p.x, 4), window.innerWidth - size - 4),
    y: Math.min(Math.max(p.y, 4), window.innerHeight - size - 4),
  };
}
