import { useEffect, useRef, useState } from 'react';
import { renderKnowledgeMarkdown } from '../markdown';

interface ToolCall { id: string; name: string; arguments: Record<string, unknown>; }
interface ToolResult { id: string; name: string; output: string; error?: string; }
interface AgentActivity {
  id: string;
  kind: 'wake' | 'tool' | 'permission' | 'receipt';
  label: string;
  detail: string;
  status: 'running' | 'completed' | 'pending' | 'failed';
  timestamp: string;
  tool?: string;
}
interface Message {
  role: 'user' | 'assistant' | 'system';
  content: string;
  toolCalls?: ToolCall[];
  toolResults?: ToolResult[];
  activities?: AgentActivity[];
  timestamp: string;
}
interface ConversationSummary {
  id: string;
  title: string;
  createdAt: string;
  updatedAt: string;
  messageCount: number;
}
interface AgentStatus {
  name: string;
  role: string;
  model: string;
  configured: boolean;
  operational: boolean;
  tools: string[];
}
interface PendingAction {
  id: string;
  tool: string;
  effect: 'write' | 'delete';
  target: string;
  summary: string;
  createdAt: string;
}
interface Props {
  apiBase: string;
  runtimeRevision?: number;
  onClose?: () => void;
  onWorldChanged?: () => void;
}

export default function AgentChat({ apiBase, runtimeRevision = 0, onClose, onWorldChanged }: Props) {
  const [messages, setMessages] = useState<Message[]>([]);
  const [conversations, setConversations] = useState<ConversationSummary[]>([]);
  const [activeConversationId, setActiveConversationId] = useState('');
  const [historyOpen, setHistoryOpen] = useState(false);
  const [input, setInput] = useState('');
  const [sending, setSending] = useState(false);
  const [status, setStatus] = useState<AgentStatus | null>(null);
  const [statusError, setStatusError] = useState('');
  const [pendingActions, setPendingActions] = useState<PendingAction[]>([]);
  const [actionBusy, setActionBusy] = useState('');
  const bottomRef = useRef<HTMLDivElement>(null);
  const inputRef = useRef<HTMLTextAreaElement>(null);

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

  async function bootstrap() {
    try {
      const response = await fetch(`${apiBase}/api/agent/conversations`);
      const data = await response.json();
      if (!data.ok) throw new Error(data.error || '无法读取对话');
      setConversations(data.conversations || []);
      const selected = activeConversationId || data.activeConversationId || data.conversations?.[0]?.id;
      if (selected) await selectConversation(selected);
    } catch {
      setStatusError('HoloLake 本地服务未启动');
    }
  }

  async function selectConversation(id: string) {
    setActiveConversationId(id);
    const [historyResponse, statusResponse, actionsResponse] = await Promise.all([
      fetch(`${apiBase}/api/agent/conversation?conversationId=${encodeURIComponent(id)}`),
      fetch(`${apiBase}/api/agent/status?conversationId=${encodeURIComponent(id)}`),
      fetch(`${apiBase}/api/agent/actions?conversationId=${encodeURIComponent(id)}`),
    ]);
    const [history, runtime, actions] = await Promise.all([historyResponse.json(), statusResponse.json(), actionsResponse.json()]);
    if (history.ok) setMessages(history.messages || []);
    if (actions.ok) setPendingActions(actions.actions || []);
    if (runtime.ok) {
      setStatusError('');
      setStatus({
        name: runtime.persona.name,
        role: runtime.persona.role,
        model: runtime.persona.model,
        configured: runtime.configured,
        operational: runtime.operational,
        tools: runtime.tools || [],
      });
    }
  }

  async function refreshConversationList() {
    const response = await fetch(`${apiBase}/api/agent/conversations`);
    const data = await response.json();
    if (data.ok) setConversations(data.conversations || []);
  }

  async function createConversation() {
    const response = await fetch(`${apiBase}/api/agent/conversations`, { method: 'POST' });
    const data = await response.json();
    if (!data.ok) return;
    await refreshConversationList();
    await selectConversation(data.conversation.id);
    setHistoryOpen(false);
    inputRef.current?.focus();
  }

  async function deleteConversation(id: string) {
    if (!confirm('删除这条对话记录？知识库文档不会被删除。')) return;
    const response = await fetch(`${apiBase}/api/agent/conversations/${encodeURIComponent(id)}`, { method: 'DELETE' });
    const data = await response.json();
    if (!data.ok) return;
    await refreshConversationList();
    await selectConversation(data.activeConversationId);
  }

  async function sendMessage() {
    const text = input.trim();
    if (!text || sending || !activeConversationId) return;
    setInput('');
    setSending(true);
    setMessages(previous => [...previous, { role: 'user', content: text, timestamp: new Date().toISOString() }]);
    try {
      const response = await fetch(`${apiBase}/api/agent/chat`, {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ message: text, conversationId: activeConversationId }),
      });
      const data = await response.json();
      if (!data.ok) throw new Error(data.error || '调用失败');
      setMessages(previous => [...previous, {
        role: 'assistant',
        content: data.reply,
        toolCalls: data.toolCalls || [],
        toolResults: data.toolResults || [],
        activities: data.activities || [],
        timestamp: new Date().toISOString(),
      }]);
      setPendingActions(data.pendingActions || []);
      await refreshConversationList();
    } catch (error) {
      setMessages(previous => [...previous, { role: 'assistant', content: `错误：${error instanceof Error ? error.message : String(error)}`, timestamp: new Date().toISOString() }]);
    } finally {
      setSending(false);
      inputRef.current?.focus();
    }
  }

  async function resolveAction(action: PendingAction, decision: 'confirm' | 'reject') {
    setActionBusy(action.id);
    try {
      const response = await fetch(`${apiBase}/api/agent/actions/${encodeURIComponent(action.id)}/${decision}`, {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ conversationId: activeConversationId }),
      });
      const data = await response.json();
      if (!data.ok) throw new Error(data.error || '动作处理失败');
      setPendingActions(data.actions || []);
      setMessages(data.messages || messages);
      await refreshConversationList();
      if (decision === 'confirm') onWorldChanged?.();
    } catch (error) {
      setMessages(previous => [...previous, { role: 'assistant', content: `动作未执行：${error instanceof Error ? error.message : String(error)}`, timestamp: new Date().toISOString() }]);
    } finally {
      setActionBusy('');
    }
  }

  return (
    <div className="agent-chat">
      <div className="agent-header">
        <div className="agent-info">
          <div className="agent-avatar" aria-hidden="true"><span /></div>
          <div className="agent-meta"><h3>{status?.name || 'HoloLake'}</h3><span className="agent-role">{status?.role || '语言操作入口'}</span></div>
        </div>
        <div className="agent-actions">
          <button type="button" onClick={createConversation} title="新建对话">＋</button>
          <button type="button" className={historyOpen ? 'selected' : ''} onClick={() => setHistoryOpen(value => !value)} title="历史记录">历史</button>
          <button type="button" onClick={onClose} title="关闭">×</button>
        </div>
      </div>

      <div className="runtime-status">
        <div className="runtime-row"><span className={`runtime-dot ${status?.operational ? 'online' : 'waiting'}`} /><span>{statusError || (status?.operational ? '语言操作入口可用' : '请在设置中验证模型')}</span><span className="runtime-tools">{status?.tools?.length || 0} 项受控能力 · {status?.model || 'offline'}</span></div>
      </div>

      <div className={`agent-body ${historyOpen ? 'history-open' : ''}`}>
        {historyOpen && (
          <aside className="agent-history" aria-label="对话历史">
            <div className="agent-history-heading"><strong>对话历史</strong><button type="button" onClick={createConversation}>新建</button></div>
            <div className="agent-history-list">
              {conversations.map(conversation => (
                <div className={`agent-history-item ${conversation.id === activeConversationId ? 'selected' : ''}`} key={conversation.id}>
                  <button type="button" onClick={() => { void selectConversation(conversation.id); setHistoryOpen(false); }}><strong>{conversation.title}</strong><small>{new Date(conversation.updatedAt).toLocaleString('zh-CN')}</small></button>
                  <button type="button" className="delete" onClick={() => void deleteConversation(conversation.id)} aria-label={`删除 ${conversation.title}`}>×</button>
                </div>
              ))}
            </div>
          </aside>
        )}

        <div className="agent-conversation">
          <div className="agent-messages">
            {messages.length === 0 && <div className="agent-welcome"><h2>语言操作入口</h2><p>人格体唤醒时，HoloLake 会先查找该人格体自己的路径页面。活动栏只显示真实发生的读取、工具、权限与回执，不使用固定步骤模板。</p></div>}
            {messages.map((message, index) => (
              <div key={`${message.timestamp}-${index}`} className={`msg msg-${message.role}`}>
                {message.role === 'user' ? <div className="msg-bubble msg-user-bubble"><p>{message.content}</p></div> : (
                  <div className="msg-bubble msg-assistant-bubble">
                    <div className="msg-avatar" aria-hidden="true"><span /></div>
                    <div className="msg-content">
                      {message.activities && message.activities.length > 0 && (
                        <details className="agent-activity" open>
                          <summary>运行活动 · {message.activities.length} 项</summary>
                          <ol>{message.activities.map(activity => <li key={activity.id} data-status={activity.status}><span /><div><strong>{activity.label}</strong><small>{activity.detail}</small></div><em>{activity.status === 'completed' ? '完成' : activity.status === 'pending' ? '待确认' : activity.status === 'failed' ? '失败' : '进行中'}</em></li>)}</ol>
                        </details>
                      )}
                      <div className="msg-markdown" dangerouslySetInnerHTML={{ __html: renderKnowledgeMarkdown(message.content) }} />
                    </div>
                  </div>
                )}
              </div>
            ))}

            {pendingActions.length > 0 && <div className="pending-actions" aria-label="待确认动作"><div className="pending-actions-heading">待确认动作</div>{pendingActions.map(action => <div className={`pending-action ${action.effect}`} key={action.id}><div><strong>{action.effect === 'delete' ? '删除' : '写入'} · {action.target}</strong><small>{action.summary}</small></div><div className="pending-action-buttons"><button onClick={() => resolveAction(action, 'reject')} disabled={Boolean(actionBusy)}>取消</button><button className={action.effect === 'delete' ? 'danger' : 'confirm'} onClick={() => resolveAction(action, 'confirm')} disabled={Boolean(actionBusy)}>{actionBusy === action.id ? '处理中…' : '确认执行'}</button></div></div>)}</div>}
            {sending && <div className="msg msg-assistant"><div className="msg-bubble msg-assistant-bubble"><div className="msg-avatar" aria-hidden="true"><span /></div><div className="msg-content typing"><span className="dot" /><span className="dot" /><span className="dot" /></div></div></div>}
            <div ref={bottomRef} />
          </div>

          <div className="agent-input-area"><div className="agent-input-wrapper"><textarea ref={inputRef} className="agent-input" placeholder="向 HoloLake 发出语言指令…" value={input} onChange={event => setInput(event.target.value)} onKeyDown={event => { if (event.key === 'Enter' && !event.shiftKey) { event.preventDefault(); void sendMessage(); } }} rows={1} disabled={sending || !status?.operational} /><button className="btn-send" onClick={sendMessage} disabled={sending || !input.trim() || !status?.operational}>↑</button></div><div className="agent-hint">写操作先确认 · 路径步骤来自人格体自己的页面 · 只展示工具与回执</div></div>
        </div>
      </div>
    </div>
  );
}
