'use client';

import { useCallback, useEffect, useState } from 'react';
import { TEMPERATURE_META, type TemperatureValue } from '@pac/types';
import { plansApi, type PoolMatrix as PoolMatrixData } from '@/components/plans/plans-api';
import { PoolMatrix } from '@/components/plans/pool-matrix';
import { useAssignmentSyncStore } from '@/stores/assignment-sync-store';
import { useAssistantStore } from '@/stores/assistant-store';

/**
 * 「分一批新的」—— **常驻面板**，摆在「我分的批次」正上方。
 *
 * 🔴 2026-08-11 产品定：**不再由按钮触发、也不再有第二版**。
 *   在此之前有两版（设计稿 `newBatchMode`）：`window` 居中 modal、`arcade` 里世界打地鼠，
 *   由头部一个「样式1 / 样式2」开关切，点「＋ 分一批新的」才展开。
 *   ⇒ 现在只保留 `window` 那份的内容（矩阵本身），并且**直接摊开**：
 *   矩阵是主管进这一屏的**第一个动作**，藏在按钮后面等于每次都要多点一下才看得到池子。
 *   ⛔ 别再把它收回浮层里 —— 上下结构（挑格子 → 看这些格子分出去之后怎么样）
 *   本身就是这一栏要讲的因果，收起来这条线就断了。
 * ⛔ 里世界那版（传送门 / 锤子光标 / 数据粒子）连同 globals.css 的 `.pac-portal-*`
 *   一起删了 —— 需要考古去翻 git，⛔ 别凭印象重写一份。
 *
 * ⛔ 挑完格子走的仍是**同一条**移交路：`useAssistantStore.handoff()` ——
 *   发数据流 → 粒子飞到助手 → 落地后自动开大窗并说那句话。
 *   ⚠️ 这条链路是现成的，⛔ 别在这儿另写一套移交：移交的时序（动画多长、
 *   什么时候开窗）是舞台层的事，业务侧复制一份必然漂。
 */

type Picked = {
  treatment: string;
  treatmentZh: string;
  temperature: TemperatureValue;
  count: number;
  rect: { x: number; y: number; w: number; h: number };
};

function handoff(c: Picked) {
  const tempZh = TEMPERATURE_META[c.temperature].zh;
  useAssistantStore.getState().handoff({
    text: `帮我给「${c.treatmentZh} · ${tempZh}」这批患者出一份分配方案`,
    from: c.rect,
    count: c.count,
    treatment: c.treatmentZh,
    temperature: tempZh,
  });
}

export function NewBatchPanel({ clinicId }: { clinicId: string | null }) {
  const [matrix, setMatrix] = useState<PoolMatrixData | null>(null);
  const [error, setError] = useState<string | null>(null);

  /**
   * 换诊所先清空 —— ⛔ 不能让上一家的人数在新诊所的标题下面多留一帧。
   * ⚠️ 只挂 `clinicId`：下面那次「分完重拉」不走这里，否则每分一批矩阵都要闪一下骨架。
   */
  useEffect(() => {
    setMatrix(null);
    setError(null);
  }, [clinicId]);

  /**
   * 取矩阵。**助手那边确认/撤销之后也要重拉**（`syncSeq`）：
   * 刚分走的人就是从这些格子里出去的，不重拉的话主管会对着**已经分掉的数**再点一次。
   */
  const syncSeq = useAssignmentSyncStore((s) => s.seq);
  useEffect(() => {
    if (!clinicId) return;
    let alive = true;
    plansApi
      .matrix(clinicId)
      .then((r) => alive && setMatrix(r))
      .catch((e) => alive && setError(e instanceof Error ? e.message : '取矩阵失败'));
    return () => {
      alive = false;
    };
  }, [clinicId, syncSeq]);

  const pick = useCallback((c: Picked) => handoff(c), []);

  return (
    <div className="flex w-full flex-col overflow-hidden rounded-lg border bg-white">
      <div className="flex flex-none flex-wrap items-baseline gap-x-2 gap-y-1 border-b px-3.5 py-2.5">
        <span className="text-[13.5px] font-semibold text-slate-900">分一批新的</span>
        <span className="text-[11px] text-slate-400">
          点一格 = 把这批人交给助手，助手出确认单
        </span>
      </div>
      {/* ⚠️ 小屏兜底:矩阵有六列,窄了就横向滚,⛔ 别让它压缩到看不清数字 */}
      <div className="overflow-x-auto">
        {!clinicId ? (
          <p className="py-8 text-center text-[12px] text-slate-400">先选一家诊所</p>
        ) : error ? (
          <p className="py-8 text-center text-[12px] text-rose-600">{error}</p>
        ) : matrix ? (
          /* ⚠️ `w-full` 覆盖组件默认的 560px（那是当年给左栏 popover 的）——
             不覆盖的话这一栏有一千多像素宽而矩阵只占 560，右边一大片空白。
             `min-w-[34rem]` 保证再窄也不把数字挤糊，由外层横向滚兜住。 */
          <PoolMatrix data={matrix} selected={null} onPick={pick} className="w-full min-w-[34rem]" />
        ) : (
          <div className="space-y-2 p-3.5">
            {Array.from({ length: 6 }).map((_, i) => (
              <div key={i} className="h-6 animate-pulse rounded bg-slate-100" />
            ))}
          </div>
        )}
      </div>
    </div>
  );
}
