import React, { useState, useEffect, useRef, useCallback } from 'react';
import './App.css';

// UUID v4 generator — works in all contexts (HTTP and HTTPS)
function generateUUID() {
  if (typeof crypto !== 'undefined' && typeof crypto.randomUUID === 'function') {
    return crypto.randomUUID();
  }
  if (typeof crypto !== 'undefined' && typeof crypto.getRandomValues === 'function') {
    const bytes = new Uint8Array(16);
    crypto.getRandomValues(bytes);
    bytes[6] = (bytes[6] & 0x0f) | 0x40;
    bytes[8] = (bytes[8] & 0x3f) | 0x80;
    const hex = Array.from(bytes, b => b.toString(16).padStart(2, '0')).join('');
    return `${hex.slice(0,8)}-${hex.slice(8,12)}-${hex.slice(12,16)}-${hex.slice(16,20)}-${hex.slice(20)}`;
  }
  return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, c => {
    const r = (Math.random() * 16) | 0;
    return (c === 'x' ? r : (r & 0x3) | 0x8).toString(16);
  });
}

const API = '';

const App = () => {
  const [activeView, setActiveView] = useState('chat');

  // Claude process status
  const [claudeStatus, setClaudeStatus] = useState('unknown');
  const [claudeSessionId, setClaudeSessionId] = useState(null);

  // Chat state
  const [chatMessages, setChatMessages] = useState([]);
  const [chatInput, setChatInput] = useState('');
  const [chatWaiting, setChatWaiting] = useState(false);
  const [chatSessionId] = useState(() => generateUUID());
  const [chatSessions, setChatSessions] = useState([]);
  const [selectedHistorySession, setSelectedHistorySession] = useState(null);
  const chatEndRef = useRef(null);
  const wsRef = useRef(null);
  const [wsConnected, setWsConnected] = useState(false);
  const [wsError, setWsError] = useState(null);
  const pendingAssistantRef = useRef('');
  const reconnectTimerRef = useRef(null);

  // Tasks state
  const [tasks, setTasks] = useState([]);
  const [showTaskForm, setShowTaskForm] = useState(false);
  const [taskForm, setTaskForm] = useState({
    name: '', description: '', prompt: '', schedule_type: 'manual',
    schedule_value: '', enabled: true, agent_tools: 'Bash,Read,Write,Edit',
    agent_system_prompt: '', agent_permission_mode: 'auto', agent_timeout: 300
  });
  const [editingTaskId, setEditingTaskId] = useState(null);
  const [taskRuns, setTaskRuns] = useState({});

  // MCP state
  const [mcpServers, setMcpServers] = useState([]);
  const [showMcpForm, setShowMcpForm] = useState(false);
  const [mcpForm, setMcpForm] = useState({ name: '', server_type: 'sse', url: '', command: '' });

  // ---- Data fetching ----
  const fetchTasks = async () => {
    try {
      const r = await fetch(`${API}/api/tasks`);
      if (r.ok) setTasks(await r.json());
    } catch (e) { /* ignore */ }
  };

  const fetchMcpServers = async () => {
    try {
      const r = await fetch(`${API}/api/mcp/servers`);
      if (r.ok) setMcpServers(await r.json());
    } catch (e) { /* ignore */ }
  };

  const fetchChatSessions = async () => {
    try {
      const r = await fetch(`${API}/api/chat/sessions`);
      if (r.ok) setChatSessions(await r.json());
    } catch (e) { /* ignore */ }
  };

  const fetchClaudeStatus = async () => {
    try {
      const r = await fetch(`${API}/api/claude/status`);
      if (r.ok) {
        const d = await r.json();
        setClaudeStatus(d.status);
        setClaudeSessionId(d.session_id);
      }
    } catch (e) { /* ignore */ }
  };

  useEffect(() => {
    fetchTasks();
    fetchMcpServers();
    fetchChatSessions();
    fetchClaudeStatus();
    const interval = setInterval(() => {
      fetchTasks();
      fetchClaudeStatus();
    }, 8000);
    return () => clearInterval(interval);
  }, []);

  useEffect(() => {
    if (chatEndRef.current) {
      chatEndRef.current.scrollIntoView({ behavior: 'smooth' });
    }
  }, [chatMessages]);

  // ---- WebSocket ----
  const connectWs = useCallback(() => {
    if (wsRef.current && wsRef.current.readyState < 2) return; // already open or connecting
    if (reconnectTimerRef.current) {
      clearTimeout(reconnectTimerRef.current);
      reconnectTimerRef.current = null;
    }

    const proto = window.location.protocol === 'https:' ? 'wss:' : 'ws:';
    const ws = new WebSocket(`${proto}//${window.location.host}/api/chat/ws`);
    wsRef.current = ws;

    ws.onopen = () => {
      setWsConnected(true);
      setWsError(null);
    };

    ws.onclose = () => {
      setWsConnected(false);
      // Auto-reconnect after 3 seconds
      reconnectTimerRef.current = setTimeout(connectWs, 3000);
    };

    ws.onerror = () => {
      setWsError('WebSocket error — reconnecting...');
    };

    ws.onmessage = (event) => {
      let data;
      try { data = JSON.parse(event.data); } catch (e) { return; }

      const type = data.type;

      if (type === 'ping') return;

      if (type === 'system') {
        const sub = data.subtype;
        if (sub === 'connected' || sub === 'status' || sub === 'start_result' || sub === 'restart_result') {
          if (data.claude_status) setClaudeStatus(data.claude_status);
          if (data.claude_session_id) setClaudeSessionId(data.claude_session_id);
        }
        if (sub === 'process_dead') {
          setClaudeStatus('dead');
          setChatWaiting(false);
          appendSystemMsg('⚠️ Claude process stopped. Click "Start Claude" to restart.');
        }
        return;
      }

      if (type === 'user_ack') {
        // We already added the user message optimistically, nothing to do
        return;
      }

      if (type === 'error') {
        setChatWaiting(false);
        appendErrorMsg(data.message || 'Unknown error');
        return;
      }

      // Claude stream-json events
      if (type === 'assistant') {
        // Full assistant message (not streaming)
        const content = data.message?.content;
        let text = '';
        if (Array.isArray(content)) {
          text = content.filter(b => b.type === 'text').map(b => b.text).join('');
        } else if (typeof content === 'string') {
          text = content;
        }
        if (text) {
          pendingAssistantRef.current += text;
          upsertStreamingMessage(pendingAssistantRef.current, false);
        }
      }

      if (type === 'content_block_delta') {
        const delta = data.delta;
        if (delta?.type === 'text_delta') {
          pendingAssistantRef.current += delta.text || '';
          upsertStreamingMessage(pendingAssistantRef.current, true);
        }
      }

      if (type === 'content_block_stop') {
        // Block done, finalize
        if (pendingAssistantRef.current) {
          upsertStreamingMessage(pendingAssistantRef.current, false);
        }
      }

      if (type === 'result') {
        // Turn complete
        const sub = data.subtype;
        if (sub === 'success' || sub === 'error_max_turns') {
          if (pendingAssistantRef.current) {
            upsertStreamingMessage(pendingAssistantRef.current, false);
            pendingAssistantRef.current = '';
          }
          if (data.session_id) setClaudeSessionId(data.session_id);
          setChatWaiting(false);
          fetchChatSessions(); // refresh session list
        }
        if (sub === 'error' || sub === 'error_during_execution') {
          pendingAssistantRef.current = '';
          setChatWaiting(false);
          appendErrorMsg(data.error || 'Claude returned an error');
        }
      }
    };
  }, []);

  useEffect(() => {
    connectWs();
    return () => {
      if (reconnectTimerRef.current) clearTimeout(reconnectTimerRef.current);
      if (wsRef.current) wsRef.current.close();
    };
  }, [connectWs]);

  const appendSystemMsg = (text) => {
    setChatMessages(prev => [...prev, {
      id: generateUUID(), role: 'system', content: text, timestamp: new Date().toISOString()
    }]);
  };

  const appendErrorMsg = (text) => {
    setChatMessages(prev => [...prev, {
      id: generateUUID(), role: 'error', content: text, timestamp: new Date().toISOString()
    }]);
  };

  const upsertStreamingMessage = (text, streaming) => {
    setChatMessages(prev => {
      const last = prev[prev.length - 1];
      if (last && last.role === 'assistant' && (last.streaming || streaming)) {
        return [...prev.slice(0, -1), { ...last, content: text, streaming }];
      }
      return [...prev, {
        id: generateUUID(), role: 'assistant', content: text,
        streaming, timestamp: new Date().toISOString()
      }];
    });
  };

  const sendMessage = () => {
    const text = chatInput.trim();
    if (!text || chatWaiting) return;

    // Optimistic UI: add user message immediately
    setChatMessages(prev => [...prev, {
      id: generateUUID(), role: 'user', content: text, timestamp: new Date().toISOString()
    }]);
    setChatInput('');
    setChatWaiting(true);
    pendingAssistantRef.current = '';

    if (!wsRef.current || wsRef.current.readyState !== 1) {
      appendErrorMsg('Not connected — reconnecting...');
      setChatWaiting(false);
      connectWs();
      return;
    }

    wsRef.current.send(JSON.stringify({
      action: 'send',
      message: text,
      session_id: chatSessionId
    }));
  };

  const handleChatKeyDown = (e) => {
    if (e.key === 'Enter' && !e.shiftKey) {
      e.preventDefault();
      sendMessage();
    }
  };

  const startClaude = () => {
    setClaudeStatus('starting');
    if (wsRef.current && wsRef.current.readyState === 1) {
      wsRef.current.send(JSON.stringify({ action: 'start_claude' }));
    } else {
      fetch(`${API}/api/claude/start`, { method: 'POST' })
        .then(r => r.json())
        .then(d => {
          setClaudeStatus(d.status);
          if (d.session_id) setClaudeSessionId(d.session_id);
        });
    }
  };

  const restartClaude = () => {
    setClaudeStatus('starting');
    if (wsRef.current && wsRef.current.readyState === 1) {
      wsRef.current.send(JSON.stringify({ action: 'restart_claude' }));
    } else {
      fetch(`${API}/api/claude/restart`, { method: 'POST' })
        .then(r => r.json())
        .then(d => {
          setClaudeStatus(d.status);
          if (d.session_id) setClaudeSessionId(d.session_id);
        });
    }
  };

  const loadHistorySession = async (sid) => {
    setSelectedHistorySession(sid);
    try {
      const r = await fetch(`${API}/api/chat/sessions/${sid}/messages`);
      if (r.ok) {
        const msgs = await r.json();
        setChatMessages(msgs.map(m => ({
          id: m.id, role: m.role, content: m.content, timestamp: m.timestamp, streaming: false
        })));
      }
    } catch (e) { /* ignore */ }
  };

  // ---- Tasks ----
  const saveTask = async () => {
    const method = editingTaskId ? 'PUT' : 'POST';
    const url = editingTaskId ? `${API}/api/tasks/${editingTaskId}` : `${API}/api/tasks`;
    try {
      const r = await fetch(url, {
        method,
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify(taskForm)
      });
      if (r.ok) {
        fetchTasks();
        setShowTaskForm(false);
        setEditingTaskId(null);
        setTaskForm({
          name: '', description: '', prompt: '', schedule_type: 'manual',
          schedule_value: '', enabled: true, agent_tools: 'Bash,Read,Write,Edit',
          agent_system_prompt: '', agent_permission_mode: 'auto', agent_timeout: 300
        });
      }
    } catch (e) { alert('Failed to save task'); }
  };

  const deleteTask = async (id) => {
    if (!window.confirm('Delete this task?')) return;
    await fetch(`${API}/api/tasks/${id}`, { method: 'DELETE' });
    fetchTasks();
  };

  const runTask = async (id) => {
    try {
      const r = await fetch(`${API}/api/tasks/${id}/run`, { method: 'POST' });
      if (r.ok) {
        alert('Task started!');
        fetchTasks();
      }
    } catch (e) { alert('Failed to run task'); }
  };

  const editTask = (task) => {
    setEditingTaskId(task.id);
    setTaskForm({ ...task });
    setShowTaskForm(true);
  };

  const fetchTaskRuns = async (taskId) => {
    try {
      const r = await fetch(`${API}/api/tasks/${taskId}/runs`);
      if (r.ok) {
        setTaskRuns(prev => ({ ...prev, [taskId]: await r.json() }));
      }
    } catch (e) { /* ignore */ }
  };

  // ---- MCP ----
  const saveMcp = async () => {
    try {
      const r = await fetch(`${API}/api/mcp/servers`, {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify(mcpForm)
      });
      if (r.ok) {
        fetchMcpServers();
        setShowMcpForm(false);
        setMcpForm({ name: '', server_type: 'sse', url: '', command: '' });
      }
    } catch (e) { alert('Failed to add MCP server'); }
  };

  const removeMcp = async (name) => {
    if (!window.confirm(`Remove MCP server "${name}"?`)) return;
    await fetch(`${API}/api/mcp/servers/${name}`, { method: 'DELETE' });
    fetchMcpServers();
  };

  // ---- Status helpers ----
  const claudeStatusColor = {
    ready: '#22c55e',
    starting: '#f59e0b',
    dead: '#ef4444',
    not_started: '#6b7280',
    unknown: '#6b7280'
  }[claudeStatus] || '#6b7280';

  const claudeStatusLabel = {
    ready: 'Running',
    starting: 'Starting…',
    dead: 'Stopped',
    not_started: 'Not Started',
    unknown: 'Unknown'
  }[claudeStatus] || claudeStatus;

  // ---- Render ----
  return (
    <div className="app">
      {/* Sidebar nav */}
      <div className="sidebar">
        <div className="sidebar-brand">
          <span className="brand-icon">⚡</span>
          <span className="brand-name">Claude Agent</span>
        </div>

        {/* Claude process status pill */}
        <div className="claude-status-pill" style={{ borderColor: claudeStatusColor }}>
          <span className="status-dot" style={{ background: claudeStatusColor }}></span>
          <span className="status-label">{claudeStatusLabel}</span>
          {claudeStatus === 'ready' && (
            <button className="btn-tiny" onClick={restartClaude} title="Restart">↺</button>
          )}
          {(claudeStatus === 'dead' || claudeStatus === 'not_started' || claudeStatus === 'unknown') && (
            <button className="btn-tiny btn-green" onClick={startClaude} title="Start">▶</button>
          )}
        </div>

        <nav className="sidebar-nav">
          <button className={`nav-item ${activeView === 'chat' ? 'active' : ''}`}
            onClick={() => setActiveView('chat')}>
            <span className="nav-icon">💬</span> Chat
          </button>
          <button className={`nav-item ${activeView === 'tasks' ? 'active' : ''}`}
            onClick={() => { setActiveView('tasks'); fetchTasks(); }}>
            <span className="nav-icon">📋</span> Tasks
          </button>
          <button className={`nav-item ${activeView === 'mcp' ? 'active' : ''}`}
            onClick={() => { setActiveView('mcp'); fetchMcpServers(); }}>
            <span className="nav-icon">🔌</span> MCP Servers
          </button>
        </nav>

        {/* Session history (chat view only) */}
        {activeView === 'chat' && (
          <div className="session-history">
            <div className="session-history-title">Session History</div>
            <button className="session-new-btn" onClick={() => {
              setChatMessages([]);
              setSelectedHistorySession(null);
              pendingAssistantRef.current = '';
            }}>+ New Chat</button>
            {chatSessions.slice(0, 15).map(s => (
              <button key={s.session_id}
                className={`session-item ${selectedHistorySession === s.session_id ? 'active' : ''}`}
                onClick={() => loadHistorySession(s.session_id)}>
                <span className="session-item-date">
                  {new Date(s.last_active).toLocaleDateString()}
                </span>
                <span className="session-item-count">{s.message_count} msgs</span>
              </button>
            ))}
            {chatSessions.length === 0 && (
              <div className="session-empty">No history yet</div>
            )}
          </div>
        )}
      </div>

      {/* Main content */}
      <div className="main-content">

        {/* ====== CHAT VIEW ====== */}
        {activeView === 'chat' && (
          <div className="chat-container">
            {/* Chat header */}
            <div className="chat-header">
              <div className="chat-header-info">
                <h2>Claude Chat</h2>
                {claudeSessionId && (
                  <span className="session-id-badge" title={claudeSessionId}>
                    Session: {claudeSessionId.slice(0, 8)}…
                  </span>
                )}
              </div>
              <div className="chat-header-status">
                <span className={`ws-badge ${wsConnected ? 'connected' : 'disconnected'}`}>
                  {wsConnected ? '● Live' : '○ Connecting…'}
                </span>
                {claudeStatus !== 'ready' && (
                  <button className="btn btn-primary btn-sm" onClick={startClaude}>
                    {claudeStatus === 'starting' ? 'Starting…' : 'Start Claude'}
                  </button>
                )}
              </div>
            </div>

            {/* Messages area */}
            <div className="chat-messages">
              {chatMessages.length === 0 && claudeStatus === 'ready' && (
                <div className="chat-empty">
                  <div className="chat-empty-icon">🤖</div>
                  <div className="chat-empty-title">Claude is ready</div>
                  <div className="chat-empty-sub">
                    You're talking to a persistent Claude Code session.
                    It remembers context across messages.
                  </div>
                </div>
              )}
              {chatMessages.length === 0 && claudeStatus !== 'ready' && (
                <div className="chat-empty">
                  <div className="chat-empty-icon">⏸️</div>
                  <div className="chat-empty-title">Claude is not running</div>
                  <div className="chat-empty-sub">
                    {claudeStatus === 'starting'
                      ? 'Starting the Claude process, please wait…'
                      : 'The Claude process needs to be started. Click "Start Claude" above.'}
                  </div>
                  {claudeStatus !== 'starting' && (
                    <button className="btn btn-primary mt-2" onClick={startClaude}>
                      Start Claude
                    </button>
                  )}
                </div>
              )}

              {chatMessages.map((msg, i) => (
                <div key={msg.id || i} className={`chat-msg chat-msg-${msg.role}`}>
                  <div className="msg-role">
                    {msg.role === 'user' ? '👤 You'
                      : msg.role === 'assistant' ? '🤖 Claude'
                      : msg.role === 'system' ? '⚙️ System'
                      : '❌ Error'}
                  </div>
                  <div className="msg-content">
                    <MessageContent content={msg.content} />
                    {msg.streaming && <span className="typing-cursor">▋</span>}
                  </div>
                  <div className="msg-time">
                    {msg.timestamp ? new Date(msg.timestamp).toLocaleTimeString() : ''}
                  </div>
                </div>
              ))}
              <div ref={chatEndRef} />
            </div>

            {/* Input area */}
            <div className="chat-input-area">
              {chatWaiting && (
                <div className="thinking-bar">
                  <span className="thinking-dots">●●●</span> Claude is thinking…
                </div>
              )}
              <div className="chat-input-row">
                <textarea
                  className="chat-textarea"
                  value={chatInput}
                  onChange={e => setChatInput(e.target.value)}
                  onKeyDown={handleChatKeyDown}
                  placeholder={
                    claudeStatus !== 'ready'
                      ? 'Start Claude to begin chatting…'
                      : 'Type a message… (Enter to send, Shift+Enter for newline)'
                  }
                  disabled={chatWaiting || claudeStatus !== 'ready'}
                  rows={3}
                />
                <button
                  className="chat-send-btn"
                  onClick={sendMessage}
                  disabled={chatWaiting || !chatInput.trim() || claudeStatus !== 'ready'}
                >
                  {chatWaiting ? '…' : '➤'}
                </button>
              </div>
            </div>
          </div>
        )}

        {/* ====== TASKS VIEW ====== */}
        {activeView === 'tasks' && (
          <div className="view-container">
            <div className="view-header">
              <h2>Scheduled Tasks</h2>
              <button className="btn btn-primary" onClick={() => {
                setShowTaskForm(true);
                setEditingTaskId(null);
                setTaskForm({
                  name: '', description: '', prompt: '', schedule_type: 'manual',
                  schedule_value: '', enabled: true, agent_tools: 'Bash,Read,Write,Edit',
                  agent_system_prompt: '', agent_permission_mode: 'auto', agent_timeout: 300
                });
              }}>+ New Task</button>
            </div>

            {showTaskForm && (
              <div className="form-card">
                <h3>{editingTaskId ? 'Edit Task' : 'New Task'}</h3>
                <div className="form-grid">
                  <div className="form-field">
                    <label>Name *</label>
                    <input value={taskForm.name}
                      onChange={e => setTaskForm(p => ({ ...p, name: e.target.value }))}
                      placeholder="My Task" />
                  </div>
                  <div className="form-field">
                    <label>Schedule</label>
                    <select value={taskForm.schedule_type}
                      onChange={e => setTaskForm(p => ({ ...p, schedule_type: e.target.value }))}>
                      <option value="manual">Manual only</option>
                      <option value="recurring">Recurring (cron)</option>
                    </select>
                  </div>
                  {taskForm.schedule_type === 'recurring' && (
                    <div className="form-field">
                      <label>Cron Expression</label>
                      <input value={taskForm.schedule_value}
                        onChange={e => setTaskForm(p => ({ ...p, schedule_value: e.target.value }))}
                        placeholder="0 9 * * 1-5 (weekdays at 9am)" />
                    </div>
                  )}
                  <div className="form-field form-field-full">
                    <label>Prompt *</label>
                    <textarea value={taskForm.prompt}
                      onChange={e => setTaskForm(p => ({ ...p, prompt: e.target.value }))}
                      placeholder="What should Claude do?" rows={4} />
                  </div>
                  <div className="form-field">
                    <label>Allowed Tools</label>
                    <input value={taskForm.agent_tools}
                      onChange={e => setTaskForm(p => ({ ...p, agent_tools: e.target.value }))}
                      placeholder="Bash,Read,Write,Edit" />
                  </div>
                  <div className="form-field">
                    <label>Permission Mode</label>
                    <select value={taskForm.agent_permission_mode}
                      onChange={e => setTaskForm(p => ({ ...p, agent_permission_mode: e.target.value }))}>
                      <option value="auto">Auto</option>
                      <option value="acceptEdits">Accept Edits</option>
                      <option value="plan">Plan only</option>
                    </select>
                  </div>
                  <div className="form-field">
                    <label>Timeout (seconds)</label>
                    <input type="number" value={taskForm.agent_timeout}
                      onChange={e => setTaskForm(p => ({ ...p, agent_timeout: parseInt(e.target.value) || 300 }))} />
                  </div>
                  <div className="form-field form-field-full">
                    <label>System Prompt (optional)</label>
                    <textarea value={taskForm.agent_system_prompt}
                      onChange={e => setTaskForm(p => ({ ...p, agent_system_prompt: e.target.value }))}
                      placeholder="Custom instructions for this task..." rows={2} />
                  </div>
                </div>
                <div className="form-actions">
                  <button className="btn btn-primary" onClick={saveTask}
                    disabled={!taskForm.name || !taskForm.prompt}>
                    {editingTaskId ? 'Update Task' : 'Create Task'}
                  </button>
                  <button className="btn btn-secondary" onClick={() => setShowTaskForm(false)}>
                    Cancel
                  </button>
                </div>
              </div>
            )}

            <div className="task-list">
              {tasks.length === 0 && (
                <div className="empty-state">No tasks yet. Create one to get started.</div>
              )}
              {tasks.map(task => (
                <div key={task.id} className="task-card">
                  <div className="task-card-header">
                    <div className="task-info">
                      <span className="task-name">{task.name}</span>
                      <span className={`task-status-badge status-${task.status}`}>
                        {task.status}
                      </span>
                      {task.schedule_type === 'recurring' && task.schedule_value && (
                        <span className="task-cron-badge">⏱ {task.schedule_value}</span>
                      )}
                    </div>
                    <div className="task-actions">
                      <button className="btn btn-sm btn-success" onClick={() => runTask(task.id)}
                        disabled={task.status === 'running'}>
                        ▶ Run
                      </button>
                      <button className="btn btn-sm btn-secondary" onClick={() => editTask(task)}>
                        Edit
                      </button>
                      <button className="btn btn-sm btn-secondary"
                        onClick={() => fetchTaskRuns(task.id)}>
                        Logs
                      </button>
                      <button className="btn btn-sm btn-danger" onClick={() => deleteTask(task.id)}>
                        Delete
                      </button>
                    </div>
                  </div>
                  {task.description && (
                    <div className="task-desc">{task.description}</div>
                  )}
                  <div className="task-prompt-preview">{task.prompt.slice(0, 120)}{task.prompt.length > 120 ? '…' : ''}</div>

                  {taskRuns[task.id] && (
                    <div className="task-runs">
                      <div className="task-runs-title">Recent Runs</div>
                      {taskRuns[task.id].slice(0, 5).map(run => (
                        <div key={run.run_id} className={`run-item run-${run.status}`}>
                          <span className="run-status">{run.status}</span>
                          <span className="run-time">{new Date(run.started_at).toLocaleString()}</span>
                          {run.output && (
                            <pre className="run-output">{run.output.slice(0, 300)}</pre>
                          )}
                          {run.error && (
                            <div className="run-error">{run.error}</div>
                          )}
                        </div>
                      ))}
                    </div>
                  )}
                </div>
              ))}
            </div>
          </div>
        )}

        {/* ====== MCP VIEW ====== */}
        {activeView === 'mcp' && (
          <div className="view-container">
            <div className="view-header">
              <h2>MCP Servers</h2>
              <button className="btn btn-primary" onClick={() => setShowMcpForm(true)}>
                + Add Server
              </button>
            </div>
            <p className="view-desc">
              Configure MCP servers that Claude can use as tools. These are saved and
              passed to Claude via its config. Restart Claude after adding servers.
            </p>

            {showMcpForm && (
              <div className="form-card">
                <h3>Add MCP Server</h3>
                <div className="form-grid">
                  <div className="form-field">
                    <label>Name</label>
                    <input value={mcpForm.name}
                      onChange={e => setMcpForm(p => ({ ...p, name: e.target.value }))}
                      placeholder="my-server" />
                  </div>
                  <div className="form-field">
                    <label>Type</label>
                    <select value={mcpForm.server_type}
                      onChange={e => setMcpForm(p => ({ ...p, server_type: e.target.value }))}>
                      <option value="sse">SSE (HTTP)</option>
                      <option value="stdio">stdio (command)</option>
                    </select>
                  </div>
                  {mcpForm.server_type === 'sse' && (
                    <div className="form-field form-field-full">
                      <label>URL</label>
                      <input value={mcpForm.url}
                        onChange={e => setMcpForm(p => ({ ...p, url: e.target.value }))}
                        placeholder="https://mcp.example.com/sse" />
                    </div>
                  )}
                  {mcpForm.server_type === 'stdio' && (
                    <div className="form-field form-field-full">
                      <label>Command</label>
                      <input value={mcpForm.command}
                        onChange={e => setMcpForm(p => ({ ...p, command: e.target.value }))}
                        placeholder="npx -y @my/mcp-server" />
                    </div>
                  )}
                </div>
                <div className="form-actions">
                  <button className="btn btn-primary" onClick={saveMcp}
                    disabled={!mcpForm.name}>
                    Add Server
                  </button>
                  <button className="btn btn-secondary" onClick={() => setShowMcpForm(false)}>
                    Cancel
                  </button>
                </div>
              </div>
            )}

            <div className="mcp-list">
              {mcpServers.length === 0 && (
                <div className="empty-state">No MCP servers configured.</div>
              )}
              {mcpServers.map(s => (
                <div key={s.name} className="mcp-card">
                  <div className="mcp-card-header">
                    <div>
                      <span className="mcp-name">{s.name}</span>
                      <span className="mcp-type-badge">{s.type || 'sse'}</span>
                    </div>
                    <button className="btn btn-sm btn-danger" onClick={() => removeMcp(s.name)}>
                      Remove
                    </button>
                  </div>
                  <div className="mcp-url">{s.url || s.command || ''}</div>
                </div>
              ))}
            </div>
          </div>
        )}

      </div>
    </div>
  );
};

// ---- MessageContent: render text with basic code block support ----
const MessageContent = ({ content }) => {
  if (!content) return null;

  // Split on code fences
  const parts = content.split(/(```[\s\S]*?```)/g);
  return (
    <div className="msg-text">
      {parts.map((part, i) => {
        if (part.startsWith('```')) {
          const lines = part.split('\n');
          const lang = lines[0].slice(3).trim();
          const code = lines.slice(1, -1).join('\n');
          return (
            <pre key={i} className="code-block">
              {lang && <span className="code-lang">{lang}</span>}
              <code>{code}</code>
            </pre>
          );
        }
        // Inline: render newlines as <br>
        return (
          <span key={i}>
            {part.split('\n').map((line, j) => (
              <React.Fragment key={j}>
                {line}
                {j < part.split('\n').length - 1 && <br />}
              </React.Fragment>
            ))}
          </span>
        );
      })}
    </div>
  );
};

export default App;
