'use client';

import { useEffect, useRef, useState } from 'react';
import ReactMarkdown from 'react-markdown';
import remarkGfm from 'remark-gfm';
import { Bot, Check, ChevronDown, ChevronRight, Loader2, Send, Sparkles, Square, Wrench } from 'lucide-react';
import { cn } from '@/lib/utils';
import { useAssistantChat, type Block, type ChatMessage, type ToolStep } from './use-assistant-chat';

const MODELS = [
  { value: 'deepseek', label: 'DeepSeek' },
  { value: 'gemini', label: 'Gemini' },
  { value: 'qwen', label: '通义千问' },
];

const EXAMPLES = [
  '查一下患者孙柯的画像价值分群和当前召回计划',
  '孙柯有哪些潜在治疗和应治未治的牙位?',
  '现在召回池里优先级最高的几位患者是谁?',
];

// ── 工具结果格式化 + 轻量摘要 ──────────────────────────────
function pretty(v: unknown): string {
  if (v == null) return '';
  if (typeof v === 'string') {
    try {
      return JSON.stringify(JSON.parse(v), null, 2);
    } catch {
      return v;
    }
  }
  return JSON.stringify(v, null, 2);
}
function resultSummary(result: unknown): string {
  if (result == null) return '';
  let v: unknown = result;
  if (typeof result === 'string') {
    try {
      v = JSON.parse(result);
    } catch {
      return '已返回';
    }
  }
  if (Array.isArray(v)) return `返回 ${v.length} 项`;
  if (v && typeof v === 'object') {
    const o = v as Record<string, unknown>;
    if (Array.isArray(o.items)) return `返回 ${o.items.length} 条`;
    if (o.recallPlan !== undefined || o.persona !== undefined) return '已返回患者数据';
    return '已返回数据';
  }
  return '已返回';
}

// ── 工具调用折叠卡(对齐设计稿)─────────────────────────────
function ToolCallView({ step }: { step: ToolStep }) {
  const [open, setOpen] = useState(false);
  return (
    <div className="overflow-hidden rounded-lg border border-slate-200 bg-slate-50/70">
      <button
        type="button"
        onClick={() => setOpen((o) => !o)}
        className="flex w-full items-center gap-2 px-3 py-2 text-left transition-colors hover:bg-slate-100/60"
      >
        <ChevronRight
          className={cn('h-3.5 w-3.5 flex-none text-slate-400 transition-transform', open && 'rotate-90')}
        />
        <Wrench className="h-3.5 w-3.5 flex-none text-slate-400" />
        <span className="flex-none text-[12px] text-slate-500">调用工具</span>
        <code className="flex-none rounded border border-slate-200 bg-white px-1.5 py-0.5 font-mono text-[11.5px] text-slate-700">
          {step.tool}
        </code>
        <span className="ml-1 truncate text-[11px] text-slate-400">
          {step.status === 'done' ? resultSummary(step.result) : ''}
        </span>
        <span className="ml-auto flex-none">
          {step.status === 'running' ? (
            <Loader2 className="h-3.5 w-3.5 animate-spin text-slate-400" />
          ) : step.status === 'error' ? (
            <span className="text-[11px] text-rose-600">出错</span>
          ) : (
            <Check className="h-3.5 w-3.5 text-emerald-600" />
          )}
        </span>
      </button>
      {open && (
        <div className="space-y-2 border-t border-slate-200/70 px-3 pb-3 pt-1">
          <CodeBlock label="入参" code={pretty(step.args) || '{}'} />
          {step.result !== undefined && <CodeBlock label="返回" code={pretty(step.result)} muted />}
        </div>
      )}
    </div>
  );
}

function CodeBlock({ label, code, muted }: { label: string; code: string; muted?: boolean }) {
  return (
    <div>
      <div className="mb-1 mt-1.5 text-[10.5px] font-medium uppercase tracking-wide text-slate-400">
        {label}
      </div>
      <pre
        className={cn(
          'overflow-x-auto rounded-md border border-slate-200 bg-white px-3 py-2 text-[11.5px] leading-relaxed text-slate-600',
          muted && 'max-h-44 overflow-y-auto',
        )}
      >
        <code>{code}</code>
      </pre>
    </div>
  );
}

// ── LLM 文本 → markdown 渲染(用户要求:不复用设计的结构卡,改 markdown 解析)──
function Markdown({ text }: { text: string }) {
  return (
    <div className="text-[13.5px] leading-relaxed text-slate-700">
      <ReactMarkdown
        remarkPlugins={[remarkGfm]}
        components={{
          h1: ({ children }) => <h1 className="mb-2 mt-3 text-[16px] font-semibold text-slate-900">{children}</h1>,
          h2: ({ children }) => <h2 className="mb-1.5 mt-3 text-[15px] font-semibold text-slate-900">{children}</h2>,
          h3: ({ children }) => <h3 className="mb-1 mt-2.5 text-[14px] font-semibold text-slate-800">{children}</h3>,
          p: ({ children }) => <p className="my-1.5">{children}</p>,
          ul: ({ children }) => <ul className="my-1.5 ml-4 list-disc space-y-1">{children}</ul>,
          ol: ({ children }) => <ol className="my-1.5 ml-4 list-decimal space-y-1">{children}</ol>,
          li: ({ children }) => <li className="leading-relaxed">{children}</li>,
          strong: ({ children }) => <strong className="font-semibold text-slate-900">{children}</strong>,
          a: ({ children, href }) => (
            <a href={href} className="text-teal-700 underline" target="_blank" rel="noreferrer">
              {children}
            </a>
          ),
          hr: () => <hr className="my-3 border-slate-200" />,
          blockquote: ({ children }) => (
            <blockquote className="my-2 border-l-2 border-teal-300 bg-teal-50/40 py-1 pl-3 text-slate-600">
              {children}
            </blockquote>
          ),
          code: ({ children, className }) =>
            className ? (
              <code className={className}>{children}</code>
            ) : (
              <code className="rounded bg-slate-100 px-1 py-0.5 font-mono text-[12px] text-slate-700">
                {children}
              </code>
            ),
          pre: ({ children }) => (
            <pre className="my-2 overflow-x-auto rounded-md border border-slate-200 bg-slate-50 p-3 text-[12px]">
              {children}
            </pre>
          ),
          table: ({ children }) => (
            <div className="my-2 overflow-x-auto">
              <table className="w-full border-collapse text-[12.5px]">{children}</table>
            </div>
          ),
          thead: ({ children }) => <thead className="bg-slate-50">{children}</thead>,
          th: ({ children }) => (
            <th className="border border-slate-200 px-2 py-1 text-left font-medium text-slate-600">{children}</th>
          ),
          td: ({ children }) => <td className="border border-slate-200 px-2 py-1 text-slate-700">{children}</td>,
        }}
      >
        {text}
      </ReactMarkdown>
    </div>
  );
}

function BlockView({ block }: { block: Block }) {
  if (block.kind === 'tool') return <ToolCallView step={block.step} />;
  return <Markdown text={block.text} />;
}

function MessageView({ message }: { message: ChatMessage }) {
  if (message.role === 'user') {
    return (
      <div className="flex justify-end gap-2.5">
        <div className="max-w-[80%] rounded-2xl rounded-tr-sm bg-slate-800 px-3.5 py-2 text-[13.5px] leading-relaxed text-white">
          {message.blocks.map((b) => (b.kind === 'text' ? b.text : '')).join('')}
        </div>
      </div>
    );
  }
  return (
    <div className="flex gap-2.5">
      <span className="mt-0.5 inline-flex h-7 w-7 flex-none items-center justify-center rounded-full bg-teal-600 text-white">
        <Bot className="h-4 w-4" />
      </span>
      <div className="min-w-0 flex-1 space-y-2.5 pt-0.5">
        {message.blocks.length === 0 ? (
          <Loader2 className="h-4 w-4 animate-spin text-slate-300" />
        ) : (
          message.blocks.map((b, i) => <BlockView key={i} block={b} />)
        )}
      </div>
    </div>
  );
}

function ModelSelect({
  model,
  setModel,
  disabled,
}: {
  model: string;
  setModel: (m: string) => void;
  disabled?: boolean;
}) {
  const [open, setOpen] = useState(false);
  const ref = useRef<HTMLDivElement>(null);
  useEffect(() => {
    const h = (e: MouseEvent) => {
      if (ref.current && !ref.current.contains(e.target as Node)) setOpen(false);
    };
    document.addEventListener('mousedown', h);
    return () => document.removeEventListener('mousedown', h);
  }, []);
  const label = MODELS.find((m) => m.value === model)?.label ?? model;
  return (
    <div className="relative" ref={ref}>
      <button
        type="button"
        disabled={disabled}
        onClick={() => setOpen((o) => !o)}
        className="inline-flex items-center gap-1.5 rounded-md border border-slate-200 bg-white px-2.5 py-1.5 text-[12.5px] text-slate-700 transition-colors hover:bg-slate-50 disabled:opacity-50"
      >
        <span className="h-1.5 w-1.5 rounded-full bg-emerald-500" />
        {label}
        <ChevronDown className={cn('h-3.5 w-3.5 text-slate-400 transition-transform', open && 'rotate-180')} />
      </button>
      {open && (
        <div className="absolute right-0 z-50 mt-1 w-40 rounded-lg border border-slate-200 bg-white py-1 shadow-lg">
          {MODELS.map((m) => (
            <button
              key={m.value}
              type="button"
              onClick={() => {
                setModel(m.value);
                setOpen(false);
              }}
              className={cn(
                'flex w-full items-center gap-2 px-3 py-1.5 text-left text-[12.5px] hover:bg-slate-50',
                m.value === model ? 'font-medium text-teal-700' : 'text-slate-700',
              )}
            >
              {m.value === model ? <Check className="h-3.5 w-3.5" /> : <span className="w-3.5" />}
              {m.label}
            </button>
          ))}
        </div>
      )}
    </div>
  );
}

export function AssistantChat() {
  const { messages, status, model, setModel, send, stop } = useAssistantChat();
  const [input, setInput] = useState('');
  const bottomRef = useRef<HTMLDivElement>(null);
  const taRef = useRef<HTMLTextAreaElement>(null);

  useEffect(() => {
    bottomRef.current?.scrollIntoView({ behavior: 'smooth' });
  }, [messages]);

  const submit = () => {
    if (!input.trim() || status === 'streaming') return;
    void send(input);
    setInput('');
    if (taRef.current) taRef.current.style.height = 'auto';
  };

  return (
    <div className="flex h-[100dvh] flex-col bg-slate-50">
      {/* Header */}
      <header className="flex-none border-b border-slate-200 bg-white/90 backdrop-blur">
        <div className="mx-auto flex h-[3.25rem] max-w-3xl items-center gap-2.5 px-4 py-2.5">
          <span className="inline-flex h-7 w-7 flex-none items-center justify-center rounded-lg bg-teal-600 text-white">
            <Bot className="h-4 w-4" />
          </span>
          <h1 className="text-[14px] font-semibold text-slate-900">PAC 助手</h1>
          <span className="inline-flex items-center gap-1 rounded-full bg-teal-50 px-1.5 py-0.5 text-[10.5px] text-teal-700 ring-1 ring-inset ring-teal-200">
            <Sparkles className="h-3 w-3" />
            MCP 患者工具
          </span>
          <div className="ml-auto">
            <ModelSelect model={model} setModel={setModel} disabled={status === 'streaming'} />
          </div>
        </div>
      </header>

      {/* Messages */}
      <div className="flex-1 overflow-y-auto">
        <div className="mx-auto max-w-3xl space-y-5 px-4 py-5">
          {messages.length === 0 ? (
            <div className="flex flex-col items-center justify-center gap-4 py-20 text-center">
              <span className="inline-flex h-12 w-12 items-center justify-center rounded-2xl bg-teal-600 text-white">
                <Bot className="h-6 w-6" />
              </span>
              <div className="max-w-md text-[13.5px] text-slate-500">
                问我关于患者的问题,我会经 MCP 工具查询 PAC 实时数据,过程透明可见。
              </div>
              <div className="flex flex-wrap justify-center gap-1.5">
                {EXAMPLES.map((ex) => (
                  <button
                    key={ex}
                    type="button"
                    onClick={() => send(ex)}
                    className="rounded-full border border-slate-200 bg-white px-3 py-1.5 text-[11.5px] text-slate-600 transition-colors hover:border-teal-300 hover:bg-teal-50/50 hover:text-teal-700"
                  >
                    {ex}
                  </button>
                ))}
              </div>
            </div>
          ) : (
            messages.map((m) => <MessageView key={m.id} message={m} />)
          )}
          <div ref={bottomRef} />
        </div>
      </div>

      {/* Composer */}
      <div className="flex-none border-t border-slate-200 bg-white">
        <div className="mx-auto max-w-3xl px-4 py-3">
          <div className="flex items-end gap-2 rounded-xl border border-slate-200 bg-white px-3 py-2 transition-all focus-within:border-teal-300 focus-within:ring-2 focus-within:ring-teal-200">
            <textarea
              ref={taRef}
              rows={1}
              value={input}
              onChange={(e) => {
                setInput(e.target.value);
                e.target.style.height = 'auto';
                e.target.style.height = Math.min(e.target.scrollHeight, 140) + 'px';
              }}
              onKeyDown={(e) => {
                if (e.key === 'Enter' && !e.shiftKey) {
                  e.preventDefault();
                  submit();
                }
              }}
              placeholder="问关于患者画像 / 事实 / 召回计划的问题…  (Enter 发送,Shift+Enter 换行)"
              className="max-h-[140px] flex-1 resize-none bg-transparent py-1 text-[13.5px] leading-relaxed text-slate-800 placeholder:text-slate-400 focus:outline-none"
            />
            {status === 'streaming' ? (
              <button
                type="button"
                onClick={stop}
                title="停止"
                className="mb-0.5 inline-flex h-8 w-8 flex-none items-center justify-center rounded-lg bg-slate-100 text-slate-500 transition-colors hover:bg-slate-200"
              >
                <Square className="h-3.5 w-3.5" />
              </button>
            ) : (
              <button
                type="button"
                onClick={submit}
                disabled={!input.trim()}
                title="发送"
                className={cn(
                  'mb-0.5 inline-flex h-8 w-8 flex-none items-center justify-center rounded-lg transition-colors',
                  input.trim() ? 'bg-teal-600 text-white hover:bg-teal-700' : 'bg-slate-100 text-slate-400',
                )}
              >
                <Send className="h-4 w-4" />
              </button>
            )}
          </div>
          <p className="mt-1.5 text-center text-[10.5px] text-slate-400">
            PAC 助手经 MCP 调用患者画像 / 事实 / 召回工具 · 结果仅供参考,请核对后使用
          </p>
        </div>
      </div>
    </div>
  );
}
