import { useEffect, useRef, useState } from 'react';
import { Button, Input, Space, App as AntApp, Empty, Spin } from 'antd';
import {
  Agent,
  ChatMessage,
  SessionAPI,
  streamChat,
  RetrievedSnippet,
  ToolCallTrace
} from '../api';
import Markdown from './Markdown';

interface Props {
  agent: Agent;
  agentId?: string;
}

interface StreamingState {
  active: boolean;
  text: string;
  retrieved: RetrievedSnippet[];
  toolCalls: ToolCallTrace[];
}

export default function ChatPreview({ agent, agentId }: Props) {
  const { message: msg } = AntApp.useApp();
  const [messages, setMessages] = useState<ChatMessage[]>([]);
  const [input, setInput] = useState('');
  const [sending, setSending] = useState(false);
  const [sessionId, setSessionId] = useState<string>('');
  const [streaming, setStreaming] = useState<StreamingState>({
    active: false,
    text: '',
    retrieved: [],
    toolCalls: []
  });
  const bodyRef = useRef<HTMLDivElement>(null);
  const abortRef = useRef<AbortController | null>(null);

  const scrollBottom = () => {
    requestAnimationFrame(() => {
      bodyRef.current?.scrollTo({ top: bodyRef.current.scrollHeight, behavior: 'smooth' });
    });
  };

  useEffect(() => {
    return () => abortRef.current?.abort();
  }, []);

  const handleSend = async () => {
    const text = input.trim();
    if (!text || !agentId || sending) return;
    setInput('');
    setSending(true);

    const tempUser: ChatMessage = {
      id: 'tmp-' + Date.now(),
      role: 'user',
      content: text,
      createdAt: Date.now()
    };
    setMessages((m) => [...m, tempUser]);
    setStreaming({ active: true, text: '', retrieved: [], toolCalls: [] });
    scrollBottom();

    abortRef.current?.abort();
    const ctrl = new AbortController();
    abortRef.current = ctrl;

    try {
      let sid = sessionId;
      if (!sid) {
        const created = await SessionAPI.create(agentId);
        sid = created.id;
        setSessionId(sid);
      }
      const model = String(agent?.model || '').split(',')[0]?.trim() || undefined;
      await streamChat(
        agentId,
        text,
        {
          onMeta: (m) => setStreaming((s) => ({ ...s, retrieved: m.retrieved || [] })),
          onDelta: (chunk) =>
            setStreaming((s) => {
              const next = { ...s, text: s.text + chunk };
              scrollBottom();
              return next;
            }),
          onToolCall: (data) =>
            setStreaming((s) => ({
              ...s,
              toolCalls: [...s.toolCalls, { name: data.name, args: data.args, result: { pending: true } }]
            })),
          onToolResult: (data) =>
            setStreaming((s) => {
              const list = [...s.toolCalls];
              for (let i = list.length - 1; i >= 0; i--) {
                if (list[i].name === data.name && (list[i].result as any)?.pending) {
                  list[i] = { ...list[i], result: data.result };
                  break;
                }
              }
              return { ...s, toolCalls: list };
            }),
          onDone: (data) => {
            setMessages((m) => [...m.filter((x) => x.id !== tempUser.id), data.user, data.assistant]);
            setStreaming({ active: false, text: '', retrieved: [], toolCalls: [] });
            scrollBottom();
          },
          onError: (errMsg) => {
            msg.error('预览失败：' + errMsg);
            setMessages((m) => m.filter((x) => x.id !== tempUser.id));
            setStreaming({ active: false, text: '', retrieved: [], toolCalls: [] });
          }
        },
        ctrl.signal,
        sid,
        model
      );
    } catch (e: any) {
      if (e?.name !== 'AbortError') {
        msg.error('请求失败：' + (e?.message ?? e));
      }
      setMessages((m) => m.filter((x) => x.id !== tempUser.id));
      setStreaming({ active: false, text: '', retrieved: [], toolCalls: [] });
    } finally {
      setSending(false);
    }
  };

  const isImageUrl = (url: string | undefined) => url?.startsWith('http') || url?.startsWith('/');

  return (
    <div className="flex flex-col h-full bg-gray-50 border-l">
      <div className="p-4 border-b bg-white flex items-center gap-2">
        <div 
          className="rounded-full text-white flex items-center justify-center font-bold overflow-hidden"
          style={{ width: 84, height: 84, background: agent.avatar || '#0891b2' }}
        >
          {isImageUrl(agent.avatar) ? (
            <img src={agent.avatar} className="w-full h-full object-cover" alt="avatar" />
          ) : (
            (agent?.name?.charAt(0) || '?').toUpperCase()
          )}
        </div>
        <div className="font-semibold text-gray-800">预览</div>
      </div>

      <div ref={bodyRef} className="flex-1 overflow-auto p-4 space-y-4">
        {messages.length === 0 && !streaming.active ? (
          <Empty description="在这里测试你的智能体" style={{ marginTop: 100 }} />
        ) : (
          <div className="flex flex-col gap-4">
            {messages.map((m) => (
              <div key={m.id} className={`flex ${m.role === 'user' ? 'justify-end' : 'justify-start'}`}>
                <div className={`bubble ${m.role === 'user' ? 'user' : 'assistant'}`}>
                  <Markdown>{m.content}</Markdown>
                </div>
              </div>
            ))}
            {streaming.active && (
              <div className="flex justify-start">
                <div className="bubble assistant">
                  {streaming.text ? (
                    <Markdown>{streaming.text + '▍'}</Markdown>
                  ) : (
                    <span className="text-gray-400">思考中...</span>
                  )}
                </div>
              </div>
            )}
          </div>
        )}
      </div>

      <div className="p-4 bg-white border-t">
        <div className="flex gap-2">
          <Input.TextArea
            value={input}
            onChange={(e) => setInput(e.target.value)}
            placeholder="输入消息测试..."
            autoSize={{ minRows: 1, maxRows: 4 }}
            onPressEnter={(e) => {
              if (!e.shiftKey) {
                e.preventDefault();
                handleSend();
              }
            }}
            disabled={sending || !agentId}
            className="rounded-lg"
          />
          <Button
            type="primary"
            onClick={handleSend}
            disabled={!agentId}
            loading={sending}
            style={{ backgroundColor: '#0891b2', height: 'auto' }}
          >
            发送
          </Button>
        </div>
        {!agentId && (
          <div className="text-xs text-gray-400 mt-1">请先保存智能体以启用预览</div>
        )}
      </div>
    </div>
  );
}
