'use client';

import { useEffect, useState } from 'react';
import { onPetEvent } from '@/lib/pet-events';

/**
 * CohortStream — 「人群移交」的**舞台层**:一串数据流粒子从矩阵格子飞进助手。
 *
 * 三层架构里它属于**身体/舞台**那一层(同 pet-body):
 *   业务侧只发一个语义事件 `cohort_handoff{ count, from }`,**不描述怎么飞**;
 *   飞法、粒子数、时长全在这里。换成传送带、换成粒子聚合,业务代码一行不动。
 *
 * ⭐ 两个端点都**在播放的那一刻现取**,不预存:
 *   起点 = 事件带来的格子矩形(浮层随后就关了,不现取就没了);
 *   终点 = 助手 FAB 的实时位置 —— 那颗钮**可以被主管拖到任意角落**并记进 localStorage,
 *   写死右下角的话,拖过钮的人看到的就是粒子飞向空气。
 */

/** 单颗粒子的飞行时长。⚠️ 与 assistant-store 的 HANDOFF_FLIGHT_MS 是同一件事,那边引这里 */
export const STREAM_FLIGHT_MS = 620;
/** 粒子数与出发间隔 —— 末颗落点 ≈ (N-1)*STAGGER + FLIGHT */
const DOTS = 10;
const STAGGER_MS = 45;
/** 整段演出总时长(末颗落地) */
export const STREAM_TOTAL_MS = (DOTS - 1) * STAGGER_MS + STREAM_FLIGHT_MS;

interface Flight {
  id: number;
  path: string;
}

export function CohortStream() {
  const [flights, setFlights] = useState<Flight[]>([]);

  useEffect(() => {
    let seq = 0;
    return onPetEvent((e) => {
      if (e.type !== 'cohort_handoff' || !e.payload.from) return;
      const from = e.payload.from;
      // 终点:助手 FAB 的**当前**位置(可拖动,所以必须现查)
      const fab = document.querySelector('[data-assistant-fab]')?.getBoundingClientRect();
      if (!fab) return; // 没挂助手(无 AGENT_INVOKE 权限)→ 不演,静默跳过
      const x0 = from.x + from.w / 2;
      const y0 = from.y + from.h / 2;
      const x1 = fab.left + fab.width / 2;
      const y1 = fab.top + fab.height / 2;
      // 控制点:取中点再往"垂直于连线"的方向抬一点 → 一条自然的弧,而不是直线飞
      // ⚠️ 抬的方向跟着走向翻转,否则从左上飞和从右下飞会一个上凸一个下凹,看着像两套动画
      const mx = (x0 + x1) / 2;
      const my = (y0 + y1) / 2;
      const dist = Math.hypot(x1 - x0, y1 - y0);
      const lift = Math.min(120, dist * 0.22);
      const cx = mx + ((y1 - y0) / (dist || 1)) * lift;
      const cy = my - ((x1 - x0) / (dist || 1)) * lift;
      const id = ++seq;
      setFlights((f) => [...f, { id, path: `path("M ${x0} ${y0} Q ${cx} ${cy} ${x1} ${y1}")` }]);
      // 自清理:动画是 forwards,不删节点会一直堆在 DOM 里
      window.setTimeout(() => setFlights((f) => f.filter((x) => x.id !== id)), STREAM_TOTAL_MS + 120);
    });
  }, []);

  if (flights.length === 0) return null;

  return (
    <>
      {flights.map((f) =>
        Array.from({ length: DOTS }, (_, i) => (
          <span
            key={`${f.id}-${i}`}
            aria-hidden
            className="pac-stream-dot bg-brand-600"
            style={
              {
                '--pac-stream-path': f.path,
                '--pac-stream-dur': `${STREAM_FLIGHT_MS}ms`,
                animationDelay: `${i * STAGGER_MS}ms`,
                // 首尾两颗淡一点、小一点 → 队列有头有尾,不是一坨方块平移
                opacity: i === 0 || i === DOTS - 1 ? 0.55 : 1,
              } as React.CSSProperties
            }
          />
        )),
      )}
    </>
  );
}
