'use client';

import { useState } from 'react';
import { ChevronDown } from 'lucide-react';
import { ASSIGNMENT_EXPIRES_DAYS_PRESETS } from '@pac/types';
import {
  Select,
  SelectContent,
  SelectItem,
  SelectTrigger,
  SelectValue,
} from '@/components/ui/select';
import { cn } from '@/lib/utils';

/**
 * 两张单子共用的**呈现原件** —— 确认单(分配)与重排单各自独立,但主管的手只学一遍。
 *
 * ═══ 为什么这两个可以共用,而组件本身不行 ═══════════════════════════
 * 这里的两个都是**没有业务语义**的交互原件:一个是"点名字复制",一个是"改天数"。
 * 它们身上那点来之不易的行为(懒挂 Radix、复制反馈)一旦抄成两份必然漂 ——
 * 而漂了的表现是**两张单子手感不一样**,正是"用户不用二次学习"要防的那件事。
 * ⚠️ 有业务语义的东西(福利、待分配、批次时限、落人算法)⛔ 仍然各归各的,
 *   ⛔ 别拿这个文件当"把两张单子缝起来"的入口(产品 2026-08-20:重排单与确认单独立)。
 */

/**
 * 患者姓名 —— **点一下复制**(2026-08-06 产品加)。
 *
 * ⚠️ 主管审这批人时常要把名字贴到别处(问医生、查宿主档案、发消息),
 *   在一个 480px 的列表里手动选中一个中文名很难选准。
 * ⚠️ `stopPropagation` 是必须的:这一行同时是**折叠开关的兄弟**且整行可拖,
 *   不拦住会连带触发别的行为。
 * ⚠️ `draggable={false}`:不加的话按住名字拖会被浏览器当成拖文本,把整行的拖拽吃掉。
 * ⛔ 复制的是**姓名本身**,不含病历号/性别年龄 —— 那些是给眼睛看的上下文,
 *   粘出去多带一串反而要手动删。
 */
export function CopyableName({ name }: { name: string }) {
  const [copied, setCopied] = useState(false);
  return (
    <button
      type="button"
      draggable={false}
      title="点击复制姓名"
      onClick={(e) => {
        e.stopPropagation();
        void navigator.clipboard?.writeText(name);
        setCopied(true);
        setTimeout(() => setCopied(false), 1200);
      }}
      className={cn(
        'rounded px-0.5 transition-colors',
        copied ? 'bg-emerald-50 text-emerald-700' : 'hover:bg-brand-50 hover:text-brand-700',
      )}
    >
      {copied ? '已复制' : name}
    </button>
  );
}

/**
 * 时限选择 —— 1~7 天。用 shadcn `Select`(Radix),不用原生 `<select>`:
 * 原生下拉在深色/窄屏下样式不可控,而这个控件现在**每一条召回计划都有一个**,
 * 出现几百次,样式必须跟卡片其余部分一致。
 * ⚠️ 值域来自 `ASSIGNMENT_EXPIRES_DAYS_PRESETS`(共享常量),⛔ 别在这里内联 [1..7]。
 */
/**
 * 时限下拉 —— **点了才挂真正的 Radix Select**。
 *
 * 🔴 由来(2026-08-05 实测):原来每一行直接渲染一个 `<Select>`。展开一个 36 条的客服组
 *   = 一次性挂 36 个 Radix Select,每个都带 portal / 焦点管理 / 键盘导航,
 *   展开那一下明显卡顿。而这些下拉**绝大多数根本不会被点** —— 主管一批 200 人,
 *   真正逐条改时限的是个位数。
 *
 * ✅ 平时只是一个 `<button>`(样式与 SelectTrigger 一致),点击才换成真 Select 并自动展开。
 * ⚠️ `defaultOpen` 是关键:换过去之后要立刻弹开,否则用户得点两下。
 * ⚠️ 收起后**不还原成按钮** —— 还原会让"刚改完又想再改"变成再等一次挂载,
 *   而且已经挂上的那一个不再是成本问题(卡的是 36 个同时挂)。
 */
export function DaySelect({
  value,
  disabled,
  onChange,
  compact,
}: {
  value: number;
  disabled?: boolean;
  onChange: (days: number) => void;
  /**
   * 条目行用紧凑版 —— **只是窄一点**,⛔ 不省单位。
   *
   * 🔴 2026-08-20 产品走查:原来紧凑版只显示一个光秃秃的数字(「1」),
   *   而它旁边一行里还有「剩 1 天」「约 2 天」这些数 —— 一个不带单位的 1 摆在中间
   *   读不出是什么。省下的那点宽度换来一次"这是什么"的停顿,不划算。
   */
  compact?: boolean;
}) {
  const [live, setLive] = useState(false);
  // ⚠️ 紧凑版从 54 放到 66:要装下「1 天」+ 箭头,54 会把「天」挤掉
  const cls = cn('h-6 gap-1 px-1.5 text-[11px]', compact ? 'w-[66px]' : 'w-[76px]');

  if (!live) {
    return (
      <button
        type="button"
        disabled={disabled}
        onClick={() => setLive(true)}
        // 样式与 SelectTrigger 对齐 —— 换过去时不许有跳动
        className={cn(
          cls,
          'inline-flex items-center justify-between rounded-md border border-input bg-transparent',
          'shadow-xs transition-colors hover:bg-accent/50 disabled:cursor-not-allowed disabled:opacity-50',
        )}
      >
        <span>{value} 天</span>
        <ChevronDown className="h-3 w-3 opacity-50" />
      </button>
    );
  }

  return (
    <Select
      value={String(value)}
      disabled={disabled}
      defaultOpen
      onValueChange={(v) => onChange(Number(v))}
    >
      <SelectTrigger className={cls}>
        <SelectValue />
      </SelectTrigger>
      {/* z 层级已在 ui/select.tsx 统一抬到 70(助手窗是 z-60,见那里的层级约定) */}
      <SelectContent>
        {ASSIGNMENT_EXPIRES_DAYS_PRESETS.map((d) => (
          <SelectItem key={d} value={String(d)} className="text-[12px]">
            {d} 天
          </SelectItem>
        ))}
      </SelectContent>
    </Select>
  );
}
