'use client';

import { useEffect, useRef, useState } from 'react';
import { X } from 'lucide-react';
import { ANCHOR_MODE_META, TEMPERATURE_META, type AnchorModeValue, type TemperatureValue } from '@pac/types';
import { assignmentsApi, type CohortPage } from '@/components/plans/assignments-api';
import { cn, formatGender } from '@/lib/utils';

/**
 * 「点了一格,先看看这批人是谁」—— 矩阵与助手之间的**中间一步**(2026-08-11 产品定)。
 *
 * ⭐ 存在的理由:主管点的是一个数字(「充填 · 3 年以上 4,159」),而他要为这批人负责。
 *   在交给助手之前先摊开"这些人是谁",比事后在确认单上一个个挑出来便宜得多。
 *
 * 🔴 **这张表与确认单必须是同一批人、同一个顺序**:数据走
 *   `GET /plans/assignments/cohort`,服务端用的是**出确认单那段同样的** SQL 与排序键。
 *   ⛔ 前端不许再排一次序、不许本地过滤 —— 那会让"我在这看到的前 20 个"跟
 *   "助手挑走的前 20 个"对不上,而且两边都不报错(T14)。
 *
 * ⚠️ **分页取**,不是一次拉全:最大的格子四千多人,一次拉回来 DOM 也撑不住,
 *   而主管本来也不会逐行看完 —— 他要的是"抽查几页 + 知道总数对不对"。
 */
export function CohortPreview({
  clinicId,
  cell,
  anchorMode,
  onCancel,
  onConfirm,
}: {
  clinicId: string;
  cell: { treatment: string; treatmentZh: string; temperature: TemperatureValue; count: number };
  anchorMode: AnchorModeValue;
  onCancel: () => void;
  /// 确定 —— 带上「确定」按钮的视口矩形,数据流粒子从那里起飞(⛔ 不能事后再查,窗已经关了)
  onConfirm: (from: { x: number; y: number; w: number; h: number }) => void;
}) {
  const [page, setPage] = useState(1);
  const [data, setData] = useState<CohortPage | null>(null);
  const [error, setError] = useState<string | null>(null);
  const [loading, setLoading] = useState(false);
  const okRef = useRef<HTMLButtonElement>(null);

  const PAGE_SIZE = 50;

  useEffect(() => {
    let alive = true;
    setLoading(true);
    assignmentsApi
      .cohort({
        clinicId,
        potentialTreatment: cell.treatment,
        temperature: cell.temperature,
        anchor: anchorMode,
        page,
        pageSize: PAGE_SIZE,
      })
      .then((r) => alive && (setData(r), setError(null)))
      .catch((e) => alive && setError(e instanceof Error ? e.message : '取患者失败'))
      .finally(() => alive && setLoading(false));
    return () => {
      alive = false;
    };
  }, [clinicId, cell.treatment, cell.temperature, anchorMode, page]);

  useEffect(() => {
    const onKey = (e: KeyboardEvent) => e.key === 'Escape' && onCancel();
    document.addEventListener('keydown', onKey);
    return () => document.removeEventListener('keydown', onKey);
  }, [onCancel]);

  const total = data?.total ?? cell.count;
  const pages = Math.max(1, Math.ceil(total / PAGE_SIZE));
  const tag = ANCHOR_MODE_META[anchorMode].batchTag;

  return (
    <div
      className="fixed inset-0 z-50 flex items-center justify-center bg-slate-900/30 p-4"
      onClick={onCancel}
    >
      <div
        className="flex max-h-[86vh] w-full max-w-[64rem] flex-col overflow-hidden rounded-xl bg-white shadow-2xl"
        onClick={(e) => e.stopPropagation()}
      >
        <div className="flex flex-none items-baseline gap-2 border-b px-4 py-3">
          <span className="text-[13.5px] font-semibold text-slate-900">
            {cell.treatmentZh} · {TEMPERATURE_META[cell.temperature].zh}
            {tag ? `（${tag}）` : ''}
          </span>
          {/* ⚠️ 总数取**服务端**的 total,⛔ 不用格子上那个数:两者应当一致,
              不一致时要让主管看见的是**真会被分的那个**(格子可能是几秒前的快照)。 */}
          <span className="nums text-[12px] text-slate-500">共 {total} 人</span>
          {data && total !== cell.count && (
            <span className="text-[11px] text-amber-700">（格子上显示 {cell.count}，池子刚变过）</span>
          )}
          <span className="ml-auto text-[11px] text-slate-400">
            按分配顺序排列，助手会从上往下取
          </span>
          <button
            type="button"
            onClick={onCancel}
            aria-label="关闭"
            className="rounded-md p-1 text-slate-500 hover:bg-slate-100"
          >
            <X className="h-4 w-4" />
          </button>
        </div>

        <div className="min-h-0 flex-1 overflow-auto">
          {error ? (
            <p className="py-10 text-center text-[12px] text-rose-600">{error}</p>
          ) : !data ? (
            <div className="space-y-2 p-4">
              {Array.from({ length: 10 }).map((_, i) => (
                <div key={i} className="h-6 animate-pulse rounded bg-slate-100" />
              ))}
            </div>
          ) : (
            <table className="w-full border-collapse text-[12.5px] text-slate-700">
              <thead>
                <tr className="sticky top-0 z-10 bg-slate-50 shadow-[inset_0_-1px_0_#E2E8F0]">
                  {['#', '患者', '病历号', '性别', '年龄', '主治医生', '上次就诊医生', '专属客服'].map(
                    (h, i) => (
                      <th
                        key={h}
                        className={cn(
                          'whitespace-nowrap px-2.5 py-1.5 text-[11px] font-medium text-slate-500',
                          i === 0 ? 'w-12 text-right' : 'text-left',
                        )}
                      >
                        {h}
                      </th>
                    ),
                  )}
                </tr>
              </thead>
              <tbody className={cn(loading && 'opacity-50')}>
                {data.items.map((r, i) => (
                  <tr key={r.planId} className="border-t hover:bg-slate-50">
                    <td className="nums px-2.5 py-1.5 text-right text-[11px] text-slate-400">
                      {(data.page - 1) * data.pageSize + i + 1}
                    </td>
                    <td className="px-2.5 py-1.5">
                      <span className="font-medium text-slate-900">
                        {r.patientName ?? `#${r.patientId.slice(0, 8)}`}
                      </span>
                      {/* ⭐ 之前被分过的人又出现了 —— 主管有权先知道,⛔ 别等他事后发现 */}
                      {r.repeated && (
                        <span className="ml-1.5 rounded bg-amber-50 px-1 py-px text-[10px] text-amber-700">
                          分过
                        </span>
                      )}
                    </td>
                    <td className="nums px-2.5 py-1.5 text-slate-500">{r.medicalRecordNumber ?? '—'}</td>
                    <td className="px-2.5 py-1.5 text-slate-500">{formatGender(r.gender) || '—'}</td>
                    <td className="nums px-2.5 py-1.5 text-slate-500">{r.age ?? '—'}</td>
                    <td className="px-2.5 py-1.5 text-slate-600">{r.attendingDoctor ?? '—'}</td>
                    <td className="px-2.5 py-1.5 text-slate-600">{r.lastVisitDoctor ?? '—'}</td>
                    <td className="px-2.5 py-1.5 text-slate-600">{r.dedicatedToName ?? '—'}</td>
                  </tr>
                ))}
              </tbody>
            </table>
          )}
        </div>

        <div className="flex flex-none items-center gap-2 border-t px-4 py-2.5">
          {/* 翻页 —— ⚠️ 页码要给全(第 3 / 84 页):主管抽查时要能回跳,这也是这里
              用 offset 而不是游标的原因(见服务端 cohortPage 注释)。 */}
          <button
            type="button"
            disabled={page <= 1 || loading}
            onClick={() => setPage((p) => Math.max(1, p - 1))}
            className="rounded-md border px-2.5 py-1 text-[12px] text-slate-600 hover:bg-slate-50 disabled:opacity-40"
          >
            上一页
          </button>
          <span className="nums text-[11.5px] text-slate-500">
            第 {data?.page ?? page} / {pages} 页
          </span>
          <button
            type="button"
            disabled={page >= pages || loading}
            onClick={() => setPage((p) => Math.min(pages, p + 1))}
            className="rounded-md border px-2.5 py-1 text-[12px] text-slate-600 hover:bg-slate-50 disabled:opacity-40"
          >
            下一页
          </button>

          <span className="ml-auto flex items-center gap-2">
            <button
              type="button"
              onClick={onCancel}
              className="rounded-lg px-3 py-1.5 text-[12.5px] text-slate-600 hover:bg-slate-100"
            >
              取消
            </button>
            <button
              ref={okRef}
              type="button"
              onClick={() => {
                const el = okRef.current;
                const b = el?.getBoundingClientRect();
                onConfirm(
                  b
                    ? { x: b.left, y: b.top, w: b.width, h: b.height }
                    : { x: window.innerWidth / 2, y: window.innerHeight / 2, w: 0, h: 0 },
                );
              }}
              className="rounded-lg bg-brand-600 px-3 py-1.5 text-[12.5px] font-medium text-white hover:bg-brand-700"
            >
              确定，交给助手
            </button>
          </span>
        </div>
      </div>
    </div>
  );
}
