'use client';

import { useEffect, useState } from 'react';
import { Loader2 } from 'lucide-react';
import {
  TEMPERATURE_META,
  TEMPERATURE_ORDER,
  potentialTreatmentItemName,
  temperatureWindowHint,
  type TemperatureValue,
} from '@pac/types';
import { cn } from '@/lib/utils';
import { plansApi, type PoolMatrix, type PoolMatrixRow } from './plans-api';

/**
 * PoolMatrix — 初选矩阵(8 潜在治疗 × 3 窗口温度)。
 *
 * 生产线的**第一环**:主管在这里点一格,就完成了「初选」,人群随即交给助手出确认单。
 * 矩阵是召回池的一个**视图模式**(tab 行「分配」浮层展开),⛔ 不新开路由 ——
 * 主管本质也是客服、也要执行,割裂成两个页面会把他劈成两个身份(T16)。
 *
 * ═══ 为什么这里**没有**配色(2026-08 产品定,是撤回不是遗漏)═══════════
 * 列头从「热 / 温 / 冷」改成**临床说法**「黄金期 / 窗口内 / 窗口外」之后,
 * 温度渐变那套颜色就成了**第二套更弱的编码** —— 名字已经把语义说准了,
 * 再刷一层冷暖色只是重复,还得额外维护对比度、色标位置、深色模式。一并撤掉。
 *
 * ⛔ **别再把冷暖色加回来**(尤其别按数量深浅上色):
 *   「这格橙是因为在黄金期、还是因为人多」分不清 —— 数量已经用数字表达了,
 *   档位已经用列头表达了,两者都不需要颜色再说一遍。
 * ⛔ 唯一允许的颜色是**交互态**(hover / 选中):那表达的是"你正指着谁",不是数据。
 */

/// 列序走共享的 TEMPERATURE_ORDER,中文走共享的 TEMPERATURE_META —— ⛔ 别在这里内联中文表
const COLUMNS = TEMPERATURE_ORDER;
type TempKey = TemperatureValue;

/// 行标签列宽。列头与每一行都靠它对齐,别在某一处手改
const LABEL_W = 'w-[52px]';

export function PoolMatrix({
  clinicId,
  selected,
  onPick,
}: {
  clinicId?: string;
  /** 当前选中的格子(回显用) */
  selected?: { treatment: string; temperature: TempKey } | null;
  /** 点格子 → 初选完成,把这一格的人群交出去 */
  onPick: (cell: { treatment: string; treatmentZh: string; temperature: TempKey; count: number }) => void;
}) {
  const [data, setData] = useState<PoolMatrix | null>(null);
  const [error, setError] = useState<string | null>(null);

  useEffect(() => {
    let alive = true;
    setError(null);
    plansApi
      .matrix(clinicId)
      .then((d) => alive && setData(d))
      .catch((e: unknown) => alive && setError(e instanceof Error ? e.message : String(e)));
    return () => {
      alive = false;
    };
  }, [clinicId]);

  if (error) {
    return <div className="p-3 text-[12px] text-rose-600">矩阵加载失败:{error}</div>;
  }
  if (!data) {
    return (
      <div className="flex items-center justify-center gap-2 p-6 text-[12px] text-slate-400">
        <Loader2 className="h-3.5 w-3.5 animate-spin" />
        正在数人…
      </div>
    );
  }

  const showUnknown = data.unknownTotal > 0;

  return (
    <div className="p-2">
      {/* 列头 —— 三档用**临床说法**,不是「热/温/冷」那套比喻 */}
      <div className="flex items-center border-b border-slate-100 pb-1">
        <div className={cn(LABEL_W, 'shrink-0 text-[11px] text-slate-400')}>潜在治疗</div>
        <div className="flex flex-1">
          {COLUMNS.map((c) => (
            <div
              key={c}
              title={TEMPERATURE_META[c].hint}
              className="flex-1 text-center text-[12px] font-medium text-slate-700"
            >
              {TEMPERATURE_META[c].zh}
            </div>
          ))}
        </div>
        {showUnknown && <div className="w-11 shrink-0 text-center text-[11px] text-slate-400">待重算</div>}
      </div>

      <div className="mt-0.5">
        {data.rows.map((row) => (
          <MatrixRow
            key={row.key}
            row={row}
            showUnknown={showUnknown}
            selected={selected}
            onPick={onPick}
          />
        ))}
      </div>

      {data.note && (
        <p className="mt-1.5 rounded bg-amber-50 px-2 py-1.5 text-[10.5px] leading-relaxed text-amber-800">
          {data.note}
        </p>
      )}
    </div>
  );
}

function MatrixRow({
  row,
  showUnknown,
  selected,
  onPick,
}: {
  row: PoolMatrixRow;
  showUnknown: boolean;
  selected?: { treatment: string; temperature: TempKey } | null;
  onPick: (cell: { treatment: string; treatmentZh: string; temperature: TempKey; count: number }) => void;
}) {
  // ⛔ 中文一律查 labels.ts,别在组件里另写一张表 —— 改措辞要即时生效、且全站一处。
  //   用**项目名**(种植 / 早矫 / 拔牙)而不是卡片措辞(种植治疗):
  //   8×3 的表里每行都拖着「治疗」两个字纯属噪声,还挤掉列宽。
  const zh = potentialTreatmentItemName(row.key);
  return (
    <div className="flex items-stretch">
      <div className={cn(LABEL_W, 'shrink-0 self-center pr-1.5 text-right text-[11.5px] text-slate-600')}>
        {zh}
      </div>
      <div className="flex flex-1">
        {COLUMNS.map((c) => {
          const n = row[c];
          const isSelected = selected?.treatment === row.key && selected.temperature === c;
          return (
            <button
              key={c}
              type="button"
              disabled={n === 0}
              onClick={() => onPick({ treatment: row.key, treatmentZh: zh, temperature: c, count: n })}
              // ⭐ hover 只给**天数区间**,不给解释:格子里已经有数字、列头已经写了档位名,
              //   再叠一段说明就是噪声。区间是主管唯一看不出来的那个信息。
              title={temperatureWindowHint(row.key, c)}
              className={cn(
                'flex-1 rounded py-1.5 text-[12px] tabular-nums transition-colors',
                // ⛔ 颜色只表达**交互态**,不表达数据(见文件头)
                n === 0
                  ? 'cursor-default text-slate-300'
                  : 'cursor-pointer font-medium text-slate-700 hover:bg-slate-100',
                isSelected && 'bg-slate-100 ring-1 ring-inset ring-slate-700',
              )}
            >
              {n || '—'}
            </button>
          );
        })}
      </div>
      {showUnknown && (
        <div
          className="flex w-11 shrink-0 items-center justify-center bg-slate-50 text-[11.5px] tabular-nums text-slate-400"
          title="温度待重算 —— 画像还没算出窗口边界"
        >
          {row.unknown || '—'}
        </div>
      )}
    </div>
  );
}
