// AGENTFORGE-IA — Pruebas (chat operativo por agente)
const Playground = ({ data, activeAgentId, setRoute }) => {
  const [threadId, setThreadId] = React.useState('t1');
  const [selectedAgentId, setSelectedAgentId] = React.useState(activeAgentId || '');
  const [input, setInput] = React.useState('');
  const [sending, setSending] = React.useState(false);
  const [threadMessages, setThreadMessages] = React.useState({});
  const [threadTrace, setThreadTrace] = React.useState({});
  const [threadStats, setThreadStats] = React.useState({});

  const notify = (msg) => window.afNotify && window.afNotify(msg);

  const activeAgent = React.useMemo(() => {
    const source = Array.isArray(data.agents) ? data.agents : [];
    if (!selectedAgentId) return null;
    return source.find((a) => String(a.id) === String(selectedAgentId)) || null;
  }, [data.agents, selectedAgentId]);

  const activeCat = React.useMemo(() => {
    if (!activeAgent) return null;
    return (data.categories || []).find((c) => c.id === activeAgent.cat) || null;
  }, [data.categories, activeAgent]);

  const [threads, setThreads] = React.useState([{ id: 't1', name: 'Conversación actual', when: 'ahora', snip: 'Hilo activo' }]);

  const bootMessage = React.useMemo(() => {
    if (!activeAgent) {
      return 'Selecciona un agente para iniciar la prueba. Puedes elegir uno del Marketplace o de Mis agentes.';
    }
    return `Prueba lista para ${activeAgent.name}. Escribe tu caso y pulsa Enter para ejecutar.`;
  }, [activeAgent]);

  const messages = threadMessages[threadId] || [{ id: `boot_${threadId}`, who: 'agent', kind: 'text', text: bootMessage }];
  const trace = threadTrace[threadId] || [];
  const stats = threadStats[threadId] || { runId: '-', latencyMs: 0, tokens: 0 };

  /**
   * Actualiza mensajes del hilo activo.
   * @param {Array<{id:string,who:string,kind:string,text:string}> | ((prev: Array<{id:string,who:string,kind:string,text:string}>) => Array<{id:string,who:string,kind:string,text:string}>)} updater
   * @returns {void}
   */
  const updateCurrentThreadMessages = (updater) => {
    setThreadMessages((prev) => {
      const current = prev[threadId] || [{ id: `boot_${threadId}`, who: 'agent', kind: 'text', text: bootMessage }];
      const next = typeof updater === 'function' ? updater(current) : updater;
      return { ...prev, [threadId]: next };
    });
  };

  React.useEffect(() => {
    if (!activeAgentId) return;
    setSelectedAgentId(String(activeAgentId));
  }, [activeAgentId]);

  React.useEffect(() => {
    setThreads([{ id: 't1', name: 'Conversación actual', when: 'ahora', snip: 'Hilo activo' }]);
    setThreadId('t1');
    setThreadMessages({
      t1: [{ id: crypto.randomUUID(), who: 'agent', kind: 'text', text: bootMessage }],
    });
    setThreadTrace({ t1: [] });
    setThreadStats({ t1: { runId: '-', latencyMs: 0, tokens: 0 } });
  }, [activeAgent?.id, bootMessage]);

  /**
   * Ejecuta una iteración de prueba backend del agente seleccionado.
   * @param {string} prompt
   * @returns {Promise<void>}
   */
  const runAgent = async (prompt) => {
    const cleanPrompt = String(prompt || '').trim();
    if (!cleanPrompt || sending || !activeAgent) return;

    setSending(true);
    const userMessage = { id: crypto.randomUUID(), who: 'user', kind: 'text', text: cleanPrompt };
    updateCurrentThreadMessages((prev) => [...prev, userMessage]);

    const baseMessages = messages
      .filter((m) => m && m.kind === 'text' && typeof m.text === 'string' && m.text.trim())
      .filter((m) => !String(m.text).startsWith('Prueba lista para '));

    const historyPayload = baseMessages
      .map((m) => ({
        role: m.who === 'user' ? 'user' : 'assistant',
        content: String(m.text),
      }))
      .slice(-24);

    historyPayload.push({ role: 'user', content: cleanPrompt });

    try {
      const token = sessionStorage.getItem('af_token') || '';
      if (!token) {
        throw new Error('Sesión no iniciada');
      }

      const res = await fetch('/api/v1/integrations/external-agents/test-run', {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
          Authorization: 'Bearer ' + token,
        },
        body: JSON.stringify({
          agent_id: activeAgent.id,
          agent_name: activeAgent.name,
          prompt: cleanPrompt,
          thread_id: threadId,
          history: historyPayload,
        }),
      });

      if (!res.ok) {
        let reason = `HTTP ${res.status}`;
        try {
          const payload = await res.json();
          reason = payload?.detail || reason;
        } catch (_) {
          const text = await res.text();
          if (text) reason = text;
        }
        throw new Error(reason);
      }

      const payload = await res.json();
      setThreadTrace((prev) => ({ ...prev, [threadId]: (Array.isArray(payload.trace) ? payload.trace : []) }));
      const latencyMs = Number(payload.latency_ms || 0);
      const tokensUsed = Number(payload.tokens || 0);
      setThreadStats((prev) => ({
        ...prev,
        [threadId]: {
          runId: payload.run_id || '-',
          latencyMs,
          tokens: tokensUsed,
        },
      }));

      updateCurrentThreadMessages((prev) => [
        ...prev,
        {
          id: crypto.randomUUID(),
          who: 'agent',
          kind: 'text',
          text: String(payload.assistant_message || 'Sin respuesta del agente.'),
        },
      ]);

      // Log run fire-and-forget
      fetch('/api/v1/runs/log', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json', Authorization: 'Bearer ' + token },
        body: JSON.stringify({
          agent_name: activeAgent.name,
          status: 'ok',
          trigger_type: 'playground',
          duration_ms: latencyMs || null,
          tokens_used: tokensUsed,
          cost_eur: parseFloat((tokensUsed * 0.000003).toFixed(4)),
        }),
      }).catch(() => {});
    } catch (err) {
      const msg = err instanceof Error ? err.message : 'Error desconocido';
      updateCurrentThreadMessages((prev) => [
        ...prev,
        {
          id: crypto.randomUUID(),
          who: 'agent',
          kind: 'text',
          text: `Error ejecutando la prueba del agente: ${msg}`,
        },
      ]);

      // Log failed run fire-and-forget
      fetch('/api/v1/runs/log', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json', Authorization: 'Bearer ' + (sessionStorage.getItem('af_token') || '') },
        body: JSON.stringify({
          agent_name: activeAgent?.name || 'Desconocido',
          status: 'error',
          trigger_type: 'playground',
          error_message: msg.slice(0, 500),
        }),
      }).catch(() => {});

      notify('Error en prueba del agente');
    } finally {
      setSending(false);
    }
  };

  /**
   * Maneja el envío por teclado desde el textarea.
   * @param {React.KeyboardEvent<HTMLTextAreaElement>} e
   */
  const onInputKeyDown = (e) => {
    if (e.key === 'Enter' && !e.shiftKey) {
      e.preventDefault();
      const payload = input.trim();
      if (!payload) return;
      setInput('');
      runAgent(payload);
    }
  };

  /**
   * Crea un nuevo hilo de conversación.
   * @returns {void}
   */
  const createThread = () => {
    const next = `t${Date.now()}`;
    setThreads((prev) => [
      { id: next, name: `Conversación ${prev.length + 1}`, when: 'ahora', snip: 'Nuevo hilo' },
      ...prev,
    ]);
    setThreadId(next);
    setThreadMessages((prev) => ({
      ...prev,
      [next]: [
        {
          id: crypto.randomUUID(),
          who: 'agent',
          kind: 'text',
          text: `Nuevo hilo creado para ${activeAgent?.name || 'el agente seleccionado'}.`,
        },
      ],
    }));
    setThreadTrace((prev) => ({ ...prev, [next]: [] }));
    setThreadStats((prev) => ({ ...prev, [next]: { runId: '-', latencyMs: 0, tokens: 0 } }));
  };

  /**
   * Copia la traza actual al portapapeles.
   * @returns {Promise<void>}
   */
  const copyTrace = async () => {
    const payload = {
      runId: stats.runId,
      latencyMs: stats.latencyMs,
      tokens: stats.tokens,
      trace,
    };
    try {
      await navigator.clipboard.writeText(JSON.stringify(payload, null, 2));
      notify('Traza copiada');
    } catch (_) {
      notify('No se pudo copiar la traza');
    }
  };

  return (
    <div className="pg">
      <div className="pg-list">
        <div className="pg-list-head">
          <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
            <span style={{ fontSize: 13, fontWeight: 600 }}>Conversaciones</span>
            <button className="btn btn-ghost btn-icon btn-sm" onClick={createThread}>
              <Icon name="plus" size={13} />
            </button>
          </div>
        </div>
        {threads.map((t) => (
          <div key={t.id} className={'pg-thread' + (threadId === t.id ? ' active' : '')} onClick={() => setThreadId(t.id)}>
            <div className="t-head"><b>{t.name}</b><time>{t.when}</time></div>
            <div className="t-snip">{t.snip}</div>
          </div>
        ))}
      </div>

      <div className="pg-main">
        <div className="page-head" style={{ position: 'static' }}>
          <div className="agent-icon" style={{ width: 28, height: 28, color: '#60a5fa', background: '#60a5fa1a', borderColor: '#60a5fa33' }}><Icon name="headset" size={14} /></div>
          <div>
            <div style={{ fontWeight: 600, fontSize: 14 }}>{activeAgent?.name || 'Agente'} <span className="status-dot live" style={{ marginLeft: 6 }} /></div>
            <div className="mono" style={{ fontSize: 11, color: 'var(--ink-3)' }}>{activeCat?.name || 'general'} · pruebas operativas</div>
          </div>
          <select
            className="input"
            value={selectedAgentId}
            onChange={(e) => setSelectedAgentId(e.target.value)}
            style={{ minWidth: 260, maxWidth: 360 }}
          >
            <option value="">Seleccionar agente…</option>
            <optgroup label="Mis agentes">
              {(Array.isArray(data.agents) ? data.agents : [])
                .filter((a) => !!a && !!a._custom)
                .map((a) => (
                  <option key={`custom_${a.id}`} value={String(a.id)}>{a.name}</option>
                ))}
            </optgroup>
            <optgroup label="Marketplace">
              {(Array.isArray(data.agents) ? data.agents : [])
                .filter((a) => !!a && !a._custom)
                .map((a) => (
                  <option key={`market_${a.id}`} value={String(a.id)}>{a.name}</option>
                ))}
            </optgroup>
          </select>
          <div className="actions">
            <button className="btn btn-ghost btn-sm" onClick={copyTrace}><Icon name="copy" size={12} /> Copiar traza</button>
            <button className="btn btn-sm" onClick={() => setRoute && setRoute('marketplace')}><Icon name="x" size={12} /> Cerrar prueba</button>
          </div>
        </div>

        <div className="pg-stream">
          {messages.map((m) => {
            if (m.who === 'user') return <div key={m.id} className="msg msg-user">{m.text}</div>;
            return (
              <div key={m.id} className="msg msg-agent">
                <div className="av"><Icon name="sparkles" size={14} /></div>
                <div className="body">
                  <p style={{ whiteSpace: 'pre-wrap' }}>{m.text}</p>
                </div>
              </div>
            );
          })}
          {sending && (
            <div className="msg msg-agent">
              <div className="av"><Icon name="sparkles" size={14} /></div>
              <div className="body"><p className="muted"><span className="thinking"><span /><span /><span /></span> &nbsp;Procesando caso…</p></div>
            </div>
          )}
        </div>

        <div className="pg-input">
          <div className="pg-input-box">
            <textarea
              placeholder="Escribe el caso y pulsa Enter para enviar (Shift+Enter para salto de línea)."
              value={input}
              onChange={(e) => setInput(e.target.value)}
              onKeyDown={onInputKeyDown}
              disabled={!activeAgent}
            />
            <div className="pg-input-actions">
              <button className="btn btn-ghost btn-sm" onClick={() => notify('Adjuntar disponible en siguiente iteración')}><Icon name="upload" size={12} /> Adjuntar</button>
              <span className="spacer" />
              <span className="mono" style={{ fontSize: 10.5, color: 'var(--ink-4)' }}>Pulsa Enter para enviar · Shift+Enter nueva línea</span>
            </div>
          </div>
        </div>
      </div>

      <div className="pg-side">
        <div className="pg-side-head">
          <div style={{ fontWeight: 600, fontSize: 13.5 }}>Traza de ejecución</div>
          <div className="mono" style={{ fontSize: 10.5, color: 'var(--ink-3)', marginTop: 2 }}>{stats.runId} · {stats.latencyMs} ms · {stats.tokens} tokens</div>
        </div>

        <div className="pg-side-section">
          <h5>Pasos</h5>
          {trace.length === 0 && <div className="mono" style={{ color: 'var(--ink-4)', fontSize: 11 }}>Aún no hay ejecuciones.</div>}
          {trace.map((s, i) => (
            <div key={i} className="trace-step">
              <span className="ts-time">{s.time}</span>
              <span style={{ color: 'var(--ink)' }}>{s.step}</span>
              <span className="ts-tok">{s.ms} ms · {s.tokens} tok</span>
            </div>
          ))}
        </div>

        <div className="pg-side-section" style={{ borderBottom: 0 }}>
          <h5>Estado</h5>
          <div style={{ display: 'flex', justifyContent: 'space-between', padding: '4px 0', fontSize: 12 }}><span style={{ color: 'var(--ink-3)' }}>Agente activo</span><span className="mono">{activeAgent?.name || '-'}</span></div>
          <div style={{ display: 'flex', justifyContent: 'space-between', padding: '4px 0', fontSize: 12 }}><span style={{ color: 'var(--ink-3)' }}>Categoría</span><span className="mono">{activeCat?.name || '-'}</span></div>
          <div style={{ display: 'flex', justifyContent: 'space-between', padding: '4px 0', fontSize: 12 }}><span style={{ color: 'var(--ink-3)' }}>Hilo</span><span className="mono">{threadId}</span></div>
        </div>
      </div>
    </div>
  );
};

window.Playground = Playground;
