'use client';

import { useState } from 'react';
import { ChevronDown, ChevronRight } from 'lucide-react';
import type { Signal } from '@pac/types';
import { Button } from '@/components/ui/button';

/**
 * 引导节点区 —— 确认单上「还有什么要您定的」。
 *
 * 规格见 docs/design/assignment-agent-flow.md §五。这一层是**纯呈现**：
 * ⛔ 不判定该不该亮（那是服务端 `computeSignals` 的事），⛔ 不执行动作（只把 intent 抛上去）。
 *
 * ── 三条来自教条的硬要求 ────────────────────────────────────────
 * ① **不截断**：`action` 层全部展开。防噪音靠把 `info` 折叠，⛔ 不靠丢弃 ——
 *    藏起一条主管就不知道有东西卡着（G9）。
 * ② **默认永远是 no-op**：不点任何按钮 = 不动。「一条不点、直接确认」永远安全。
 *    ⚠️ "不处理会怎样"这句话由**模型在卡片上方讲**，⛔ 卡片不再重复渲染
 *    （2026-08-12 实测：两边都写全，主管要把同一件事读两遍）。
 * ③ **选项是可点击的动作，不是让他照着打字**（G10）。
 *    打字 → 模型理解 → 翻译成动作，每一环都可能错；点击是确定性的。
 */
export function ConfirmSheetSignals({
  signals,
  readOnly,
  busyIntent,
  onIntent,
  onCompose,
}: {
  signals: Signal[];
  readOnly: boolean;
  /** 正在执行的 intent（按钮转圈用）；null = 空闲 */
  busyIntent?: string | null;
  onIntent: (intent: string, args?: Record<string, unknown>) => void;
  /**
   * 兜底 —— 把一句**开头**填进输入框并聚焦，⛔ 不直接发送。
   * ⚠️ `post_confirm` 那类节点唯一的动作就是它（福利原文只能是主管的话）。
   */
  onCompose?: (draft: string) => void;
}) {
  const [infoOpen, setInfoOpen] = useState(false);
  if (signals.length === 0) return null;

  const action = signals.filter((s) => s.tier === 'action');
  const info = signals.filter((s) => s.tier === 'info');

  return (
    <div className="border-b bg-amber-50/40">
      {action.map((s) => (
        <Row
          key={s.key}
          signal={s}
          readOnly={readOnly}
          busyIntent={busyIntent}
          onIntent={onIntent}
          onCompose={onCompose}
        />
      ))}

      {/*
        ⚠️ 纯信息类默认折叠 —— 它们「不管也没事」，展开会把真正要处置的那几条挤下去。
        ⛔ 但不能不给：主管看到「405 人」时，"这数哪来的"和这个数本身一样重要（T14）。
      */}
      {info.length > 0 && (
        <div className="px-3 py-1.5">
          <button
            type="button"
            onClick={() => setInfoOpen((v) => !v)}
            className="flex items-center gap-1 text-[11px] text-slate-500 hover:text-slate-700"
          >
            {infoOpen ? <ChevronDown className="h-3 w-3" /> : <ChevronRight className="h-3 w-3" />}
            另有 {info.length} 条说明
          </button>
          {infoOpen &&
            info.map((s) => (
              <Row
                key={s.key}
                signal={s}
                readOnly={readOnly}
                busyIntent={busyIntent}
                onIntent={onIntent}
                onCompose={onCompose}
                muted
              />
            ))}
        </div>
      )}
    </div>
  );
}

function Row({
  signal: s,
  readOnly,
  busyIntent,
  onIntent,
  onCompose,
  muted,
}: {
  signal: Signal;
  readOnly: boolean;
  busyIntent?: string | null;
  onIntent: (intent: string, args?: Record<string, unknown>) => void;
  onCompose?: (draft: string) => void;
  muted?: boolean;
}) {
  /**
   * ⭐ **`post_confirm` 那类在只读态下照样可点** —— 只读说的是"这批人和时效定死了"，
   *   而这类节点恰恰是**分下去之后仍然能做**的那几件（补挂福利只影响此后生成的话术）。
   *   ⛔ 跟着 readOnly 一起禁掉，就等于摆一句「这批还没带福利」然后什么也不让他做。
   */
  const postConfirm = s.stage === 'post_confirm';
  const canAct = !readOnly || postConfirm;
  return (
    <div className={`px-3 py-2 ${muted ? 'pt-1.5' : 'border-b border-amber-100/70 last:border-b-0'}`}>
      {/*
        🔴 **卡片只说「能做什么」，「为什么 / 不管会怎样」交给模型**（2026-08-12 实测后改）。
          在此之前两边都写全，主管要把同一件事读两遍 —— 而模型那段就在卡片正上方。
        ⇒ 分工：卡片 = 动作（标题 + 按钮），对话 = 解释。
        ⛔ 但**按钮不能搬走**：打字 → 模型理解 → 翻译成 intent，每一环都可能错
          （实测栽过 owner/balance 选反，18 人被散给 17 位别人）；点击没有理解环节。
        ⚠️ `why` / `defaultLabel` 仍然随 signal 下发（模型要用），只是卡片不再渲染。
      */}
      <p className={muted ? 'text-[11.5px] text-slate-600' : 'text-[12px] font-medium text-slate-800'}>
        {s.title}
      </p>
      {/*
        折叠区里的纯信息类没有对话在旁边解释，仍要给一句。
        ⭐ `post_confirm` 同理，而且更硬：点确认**不会触发模型发言**，
          它上方那段话是确认之前说的，里面不可能有这条 —— 卡片不给，就没人给。
      */}
      {(muted || postConfirm) && (
        <p className="mt-0.5 text-[11px] leading-relaxed text-slate-500">{s.why}</p>
      )}
      {canAct && s.options.length === 0 && onCompose && (
        <div className="mt-1.5">
          <button
            type="button"
            onClick={() => onCompose(`关于「${s.title}」—— `)}
            className="rounded border border-dashed border-amber-300 px-2 py-0.5 text-[11px] leading-5 text-amber-800 transition-colors hover:bg-amber-50"
          >
            我自己说
          </button>
        </div>
      )}
      {canAct && s.options.length > 0 && (
        <div className="mt-1.5 flex flex-wrap gap-1.5">
          {s.options.map((o) => {
            const busy = busyIntent === o.intent;
            return (
              <Button
                key={`${o.intent}:${o.label}`}
                size="sm"
                variant="outline"
                disabled={busyIntent != null}
                onClick={() => onIntent(o.intent, o.args)}
                className="h-6 border-amber-300 bg-white px-2 text-[11px] text-amber-900 hover:bg-amber-50"
              >
                {busy ? '处理中…' : o.label}
              </Button>
            );
          })}
        </div>
      )}
    </div>
  );
}
