﻿/* global React, Icon, API */

const AGENT_PROFILE_DIRTY_FIELDS = new Set();
let AGENT_PROFILE_SYNCING = false;

function registerAgentProfileDirtyTracking() {
  AGENT_PROFILE_DIRTY_FIELDS.clear();
}

function setAgentProfileControlValue(id, value, prop = 'value') {
  const el = document.getElementById(id);
  if (!el || AGENT_PROFILE_DIRTY_FIELDS.has(id)) return;
  if (prop === 'checked') el.checked = !!value;
  else el.value = value == null ? '' : value;
}

window.AGENT_PROFILE_DIRTY_FIELDS = AGENT_PROFILE_DIRTY_FIELDS;
window.registerAgentProfileDirtyTracking = registerAgentProfileDirtyTracking;
window.setAgentProfileControlValue = setAgentProfileControlValue;

const studioToast = window.studioToast || function(m, t) { if (window.STUDIO?.toast) window.STUDIO.toast(m, t); };
const studioForm = window.studioForm || function(c) { return window.STUDIO?.form ? window.STUDIO.form(c) : Promise.resolve(null); };
const studioConfirm = window.studioConfirm || function(c) { return window.STUDIO?.confirm ? window.STUDIO.confirm(c) : Promise.resolve(false); };

async function copyToClipboard(text) {
  if (navigator.clipboard?.writeText) {
    try {
      await navigator.clipboard.writeText(text);
      return true;
    } catch (err) {}
  }
  const ta = document.createElement('textarea');
  ta.value = text;
  ta.setAttribute('readonly', '');
  ta.style.position = 'fixed';
  ta.style.left = '-9999px';
  document.body.appendChild(ta);
  ta.select();
  const ok = document.execCommand('copy');
  document.body.removeChild(ta);
  return ok;
}

function setupBadgeClass(status) {
  if (status === 'production') return 'ok';
  if (status === 'paused') return 'warn';
  if (status === 'ready') return 'accent';
  return 'warn';
}

const SETUP_STAGE_META = {
  created: { tab: 'instructions', title: 'Bot criado', body: 'Nome e estrutura inicial existem. Você pode ajustar depois.' },
  personality: { tab: 'instructions', title: 'Personalidade', body: 'Defina como o bot fala, quais limites segue e qual IA usa.' },
  goals: { tab: 'instructions', title: 'Objetivos', body: 'Liste o que o bot precisa conseguir durante a conversa.' },
  kb: { tab: 'knowledge', title: 'Conhecimento', body: 'Adicione documentos, URLs ou textos que o bot deve consultar.' },
  channels: { tab: 'connections', title: 'WhatsApp ou API', body: 'Receba mensagens reais por WhatsApp, API ou site. Conecte WhatsApp quando quiser repassar informacoes para alvos selecionados.' },
  tested: { tab: 'test', title: 'Teste', body: 'Teste antes de publicar. Use o sandbox para validar tom e respostas.' },
  review: { tab: 'setup', title: 'Pendências', body: 'Revise bloqueios obrigatórios e recomendações antes de publicar.' },
  publish: { tab: 'setup', title: 'Publicar', body: 'Libera o bot para responder mensagens reais. Pode pausar depois.' },
};

function parseKbSources(text) {
  return String(text || '').split(/\n+/).map(line => line.trim()).filter(Boolean).map(line => {
    if (/^https?:\/\//i.test(line)) return { source_type: 'url', uri: line };
    return { source_type: 'text', content: line };
  });
}

function readKbFiles(files) {
  const list = Array.from(files || []);
  return Promise.all(list.map(file => new Promise(resolve => {
    const reader = new FileReader();
    reader.onload = () => resolve({ source_type: 'file', uri: file.name, mime_type: file.type || 'application/octet-stream', content: reader.result });
    reader.onerror = () => resolve(null);
    reader.readAsDataURL(file);
  }))).then(items => items.filter(Boolean));
}

function normalizePublicSlugInput(value) {
  return String(value || '')
    .normalize('NFD')
    .replace(/[\u0300-\u036f]/g, '')
    .toLowerCase()
    .replace(/[^a-z0-9]+/g, '-')
    .replace(/^-+|-+$/g, '')
    .replace(/-{2,}/g, '-')
    .slice(0, 80);
}

window.AgentProfilePage = function AgentProfilePage({ agentId, onBack, initialTab, onTabChange }) {
  const agent = (window.MOCK.agents || []).find(a => String(a.id) === String(agentId)) || (window.MOCK.agents || [])[0];
  const [tab, setTab] = React.useState(initialTab || 'setup');
  const [publicLinkInfo, setPublicLinkInfo] = React.useState(null);
  const [publicLinkBusy, setPublicLinkBusy] = React.useState('');

  React.useEffect(() => {
    if (!agent) return;
    setTab(initialTab || (agent.isPublished ? 'instructions' : 'setup'));
  }, [agent?.id, initialTab]);

  if (!agent) {
    return (
      <>
        <div className="page-head">
          <div><div className="page-eyebrow">Inteligência</div><h1 className="page-title">Agente</h1><p className="page-sub">Nenhum agente criado ainda.</p></div>
          <div className="page-meta"><button onClick={onBack} className="tb-btn ghost">Voltar</button></div>
        </div>
        <div className="page"><div className="panel empty">Crie um agente para abrir o perfil.</div></div>
      </>
    );
  }

  const tabs = [
    { id: 'setup', label: 'Setup' },
    { id: 'instructions', label: 'Instruções' },
    { id: 'test', label: 'Teste' },
    { id: 'knowledge', label: 'Conhecimento' },
    { id: 'tools', label: 'Ferramentas' },
    { id: 'conditionals', label: 'Condicionais' },
    { id: 'conversations', label: 'Conversas' },
    { id: 'logs', label: 'Logs' },
    { id: 'connections', label: 'Conexões' },
  ];
  const status = agent.statusTag || (agent.status === 'online' ? 'ok' : ['connecting', 'not_found'].includes(agent.status) ? 'warn' : agent.status === 'offline' ? 'bad' : '');

  function selectTab(nextTab) {
    setTab(nextTab);
    if (onTabChange) onTabChange(nextTab);
  }

  async function resolvePublicTestLink(action) {
    if (publicLinkBusy) return;
    let publicTestWindow = null;
    if (action === 'open') {
      publicTestWindow = window.open(`/chat/${agent.raw?.public_slug || agent.id}`, '_blank');
      if (publicTestWindow) publicTestWindow.opener = null;
    }
    setPublicLinkBusy(action);
    try {
      const info = await API.getAgentPublicTestLink(agent.id);
      setPublicLinkInfo(info);
      if (action === 'copy') {
        if (!info.can_share) {
          studioToast(info.message || 'Configure um tunnel antes de compartilhar este link.', 'bad');
          return;
        }
        const copied = await copyToClipboard(info.url);
        studioToast(copied ? 'Link copiado.' : 'Não foi possível copiar.', copied ? '' : 'bad');
      } else {
        if (publicTestWindow) publicTestWindow.location.href = info.url;
        else window.open(info.url, '_blank', 'noopener');
        if (!info.can_share) studioToast('Teste aberto localmente. Para compartilhar, configure um tunnel público.', 'bad');
      }
    } catch (err) {
      if (publicTestWindow) publicTestWindow.close();
      studioToast(err.message || String(err), 'bad');
    } finally {
      setPublicLinkBusy('');
    }
  }

  return (
    <>
      <div className="page-head">
        <div>
          <div className="page-eyebrow">
            <button onClick={onBack} className="tb-btn ghost" style={{padding:'2px 6px', fontSize:12, marginRight:6}}>Voltar</button>
            Inteligência - {agent.role}
          </div>
          <h1 className="page-title">{agent.name}</h1>
          <p className="page-sub">
            Modelo <code style={{fontFamily:'var(--mono)', fontSize:12.5}}>{agent.model}</code>
            {' - '}canal {agent.channel}{' - '}{agent.kbSources} fontes{' - '}{agent.tools} ferramentas
          </p>
        </div>
        <div className="page-meta">
          <span className={`badge ${status}`} title="Status da conexão WhatsApp"><span className={`sw ${status}`}/> {agent.statusLabel || agent.status}</span>
          <div className="meta-row">{agent.conversations.toLocaleString('pt-BR')} conversas - {agent.tickets} tickets</div>
          <div className="public-test-actions">
            <button className="tb-btn ghost" title="Copiar link público de teste" onClick={() => resolvePublicTestLink('copy')} disabled={!!publicLinkBusy}><Icon name="share" size={13}/> Copiar link</button>
            <button className="tb-btn ghost" title="Abrir página pública de teste" onClick={() => resolvePublicTestLink('open')} disabled={!!publicLinkBusy}>Abrir teste</button>
          </div>
          {publicLinkInfo?.requires_tunnel && !publicLinkInfo?.can_share && (
            <div className="public-link-hint">Localhost detectado. Configure <code>PUBLIC_CHAT_BASE_URL</code> ou <code>PUBLIC_TEST_BASE_URL</code> para compartilhar com domínio próprio.</div>
          )}
        </div>
      </div>

      <div className="page">
        <div className="filter-row" style={{ borderBottom: '1px solid var(--rule)', paddingBottom: 0, gap: 0, marginBottom: 4 }}>
          {tabs.map(t => (
            <button key={t.id} onClick={() => selectTab(t.id)} className={`profile-tab ${tab === t.id ? 'active' : ''}`}>{t.label}</button>
          ))}
        </div>

        {tab === 'setup' && <SetupTab agent={agent} setTab={selectTab}/>}
        {tab === 'instructions' && <InstructionsTab agent={agent}/>}
        {tab === 'test' && <AgentTestTab agent={agent}/>}
        {tab === 'connections' && <ConnectionsTab agent={agent}/>}
        {tab === 'knowledge' && <KnowledgeTab agent={agent}/>}
        {tab === 'tools' && <ToolsTab agent={agent}/>}
        {tab === 'conditionals' && <ConditionalsTab agent={agent}/>}
        {tab === 'conversations' && <AgentConversationsTab agent={agent}/>}
        {tab === 'logs' && <AgentLogsTab agent={agent}/>}
      </div>
    </>
  );
};

function SetupTab({ agent, setTab }) {
  const [readiness, setReadiness] = React.useState(null);
  const [loading, setLoading] = React.useState(true);
  const [busy, setBusy] = React.useState('');
  const statusLabel = readiness ? window.setupStatusLabel(readiness.stage) : agent.setupLabel;
  const statusClass = setupBadgeClass(readiness?.stage || agent.setupStatus);
  const steps = readiness?.steps || [];
  const activeStage = (steps.find(step => !step.done) || steps[steps.length - 1] || {}).id;
  const blockers = readiness?.blockers || [];
  const required = blockers.filter(item => item.severity === 'required');
  const recommended = blockers.filter(item => item.severity !== 'required');
  const percent = readiness?.percent ?? Math.round(((agent.setupProgress?.completed_count || 0) / Math.max(agent.setupProgress?.total_count || 1, 1)) * 100);

  async function load() {
    setLoading(true);
    try {
      setReadiness(await API.getAgentReadiness(agent.id));
    } catch (err) {
      studioToast(err.message || String(err), 'bad');
    } finally {
      setLoading(false);
    }
  }

  React.useEffect(() => { load(); }, [agent.id]);

  function goStage(stage) {
    setTab(SETUP_STAGE_META[stage]?.tab || 'instructions');
  }

  async function publish() {
    if (busy) return;
    setBusy('publish');
    try {
      await API.publishAgent(agent.id);
      await window.STUDIO.refresh();
      await load();
      studioToast('Bot publicado. Ele já pode responder mensagens reais.');
    } catch (err) {
      studioToast(err.message || String(err), 'bad');
      await load();
    } finally {
      setBusy('');
    }
  }

  async function pause() {
    if (busy) return;
    setBusy('pause');
    try {
      await API.unpublishAgent(agent.id);
      await window.STUDIO.refresh();
      await load();
      studioToast('Bot pausado. Mensagens reais não seráo respondidas pela IA.');
    } catch (err) {
      studioToast(err.message || String(err), 'bad');
    } finally {
      setBusy('');
    }
  }

  const doneCount = steps.filter(s => s.done).length;

  return (
    <div className="setup-page">

      {/* Hero status strip */}
      <div className={`setup-hero ${statusClass}`}>
        <div className="setup-hero-left">
          <div className="setup-hero-pct">{loading ? '…' : `${percent}%`}</div>
          <div>
            <div className="setup-hero-title">{statusLabel}</div>
            <div className="setup-hero-sub">{doneCount} de {steps.length} etapas concluídas</div>
          </div>
        </div>
        <div className="setup-hero-bar"><span style={{width:`${percent}%`}}/></div>
        <div className="setup-hero-actions">
          {readiness?.is_published
            ? <button className="tb-btn" onClick={pause} disabled={!!busy}>{busy === 'pause' ? 'Pausando…' : 'Pausar bot'}</button>
            : <button className={`tb-btn primary ${!readiness?.can_publish ? 'disabled' : ''}`} onClick={publish} disabled={!!busy || !readiness?.can_publish}>{busy === 'publish' ? 'Publicando…' : 'Publicar bot'}</button>}
        </div>
      </div>

      {blockers.length > 0 && (
        <div className="setup-blockers-banner">
          {required.length > 0 && <span className="pill pill-bad">{required.length} obrigatória{required.length > 1 ? 's' : ''}</span>}
          {required.map((item, idx) => (
            <button key={`r-${idx}`} className="blocker required" onClick={() => goStage(item.stage)}>
              <span className="blocker-icon">!</span>{item.message}
            </button>
          ))}
          {recommended.map((item, idx) => (
            <button key={`w-${idx}`} className="blocker" onClick={() => goStage(item.stage)}>
              <span className="blocker-icon">·</span>{item.message}
            </button>
          ))}
        </div>
      )}

      <div className="setup-workbench setup-workbench-single">
        <div className="setup-steps-rail stagger-children">
          {steps.map((step, idx) => {
            const meta = SETUP_STAGE_META[step.id] || {};
            const isCurrent = step.id === activeStage;
            const stepBlockers = blockers.filter(b => b.stage === step.id);
            return (
              <button key={step.id} className={`setup-step-row ${step.done ? 'done' : ''} ${isCurrent ? 'current' : ''}`} onClick={() => goStage(step.id)}>
                <div className="setup-step-num">{step.done ? <Icon name="check" size={12}/> : String(idx+1).padStart(2,'0')}</div>
                <div className="setup-step-body">
                  <div className="setup-step-title">{meta.title || step.label}</div>
                  <div className="setup-step-desc">{meta.body || ''}</div>
                  {stepBlockers.length > 0 && <div className="setup-step-blockers">{stepBlockers.map((b,i) => <span key={i} className={`pill pill-sm ${b.severity === 'required' ? 'pill-bad' : 'pill-warn'}`}>{b.message}</span>)}</div>}
                </div>
                <span className={`pill ${step.done ? 'pill-ok' : isCurrent ? 'pill-accent' : 'pill-muted'}`}>{step.done ? 'Pronto' : isCurrent ? 'Agora' : 'Pendente'}</span>
                <Icon name="arrow" size={13}/>
              </button>
            );
          })}
        </div>
        {!readiness?.can_publish && <div className="field-hint" style={{textAlign:'center',marginTop:8}}>Resolva pendências obrigatórias para publicar.</div>}
      </div>
    </div>
  );
}

function InstructionsTab({ agent }) {
  const raw = agent.raw || {};
  const [form, setForm] = React.useState(() => formFromAgent(agent));
  const [saving, setSaving] = React.useState(false);

  React.useEffect(() => {
    AGENT_PROFILE_SYNCING = true;
    registerAgentProfileDirtyTracking();
    setForm(formFromAgent(agent));
    AGENT_PROFILE_SYNCING = false;
  }, [agent.id]);

  function set(name, value, id) {
    if (!AGENT_PROFILE_SYNCING && id) AGENT_PROFILE_DIRTY_FIELDS.add(id);
    setForm(prev => ({ ...prev, [name]: value }));
  }

  function setModelPreset(presetId) {
    const preset = window.WA.modelPresetById(presetId);
    setForm(prev => ({ ...prev, model_preset: preset.id, ai_model: preset.model, temperature: preset.temperature }));
  }

  async function save() {
    if (!form.instance_name.trim()) {
      studioToast('Informe o nome interno do agente.', 'bad');
      return;
    }
    if (!/^(?=.*[a-z])[a-z0-9]+(?:-[a-z0-9]+)*$/.test(form.public_slug || '')) {
      studioToast('Use um slug público com letras minúsculas, números e hífens.', 'bad');
      return;
    }
    setSaving(true);
    try {
      const payload = {
        name: form.name,
        public_slug: form.public_slug,
        instance_name: form.instance_name,
        description: form.description,
        ai_model: form.ai_model,
        temperature: Number(form.temperature || 0.7),
        system_prompt: form.system_prompt,
        negative_rules: lines(form.negative_rules),
        conversation_goals: lines(form.conversation_goals),
        final_goal: form.final_goal,
        handoff_config: { enabled: form.handoff_enabled },
      };
      const apiKey = String(form.ai_api_key || '').trim();
      if (apiKey) payload.ai_api_key = apiKey;
      await API.updateAgent(agent.id, payload);
      if (apiKey) setForm(prev => ({ ...prev, ai_api_key: '' }));
      await window.STUDIO.refresh();
      studioToast('Agente salvo.');
    } catch (err) {
      studioToast(err.message || String(err), 'bad');
    } finally {
      setSaving(false);
    }
  }

  return (
    <>
      <div className="grid-2">
        <div className="panel">
          <div className="panel-head"><div className="panel-title">Identidade</div><span className="muted" style={{fontSize:11}}>configuração</span></div>
          <div className="form-grid">
            <Field label="Nome do bot de IA" value={form.name} onChange={v => set('name', v)} helper="Nome visivel no painel. Pode mudar depois." required/>
            <Field label="Slug público" value={form.public_slug} onChange={v => set('public_slug', normalizePublicSlugInput(v))} helper="Usado no link público. Ex: sm-lead-assistant." required/>
            <Field id="ap-instance" label="Nome interno" value={form.instance_name} onChange={v => set('instance_name', v, 'ap-instance')} helper="Apelido usado para vincular WhatsApp. Use letras, números e hífen."/>
            <Field label="Descrição curta" value={form.description} onChange={v => set('description', v)} multiline helper="Resumo para a equipe entender o papel deste bot."/>
          </div>
        </div>

        <div className="panel">
          <div className="panel-head"><div className="panel-title">Modelo & parametros</div></div>
          <div className="form-grid">
            <ModelPresetField value={form.model_preset} model={form.ai_model} onChange={setModelPreset}/>
            <Field
              id="ap-key"
              label="Chave de API do agente"
              type="password"
              value={form.ai_api_key}
              onChange={v => set('ai_api_key', v, 'ap-key')}
              placeholder={raw.has_api_key ? 'Manter atual se vazio' : 'Cole a chave do provedor'}
              helper={raw.has_api_key ? 'Chave atual configurada. Preencha apenas para substituir.' : 'Use a chave do provedor escolhido ou configure a chave global no .env.'}
              autoComplete="new-password"
            />
            <Field label="Criatividade" value={String(form.temperature)} onChange={v => set('temperature', v)} helper="Baixa = mais consistente. Alta = mais livre."/>
            <label className="soft-row">
              <span>Repasse humano</span>
              <input type="checkbox" checked={form.handoff_enabled} onChange={e => set('handoff_enabled', e.target.checked)}/>
            </label>
          </div>
        </div>
      </div>

      <div className="panel">
        <div className="panel-head">
          <div className="panel-title">Prompt principal</div>
          <button className="tb-btn primary" onClick={save} disabled={saving}>{saving ? 'Salvando...' : 'Salvar agente'}</button>
        </div>
        <div style={{ padding: 14 }}>
          <div className="help-card inline-help"><div className="help-card-title">Como escrever</div><div className="help-card-body">Diga quem o bot representa, como deve falar, o que deve fazer e quando deve chamar humano.</div></div>
          <textarea className="input prose-input" style={{ height: 220 }} value={form.system_prompt} onChange={e => set('system_prompt', e.target.value)}/>
        </div>
      </div>

      <div className="grid-2">
        <div className="panel">
          <div className="panel-head"><div className="panel-title">Regras (não-fazer)</div></div>
          <div style={{ padding: 14 }}>
            <textarea className="input prose-input" style={{minHeight:130}} value={form.negative_rules} onChange={e => set('negative_rules', e.target.value)}/>
          </div>
        </div>
        <div className="panel">
          <div className="panel-head"><div className="panel-title">Objetivos</div></div>
          <div style={{ padding: 14, display:'grid', gap: 12 }}>
            <Field label="Objetivos por linha" value={form.conversation_goals} onChange={v => set('conversation_goals', v)} multiline/>
            <Field label="Objetivo final" value={form.final_goal} onChange={v => set('final_goal', v)} multiline/>
          </div>
        </div>
      </div>
    </>
  );
}

function newAgentTestSessionId(agentId) {
  const suffix = window.crypto?.randomUUID ? window.crypto.randomUUID() : `${Date.now()}-${Math.random().toString(16).slice(2)}`;
  return `agent-${agentId}-${suffix}`;
}

function testMessageFromApi(message) {
  const role = message.role || 'system';
  return {
    id: message.id || `${role}-${message.created_at || Date.now()}`,
    role,
    dir: role === 'assistant' ? 'out' : role === 'user' ? 'in' : 'system',
    text: message.content || '',
    time: window.fmtTime ? window.fmtTime(message.created_at) : '--:--',
  };
}

function agentTestFriendlyError(err) {
  const raw = String(err?.message || err || '');
  if (/internal server error/i.test(raw)) return 'O Testador encontrou uma falha interna. Atualize o agente e tente novamente.';
  if (/timeout|timed out/i.test(raw)) return 'O modelo demorou para responder. Tente novamente em alguns instantes.';
  return raw || 'Não foi possível concluir o teste agora.';
}

function AgentTestTab({ agent }) {
  const storageKey = `sm_agent_test_session_${agent.id}`;
  const initialSession = () => {
    const stored = window.localStorage?.getItem(storageKey);
    if (stored) return stored;
    const fresh = newAgentTestSessionId(agent.id);
    window.localStorage?.setItem(storageKey, fresh);
    return fresh;
  };
  const [sessionId, setSessionId] = React.useState(initialSession);
  const [messages, setMessages] = React.useState([]);
  const [draft, setDraft] = React.useState('');
  const [sending, setSending] = React.useState(false);
  const [pendingMessage, setPendingMessage] = React.useState('');
  const [sessions, setSessions] = React.useState([]);
  const [sessionsLoading, setSessionsLoading] = React.useState(false);
  const [sessionBusy, setSessionBusy] = React.useState(false);
  const [runtime, setRuntime] = React.useState(null);
  const [error, setError] = React.useState('');
  const endRef = React.useRef(null);
  const sourcesCount = runtime?.sources?.length || 0;
  const toolsCount = runtime?.tool_decisions?.length || 0;
  const conditionalCount = runtime?.conditional_prompts?.matched?.length || 0;
  const handoff = runtime?.human_handoff || {};
  const handoffTicket = runtime?.handoff_ticket || {};
  const whatsappNotify = handoffTicket?.whatsapp_notify || {};
  const lastWhatsappNotification = runtime?.last_whatsapp_notification || null;
  const lastWhatsappError = runtime?.last_whatsapp_notification_error || null;
  const whatsappTargets = whatsappNotify.targets || lastWhatsappNotification?.targets || [];
  const whatsappNotifySent = Boolean(whatsappNotify.sent || lastWhatsappNotification);
  const whatsappNotifyError = whatsappNotify.error || lastWhatsappError?.reason || '';
  const whatsappNotifySkipped = whatsappNotify.skipped || '';
  const showHandoffDelivery = Boolean(handoff.requested || handoffTicket.ticket || whatsappNotifySent || whatsappNotifyError || whatsappNotifySkipped);

  React.useEffect(() => {
    const stored = window.localStorage?.getItem(storageKey);
    const fresh = stored || newAgentTestSessionId(agent.id);
    window.localStorage?.setItem(storageKey, fresh);
    setSessionId(fresh);
    setMessages([]);
    setRuntime(null);
    setError('');
    setDraft('');
    setPendingMessage('');
  }, [agent.id]);

  React.useEffect(() => {
    let alive = true;
    setSessionsLoading(true);
    API.getAgentTestSessions(agent.id)
      .then(rows => {
        if (!alive) return;
        setSessions(rows || []);
        const stored = window.localStorage?.getItem(storageKey);
        const exists = (rows || []).some(item => item.session_id === stored);
        if (!stored || (!exists && (rows || []).length)) {
          const next = rows[0].session_id;
          window.localStorage?.setItem(storageKey, next);
          setSessionId(next);
        }
      })
      .catch(err => setError(err.message || String(err)))
      .finally(() => { if (alive) setSessionsLoading(false); });
    return () => { alive = false; };
  }, [agent.id]);

  React.useEffect(() => {
    if (!sessionId) return undefined;
    let alive = true;
    API.getAgentTestSession(agent.id, sessionId)
      .then(item => {
        if (!alive) return;
        setMessages((item.messages || []).map(testMessageFromApi));
        setRuntime(prev => ({
          ...(prev || {}),
          status: item.last_status || prev?.status,
          latency_ms: item.latency_ms ?? prev?.latency_ms,
          run_id: item.last_run_id || prev?.run_id,
          conversation_id: item.conversation_id,
        }));
      })
      .catch(() => {
        if (alive) setMessages([]);
      });
    return () => { alive = false; };
  }, [agent.id, sessionId]);

  React.useEffect(() => {
    endRef.current?.scrollIntoView({ block: 'end' });
  }, [messages.length, sending]);

  async function refreshSessions() {
    const rows = await API.getAgentTestSessions(agent.id);
    setSessions(rows || []);
    return rows || [];
  }

  function openAssistantTester() {
    window.localStorage?.setItem('sm_assistant_focus_agent_id', String(agent.id));
    window.location.hash = 'assistants';
  }

  async function selectSession(item) {
    window.localStorage?.setItem(storageKey, item.session_id);
    setSessionId(item.session_id);
    setMessages([]);
    setRuntime(null);
    setError('');
    setDraft('');
    setPendingMessage('');
  }

  async function startNewSession() {
    if (sessionBusy) return;
    setSessionBusy(true);
    try {
      const created = await API.createAgentTestSession(agent.id, { name: `Teste ${new Date().toLocaleString('pt-BR')}` });
      await refreshSessions();
      await selectSession(created);
      studioToast('Nova sessão de teste iniciada.');
    } catch (err) {
      studioToast(err.message || String(err), 'bad');
    } finally {
      setSessionBusy(false);
    }
  }

  async function deleteSession(item) {
    if (sessionBusy) return;
    if (!(await studioConfirm({ title: 'Excluir sessão de teste', message: `Excluir "${item.name || item.session_id}"?`, confirmLabel: 'Excluir', danger: true }))) return;
    setSessionBusy(true);
    try {
      await API.deleteAgentTestSession(agent.id, item.session_id);
      const rows = await refreshSessions();
      const next = rows[0];
      if (next) await selectSession(next);
      else {
        const fresh = newAgentTestSessionId(agent.id);
        window.localStorage?.setItem(storageKey, fresh);
        setSessionId(fresh);
        setMessages([]);
        setRuntime(null);
      }
      studioToast('Sessão de teste removida.');
    } catch (err) {
      studioToast(err.message || String(err), 'bad');
    } finally {
      setSessionBusy(false);
    }
  }

  async function deleteAllSessions() {
    if (sessionBusy || !sessions.length) return;
    if (!(await studioConfirm({
      title: 'Excluir conversas de teste',
      message: `Excluir todas as conversas de teste de "${agent.name}"?`,
      confirmLabel: 'Excluir testes',
      danger: true,
    }))) return;
    setSessionBusy(true);
    try {
      const res = await API.deleteAgentTestSessions(agent.id);
      await refreshSessions();
      const fresh = newAgentTestSessionId(agent.id);
      window.localStorage?.setItem(storageKey, fresh);
      setSessionId(fresh);
      setMessages([]);
      setRuntime(null);
      setPendingMessage('');
      setError('');
      setDraft('');
      setPendingMessage('');
      studioToast(`${res.deleted_count || 0} conversa(s) de teste removida(s).`);
    } catch (err) {
      studioToast(err.message || String(err), 'bad');
    } finally {
      setSessionBusy(false);
    }
  }

  async function send() {
    const text = draft.trim();
    if (!text || sending) return;
    const now = new Date().toLocaleTimeString('pt-BR', { hour: '2-digit', minute: '2-digit' });
    setMessages(prev => [...prev, { id: `u-${Date.now()}`, role: 'user', dir: 'in', text, time: now }]);
    setDraft('');
    setPendingMessage(text);
    setSending(true);
    setError('');
    try {
      const data = await API.testAgentChat(agent.id, { message: text, session_id: sessionId, customer_name: 'Teste interno' });
      setRuntime({ ...(data.runtime || {}), status: data.status, latency_ms: data.latency_ms, run_id: data.run_id, conversation_id: data.conversation_id });
      setMessages(prev => [...prev, {
        id: `a-${data.run_id || Date.now()}`,
        role: 'assistant',
        dir: 'out',
        text: data.reply || data.message || '',
        time: new Date().toLocaleTimeString('pt-BR', { hour: '2-digit', minute: '2-digit' }),
      }]);
      refreshSessions().catch(() => {});
    } catch (err) {
      const msg = err.message || String(err);
      setError(msg);
      setMessages(prev => [...prev, { id: `e-${Date.now()}`, role: 'system', dir: 'system', text: msg, time: now }]);
    } finally {
      setSending(false);
      setPendingMessage('');
    }
  }

  function onKeyDown(event) {
    if (event.key === 'Enter' && !event.shiftKey) {
      event.preventDefault();
      send();
    }
  }

  return (
    <div className="panel agent-test-panel">
      <div className="panel-head">
        <div>
          <div className="panel-title">Teste do agente</div>
          <div className="muted" style={{fontSize:12}}>{agent.name} - sessão interna</div>
        </div>
        <div className="row-actions compact-actions">
          <button className="tb-btn ghost" onClick={openAssistantTester}>Abrir testador</button>
          <button className="tb-btn danger" onClick={deleteAllSessions} disabled={sessionBusy || sessionsLoading || !sessions.length}>Excluir testes</button>
          <button className="tb-btn" onClick={startNewSession} disabled={sessionBusy}><Icon name="plus" size={12}/> {sessionBusy ? 'Aguarde...' : 'Nova sessão'}</button>
        </div>
      </div>
      <div className="agent-test-redirect">
        <span>O testador automático fica em Assistentes para comparar cenários e enviar melhorias ao Otimizador.</span>
        <button className="tb-btn ghost" onClick={openAssistantTester}>Ir para testador</button>
      </div>
      <div className="agent-test-shell">
        <aside className="agent-test-sessions">
          <div className="rt-label">Sessões</div>
          <div className="test-session-list">
            {sessionsLoading && <div className="empty tiny">Carregando sessoes...</div>}
            {!sessionsLoading && sessions.map(item => (
              <button key={item.session_id} className={`test-session-row ${item.session_id === sessionId ? 'active' : ''}`} onClick={() => selectSession(item)}>
                <span className="session-title">{item.name || 'Teste interno'}</span>
                <span className="session-meta">{item.messages_count || 0} msg - {window.fmtShortDate ? window.fmtShortDate(item.updated_at) : '--'}</span>
                <span className={`badge ${runtimeBadgeClass(item.last_status || 'pronto')}`}>{item.last_status || 'pronto'}</span>
              </button>
            ))}
            {!sessionsLoading && !sessions.length && <div className="empty tiny">Nenhuma sessão salva.</div>}
          </div>
          <button className="tb-btn ghost" onClick={() => refreshSessions().catch(err => studioToast(err.message || String(err), 'bad'))}>Atualizar</button>
          {sessions.find(item => item.session_id === sessionId) && (
            <button className="tb-btn danger" onClick={() => deleteSession(sessions.find(item => item.session_id === sessionId))} disabled={sessionBusy}>Excluir atual</button>
          )}
        </aside>
        <div className="agent-test-chat">
          <div className="conv-header agent-test-header">
            <span className="badge ok"><Icon name="play" size={10}/> interno</span>
            <span className="badge">sem canal externo</span>
            <span className="badge mono">{sessionId.slice(0, 18)}...</span>
          </div>
          <div className="conv-msgs agent-test-msgs">
            {messages.map(item => (
              <div key={item.id} className={`msg ${item.dir}`}>
                <div className="msg-bubble">{item.text}</div>
                <div className="msg-meta">{item.role === 'assistant' ? 'agente - ' : item.role === 'system' ? 'sistema - ' : 'teste - '}{item.time}</div>
              </div>
            ))}
        {sending && (
          <div className="msg out agent-thinking-msg">
            <div className="msg-bubble"><LiveStatus message={pendingMessage} label="Agente respondendo" compact/></div>
            <div className="msg-meta">processando resposta</div>
          </div>
        )}
            {!messages.length && <div className="empty">Envie uma mensagem para testar este agente.</div>}
            <div ref={endRef}/>
          </div>
          <div className="conv-composer agent-test-composer">
            <textarea value={draft} onChange={e => setDraft(e.target.value)} onKeyDown={onKeyDown} placeholder="Digite como cliente..."/>
            <div className="conv-composer-actions">
              {error && <span className="badge bad">{error}</span>}
              <button className="tb-btn primary" style={{marginLeft:'auto'}} onClick={send} disabled={sending || !draft.trim()}>
                {sending ? 'Enviando...' : 'Enviar teste'}
              </button>
            </div>
          </div>
        </div>
        <aside className="agent-test-runtime">
          <div className="runtime-section">
            <div className="rt-label">Resultado</div>
            <dl className="rt-kv compact">
              <dt>Status</dt><dd><span className={`badge ${runtimeBadgeClass(runtime?.status || 'pronto')}`}>{runtime?.status || 'pronto'}</span></dd>
              <dt>Latência</dt><dd>{runtime?.latency_ms != null ? `${runtime.latency_ms} ms` : '--'}</dd>
              <dt>Run</dt><dd>{runtime?.run_id || '--'}</dd>
              <dt>Conversa</dt><dd>{runtime?.conversation_id || '--'}</dd>
            </dl>
          </div>
          <div className="runtime-section">
            <div className="rt-label">Runtime</div>
            <dl className="rt-kv compact">
              <dt>Fontes</dt><dd>{sourcesCount}</dd>
              <dt>Ferramentas</dt><dd>{toolsCount}</dd>
              <dt>Condicionais</dt><dd>{conditionalCount}</dd>
              <dt>Handoff</dt><dd>{handoff.requested ? 'solicitado' : 'não'}</dd>
            </dl>
          </div>
          {showHandoffDelivery && (
            <div className="runtime-section">
              <div className="rt-label">Repasse humano</div>
              <dl className="rt-kv compact">
                <dt>Ticket</dt><dd>{handoffTicket.ticket?.id ? `T-${handoffTicket.ticket.id}` : '--'}</dd>
                <dt>WhatsApp</dt><dd>{whatsappNotifySent ? 'enviado' : whatsappNotifyError ? 'erro' : whatsappNotifySkipped ? 'não enviado' : 'aguardando'}</dd>
              </dl>
              {whatsappNotifyError && <div className="empty tiny bad-text">{whatsappNotifyError}</div>}
              {whatsappNotifySkipped && !whatsappNotifyError && <div className="empty tiny">{whatsappNotifySkipped}</div>}
              {!!whatsappTargets.length && (
                <div className="rt-list">
                  {whatsappTargets.slice(0, 4).map((target, idx) => (
                    <div className="item" key={`${target.id || idx}-${idx}`}>
                      <span className="t">{target.name || target.id || `Alvo ${idx + 1}`}</span>
                      {target.kind || 'whatsapp'}
                    </div>
                  ))}
                </div>
              )}
            </div>
          )}
          <div className="runtime-section">
            <div className="rt-label">Fontes usadas</div>
            <div className="rt-list">
              {(runtime?.sources || []).slice(0, 5).map((item, idx) => (
                <div className="item" key={item.id || item.uri || idx}>
                  <span className="t">{item.title || item.uri || `Fonte ${idx + 1}`}</span>
                  {item.score != null ? `score ${Number(item.score).toFixed(2)}` : item.uri || 'knowledge base'}
                </div>
              ))}
              {!sourcesCount && <div className="empty tiny">Nenhuma fonte retornada.</div>}
            </div>
          </div>
        </aside>
      </div>
    </div>
  );
}

function AgentAutoList({ title, items }) {
  const list = Array.isArray(items) ? items : [];
  return (
    <div className="agent-auto-list">
      <span>{title}</span>
      {list.length ? list.slice(0, 4).map((item, idx) => <p key={idx}>{typeof item === 'string' ? item : window.prettyStudioValue?.(item) || String(item)}</p>) : <p>Nenhum item.</p>}
    </div>
  );
}

function ConnectionsTab({ agent }) {
  const [qrData, setQrData] = React.useState(null);
  const [qrLoading, setQrLoading] = React.useState(false);
  const [qrError, setQrError] = React.useState('');
  const token = agent.raw?.instance_token || agent.channel;
  const inst = (window.MOCK?.instances || []).find(item => item.id === token || item.name === token || item.raw?.name === token);
  const waInfo = whatsappInstanceUiState(inst, token);

  React.useEffect(() => {
    setQrData(null);
    setQrError('');
  }, [agent.id]);

  async function loadQr() {
    setQrLoading(true);
    setQrError('');
    try {
      setQrData(await API.getQr(agent.id));
    } catch (err) {
      setQrError(err.message || String(err));
      setQrData(null);
    } finally {
      setQrLoading(false);
    }
  }

  return (
    <div className="panel">
      <div className="panel-head">
        <div>
          <div className="panel-title">Conexões do agente</div>
          <div className="muted" style={{fontSize:12}}>Site e WhatsApp podem ficar ativos ao mesmo tempo.</div>
        </div>
        <div className="connection-picker">
          <span className="badge accent" title="Canal de site disponível para instalar no seu site. Não indica conexão WhatsApp.">Site disponível</span>
          <span className={`badge ${waInfo.tag}`} title={`WhatsApp: ${waInfo.label}. ${qrData ? 'QR pronto para escanear.' : qrError ? 'Falha ao gerar QR.' : 'Use Gerar QR para vincular o aparelho.'}`}>WhatsApp {waInfo.label}</span>
          <span className="badge accent">Site -> WhatsApp</span>
        </div>
      </div>
      <div className="connection-flow-note">
        Quando uma conversa do site indicar negócio fechado, a IA gera um resumo com LLM e envia pelo WhatsApp do agente para os alvos configurados em Ferramentas.
      </div>
      <div className="connections-dual-grid">
        <section className="connection-section">
          <SiteInstallPanel agent={agent} framed={false}/>
        </section>
        <section className="connection-section">
          <WhatsappConnectionPanel agent={agent} qrData={qrData} loading={qrLoading} error={qrError} onRefresh={loadQr} statusInfo={waInfo}/>
        </section>
      </div>
      <SharedChatSecurityPanel agent={agent}/>
    </div>
  );
}

const SHARED_CHAT_PRESET_LIMITS = {
  low: { max_messages_per_conversation: 10, max_chars_per_message: 500, max_total_chars_per_conversation: 3000 },
  medium: { max_messages_per_conversation: 30, max_chars_per_message: 1000, max_total_chars_per_conversation: 10000 },
  high: { max_messages_per_conversation: 100, max_chars_per_message: 2000, max_total_chars_per_conversation: 30000 },
};

function sharedChatConfigToForm(config) {
  const raw = config || {};
  const limits = raw.limits || SHARED_CHAT_PRESET_LIMITS.medium;
  const messages = raw.messages || {};
  const ui = raw.ui || {};
  const contact = raw.contact || {};
  return {
    preset: raw.preset || 'medium',
    maxMessages: String(limits.max_messages_per_conversation || 30),
    maxChars: String(limits.max_chars_per_message || 1000),
    maxTotalChars: String(limits.max_total_chars_per_conversation || 10000),
    showCounter: ui.show_character_counter !== false,
    showWarning: ui.show_near_limit_warning !== false,
    nearLimit: messages.near_limit || 'Você está chegando ao limite de mensagens desta conversa.',
    limitReached: messages.limit_reached || 'Este chat atingiu o limite de uso configurado. Para continuar o atendimento, entre em contato com nossa equipe.',
    charLimit: messages.char_limit || 'Sua mensagem ultrapassou o limite de caracteres permitido. Reduza o texto para continuar.',
    contactEnabled: contact.enabled !== false,
    allowErrorReport: contact.allow_error_report !== false,
    requireName: !!contact.require_name,
    requireEmail: contact.require_email !== false,
    requirePhone: !!contact.require_phone,
    destinationEmail: contact.destination_email || '',
  };
}

function SharedChatSecurityPanel({ agent }) {
  const initialConfig = agent.sharedChatConfig || agent.raw?.shared_chat_config || {};
  const [form, setForm] = React.useState(() => sharedChatConfigToForm(initialConfig));
  const [saving, setSaving] = React.useState(false);

  React.useEffect(() => {
    setForm(sharedChatConfigToForm(agent.sharedChatConfig || agent.raw?.shared_chat_config || {}));
  }, [agent.id, JSON.stringify(agent.sharedChatConfig || agent.raw?.shared_chat_config || {})]);

  function setField(name, value) {
    setForm(prev => ({ ...prev, [name]: value }));
  }

  function numericField(label, name, min, max) {
    return (
      <label>{label}
        <input type="number" min={min} max={max} value={form[name]} onChange={e => setField(name, e.target.value)}/>
      </label>
    );
  }

  function payload() {
    return {
      preset: form.preset,
      limits: {
        max_messages_per_conversation: Number(form.maxMessages),
        max_chars_per_message: Number(form.maxChars),
        max_total_chars_per_conversation: Number(form.maxTotalChars),
      },
      ui: {
        show_character_counter: !!form.showCounter,
        show_near_limit_warning: !!form.showWarning,
      },
      messages: {
        near_limit: form.nearLimit,
        limit_reached: form.limitReached,
        char_limit: form.charLimit,
      },
      contact: {
        enabled: !!form.contactEnabled,
        allow_error_report: !!form.allowErrorReport,
        require_name: !!form.requireName,
        require_email: !!form.requireEmail,
        require_phone: !!form.requirePhone,
        destination_email: form.destinationEmail,
        request_types: ['Dúvida', 'Erro no chat', 'Resposta incorreta', 'Quero falar com uma pessoa', 'Problema técnico', 'Sugestão', 'Sugestão de melhoria', 'Outro'],
      },
    };
  }

  async function save() {
    setSaving(true);
    try {
      await API.updateAgent(agent.id, { shared_chat_config: payload() });
      await window.STUDIO.refresh();
      studioToast('Limites do chat compartilhável salvos.');
    } catch (err) {
      studioToast(err.message || String(err), 'bad');
    } finally {
      setSaving(false);
    }
  }

  const presetLimits = SHARED_CHAT_PRESET_LIMITS[form.preset] || {
    max_messages_per_conversation: form.maxMessages,
    max_chars_per_message: form.maxChars,
    max_total_chars_per_conversation: form.maxTotalChars,
  };

  return (
    <section className="shared-security-panel">
      <div className="panel-head compact">
        <div>
          <div className="panel-title">Limites e segurança</div>
          <div className="muted" style={{fontSize:12}}>Configuração aplicada somente ao Chat Compartilhado.</div>
        </div>
        <button className="tb-btn primary" onClick={save} disabled={saving}>{saving ? 'Salvando...' : 'Salvar limites'}</button>
      </div>

      <div className="shared-security-grid">
        <div className="security-card">
          <div className="section-kicker">Uso</div>
          <label>Preset
            <select value={form.preset} onChange={e => setField('preset', e.target.value)}>
              <option value="low">Baixo</option>
              <option value="medium">Médio</option>
              <option value="high">Alto</option>
              <option value="custom">Personalizado</option>
            </select>
          </label>
          {form.preset === 'custom' ? (
            <div className="security-fields">
              {numericField('Máximo de mensagens por conversa', 'maxMessages', 1, 500)}
              {numericField('Caracteres por mensagem', 'maxChars', 50, 10000)}
              {numericField('Caracteres totais por conversa', 'maxTotalChars', 100, 200000)}
            </div>
          ) : (
            <div className="limit-preview">
              <span>{presetLimits.max_messages_per_conversation} mensagens</span>
              <span>{presetLimits.max_chars_per_message} caracteres por mensagem</span>
              <span>{presetLimits.max_total_chars_per_conversation} caracteres totais</span>
            </div>
          )}
          <label className="checkline"><input type="checkbox" checked={form.showCounter} onChange={e => setField('showCounter', e.target.checked)}/> Mostrar contador de caracteres</label>
          <label className="checkline"><input type="checkbox" checked={form.showWarning} onChange={e => setField('showWarning', e.target.checked)}/> Avisar próximo do limite</label>
        </div>

        <div className="security-card">
          <div className="section-kicker">Mensagens</div>
          <label>Aviso próximo do limite
            <textarea value={form.nearLimit} onChange={e => setField('nearLimit', e.target.value)} rows="2"/>
          </label>
          <label>Limite atingido
            <textarea value={form.limitReached} onChange={e => setField('limitReached', e.target.value)} rows="2"/>
          </label>
          <label>Limite por mensagem
            <textarea value={form.charLimit} onChange={e => setField('charLimit', e.target.value)} rows="2"/>
          </label>
        </div>

        <div className="security-card">
          <div className="section-kicker">Contato</div>
          <label className="checkline"><input type="checkbox" checked={form.contactEnabled} onChange={e => setField('contactEnabled', e.target.checked)}/> Habilitar Fale Conosco</label>
          <label className="checkline"><input type="checkbox" checked={form.allowErrorReport} onChange={e => setField('allowErrorReport', e.target.checked)}/> Habilitar Encontrou erro?</label>
          <label className="checkline"><input type="checkbox" checked={form.requireName} onChange={e => setField('requireName', e.target.checked)}/> Exigir nome</label>
          <label className="checkline"><input type="checkbox" checked={form.requireEmail} onChange={e => setField('requireEmail', e.target.checked)}/> Exigir e-mail</label>
          <label className="checkline"><input type="checkbox" checked={form.requirePhone} onChange={e => setField('requirePhone', e.target.checked)}/> Exigir telefone</label>
          <label>Destino interno opcional
            <input value={form.destinationEmail} onChange={e => setField('destinationEmail', e.target.value)} placeholder="equipe@empresa.com"/>
          </label>
          <div className="field-helper">Tipos: Dúvida, Erro no chat, Resposta incorreta, Quero falar com uma pessoa, Problema técnico, Sugestão, Sugestão de melhoria e Outro.</div>
        </div>
      </div>
    </section>
  );
}

function WhatsappConnectionPanel({ agent, qrData, loading, error, onRefresh, statusInfo }) {
  const status = statusInfo || { label: 'Sem conexão', tag: 'warn' };
  return (
    <div className="site-install-body">
      <div className="qr-panel connection-qr-panel">
        <div className={`qr-status ${error ? 'bad' : ''}`}>
          <span>{error ? 'Falha ao gerar QR' : qrData ? 'QR pronto' : loading ? 'Gerando QR...' : `WhatsApp ${status.label}`}</span>
          <button className="tb-btn primary" onClick={onRefresh} disabled={loading}>{loading ? 'Gerando...' : 'Gerar QR'}</button>
        </div>
        <div className="field-helper mono">{agent.raw?.instance_token || agent.channel}</div>
        <div className="qrbox">
          {qrData?.base64 || qrData?.qrcode
            ? <img alt="QR Code WhatsApp" src={agentQrSrc(qrData)}/>
            : <div className="empty">{error || (loading ? 'Gerando QR Code...' : 'Clique para gerar QR.')}</div>}
        </div>
        <div className="qr-help">WhatsApp > Aparelhos conectados > Conectar aparelho. Se expirar, gere outro QR.</div>
      </div>
    </div>
  );
}

function KnowledgeTab({ agent }) {
  const [kbSources, setKbSources] = React.useState([]);
  const [sourceText, setSourceText] = React.useState('');
  const [sourceFiles, setSourceFiles] = React.useState([]);
  const [sourceDetail, setSourceDetail] = React.useState(null);
  const [loadingSourceId, setLoadingSourceId] = React.useState(null);
  const docCount = kbSources.reduce((sum, item) => sum + Number(item.document_count || 0), 0);
  const chunkCount = kbSources.reduce((sum, item) => sum + Number(item.chunk_count || 0), 0);

  async function loadKbSources() {
    try {
      setKbSources(await API.getKbSources(agent.id));
    } catch (err) {
      setKbSources([]);
    }
  }

  React.useEffect(() => { loadKbSources(); }, [agent.id]);

  async function addSources() {
    const fileSources = await readKbFiles(sourceFiles);
    const sources = [...parseKbSources(sourceText), ...fileSources];
    if (!sources.length) {
      studioToast('Cole uma URL, texto ou anexe um arquivo.', 'bad');
      return;
    }
    try {
      await API.addKbSource(agent.id, { sources });
      setSourceText('');
      setSourceFiles([]);
      await loadKbSources();
      await window.STUDIO.refresh();
      studioToast('Fonte adicionada a base.');
    } catch (err) {
      studioToast(err.message || String(err), 'bad');
    }
  }

  async function openSourceData(source) {
    if (!source?.id) return;
    setLoadingSourceId(source.id);
    try {
      setSourceDetail(await API.getKbSource(agent.id, source.id));
    } finally {
      setLoadingSourceId(null);
    }
  }

  return (
    <>
      <div className="grid-kpis" style={{ gridTemplateColumns: 'repeat(4, 1fr)' }}>
        <Kpi label="Fontes" value={String(kbSources.length)}/>
        <Kpi label="Documentos" value={String(docCount)}/>
        <Kpi label="Chunks" value={String(chunkCount)}/>
        <Kpi label="Status" value={kbSources.length ? 'ativo' : 'vazio'} sub="KB do agente"/>
      </div>

      <div className="panel">
        <div className="panel-head">
          <div>
            <div className="panel-title">Conhecimento do agente</div>
            <div className="muted" style={{fontSize:12}}>Cole URLs, textos ou anexe arquivos. A base técnica e criada automaticamente.</div>
          </div>
          <button className="tb-btn primary" onClick={() => addSources().catch(err => studioToast(err.message || String(err), 'bad'))}><Icon name="plus" size={11}/> Adicionar fontes</button>
        </div>
        <div className="kb-source-composer">
          <label className="fg">
            <span className="fl">URLs ou texto direto</span>
            <textarea className="input prose-input" rows="4" value={sourceText} onChange={e => setSourceText(e.target.value)} placeholder={"https://exemplo.com/manual\nTexto interno curto..."}/>
          </label>
          <label className="fg">
            <span className="fl">Arquivos</span>
            <input className="input file-input" type="file" multiple onChange={e => setSourceFiles(Array.from(e.target.files || []))}/>
            <span className="field-hint">{sourceFiles.length ? `${sourceFiles.length} arquivo(s) selecionado(s)` : 'PDF, DOCX ou texto.'}</span>
          </label>
        </div>
        <table className="dt">
          <thead><tr><th>Fonte</th><th>Tipo</th><th>Status</th><th>Docs</th><th>Chunks</th><th>Criada</th><th>Ações</th></tr></thead>
          <tbody>
            {kbSources.map(s => (
              <tr key={s.id}>
                <td data-label="Fonte" className="mono truncate-cell">{s.uri || '--'}</td>
                <td data-label="Tipo"><span className="badge accent">{s.source_type || 'text'}</span></td>
                <td data-label="Status"><span className={`badge ${s.status === 'duplicate' ? 'warn' : s.status === 'pending' ? '' : 'ok'}`}>{s.status || 'ingested'}</span></td>
                <td data-label="Docs" className="num">{s.document_count || 0}</td>
                <td data-label="Chunks" className="num">{s.chunk_count || 0}</td>
                <td data-label="Criada" className="num muted">{window.fmtShortDate ? window.fmtShortDate(s.created_at) : '--'}</td>
                <td data-label="Ações"><button className="tb-btn ghost" onClick={() => openSourceData(s)} disabled={loadingSourceId === s.id}>{loadingSourceId === s.id ? 'Abrindo...' : 'Dados'}</button></td>
              </tr>
            ))}
            {!kbSources.length && <tr><td colSpan="7" className="empty">Nenhuma fonte indexada ainda.</td></tr>}
          </tbody>
        </table>
        {sourceDetail && (
          <div style={{marginTop:16, borderTop:'1px solid var(--line)', paddingTop:16}}>
            <div className="panel-subtitle">Dados da fonte</div>
            <div className="soft-row"><span>Fonte</span><strong>{sourceDetail.uri || `Fonte ${sourceDetail.id}`}</strong></div>
            <div className="soft-row"><span>Chunks carregados</span><strong>{sourceDetail.chunks_returned || 0} de {sourceDetail.chunk_count || 0}</strong></div>
            {(sourceDetail.documents || []).map(doc => (
              <div key={doc.id} style={{marginTop:12}}>
                <div className="muted" style={{fontSize:12, marginBottom:6}}>{doc.title || `Documento ${doc.id}`}</div>
                {(doc.chunks || []).map(chunk => (
                  <pre key={chunk.id} className="input" style={{whiteSpace:'pre-wrap', overflow:'auto', maxHeight:220, margin:'8px 0', fontSize:12, lineHeight:1.45}}>{chunk.content}</pre>
                ))}
              </div>
            ))}
          </div>
        )}
      </div>
    </>
  );
}

function normalizeWhatsAppTargetId(value, kind) {
  const raw = String(value || '').trim();
  if (!raw) return '';
  let compact = raw.replace(/\s+/g, '');
  const lowered = compact.toLowerCase();
  if (lowered.endsWith('@g.us')) return lowered;
  if (compact.includes('@') && String(kind || '').toLowerCase() !== 'group') {
    compact = compact.split('@')[0];
  }
  const digits = compact.replace(/\D+/g, '');
  if (digits && String(kind || '').toLowerCase() !== 'group') return digits;
  return compact.includes('@') ? compact.toLowerCase() : compact;
}

function normalizeWaTargetItem(item, fallbackKind) {
  const kind = item?.kind || fallbackKind || (String(item?.id || '').toLowerCase().endsWith('@g.us') ? 'group' : 'contact');
  const id = normalizeWhatsAppTargetId(item?.id || item?.target_id || item?.number, kind);
  if (!id) return null;
  return { ...item, id, kind, name: item?.name || item?.target_name || id };
}

function uniqueWaTargets(items) {
  const out = [];
  const seen = new Set();
  (items || []).forEach(item => {
    const normalized = normalizeWaTargetItem(item);
    if (!normalized || seen.has(normalized.id)) return;
    seen.add(normalized.id);
    out.push(normalized);
  });
  return out;
}

function ToolsTab({ agent }) {
  const tools = (window.MOCK.tools || []).filter(item => String(item.agent_id) === String(agent.id));
  const notifyTool = tools.find(item => item.tool_type === 'whatsapp_notify');
  const [waTargets, setWaTargets] = React.useState({ contacts: [], groups: [] });
  const [waSearchTargets, setWaSearchTargets] = React.useState(null);
  const [waTargetError, setWaTargetError] = React.useState('');
  const [waTargetStatus, setWaTargetStatus] = React.useState('Preparando agenda...');
  const [waTargetsLoading, setWaTargetsLoading] = React.useState(true);
  const [waSearchLoading, setWaSearchLoading] = React.useState(false);
  const [waTargetQuery, setWaTargetQuery] = React.useState('');
  const [notifyTargetId, setNotifyTargetId] = React.useState('');
  const [notifyTargetIds, setNotifyTargetIds] = React.useState([]);
  const [notifyManualId, setNotifyManualId] = React.useState('');
  const [notifyTriggerMode, setNotifyTriggerMode] = React.useState(notifyTool?.config?.trigger_mode || 'handoff_or_qualified');
  const [savingNotify, setSavingNotify] = React.useState(false);
  const currentNotifyTarget = notifyTool?.config?.target_id
    ? [{
        id: notifyTool.config.target_id,
        name: notifyTool.config.target_name || notifyTool.config.target_id,
        kind: notifyTool.config.target_kind || (String(notifyTool.config.target_id).toLowerCase().endsWith('@g.us') ? 'group' : 'contact'),
        source: 'config',
      }]
    : [];
  const sourceWaTargets = waSearchTargets || waTargets;
  const allWaTargets = React.useMemo(() => uniqueWaTargets([
    ...(sourceWaTargets.contacts || []).map(item => ({ ...item, kind: 'contact' })),
    ...(sourceWaTargets.groups || []).map(item => ({ ...item, kind: 'group' })),
    ...currentNotifyTarget,
  ]), [sourceWaTargets.contacts, sourceWaTargets.groups, notifyTool?.config?.target_id, notifyTool?.config?.target_name, notifyTool?.config?.target_kind]);
  const targetQuery = waTargetQuery.trim().toLowerCase();
  let visibleWaTargets = React.useMemo(() => allWaTargets
    .filter(item => !targetQuery || `${item.name || ''} ${item.id || ''}`.toLowerCase().includes(targetQuery))
    .slice(0, 250), [allWaTargets, targetQuery]);
  const selectedVisible = allWaTargets.find(item => String(item.id) === String(notifyTargetId));
  if (selectedVisible && !visibleWaTargets.some(item => item.id === selectedVisible.id)) {
    visibleWaTargets = [selectedVisible, ...visibleWaTargets];
  }

  React.useEffect(() => {
    let alive = true;
    setWaTargetError('');
    setWaTargetsLoading(true);
    setWaTargetStatus('Carregando agenda WhatsApp...');
    setWaSearchTargets(null);
    setNotifyTargetId(normalizeWhatsAppTargetId(notifyTool?.config?.target_id || '', notifyTool?.config?.target_kind));
    setNotifyTargetIds(uniqueWaTargets(notifyTool?.config?.targets || []).map(item => item.id));
    setNotifyTriggerMode(notifyTool?.config?.trigger_mode || 'handoff_or_qualified');
    setNotifyManualId('');
    const started = performance.now();
    API.getWhatsappTargets(agent.id)
      .then(data => {
        if (!alive) return;
        setWaTargets(data || { contacts: [], groups: [] });
        setWaTargetError(Array.isArray(data?.errors) && data.errors.length ? data.errors.join(' | ') : '');
        const total = (data?.contacts?.length || 0) + (data?.groups?.length || 0);
        const ms = Math.max(1, Math.round(performance.now() - started));
        setWaTargetStatus(`${total} alvos carregados em ${ms}ms${data?.cached ? ' (cache)' : ''}.`);
      })
      .catch(err => {
        if (!alive) return;
        setWaTargets({ contacts: [], groups: [] });
        setWaTargetError(err.message || String(err));
        setWaTargetStatus('Falha ao carregar agenda.');
      })
      .finally(() => {
        if (alive) setWaTargetsLoading(false);
      });
    return () => { alive = false; };
  }, [agent.id, notifyTool?.id]);

  React.useEffect(() => {
    const query = waTargetQuery.trim();
    if (query.length < 2) {
      setWaSearchTargets(null);
      setWaSearchLoading(false);
      return undefined;
    }
    let alive = true;
    const timer = setTimeout(() => {
      const started = performance.now();
      setWaSearchLoading(true);
      setWaTargetStatus(`Pesquisando "${query}"...`);
      API.getWhatsappTargets(agent.id, query)
        .then(data => {
          if (!alive) return;
          setWaSearchTargets(data || { contacts: [], groups: [] });
          setWaTargetError(Array.isArray(data?.errors) && data.errors.length ? data.errors.join(' | ') : '');
          const total = (data?.contacts?.length || 0) + (data?.groups?.length || 0);
          const ms = Math.max(1, Math.round(performance.now() - started));
          setWaTargetStatus(`${total} resultado(s) para "${query}" em ${ms}ms${data?.cached ? ' (cache)' : ''}.`);
        })
        .catch(err => {
          if (!alive) return;
          setWaTargetError(err.message || String(err));
          setWaTargetStatus(`Pesquisa de "${query}" falhou.`);
        })
        .finally(() => {
          if (alive) setWaSearchLoading(false);
        });
    }, 280);
    return () => {
      alive = false;
      clearTimeout(timer);
    };
  }, [agent.id, waTargetQuery]);

  async function saveWhatsappNotifyTool() {
    const selectedTargets = notifyTargetIds
      .map(id => allWaTargets.find(item => String(item.id) === String(id)) || normalizeWaTargetItem({ id }))
      .filter(Boolean);
    const manualId = normalizeWhatsAppTargetId(notifyManualId);
    if (manualId && !selectedTargets.some(item => item.id === manualId)) {
      selectedTargets.push({ id: manualId, name: manualId, kind: manualId.endsWith('@g.us') ? 'group' : 'contact' });
    }
    const targets = uniqueWaTargets(selectedTargets);
    if (!targets.length) {
      studioToast('Selecione ou informe ao menos um número/grupo para notificar.', 'bad');
      return;
    }
    const primary = targets[0];
    const payload = {
      name: 'Notificar humano WhatsApp',
      agent_id: agent.id,
      tool_type: 'whatsapp_notify',
      description: 'Envia resumo de lead, negócio fechado ou repasse para humano no WhatsApp selecionado.',
      enabled: true,
      config: {
        target_id: primary.id,
        target_name: primary.name || primary.id,
        target_kind: primary.kind,
        targets,
        allow_dynamic_target: false,
        trigger_mode: notifyTriggerMode,
      },
    };
    try {
      setSavingNotify(true);
      if (notifyTool) await API.updateTool(notifyTool.id, payload);
      else await API.createTool(payload);
      await window.STUDIO.refresh();
      studioToast('Notificacao WhatsApp configurada.');
    } catch (err) {
      studioToast(err.message || String(err), 'bad');
    } finally {
      setSavingNotify(false);
    }
  }

  function addNotifyTarget() {
    const normalized = normalizeWhatsAppTargetId(notifyTargetId);
    if (!normalized) return;
    setNotifyTargetIds(prev => prev.includes(normalized) ? prev : [...prev, normalized]);
  }

  function removeNotifyTarget(id) {
    setNotifyTargetIds(prev => prev.filter(item => item !== id));
  }

  async function createTool() {
    const values = await studioForm({
      title: 'Nova ferramenta do agente',
      description: 'Esta ferramenta aparece somente neste perfil.',
      submitLabel: 'Criar ferramenta',
      fields: [
        { name: 'name', label: 'Nome', required: true, placeholder: 'Consultar base' },
        {
          name: 'tool_type',
          label: 'Tipo',
          type: 'select',
          value: 'knowledge_base',
          options: [
            { value: 'knowledge_base', label: 'Knowledge base' },
            { value: 'web_search', label: 'Web search' },
            { value: 'data_table', label: 'Data table' },
            { value: 'ticket_creation', label: 'Ticket creation' },
            { value: 'whatsapp_notify', label: 'WhatsApp notify' },
            { value: 'contextual_memory', label: 'Contextual memory' },
          ],
        },
        { name: 'description', label: 'Descrição', type: 'textarea' },
      ],
    });
    if (!values?.name?.trim()) return;
    try {
      await API.post('/api/tools', {
        name: values.name.trim(),
        agent_id: agent.id,
        tool_type: values.tool_type || 'knowledge_base',
        description: values.description || '',
        enabled: true,
      });
      await window.STUDIO.refresh();
      studioToast('Ferramenta vinculada ao agente.');
    } catch (err) {
      studioToast(err.message || String(err), 'bad');
    }
  }

  function toggle(tool) {
    API.put(`/api/tools/${tool.id}`, { enabled: !tool.enabled })
      .then(() => window.STUDIO.refresh())
      .catch(err => studioToast(err.message || String(err), 'bad'));
  }

  async function editTool(tool) {
    const values = await studioForm({
      title: 'Editar ferramenta',
      submitLabel: 'Salvar ferramenta',
      fields: [
        { name: 'name', label: 'Nome', required: true, value: tool.name || '' },
        {
          name: 'tool_type',
          label: 'Tipo',
          type: 'select',
          value: tool.tool_type || 'knowledge_base',
          options: [
            { value: 'knowledge_base', label: 'Knowledge base' },
            { value: 'web_search', label: 'Web search' },
            { value: 'data_table', label: 'Data table' },
            { value: 'ticket_creation', label: 'Ticket creation' },
            { value: 'whatsapp_notify', label: 'WhatsApp notify' },
            { value: 'contextual_memory', label: 'Contextual memory' },
          ],
        },
        { name: 'description', label: 'Descrição', type: 'textarea', value: tool.description || '' },
        { name: 'enabled', label: 'Ativa', type: 'select', value: tool.enabled ? 'true' : 'false', options: [{ value: 'true', label: 'Ativa' }, { value: 'false', label: 'Inativa' }] },
      ],
    });
    if (!values?.name?.trim()) return;
    try {
      await API.updateTool(tool.id, {
        name: values.name.trim(),
        tool_type: values.tool_type || tool.tool_type,
        description: values.description || '',
        enabled: values.enabled !== 'false',
      });
      await window.STUDIO.refresh();
      studioToast('Ferramenta atualizada.');
    } catch (err) {
      studioToast(err.message || String(err), 'bad');
    }
  }

  async function deleteTool(tool) {
    if (!(await studioConfirm({ title: 'Excluir ferramenta', message: `Excluir "${tool.name}" deste agente?`, confirmLabel: 'Excluir', danger: true }))) return;
    try {
      await API.deleteTool(tool.id);
      await window.STUDIO.refresh();
      studioToast('Ferramenta excluida.');
    } catch (err) {
      studioToast(err.message || String(err), 'bad');
    }
  }

  return (
    <>
      <div className="panel">
        <div className="panel-head">
          <div>
          <div className="panel-title">Repasse humano para alvos *</div>
          <div className="muted" style={{fontSize:12}}>O agente pode receber mensagens por WhatsApp, API ou site. Para repassar informacoes a alvos, conecte uma conta WhatsApp.</div>
          </div>
          <div style={{display:'flex', alignItems:'center', gap:8, flexWrap:'wrap', justifyContent:'flex-end'}}>
            <span className={`badge ${waTargetsLoading || waSearchLoading ? 'warn' : waTargetError ? 'bad' : 'ok'}`}>
              {(waTargetsLoading || waSearchLoading) && <span className="mini-spinner"/>}
              {waTargetsLoading ? 'carregando' : waSearchLoading ? 'pesquisando' : waTargetError ? 'parcial' : 'pronto'}
            </span>
            <button className="tb-btn primary" onClick={saveWhatsappNotifyTool} disabled={savingNotify}>{savingNotify ? 'Salvando...' : 'Salvar repasse'}</button>
          </div>
        </div>
        <div className="grid-2" style={{padding:14, alignItems:'end'}}>
          <label className="field-block">
          <span className="field-label fl-required">Alvo</span>
          <input className="input" value={waTargetQuery} onChange={e => setWaTargetQuery(e.target.value)} placeholder="Buscar nome, número ou grupo..."/>
            <select className="input" value={notifyTargetId} onChange={e => setNotifyTargetId(e.target.value)}>
              <option value="">Selecionar alvo conectado...</option>
              {(waTargetsLoading || waSearchLoading) && <option value="" disabled>{waTargetsLoading ? 'Carregando agenda...' : 'Pesquisando alvos...'}</option>}
              {!waTargetsLoading && !waSearchLoading && !visibleWaTargets.length && <option value="" disabled>Nenhum alvo encontrado. Use número manual.</option>}
              {visibleWaTargets.map(item => (
                <option key={`${item.kind}-${item.id}`} value={item.id}>{item.kind === 'group' ? 'Grupo' : 'Contato'} - {item.name || item.id}</option>
              ))}
            </select>
            <button type="button" className="tb-btn ghost" onClick={addNotifyTarget} disabled={!notifyTargetId}>Adicionar alvo</button>
            <div className="notify-target-list">
              {notifyTargetIds.map(id => {
                const item = allWaTargets.find(target => target.id === id) || { id, name: id, kind: id.endsWith('@g.us') ? 'group' : 'contact' };
                return (
                  <span className="badge accent" key={id}>
                    {item.kind === 'group' ? 'Grupo' : 'Contato'} - {item.name || item.id}
                    <button type="button" className="chip-x" onClick={() => removeNotifyTarget(id)}>x</button>
                  </span>
                );
              })}
              {!notifyTargetIds.length && <span className="field-hint">Nenhum alvo selecionado ainda.</span>}
            </div>
          <span className="field-hint">* Alvos são contatos ou grupos do WhatsApp conectados no sistema que recebem o resumo do repasse humano.</span>
          <span className="field-hint">{waTargetError ? `Lista de contatos parcial: ${waTargetError}. ${waTargetStatus}` : waTargetStatus}</span>
          </label>
          <label className="field-block">
            <span className="field-label">Número/JID manual</span>
            <input className="input mono" value={notifyManualId} onChange={e => setNotifyManualId(e.target.value)} placeholder="5511999999999 ou 1203...@g.us"/>
            <span className="field-hint">{notifyManualId ? `Será salvo como: ${normalizeWhatsAppTargetId(notifyManualId) || '--'}` : notifyTool ? `Atual: ${notifyTool.config?.target_name || notifyTool.config?.target_id || '--'}` : 'Opcional quando a lista ainda não carregou.'}</span>
          </label>
          <label className="field-block">
            <span className="field-label">Quando enviar para o humano</span>
            <select className="input" value={notifyTriggerMode} onChange={e => setNotifyTriggerMode(e.target.value)}>
              <option value="handoff_or_qualified">Pedido humano, lead qualificado ou negócio fechado</option>
              <option value="human_request">Somente pedido humano explícito</option>
              <option value="qualified_lead">Somente lead qualificado/negócio pronto</option>
              <option value="deal_closed">Somente negócio fechado no site</option>
              <option value="manual">Sem trava automatica</option>
            </select>
            <span className="field-hint">Não cria ticket nem pausa conversa. Site e WhatsApp podem trabalhár juntos.</span>
          </label>
        </div>
      </div>
      <div className="grid-2">
        {tools.map(tool => <ToolCard key={tool.id} tool={tool} onToggle={() => toggle(tool)} onEdit={() => editTool(tool)} onDelete={() => deleteTool(tool)}/>)}
        {!tools.length && <div className="panel empty">Nenhuma ferramenta ligada a este agente.</div>}
      </div>
      <div className="panel">
        <div className="panel-head">
          <div className="panel-title">Ferramentas do backend</div>
          <button className="tb-btn primary" onClick={createTool}><Icon name="plus" size={11}/> Nova ferramenta</button>
        </div>
      </div>
    </>
  );
}

function ConditionalsTab({ agent }) {
  const [rows, setRows] = React.useState([]);
  const [loading, setLoading] = React.useState(true);

  function load() {
    setLoading(true);
    API.getConditionalPrompts(agent.id)
      .then(items => setRows(Array.isArray(items) ? items : []))
      .catch(() => setRows([]))
      .finally(() => setLoading(false));
  }

  React.useEffect(load, [agent.id]);

  async function createConditional() {
    const values = await studioForm({
      title: 'Nova regra condicional',
      description: 'Injeta prompt extra quando a condicao bater.',
      submitLabel: 'Criar regra',
      fields: [
        { name: 'name', label: 'Nome da regra', required: true, placeholder: 'Urgencia' },
        {
          name: 'condition_type',
          label: 'Tipo',
          type: 'select',
          value: 'intent',
          options: [
            { value: 'intent', label: 'Intent' },
            { value: 'regex', label: 'Regex' },
            { value: 'state_equals', label: 'State equals' },
            { value: 'always', label: 'Always' },
          ],
        },
        { name: 'condition_value', label: 'Condicao', placeholder: 'pedido urgente' },
        { name: 'system_prompt', label: 'Prompt a injetar', type: 'textarea', value: 'Ajuste a resposta para este contexto.' },
      ],
    });
    if (!values?.name?.trim()) return;
    API.createConditional(agent.id, {
      name: values.name.trim(),
      condition_type: values.condition_type || 'intent',
      condition_value: values.condition_value || values.name.trim(),
      system_prompt: values.system_prompt || '',
      enabled: true,
    }).then(() => {
      studioToast('Regra criada.');
      load();
    }).catch(err => studioToast(err.message || String(err), 'bad'));
  }

  function toggle(row) {
    API.updateConditional(row.id, { enabled: !row.enabled }).then(load).catch(err => studioToast(err.message || String(err), 'bad'));
  }

  async function remove(row) {
    if (!(await studioConfirm({ title: 'Excluir regra', message: 'Excluir prompt condicional?', confirmLabel: 'Excluir', danger: true }))) return;
    API.deleteConditional(row.id).then(load).catch(err => studioToast(err.message || String(err), 'bad'));
  }

  return (
    <div className="panel">
      <div className="panel-head">
        <div>
          <div className="panel-eyebrow">intent, regex, state_equals, always</div>
          <div className="panel-title">Prompts condicionais</div>
        </div>
        <button className="tb-btn primary" onClick={createConditional}><Icon name="plus" size={11}/> Nova regra</button>
      </div>
      <table className="dt">
        <thead><tr><th>Regra</th><th>Tipo</th><th>Condicao</th><th>Prompt</th><th>Status</th><th></th></tr></thead>
        <tbody>
          {rows.map(row => (
            <tr key={row.id}>
              <td data-label="Regra" className="mono">{row.name}</td>
              <td data-label="Tipo">{row.condition_type || '--'}</td>
              <td data-label="Condicao" className="muted">{row.condition_value || row.intent || row.regex || '--'}</td>
              <td data-label="Prompt" className="muted" style={{maxWidth:360}}>{row.system_prompt || row.prompt || '--'}</td>
              <td data-label="Status"><span className={`badge ${row.enabled ? 'ok' : ''}`}><span className={`sw ${row.enabled ? 'ok' : ''}`}/> {row.enabled ? 'ativa' : 'inativa'}</span></td>
              <td data-label=""><div className="row-actions">
                <button className="tb-btn ghost" onClick={() => toggle(row)}>{row.enabled ? 'Pausar' : 'Ativar'}</button>
                <button className="tb-btn danger" onClick={() => remove(row)}>Excluir</button>
              </div></td>
            </tr>
          ))}
          {!rows.length && <tr><td colSpan="6" className="empty">{loading ? 'Carregando...' : 'Nenhum prompt condicional.'}</td></tr>}
        </tbody>
      </table>
    </div>
  );
}

function AgentConversationsTab({ agent }) {
  const ConversationWorkspace = window.ConversationWorkspace || window.ConversationsPage;
  if (ConversationWorkspace) {
    return <ConversationWorkspace agentId={agent.id} embedded={true}/>;
  }
  const list = (window.MOCK.conversations || []).filter(c => String(c.agentId) === String(agent.id));
  return (
    <>
      <div className="grid-kpis" style={{ gridTemplateColumns: 'repeat(4, 1fr)' }}>
        <Kpi label="Conversas" value={agent.conversations.toLocaleString('pt-BR')}/>
        <Kpi label="Em handoff" value={String(list.filter(c => c.paused).length)} sub="pausadas"/>
        <Kpi label="Tickets" value={String(agent.tickets)}/>
        <Kpi label="Latência média" value={agent.latency ? agent.latency + ' ms' : '--'}/>
      </div>
      <div className="panel">
        <div className="panel-head"><div className="panel-title">Conversas atendidas</div></div>
        <table className="dt">
          <thead><tr><th>Cliente</th><th>Última mensagem</th><th>Ticket</th><th>Status</th><th>Hora</th></tr></thead>
          <tbody>
            {list.map(c => (
              <tr key={c.id}>
                <td data-label="Cliente"><div className="av"><span className="av-mark">{c.name[0]}</span><span className="av-name">{c.name}</span></div></td>
                <td data-label="Última mensagem" style={{maxWidth:340, color:'var(--ink-2)'}}>{c.last}</td>
                <td data-label="Ticket" className="muted mono">{c.ticket || '--'}</td>
                <td data-label="Status">{c.paused ? <span className="badge bad"><span className="sw bad"/> pausada</span> : <span className="badge ok"><span className="sw ok"/> ativa</span>}</td>
                <td data-label="Hora" className="num muted">{c.time}</td>
              </tr>
            ))}
            {!list.length && <tr><td colSpan="5" className="empty">Sem conversa para este agente.</td></tr>}
          </tbody>
        </table>
      </div>
    </>
  );
}

function AgentLogsTab({ agent }) {
  const rows = (window.MOCK.runs || []).filter(r => String(r.agent_id) === String(agent.id)).slice(0, 80);
  return (
    <>
      <div className="grid-kpis" style={{ gridTemplateColumns: 'repeat(4, 1fr)' }}>
        <Kpi label="Execuções" value={String(rows.length)}/>
        <Kpi label="Erros" value={String(rows.filter(r => r.error).length)}/>
        <Kpi label="Latência média" value={agent.latency ? agent.latency + ' ms' : '--'}/>
        <Kpi label="Modelo" value={agent.model}/>
      </div>
      <div className="panel">
        <div className="panel-head"><div className="panel-title">Execuções recentes</div></div>
        <table className="dt">
          <thead><tr><th>Hora</th><th>Conversa</th><th>Status</th><th className="num">Latência</th><th>Mensagem</th></tr></thead>
          <tbody>
            {rows.map(r => {
              const cls = r.error ? 'bad' : Number(r.latency_ms || 0) > 1500 ? 'warn' : 'ok';
              return (
                <tr key={r.id}>
                  <td data-label="Hora" className="mono">{window.fmtTime ? window.fmtTime(r.created_at) : '--'}</td>
                  <td data-label="Conversa" className="mono">{r.conversation_id || '--'}</td>
                  <td data-label="Status"><span className={`badge ${cls}`}><span className={`sw ${cls}`}/> {r.status || 'ok'}</span></td>
                  <td className="num mono" data-label="Latência">{r.latency_ms ? `${r.latency_ms} ms` : '--'}</td>
                  <td data-label="Mensagem" className="muted">{r.error || 'OK'}</td>
                </tr>
              );
            })}
            {!rows.length && <tr><td colSpan="5" className="empty">Sem run para este agente.</td></tr>}
          </tbody>
        </table>
      </div>
    </>
  );
}

function formFromAgent(agent) {
  const raw = agent.raw || {};
  const model = raw.ai_model || agent.model || 'gpt-4o-mini';
  const preset = window.WA.modelPresetForModel(model);
  return {
    name: raw.name || agent.name || '',
    public_slug: raw.public_slug || '',
    instance_name: raw.instance_token || agent.channel || '',
    description: raw.description || agent.role || '',
    ai_model: model,
    model_preset: preset?.id || 'current-model',
    ai_api_key: '',
    temperature: raw.temperature ?? 0.7,
    system_prompt: raw.system_prompt || `Você é ${agent.name}. Atenda nos canais conectados do agente em pt-BR.`,
    negative_rules: linesToEditableText(raw.negative_rules),
    conversation_goals: linesToEditableText(raw.conversation_goals),
    final_goal: raw.final_goal || '',
    handoff_enabled: raw.handoff_config?.enabled !== false,
  };
}

function lines(value) {
  return String(value || '').split('\n').map(s => s.trim()).filter(Boolean);
}

function linesToEditableText(value) {
  if (Array.isArray(value)) return value.map(lineItemToText).filter(Boolean).join('\n');
  return lineItemToText(value);
}

function lineItemToText(value) {
  if (value == null) return '';
  if (typeof value === 'string') return value;
  if (typeof value === 'number' || typeof value === 'boolean') return String(value);
  if (Array.isArray(value)) return value.map(lineItemToText).filter(Boolean).join(' - ');
  const direct = value.text || value.goal || value.rule || value.description || value.content || value.value || value.name || value.title;
  if (direct) return String(direct);
  const flat = Object.values(value).filter(item => item != null && typeof item !== 'object').map(String).filter(Boolean);
  return flat.length ? flat.join(' - ') : window.prettyStudioValue?.(value) || String(value);
}

function Field({ id, label, value, onChange, multiline, helper, required, type = 'text', placeholder, autoComplete }) {
  return (
    <label className="field-block">
      <div className={`field-label ${required ? 'fl-required' : ''}`}>{label}</div>
      {multiline
        ? <textarea id={id} className="input prose-input" style={{minHeight:80}} value={value} onChange={e => onChange(e.target.value)}/>
        : <input id={id} className="input" type={type} value={value} placeholder={placeholder || ''} autoComplete={autoComplete} spellCheck={type === 'password' ? false : undefined} onChange={e => onChange(e.target.value)}/>}
      {helper && <span className="field-helper">{helper}</span>}
    </label>
  );
}

function ModelPresetField({ value, model, onChange }) {
  const hasCurrentModel = !window.WA.modelPresetForModel(model);
  return (
    <label className="field-block">
      <div className="field-label fl-required">Qual IA usar?</div>
      <select className="input" value={hasCurrentModel ? 'current-model' : value} onChange={e => onChange(e.target.value)}>
        {hasCurrentModel && <option value="current-model">{model} - atual</option>}
        {window.WA.MODEL_PRESETS.map(preset => <option key={preset.id} value={preset.id}>{preset.label} - temp {preset.temperature}</option>)}
      </select>
      <span className="field-helper">OpenAI rápido para atendimento geral; Groq forte para fluxos com mais raciocínio. Atual: {model}</span>
    </label>
  );
}

function SiteInstallPanel({ agent, framed = true }) {
  const apiUrl = window.WA.siteAgentApiUrl(agent);
  const code = window.WA.siteAgentEmbedCode(agent);
  function copy(text, label) {
    navigator.clipboard?.writeText(text)
      .then(() => studioToast(`${label} copiado.`))
      .catch(() => studioToast('Não foi possível copiar automaticamente.', 'bad'));
  }
  const content = (
    <>
      <div className="site-install-body">
        {!framed && (
          <div>
            <div className="panel-title">API para site</div>
            <div className="muted" style={{fontSize:12, marginTop:4}}>Endpoint ?nico deste agente para embed no site.</div>
          </div>
        )}
        <label className="field-block">
          <span className="field-label">Endpoint</span>
          <div className="copy-row">
            <input className="input mono" readOnly value={apiUrl}/>
            <button className="tb-btn" onClick={() => copy(apiUrl, 'Endpoint')}>Copiar API</button>
          </div>
        </label>
        <label className="field-block">
          <span className="field-label">Snippet</span>
          <textarea className="input code-input" readOnly rows="10" value={code}/>
        </label>
      </div>
    </>
  );
  if (!framed) return content;
  return (
    <div className="panel site-install-panel">
      <div className="panel-head">
        <div>
          <div className="panel-title">API para site</div>
          <div className="muted" style={{fontSize:12}}>Use este endpoint no site oficial ou cole o snippet no arquivo da página.</div>
        </div>
        <button className="tb-btn primary" onClick={() => copy(code, 'Snippet')}>Copiar snippet</button>
      </div>
      {content}
    </div>
  );
}

function agentQrSrc(data) {
  const qr = data?.base64 || data?.qrcode || data?.qrCode || data?.code || '';
  return String(qr).startsWith('data:image') ? qr : `data:image/png;base64,${qr}`;
}

function Kpi({ label, value, sub }) {
  return (
    <div className="kpi">
      <div className="kpi-label">{label}</div>
      <div className="kpi-value">{value}</div>
      {sub && <div className="kpi-foot"><span className="muted">{sub}</span><span/></div>}
    </div>
  );
}

function ToolCard({ tool, onToggle, onEdit, onDelete }) {
  return (
    <div className="panel tool-tile">
      <div>
        <div style={{ display:'flex', alignItems:'center', gap:8, marginBottom: 4 }}>
          <span className="mono">{tool.name}</span>
          {tool.enabled ? <span className="badge ok"><span className="sw ok"/> ativo</span> : <span className="badge"><span className="sw"/> inativo</span>}
        </div>
        <div className="muted" style={{ fontSize: 12.5, marginBottom: 6 }}>{tool.description || tool.tool_type}</div>
        <div className="muted" style={{ fontSize: 11.5}}>{tool.requires_approval ? 'requer aprovação' : 'auto'}</div>
      </div>
      <div className="tool-actions">
        <button className="switch-btn" data-on={tool.enabled ? 'true' : 'false'} onClick={onToggle} aria-label="Alternar ferramenta"><span className={tool.enabled ? 'on' : ''}/></button>
        <button className="tb-btn ghost" onClick={onEdit}>Alterar</button>
        <button className="tb-btn danger" onClick={onDelete}>Excluir</button>
      </div>
    </div>
  );
}
