'use client';

import { useState } from 'react';
import {
  ABANDON_REASON_META,
  AbandonReason,
  abandonReasonsFor,
  potentialTreatmentCardLabel,
} from '@pac/types';
import { cn } from '@/lib/utils';
import { Button } from '@/components/ui/button';
import {
  Dialog,
  DialogContent,
  DialogHeader,
  DialogTitle,
  DialogFooter,
} from '@/components/ui/dialog';

/**
 * 关闭机会弹窗 —— 宿主回访模式下(顶栏有「回访」按钮)替代通话结果区的关闭入口。
 *
 * ⭐ 这只是**展示层的一张皮**:落库仍是 outcome='abandoned' + abandon_reasons,
 *   跟 PAC 自带表单同一套机制、同一列。PAC 侧不存在「关闭」这个概念,
 *   分叉只在文案(ABANDON_REASON_META.shownIn='close' 的那几项)。
 *
 * **多选,无上限** —— 真实关闭常是复合原因(如「价格因素 + 选择竞品机构」),
 * 逼客服挑一个主因只会让数据失真。
 */
const CLOSE_REASONS = abandonReasonsFor('close').map((key) => ({
  key,
  ...ABANDON_REASON_META[key],
}));

export type CloseReasonKey = AbandonReason;

export function CloseOpportunityDialog({
  open,
  onOpenChange,
  onConfirm,
  potentialTreatments = [],
}: {
  open: boolean;
  onOpenChange: (open: boolean) => void;
  /** 确认关闭(原因多选 + 需要说明时的文字 + 「识别不准确」勾中的治疗 code)。 */
  onConfirm?: (reasons: CloseReasonKey[], note?: string, inaccurateTreatments?: string[]) => void;
  /**
   * 本患者的潜在治疗 **code**(画像 potential_treatment.types)—— 「机会识别不准确」的候选项。
   * 跟召回池卡片那排标签同一个来源,所以每个患者不一样;中文在这里查表(改措辞即时生效)。
   */
  potentialTreatments?: string[];
}) {
  const [reasons, setReasons] = useState<CloseReasonKey[]>([]);
  const [note, setNote] = useState('');
  const [inaccurate, setInaccurate] = useState<string[]>([]);

  const toggle = (key: CloseReasonKey) =>
    setReasons((prev) => (prev.includes(key) ? prev.filter((k) => k !== key) : [...prev, key]));

  const selected = CLOSE_REASONS.filter((r) => reasons.includes(r.key));
  // 勾中任一 needNote 项(目前只有「其他」)→ 说明必填
  const needNote = selected.some((r) => r.needNote === true);
  // ⭐ 勾了「机会识别不准确」→ 必须说清是哪几类治疗不准。
  //   这条反馈的唯一用途是回头统计"哪类召回最容易被判不准"去改规则,收进来一批空的就等于白填,
  //   而且事后补不回来(没人会为一条已结案的单再来一遍)。服务端同样会拦。
  //   ⚠️ 只跟 inaccurate 关联,跟「其他原因」不构成关联(业务 2026-07-30)。
  const needInaccurate = reasons.includes('inaccurate');
  // 患者没有潜在治疗标签时不卡住(理论上不该发生 —— 没有机会何来"识别不准"),
  // 但真遇到了宁可放行,不能让客服卡在一个填不了的必填项上
  const inaccurateOk = !needInaccurate || potentialTreatments.length === 0 || inaccurate.length > 0;
  const canConfirm = reasons.length > 0 && (!needNote || note.trim().length > 0) && inaccurateOk;

  const toggleInaccurate = (code: string) =>
    setInaccurate((prev) => (prev.includes(code) ? prev.filter((c) => c !== code) : [...prev, code]));

  const reset = () => {
    setReasons([]);
    setNote('');
    setInaccurate([]);
  };

  return (
    <Dialog
      open={open}
      onOpenChange={(v) => {
        onOpenChange(v);
        if (!v) reset();
      }}
    >
      <DialogContent className="sm:max-w-[520px]">
        <DialogHeader>
          <DialogTitle className="text-[15px]">关闭机会</DialogTitle>
        </DialogHeader>

        <div className="space-y-3">
          <div className="text-[12.5px] font-medium text-slate-900">
            选择关闭原因(可多选) <span className="text-rose-600">*</span>
          </div>
          {/* 原因多选卡:两列;「其他原因」独占整行 */}
          <div className="grid grid-cols-2 gap-2">
            {CLOSE_REASONS.map((r) => {
              const active = reasons.includes(r.key);
              return (
                <button
                  key={r.key}
                  type="button"
                  onClick={() => toggle(r.key)}
                  className={cn(
                    'flex items-center gap-2 rounded-md border px-3 py-2.5 text-left text-[12.5px] transition-colors',
                    r.key === 'other' && 'col-span-2',
                    active
                      ? 'border-brand-400 bg-brand-50 font-medium text-brand-800'
                      : 'border-slate-200 bg-white text-slate-700 hover:border-brand-300 hover:bg-brand-50/50',
                  )}
                >
                  <span
                    className={cn(
                      'flex h-3.5 w-3.5 flex-none items-center justify-center rounded-[3px] border',
                      active ? 'border-brand-600 bg-brand-600' : 'border-slate-300',
                    )}
                  >
                    {active && (
                      <svg viewBox="0 0 12 12" className="h-2.5 w-2.5 text-white" aria-hidden>
                        <path
                          d="M2.5 6.2l2.3 2.3 4.7-5"
                          fill="none"
                          stroke="currentColor"
                          strokeWidth="2"
                          strokeLinecap="round"
                          strokeLinejoin="round"
                        />
                      </svg>
                    )}
                  </span>
                  {r.labelZh}
                </button>
              );
            })}
          </div>

          {/* 「机会识别不准确」的限定:哪几类推荐治疗不准 —— 候选项 = 本患者的潜在治疗标签 */}
          {needInaccurate && potentialTreatments.length > 0 && (
            <div className="space-y-1.5">
              <div className="text-[12.5px] font-medium text-slate-900">
                哪些推荐治疗不准确?(可多选) <span className="text-rose-600">*</span>
              </div>
              <div className="flex flex-wrap gap-1.5">
                {potentialTreatments.map((code) => {
                  const on = inaccurate.includes(code);
                  return (
                    <button
                      key={code}
                      type="button"
                      onClick={() => toggleInaccurate(code)}
                      className={cn(
                        'rounded-md border px-2.5 py-1 text-[12px] transition-colors',
                        on
                          ? 'border-brand-400 bg-brand-50 font-medium text-brand-800'
                          : 'border-slate-200 bg-white text-slate-700 hover:border-brand-300 hover:bg-brand-50/50',
                      )}
                    >
                      {potentialTreatmentCardLabel(code)}
                    </button>
                  );
                })}
              </div>
            </div>
          )}

          {needNote && (
            <div className="space-y-1.5">
              <div className="text-[12.5px] font-medium text-slate-900">
                请描述具体原因 <span className="text-rose-600">*</span>
              </div>
              <textarea
                value={note}
                onChange={(e) => setNote(e.target.value)}
                rows={3}
                placeholder="请详细描述关闭机会的具体原因,以便后续分析和改进…"
                className="w-full resize-y rounded-md border border-slate-200 bg-white px-3 py-2 text-[12.5px] text-slate-900 placeholder:text-slate-400 focus:outline-none focus:ring-2 focus:ring-brand-200 focus:border-brand-400"
              />
            </div>
          )}

          {selected.length > 0 && (
            <div className="rounded-md border border-brand-100 bg-brand-50/60 px-3 py-2">
              <div className="text-[11.5px] font-semibold text-brand-800">
                已选关闭原因 · {selected.length} 项
              </div>
              <ul className="mt-0.5 space-y-0.5">
                {selected.map((r) => (
                  <li key={r.key} className="text-[12px] text-slate-700">
                    {r.labelZh} · {r.desc}
                  </li>
                ))}
              </ul>
            </div>
          )}
        </div>

        <DialogFooter>
          <Button variant="outline" size="sm" onClick={() => onOpenChange(false)}>
            取消
          </Button>
          <Button
            size="sm"
            disabled={!canConfirm}
            onClick={() => {
              if (reasons.length === 0) return;
              // 只在选了 inaccurate 时带上,其他原因不构成关联(免得残留勾选污染统计)
              onConfirm?.(
                reasons,
                note.trim() ? note.trim() : undefined,
                needInaccurate ? inaccurate : undefined,
              );
              onOpenChange(false);
              reset();
            }}
          >
            确认关闭
          </Button>
        </DialogFooter>
      </DialogContent>
    </Dialog>
  );
}
