﻿/* global React, Icon, API */

const { useState: useExtraState, useEffect: useExtraEffect } = React;

function studioData() {
  return window.MOCK || {};
}

function refreshStudio() {
  return window.STUDIO && window.STUDIO.refresh ? window.STUDIO.refresh() : Promise.resolve();
}

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); };

function agentName(id) {
  const agent = (studioData().agents || []).find(item => String(item.id) === String(id));
  return agent ? agent.name : '--';
}

function statusTag(value) {
  if (['online', 'open', 'ok', 'finished'].includes(value)) return 'ok';
  if (['connecting', 'qr-pendente', 'in_progress', 'warn', 'pausado', 'not_found'].includes(value)) return 'warn';
  if (['unanswered', 'offline', 'expired', 'bad', 'error'].includes(value)) return 'bad';
  return '';
}

function channelStatusInfo(instanceName) {
  const inst = (studioData().instances || []).find(item => item.id === instanceName || item.name === instanceName || item.raw?.name === instanceName);
  return whatsappInstanceUiState(inst, instanceName);
}

function channelStatus(instanceName) {
  return channelStatusInfo(instanceName).status;
}

function firstAgentId() {
  return (studioData().agents || [])[0]?.id || null;
}

function assistantInitialAgentId(agents) {
  const stored = window.localStorage?.getItem('sm_assistant_focus_agent_id');
  if (stored && agents.some(agent => String(agent.id) === String(stored))) return String(stored);
  return String(agents[0]?.id || '');
}

const TESTER_FLOW_STEPS = [
  'Preparando cenários',
  'Lendo configuração',
  'Verificando materiais',
  'Enviando perguntas',
  'Analisando respostas',
  'Gerando diagnóstico',
  'Sugerindo melhorias',
];

const OPTIMIZER_FLOW_STEPS = [
  'Analisando configuração',
  'Revisando testes',
  'Verificando conhecimento',
  'Identificando falhas',
  'Gerando melhorias',
  'Comparando versões',
  'Preparando histórico',
];

function useAssistantFlow(active, labels) {
  const [current, setCurrent] = useExtraState(0);
  useExtraEffect(() => {
    if (!active) {
      setCurrent(0);
      return undefined;
    }
    setCurrent(0);
    const timer = window.setInterval(() => {
      setCurrent(prev => Math.min(prev + 1, labels.length - 1));
    }, 950);
    return () => window.clearInterval(timer);
  }, [active, labels.length]);
  return labels.map((label, index) => ({
    label,
    status: active ? (index < current ? 'done' : index === current ? 'running' : 'pending') : 'pending',
  }));
}

function flowState(labels, active, finished, runningSteps) {
  if (active) return runningSteps;
  return labels.map(label => ({ label, status: finished ? 'done' : 'pending' }));
}

function fieldNames(table) {
  const fields = table?.schema_json?.fields;
  return Array.isArray(fields) ? fields.map(f => f.name || f.id).filter(Boolean) : [];
}

async function runAction(fn) {
  try {
    await fn();
    await refreshStudio();
  } catch (err) {
    studioToast(err.message || String(err), 'bad');
  }
}

function PageTitle({ eyebrow, title, sub, meta, action }) {
  return (
    <div className="page-head">
      <div>
        <div className="page-eyebrow">{eyebrow}</div>
        <h1 className="page-title">{title}</h1>
        <p className="page-sub">{sub}</p>
      </div>
      <div className="page-meta">{action || meta}</div>
    </div>
  );
}

function MiniKpi({ 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 EmptyRow({ cols, text }) {
  return <tr><td colSpan={cols} className="empty">{text}</td></tr>;
}

function prettyPageValue(value) {
  return window.prettyStudioValue ? window.prettyStudioValue(value) : String(value == null ? '' : value);
}

function truncateText(value, max = 220) {
  const text = typeof value === 'object' && value !== null ? prettyPageValue(value) : String(value == null ? '' : value);
  return text.length > max ? text.slice(0, max - 1).trimEnd() + '...' : text;
}

function pickDisplayColumns(columns) {
  const priority = ['conversation_id', 'agent_id', 'agent_name', 'customer_phone', 'customer_name', 'event', 'summary', 'created_at'];
  const picked = priority.filter(col => columns.includes(col));
  columns.forEach(col => {
    if (picked.length < 6 && !picked.includes(col)) picked.push(col);
  });
  return picked.slice(0, 6);
}

function recordCellClass(col) {
  return /summary|transcript|metadata|message|content/i.test(col) ? 'record-long' : '';
}

const ECOSYSTEM_STEPS = [
  ['tables', 'Dados'],
  ['knowledge_bases', 'Conhecimento'],
  ['agents', 'Agentes'],
  ['squads', 'Squads'],
  ['tools', 'Ferramentas'],
  ['channels', 'Canais'],
  ['teams', 'Time humano'],
  ['tested', 'Teste'],
  ['published', 'Produção'],
];

function ecosystemRoute(id) {
  if (id === 'knowledge_bases') return 'kb';
  if (id === 'teams') return 'team';
  if (id === 'published' || id === 'tested') return 'agents';
  if (id === 'attendance') return 'team';
  return id;
}

function ecosystemStateLabel(percent) {
  if (percent >= 85) return 'Pronto para produção assistida';
  if (percent >= 55) return 'Setup em validação';
  if (percent >= 25) return 'Fundação em montagem';
  return 'Começo guiado';
}

window.EcosystemPage = function EcosystemPage({ setPage, onOpenAgent }) {
  const [status, setStatus] = useExtraState(null);
  const [loading, setLoading] = useExtraState(true);
  const [error, setError] = useExtraState('');
  const data = studioData();
  const agents = data.agents || [];
  const progress = status?.setup_progress || {};
  const readyCount = ECOSYSTEM_STEPS.filter(([id]) => !!progress[id]).length;
  const percent = Math.round((readyCount / ECOSYSTEM_STEPS.length) * 100);

  async function load() {
    setLoading(true);
    setError('');
    try {
      setStatus(await API.getEcosystemStatus());
    } catch (err) {
      setError(err.message || String(err));
      setStatus(null);
    } finally {
      setLoading(false);
    }
  }

  useExtraEffect(() => { load(); }, []);

  const recs = status?.recommendations || [];
  const stateLabel = ecosystemStateLabel(percent);
  const publishedCount = agents.filter(agent => agent.isPublished).length;
  const openTicketCount = (data.tickets || []).filter(ticket => ['unanswered', 'in_progress'].includes(ticket.rawStatus || ticket.raw?.status)).length;
  const publicConversationCount = (data.conversations || []).filter(conv => conv.channel === 'public' || conv.raw?.state?.source === 'public_test' || String(conv.number || '').startsWith('pub-')).length;

  return (
    <>
      <PageTitle
        eyebrow="Início - operação por agente"
        title="Mapa do Ecossistema"
        sub="Visão direta do estado de cada agente: canais, conhecimento, ferramentas, filas, atendimentos, testes, publicação e pendências."
        action={<div className="row-actions"><button className="tb-btn" onClick={() => setPage('agents')}>Gerenciar agentes</button><button className="tb-btn primary" onClick={load}>{loading ? 'Atualizando...' : 'Atualizar mapa'}</button></div>}
      />
      <div className="page ecosystem-page ecosystem-redesign">
        {error && <div className="assistant-error-card">Falha ao carregar mapa. Atualize novamente ou verifique o backend. <span>{error}</span></div>}
        <section className="ecosystem-overview">
          <div className="ecosystem-overview-copy">
            <span className="command-kicker">Saúde operacional</span>
            <h2>{agents.length ? stateLabel : 'Nenhum agente criado'}</h2>
            <p>{agents.length ? `${readyCount} de ${ECOSYSTEM_STEPS.length} etapas gerais estão prontas. A leitura principal agora é por agente, sem painel genérico misturado com cards antigos.` : 'Crie o primeiro bot para liberar o mapa por agente, testes internos, link público e checklist de publicação.'}</p>
            <div className="ecosystem-progress-line"><span style={{width: `${percent}%`}}></span></div>
          </div>
          <div className="ecosystem-overview-metrics">
            <div><span>Agentes</span><strong>{agents.length}</strong></div>
            <div><span>Publicados</span><strong>{publishedCount}</strong></div>
            <div><span>Filas abertas</span><strong>{openTicketCount}</strong></div>
            <div><span>Testes públicos</span><strong>{publicConversationCount}</strong></div>
          </div>
        </section>

        {!agents.length ? (
          <section className="ecosystem-empty-state">
            <div className="success-mark"><Icon name="agents" size={18}/></div>
            <strong>Crie o primeiro agente para montar o ecossistema.</strong>
            <p>Depois disso o mapa passa a mostrar canais, conhecimento, ferramentas, filas, atendimentos, testes, publicação e pendências por agente.</p>
            <div className="row-actions">
              <button className="tb-btn primary" onClick={() => setPage('agents')}><Icon name="plus" size={13}/> Criar bot de IA</button>
              <button className="tb-btn" onClick={() => setPage('assistants')}>Abrir Guia</button>
            </div>
          </section>
        ) : (
          <section className="ecosystem-agent-map">
            {agents.map(agent => {
              const agentId = String(agent.id);
              const agentConvs = (data.conversations || []).filter(conv => String(conv.agentId || conv.agent_id || conv.raw?.agent_id || '') === agentId);
              const publicConvs = agentConvs.filter(conv => conv.channel === 'public' || conv.raw?.state?.source === 'public_test' || String(conv.number || '').startsWith('pub-'));
              const agentTickets = (data.tickets || []).filter(ticket => String(ticket.raw?.agent_id || ticket.agent_id || '') === agentId);
              const openTickets = agentTickets.filter(ticket => ['unanswered', 'in_progress'].includes(ticket.rawStatus || ticket.raw?.status));
              const agentRuns = (data.runs || []).filter(run => String(run.agent_id || '') === agentId);
              const testRuns = agentRuns.filter(run => run.is_test || ['agent_test', 'sandbox', 'system_assistant_tester'].includes(run.input?.source));
              const agentKbs = (data.knowledge || []).filter(kb => String(kb.agent_id || '') === agentId);
              const agentTools = (data.tools || []).filter(tool => String(tool.agent_id || '') === agentId);
              const agentChannels = (data.channels || []).filter(channel => String(channel.agent_id || '') === agentId || channel.instance_name === agent.channel || channel.instance_name === agent.raw?.instance_token);
              const agentRecs = recs.filter(item => String(item.agent_id || '') === agentId);
              const channelState = agent.statusTag || statusTag(agent.status);
              const pendingItems = [
                !(agent.kbSources || agentKbs.length) && 'Adicionar conhecimento',
                !agentTools.length && 'Ativar ferramentas',
                !agentChannels.length && 'Vincular canal',
                !testRuns.length && 'Rodar teste',
                !agent.isPublished && 'Publicar quando pronto',
                ...agentRecs.map(item => item.message),
              ].filter(Boolean).slice(0, 4);
              return (
                <article key={agent.id} className="ecosystem-agent-board">
                  <div className="eco-board-head">
                    <div className="eco-agent-head">
                      <div className="av av-mark lg" style={{background: `hsl(${(agent.id * 47) % 360}, 55%, 45%)`}}>{(agent.name || '?')[0].toUpperCase()}</div>
                      <div className="eco-agent-info"><strong>{agent.name}</strong><span>{agent.model || 'modelo não informado'}</span></div>
                    </div>
                    <div className="row-actions">
                      <button className="tb-btn" onClick={() => onOpenAgent ? onOpenAgent(agent.id, 'setup') : setPage('agents')}>Setup</button>
                      <button className="tb-btn" onClick={() => onOpenAgent ? onOpenAgent(agent.id, 'test') : setPage('agents')}>Teste</button>
                      <button className={`tb-btn ${agent.isPublished ? '' : 'primary'}`} onClick={() => onOpenAgent ? onOpenAgent(agent.id, agent.isPublished ? 'conversations' : 'setup') : setPage('agents')}>{agent.isPublished ? 'Atendimentos' : 'Publicar'}</button>
                    </div>
                  </div>
                  <div className="eco-health-grid">
                    <div><span>Status</span><strong>{agent.setupLabel || 'Rascunho'}</strong></div>
                    <div><span>Canais</span><strong className={channelState}>{agentChannels.length || (agent.channel && agent.channel !== '--' ? 1 : 0)} · {agent.statusLabel || 'sem conexão'}</strong></div>
                    <div><span>Conhecimento</span><strong>{agent.kbSources || agentKbs.length} base(s)</strong></div>
                    <div><span>Ferramentas</span><strong>{agent.tools || agentTools.length} ativa(s)</strong></div>
                    <div><span>Filas</span><strong>{openTickets.length} abertas</strong></div>
                    <div><span>Atendimentos</span><strong>{agentConvs.length} threads</strong></div>
                    <div><span>Testes</span><strong>{testRuns.length} internos · {publicConvs.length} públicos</strong></div>
                    <div><span>Publicação</span><strong className={agent.isPublished ? 'ok' : 'warn'}>{agent.isPublished ? 'Publicado' : 'Rascunho'}</strong></div>
                  </div>
                  <div className="eco-board-lanes">
                    <div>
                      <span className="rt-label">Canais</span>
                      {agentChannels.length ? agentChannels.slice(0, 3).map(channel => <button key={channel.id || channel.instance_name} className="eco-mini-row" onClick={() => setPage('channels')}><strong>{channel.name || channel.instance_name || 'Canal'}</strong><em>{channel.agent_name || agent.name}</em></button>) : <button className="eco-mini-row muted-row" onClick={() => onOpenAgent ? onOpenAgent(agent.id, 'connections') : setPage('channels')}>Vincular WhatsApp ou site</button>}
                    </div>
                    <div>
                      <span className="rt-label">Pendências</span>
                      {pendingItems.length ? pendingItems.map((item, idx) => <button key={idx} className="eco-mini-row warn-row" onClick={() => onOpenAgent ? onOpenAgent(agent.id, 'setup') : setPage('agents')}>{item}</button>) : <div className="eco-mini-row ok-row">Sem pendências críticas</div>}
                    </div>
                  </div>
                </article>
              );
            })}
          </section>
        )}

        <section className="ecosystem-recommendations">
          <div className="panel-head"><div><div className="panel-title">Recomendações do sistema</div><div className="panel-subtitle">Priorizadas a partir das configurações atuais.</div></div></div>
          <div className="recommendation-list">
            {recs.map((item, idx) => (
              <button key={`${item.module}-${idx}`} className={`recommendation-row ${item.type || ''}`} onClick={() => setPage(ecosystemRoute(item.action || item.module || 'dashboard'))}>
                <span className="recommendation-number">{String(idx + 1).padStart(2, '0')}</span>
                <strong>{item.type === 'success' ? 'Pronto' : item.type === 'warning' ? 'Atenção' : 'Sugestão'}</strong>
                <p>{item.message}</p>
                <em>Abrir</em>
              </button>
            ))}
            {!recs.length && <div className="empty-cta"><strong>Nenhuma recomendação pendente.</strong><span>Continue monitorando conversas e testes antes de escalar o uso.</span></div>}
          </div>
        </section>
      </div>
    </>
  );
};

const PATCH_LABELS = {
  description: 'Descrição',
  system_prompt: 'Prompt do agente',
  negative_rules: 'Regras negativas',
  conversation_goals: 'Objetivos da conversa',
  final_goal: 'Objetivo final',
  handoff_config: 'Repasse humano',
};

function patchPreview(value) {
  if (Array.isArray(value)) return value.map(item => typeof item === 'string' ? item : prettyPageValue(item)).join('\n');
  if (value && typeof value === 'object') return prettyPageValue(value);
  return String(value || '');
}

function currentPatchPreview(value) {
  if (value == null || value === '') return '(vazio)';
  if (typeof value === 'string') return value;
  return prettyPageValue(value);
}

function assistantFriendlyError(err) {
  const raw = String(err?.message || err || '');
  if (/list.*mapping|object is not a mapping/i.test(raw)) return 'O Otimizador recebeu uma resposta em formato inesperado. Gere a prévia novamente; o sistema agora normaliza esse retorno antes de aplicar.';
  if (/internal server error/i.test(raw)) return 'O assistente encontrou uma falha interna. Corrija o diagnóstico do agente e tente novamente.';
  if (/timeout|timed out/i.test(raw)) return 'O modelo demorou para responder. Tente novamente em alguns instantes.';
  if (/api|key|chave|unauthorized|401/i.test(raw)) return 'A chave do modelo não respondeu corretamente. Verifique as credenciais dos assistentes.';
  return raw || 'Não foi possível concluir a ação agora.';
}

function testerMessageText(message) {
  if (message == null || message === '') return '';
  if (typeof message === 'string') return message;
  if (typeof message.content === 'string') return message.content;
  if (typeof message.message === 'string') return message.message;
  if (typeof message.text === 'string') return message.text;
  return prettyPageValue(message);
}

function testerScenarioMessages(item) {
  const scenario = item?.scenario || {};
  const input = item?.input || {};
  const candidates = [
    scenario.messages,
    item?.messages,
    input.messages,
    scenario.message,
    scenario.input,
    input.message,
    item?.message,
    item?.prompt,
  ];
  const raw = candidates.find(value => Array.isArray(value) ? value.length : value);
  const list = Array.isArray(raw) ? raw : [raw];
  return list.map(testerMessageText).filter(Boolean);
}

function asList(value) {
  if (Array.isArray(value)) return value.filter(item => item !== null && item !== undefined && item !== '');
  if (value === null || value === undefined || value === '') return [];
  if (typeof value === 'object') {
    const itemKeys = ['problem', 'finding', 'summary', 'recommendation', 'reason', 'name', 'passed', 'scenario', 'status', 'evidence', 'message', 'value'];
    if (itemKeys.some(key => Object.prototype.hasOwnProperty.call(value, key))) return [value];
    return Object.entries(value)
      .filter(([, item]) => item !== null && item !== undefined && item !== '')
      .map(([key, item]) => {
        if (item && typeof item === 'object' && !Array.isArray(item)) return { name: key, ...item };
        return { name: key, value: item };
      });
  }
  return [value];
}

function reportItemText(item) {
  if (item === null || item === undefined || item === '') return '';
  if (typeof item === 'boolean') return item ? 'Confirmado.' : '';
  if (typeof item === 'string' || typeof item === 'number') return String(item);
  if (typeof item !== 'object') return String(item);
  if (Object.prototype.hasOwnProperty.call(item, 'value') && item.name) return `${item.name}: ${testerMessageText(item.value)}`;
  const label = item.problem || item.finding || item.summary || item.recommendation || item.reason || item.name || item.status || item.evidence || item.message;
  const context = item.scenario || item.category || item.severity;
  if (context && label && context !== label) return `${context}: ${label}`;
  if (label) return String(label);
  const fields = ['what', 'impact', 'expected_behavior', 'tester_message', 'agent_reply_summary', 'rating']
    .map(key => item[key] ? `${key.replace(/_/g, ' ')}: ${testerMessageText(item[key])}` : '')
    .filter(Boolean);
  return fields.join('\n');
}

function issueText(item) {
  if (!item || typeof item !== 'object') return reportItemText(item);
  const severity = item.severity || item.priority || 'médio';
  const problem = item.problem || item.finding || item.message || item.evidence || 'problema identificado';
  const scenario = item.scenario ? `${item.scenario}: ` : '';
  return `${severity} - ${scenario}${problem}`;
}

function scenarioEvaluationText(item) {
  if (!item || typeof item !== 'object') return reportItemText(item);
  const lines = [
    `${item.scenario || item.name || 'Cenário'}: ${item.finding || item.problem || item.status || item.evidence || 'avaliado'}`,
  ];
  if (item.tester_message) lines.push(`Pergunta: ${item.tester_message}`);
  if (item.agent_reply_summary) lines.push(`Resposta: ${item.agent_reply_summary}`);
  if (item.rating) lines.push(`Avaliação: ${item.rating}`);
  if (item.expected_behavior) lines.push(`Esperado: ${item.expected_behavior}`);
  return lines.join('\n');
}

function scoreValue(value) {
  const parsed = Number.parseFloat(String(value ?? 0).replace('%', ''));
  if (!Number.isFinite(parsed)) return 0;
  return Math.max(0, Math.min(100, Math.round(parsed)));
}

function criterionInfo(item) {
  if (!item || typeof item !== 'object') return { label: reportItemText(item), passed: null };
  const explicitPassed = Object.prototype.hasOwnProperty.call(item, 'passed') ? item.passed : item.value;
  return {
    label: item.name || item.label || item.criterion || reportItemText(item),
    passed: explicitPassed === false || item.status === 'failed' || item.ok === false ? false : true,
  };
}

function cleanReportText(value) {
  const text = String(value || '').trim();
  if (!text) return '';
  if (/^(true|false|null|undefined|\[object object\])$/i.test(text)) return '';
  return text;
}

function reportItems(items, emptyFallback) {
  const list = asList(items).map(reportItemText).map(cleanReportText).filter(Boolean);
  return list.length ? list : emptyFallback ? [emptyFallback] : [];
}

function preserveReportItems(items) {
  return asList(items)
    .map(item => typeof item === 'boolean' ? '' : reportItemText(item))
    .map(cleanReportText)
    .filter(Boolean);
}

function recommendationPriority(text, tone) {
  const value = String(text || '').toLowerCase();
  if (tone === 'positive' || tone === 'preserve') return '';
  if (/(timeout|sil[eê]ncio|falha|cr[ií]tico|risco|n[aã]o respondeu|ausente|kb|base de conhecimento|invent)/.test(value)) return 'Alta';
  if (/(implementar|adicionar|corrigir|validar|reduzir|refinar|ajustar|treinar)/.test(value)) return 'Média';
  return tone === 'next' ? 'Baixa' : '';
}

function reportPriorityClass(priority) {
  if (priority === 'Alta' || priority === 'Crítico') return 'high';
  if (priority === 'Média') return 'medium';
  if (priority === 'Baixa') return 'low';
  return 'neutral';
}

function reportToneIcon(tone) {
  if (tone === 'positive' || tone === 'preserve') return 'check';
  if (tone === 'risk') return 'x';
  if (tone === 'next') return 'arrow';
  if (tone === 'knowledge') return 'kb';
  if (tone === 'recommendation') return 'tools';
  return 'logs';
}

function reportItemParts(text, tone) {
  let clean = String(text || '').replace(/\r\n/g, '\n').trim();
  let priority = '';
  const prefix = clean.match(/^(cr[ií]tico|alta|m[eé]dia|media|m[eé]dio|medio|baixa)\s*[-:]\s*/i);
  if (prefix) {
    priority = /cr/i.test(prefix[1]) ? 'Crítico' : /alt/i.test(prefix[1]) ? 'Alta' : /m[eé]dia|media|m[eé]dio|medio/i.test(prefix[1]) ? 'Média' : 'Baixa';
    clean = clean.slice(prefix[0].length).trim();
  }
  const suffix = clean.match(/\s+[-–—:]?\s*(cr[ií]tico|alta|m[eé]dia|media|m[eé]dio|medio|baixa)$/i);
  if (suffix && clean.length > suffix[0].length + 12) {
    priority = priority || (/cr/i.test(suffix[1]) ? 'Crítico' : /alt/i.test(suffix[1]) ? 'Alta' : /m[eé]dia|media|m[eé]dio|medio/i.test(suffix[1]) ? 'Média' : 'Baixa');
    clean = clean.slice(0, clean.length - suffix[0].length).trim();
  }
  priority = priority || recommendationPriority(clean, tone);
  const lines = clean.split('\n').map(line => line.trim()).filter(Boolean);
  let title = lines.shift() || clean || 'Item';
  const body = [];
  const colon = title.indexOf(':');
  if (colon > 0 && colon < 42) {
    const before = title.slice(0, colon).trim();
    const after = title.slice(colon + 1).trim();
    title = before;
    if (after) body.push(after);
  }
  body.push(...lines);
  return { title, body, priority };
}

function scoreBand(score) {
  if (score >= 85) return { label: 'Excelente', tone: 'positive', readiness: 'Pronto para uso assistido' };
  if (score >= 70) return { label: 'Bom', tone: 'positive', readiness: 'Pronto com pequenos ajustes' };
  if (score >= 50) return { label: 'Precisa de ajustes', tone: 'warn', readiness: 'Revisão recomendada' };
  return { label: 'Crítico', tone: 'risk', readiness: 'Não publicar sem correção' };
}

function testerHistoryStatusClass(status) {
  const value = String(status || '').toLowerCase();
  if (['completed', 'done', 'ok'].includes(value)) return 'ok';
  if (['started', 'running', 'pending'].includes(value)) return 'warn';
  if (['failed', 'error'].includes(value)) return 'bad';
  return '';
}

function testerHistoryDate(value) {
  return window.fmtDate ? window.fmtDate(value) : (value || '--');
}

function testerHistoryScore(item) {
  const score = scoreValue(item?.score);
  return item?.score == null ? '--' : `${score}%`;
}

function testerHistoryMessages(detail) {
  const direct = Array.isArray(detail?.messages) ? detail.messages : [];
  if (direct.length) return direct;
  return asList(detail?.output?.transcripts).flatMap((item, idx) => {
    const scenario = item?.scenario || {};
    const label = scenario.name || `Cenário ${idx + 1}`;
    return [
      scenario.message && { role: 'user', content: scenario.message, scenario: label, latency_ms: item.latency_ms },
      item.reply && { role: 'assistant', content: item.reply, scenario: label, latency_ms: item.latency_ms },
      item.error && { role: 'system', content: item.error, scenario: label, latency_ms: item.latency_ms },
    ].filter(Boolean);
  });
}

window.SystemAssistantsPage = function SystemAssistantsPage({ onOpenAgent, setPage }) {
  const data = studioData();
  const agents = data.agents || [];
  const [tab, setTab] = useExtraState('tester');
  const [agentId, setAgentId] = useExtraState(() => assistantInitialAgentId(agents));
  const [testerMode, setTesterMode] = useExtraState('quick');
  const [testerObjective, setTesterObjective] = useExtraState('');
  const [testerLoading, setTesterLoading] = useExtraState(false);
  const [testerReport, setTesterReport] = useExtraState(null);
  const [optimizerLoading, setOptimizerLoading] = useExtraState(false);
  const [optimizerPreview, setOptimizerPreview] = useExtraState(null);
  const [selectedSections, setSelectedSections] = useExtraState({});
  const [agentVersions, setAgentVersions] = useExtraState([]);
  const [assistantError, setAssistantError] = useExtraState('');
  const [testerHistory, setTesterHistory] = useExtraState({ items: [], total: 0, limit: 6, offset: 0 });
  const [testerHistoryLimit, setTesterHistoryLimit] = useExtraState(6);
  const [testerHistoryLoading, setTesterHistoryLoading] = useExtraState(false);
  const [testerHistoryOpen, setTesterHistoryOpen] = useExtraState(true);
  const [testerHistoryDetail, setTesterHistoryDetail] = useExtraState(null);
  const [testerHistoryDetailLoading, setTesterHistoryDetailLoading] = useExtraState(false);
  const selectedAgent = agents.find(agent => String(agent.id) === String(agentId));
  const testerFlowRunning = useAssistantFlow(testerLoading, TESTER_FLOW_STEPS);
  const optimizerFlowRunning = useAssistantFlow(optimizerLoading, OPTIMIZER_FLOW_STEPS);
  const testerFlowSteps = flowState(TESTER_FLOW_STEPS, testerLoading, !!testerReport, testerFlowRunning);
  const optimizerFlowSteps = flowState(OPTIMIZER_FLOW_STEPS, optimizerLoading, !!optimizerPreview, optimizerFlowRunning);

  useExtraEffect(() => {
    if (!agentId && agents[0]?.id) setAgentId(assistantInitialAgentId(agents));
  }, [agents.length]);

  useExtraEffect(() => {
    if (agentId) window.localStorage?.setItem('sm_assistant_focus_agent_id', String(agentId));
  }, [agentId]);

  useExtraEffect(() => {
    if (!agentId) {
      setAgentVersions([]);
      return undefined;
    }
    let alive = true;
    API.getAgentVersions(Number(agentId))
      .then(rows => { if (alive) setAgentVersions(rows || []); })
      .catch(() => { if (alive) setAgentVersions([]); });
    return () => { alive = false; };
  }, [agentId]);

  async function loadTesterHistory(limit = testerHistoryLimit) {
    if (!agentId) {
      setTesterHistory({ items: [], total: 0, limit, offset: 0 });
      return { items: [], total: 0, limit, offset: 0 };
    }
    setTesterHistoryLoading(true);
    try {
      const data = await API.getSystemTesterHistory({ agent_id: Number(agentId), limit, offset: 0 });
      setTesterHistory(data || { items: [], total: 0, limit, offset: 0 });
      return data;
    } catch (err) {
      setTesterHistory({ items: [], total: 0, limit, offset: 0 });
      return null;
    } finally {
      setTesterHistoryLoading(false);
    }
  }

  useExtraEffect(() => {
    let alive = true;
    if (!agentId || tab !== 'tester') return undefined;
    setTesterHistoryLoading(true);
    API.getSystemTesterHistory({ agent_id: Number(agentId), limit: testerHistoryLimit, offset: 0 })
      .then(data => { if (alive) setTesterHistory(data || { items: [], total: 0, limit: testerHistoryLimit, offset: 0 }); })
      .catch(() => { if (alive) setTesterHistory({ items: [], total: 0, limit: testerHistoryLimit, offset: 0 }); })
      .finally(() => { if (alive) setTesterHistoryLoading(false); });
    return () => { alive = false; };
  }, [agentId, tab, testerHistoryLimit]);

  async function refreshVersions() {
    if (!agentId) return [];
    const rows = await API.getAgentVersions(Number(agentId));
    setAgentVersions(rows || []);
    return rows || [];
  }

  async function openTesterHistoryDetail(item) {
    if (!item?.id) return;
    setTesterHistoryDetailLoading(true);
    try {
      const detail = await API.getSystemTesterHistoryDetail(item.id);
      setTesterHistoryDetail(detail);
    } catch (err) {
      studioToast(err.message || String(err), 'bad');
    } finally {
      setTesterHistoryDetailLoading(false);
    }
  }

  function loadMoreTesterHistory() {
    setTesterHistoryLimit(value => Math.min(value + 6, 48));
  }

  async function runTester() {
    if (!agentId) return studioToast('Selecione um agente para testar.', 'bad');
    setTesterLoading(true);
    setTesterReport(null);
    setAssistantError('');
    try {
      const res = await API.runSystemTester({ agent_id: Number(agentId), mode: testerMode, objective: testerObjective });
      setTesterReport(res);
      setTesterHistoryLimit(6);
      loadTesterHistory(6).catch(() => {});
      studioToast('Teste interno concluído.');
    } catch (err) {
      const friendly = assistantFriendlyError(err);
      setAssistantError(friendly);
      studioToast(friendly, 'bad');
    } finally {
      setTesterLoading(false);
    }
  }

  async function previewOptimizer(report = testerReport) {
    if (!agentId) return studioToast('Selecione um agente para otimizar.', 'bad');
    setOptimizerLoading(true);
    setOptimizerPreview(null);
    setAssistantError('');
    try {
      const res = await API.previewSystemOptimizer({ agent_id: Number(agentId), tester_report: report || null });
      const sections = {};
      Object.keys(res.patch || {}).forEach(key => { sections[key] = true; });
      setSelectedSections(sections);
      setOptimizerPreview(res);
      setAgentVersions(res.versions || agentVersions);
      setTab('optimizer');
      studioToast('Prévia de melhoria gerada.');
    } catch (err) {
      const friendly = assistantFriendlyError(err);
      setAssistantError(friendly);
      studioToast(friendly, 'bad');
    } finally {
      setOptimizerLoading(false);
    }
  }

  async function applyOptimizer() {
    if (!optimizerPreview?.patch) return;
    const sections = Object.keys(selectedSections).filter(key => selectedSections[key]);
    if (!sections.length) return studioToast('Selecione ao menos uma seção para aplicar.', 'bad');
    const ok = await studioConfirm({
      title: 'Aplicar melhorias no agente?',
      message: 'As seções selecionadas serão salvas no agente. Se ele estiver publicado, revise o comportamento antes de novos atendimentos reais.',
      confirmLabel: 'Aplicar melhorias',
      danger: false,
    });
    if (!ok) return;
    try {
      const res = await API.applySystemOptimizer({ agent_id: Number(agentId), patch: optimizerPreview.patch, sections });
      await refreshStudio();
      setAgentVersions(res.versions || await refreshVersions());
      studioToast(`Melhorias aplicadas: ${(res.applied || []).length}`);
      if (onOpenAgent) onOpenAgent(Number(agentId), 'instructions');
    } catch (err) {
      const friendly = assistantFriendlyError(err);
      setAssistantError(friendly);
      studioToast(friendly, 'bad');
    }
  }

  async function restoreVersion(version) {
    if (!version?.id || !agentId) return;
    const ok = await studioConfirm({
      title: 'Restaurar versão do agente?',
      message: `Restaurar a versão "${version.label || version.id}"? O estado atual será salvo antes da restauração.`,
      confirmLabel: 'Restaurar',
      danger: false,
    });
    if (!ok) return;
    try {
      const res = await API.restoreAgentVersion(Number(agentId), version.id);
      await refreshStudio();
      await refreshVersions();
      studioToast(`Versão restaurada: ${(res.restored || []).length} seção(ões).`);
      if (onOpenAgent) onOpenAgent(Number(agentId), 'instructions');
    } catch (err) {
      const friendly = assistantFriendlyError(err);
      setAssistantError(friendly);
      studioToast(friendly, 'bad');
    }
  }

  const patchEntries = Object.entries(optimizerPreview?.patch || {});
  const testerScore = scoreValue(testerReport?.score);
  const assistantCards = [
    { id: 'tester', label: 'Testador de Agente', status: testerLoading ? 'testando' : testerReport ? `${testerScore}% no último teste` : 'pronto', detail: 'Executa cenários automáticos contra o agente selecionado.' },
    { id: 'optimizer', label: 'Otimizador de Agente', status: optimizerLoading ? 'gerando' : optimizerPreview ? 'prévia gerada' : 'aguardando', detail: 'Propõe melhorias revisáveis antes de salvar.' },
  ];
  const testerBand = scoreBand(testerScore);
  const testerReportSections = testerReport ? [
    { key: 'strengths', title: 'Forças', icon: 'check', tone: 'positive', items: testerReport.strengths, empty: 'Nenhuma força específica registrada.' },
    { key: 'issues', title: 'Problemas', icon: 'x', tone: 'risk', items: asList(testerReport.issues).map(issueText), empty: 'Nenhum problema crítico registrado.' },
    { key: 'improvements', title: 'Melhorias', icon: 'arrow', tone: 'improvement', items: testerReport.improvements, empty: 'Nenhuma melhoria objetiva registrada.' },
    { key: 'next_tests', title: 'Próximos testes', icon: 'refresh', tone: 'next', items: testerReport.next_tests, empty: 'Nenhum próximo teste sugerido.' },
    { key: 'kb', title: 'Uso da KB', icon: 'kb', tone: 'knowledge', items: testerReport.kb_findings, empty: 'A base de conhecimento não trouxe achados específicos neste teste.' },
    { key: 'tone', title: 'Tom e escopo', icon: 'assistants', tone: 'neutral', items: testerReport.tone_findings, empty: 'Nenhuma observação específica sobre tom e escopo.' },
    { key: 'scenarios', title: 'Avaliação por cenário', icon: 'logs', tone: 'scenario', items: asList(testerReport.scenario_evaluations).map(scenarioEvaluationText), empty: 'Nenhuma avaliação por cenário registrada.' },
    { key: 'preserve', title: 'O que preservar', icon: 'check', tone: 'preserve', items: preserveReportItems(testerReport.preserve), empty: 'Nenhum ponto específico informado para preservação.' },
    { key: 'optimizer', title: 'Recomendações para o Otimizador', icon: 'tools', tone: 'recommendation', items: testerReport.optimizer_recommendations, empty: 'Nenhuma recomendação específica para o Otimizador.' },
  ] : [];

  return (
    <>
      <PageTitle
        eyebrow="Início - assistentes internos"
        title="Assistentes do Sistema"
        sub="Central para orientação, auditoria de agentes e melhoria segura com revisão humana."
        action={<div className="row-actions"><button className="tb-btn" onClick={() => setPage('ecosystem')}>Abrir mapa</button><button className="tb-btn primary" onClick={() => setTab('tester')}>Testar agente</button></div>}
      />
      <div className="page assistants-page assistants-redesign">
        {assistantError && <div className="assistant-error-card">{assistantError}<span>Se persistir, rode o teste automático ou confira as credenciais do modelo.</span></div>}
        <section className="assistant-command-center">
          <div className="assistant-command-copy">
            <span>Operação assistida</span>
            <h2>Dois assistentes internos, um fluxo de melhoria.</h2>
            <p>Use o Testador para auditar um agente real e o Otimizador para aplicar somente ajustes revisados. O Guia do Sistema está disponível na barra superior.</p>
          </div>
        </section>

        <div className="assistant-switchboard">
          {assistantCards.map(card => (
            <button key={card.id} className={`assistant-switch-card ${tab === card.id ? 'active' : ''}`} onClick={() => setTab(card.id)}>
              <span className="assistant-switch-index">{card.id === 'tester' ? '01' : '02'}</span>
              <strong>{card.label}</strong>
              <em>{card.status}</em>
              <p>{card.detail}</p>
            </button>
          ))}
        </div>

        {tab === 'tester' && (
          <div className="assistant-stage tester-stage">
            <div className="assistant-flow-strip">
              <StepIndicator steps={testerFlowSteps}/>
            </div>
            <div className="assistant-left-stack">
              <div className="assistant-control assistant-feature-panel">
                <div className="panel-title">Testador de Agente</div>
                <div className="panel-subtitle">Roda cenários internos, avalia respostas, ferramentas, KBs e pontos de melhoria.</div>
                <label className="field-block">
                  <span className="field-label fl-required">Agente</span>
                  <select className="input" value={agentId} onChange={e => setAgentId(e.target.value)}>
                    <option value="">Selecione</option>
                    {agents.map(agent => <option key={agent.id} value={agent.id}>{agent.name}</option>)}
                  </select>
                </label>
                <label className="field-block">
                  <span className="field-label">Modo</span>
                  <select className="input" value={testerMode} onChange={e => setTesterMode(e.target.value)}>
                    <option value="quick">Rápido</option>
                    <option value="deep">Profundo</option>
                  </select>
                </label>
                <label className="field-block">
                  <span className="field-label">Objetivo do teste</span>
                  <textarea className="input prose-input" rows="3" value={testerObjective} onChange={e => setTesterObjective(e.target.value)} placeholder="Opcional. Ex: testar se ele usa a KB e encaminhar para humano quando necessário."/>
                </label>
                <button className="tb-btn primary" onClick={runTester} disabled={testerLoading || !agentId}>{testerLoading ? 'Testando...' : 'Rodar teste'}</button>
                {selectedAgent && <button className="tb-btn" onClick={() => onOpenAgent && onOpenAgent(Number(agentId), 'test')}>Abrir aba Teste do perfil</button>}
              </div>
              <TesterHistoryModule
                history={testerHistory}
                loading={testerHistoryLoading}
                open={testerHistoryOpen}
                onToggle={() => setTesterHistoryOpen(value => !value)}
                onOpenDetail={openTesterHistoryDetail}
                onRefresh={() => loadTesterHistory().catch(() => {})}
                onLoadMore={loadMoreTesterHistory}
                detailLoading={testerHistoryDetailLoading}
              />
            </div>
            <div className="assistant-report assistant-feature-panel">
              {testerLoading ? (
                <div className="assistant-live-run">
                  <LiveStatus statuses={['Preparando cenários de teste...', 'Lendo configuração do agente...', 'Verificando materiais disponíveis...', 'Enviando perguntas simuladas...', 'Analisando respostas recebidas...', 'Gerando diagnóstico seguro...']} label="Auditoria em andamento"/>
                  <StepIndicator steps={testerFlowSteps} vertical/>
                </div>
              ) : !testerReport ? (
                <EmptyState icon="logs" title="Nenhuma auditoria rodada" description="Selecione um agente e execute o Testador para receber score, evidências e próximos testes."/>
              ) : (
                <>
                  <div className={`tester-score-header report-hero ${testerBand.tone}`}>
                    <ScoreRing value={testerScore} size={72}/>
                    <div>
                      <div className="panel-title">Diagnóstico de {selectedAgent?.name || 'agente'}</div>
                      <div className="muted">{testerReport.summary}</div>
                      {testerReport.score_0_10 !== undefined && <div className="muted">Nota final: {testerReport.score_0_10}/10</div>}
                      <span className={`pill ${testerScore >= 75 ? 'pill-ok' : testerScore >= 50 ? 'pill-warn' : 'pill-bad'}`}>{testerReport.quality_label || testerBand.label}</span>
                    </div>
                    <button className="tb-btn primary" onClick={() => previewOptimizer(testerReport)}>Enviar para otimização</button>
                  </div>

                  <div className="report-overview-grid">
                    <div className={`report-metric ${testerBand.tone}`}>
                      <span>Prontidão</span>
                      <strong>{testerBand.readiness}</strong>
                      <em>{testerBand.label}</em>
                    </div>
                    <div className="report-metric risk">
                      <span>Alertas</span>
                      <strong>{asList(testerReport.issues).length}</strong>
                      <em>problemas encontrados</em>
                    </div>
                    <div className="report-metric improvement">
                      <span>Melhorias</span>
                      <strong>{asList(testerReport.improvements).length}</strong>
                      <em>ações recomendadas</em>
                    </div>
                    <div className="report-metric scenario">
                      <span>Cenários</span>
                      <strong>{asList(testerReport.scenario_evaluations).length || asList(testerReport.transcripts).length}</strong>
                      <em>rodadas avaliadas</em>
                    </div>
                  </div>

                  {asList(testerReport.transcripts).length > 0 && (
                    <div className="tester-conversation">
                      <div className="rt-label">Conversa simulada</div>
                      {asList(testerReport.transcripts).map((item, idx) => (
                        <div className="tester-round" key={idx}>
                          <div className="tester-round-header">
                            <span className="tester-round-label">Rodada {idx + 1}</span>
                            <span className="tester-round-name">{item?.scenario?.name || `Cenário ${idx + 1}`}</span>
                            <span className={`pill pill-sm ${item?.status === 'ok' || item?.status === 'passed' || item?.status === 'completed' ? 'pill-ok' : item?.status === 'error' || item?.status === 'failed' ? 'pill-bad' : 'pill-warn'}`}>{item?.status || 'avaliado'}</span>
                          </div>
                          <div className="tester-round-context">
                            <div>
                              <span>O testador enviou</span>
                              {(testerScenarioMessages(item).length ? testerScenarioMessages(item) : ['Mensagem enviada não registrada neste relatório.']).map((msg, mi) => (
                                <ChatBubble key={`t-${idx}-${mi}`} role="tester" text={msg} avatar="T"/>
                              ))}
                            </div>
                            {item?.scenario?.expectation && (
                              <div className="tester-expectation">
                                <span>Critério esperado</span>
                                <p>{item.scenario.expectation}</p>
                              </div>
                            )}
                          </div>
                          <div className="tester-agent-response">
                            <span>O agente respondeu</span>
                            <ChatBubble role="agent" text={item?.reply || item?.error || reportItemText(item) || 'Sem resposta.'} avatar={<Icon name="agents" size={13}/>}/>
                          </div>
                        </div>
                      ))}
                    </div>
                  )}

                  <div className="tester-criteria report-criteria-strip">
                    {asList(testerReport.criteria).map((c, i) => {
                      const info = criterionInfo(c);
                      return <span key={i} className={`pill ${info.passed === null ? 'pill-muted' : info.passed ? 'pill-ok' : 'pill-warn'}`}>{info.label}</span>;
                    })}
                    {!asList(testerReport.criteria).length && ['KB', 'Ferramentas', 'Tom', 'Handoff'].map(c => (
                      <span key={c} className="pill pill-muted">{c}</span>
                    ))}
                  </div>

                  <div className="assistant-report-grid report-dashboard-grid">
                    {testerReportSections.map(section => (
                      <ReportList
                        key={section.key}
                        title={section.title}
                        items={section.items}
                        icon={section.icon}
                        tone={section.tone}
                        empty={section.empty}
                      />
                    ))}
                  </div>
                </>
              )}
            </div>
          </div>
        )}

        {tab === 'optimizer' && (
          <div className="assistant-stage optimizer-stage">
            <div className="optimizer-steps-bar">
              <StepIndicator steps={optimizerFlowSteps}/>
            </div>
            <div className="assistant-control assistant-feature-panel">
              <div className="panel-title">Otimizador de Agente</div>
              <div className="panel-subtitle">Gera uma proposta de melhoria e só aplica o que você selecionar.</div>
              <label className="field-block">
                <span className="field-label fl-required">Agente</span>
                <select className="input" value={agentId} onChange={e => setAgentId(e.target.value)}>
                  <option value="">Selecione</option>
                  {agents.map(agent => <option key={agent.id} value={agent.id}>{agent.name}</option>)}
                </select>
              </label>
              <button className="tb-btn primary" onClick={() => previewOptimizer(testerReport)} disabled={optimizerLoading || !agentId}>{optimizerLoading ? 'Gerando...' : 'Gerar melhoria'}</button>
              {testerReport && <div className="help-card">Usando o diagnóstico mais recente do Testador como contexto.</div>}
            </div>
            <div className="assistant-report assistant-feature-panel">
              {optimizerLoading ? (
                <div className="assistant-live-run">
                  <LiveStatus statuses={['Analisando configuração atual...', 'Revisando resultados dos testes...', 'Verificando conhecimento vinculado...', 'Identificando falhas principais...', 'Gerando melhorias revisáveis...', 'Comparando versões...', 'Preparando alteração reversível...']} label="Otimização em andamento"/>
                  <StepIndicator steps={optimizerFlowSteps} vertical/>
                </div>
              ) : !optimizerPreview ? (
                <EmptyState icon="tools" title="Prévia ainda não gerada" description="O Otimizador nunca salva sozinho. Gere uma proposta, revise os blocos e aplique só o que fizer sentido."/>
              ) : (
                <>
                  <div className="report-head optimizer-preview-head">
                    <div>
                      <div className="panel-title">Prévia de melhoria</div>
                      <div className="muted">{optimizerPreview.summary}</div>
                      <span className="pill pill-ok">reversível</span>
                    </div>
                    <div className="optimizer-preview-actions">
                      <span className="pill pill-muted">{patchEntries.filter(([key]) => selectedSections[key]).length} selecionada{patchEntries.filter(([key]) => selectedSections[key]).length === 1 ? '' : 's'}</span>
                      <button className="tb-btn" onClick={() => { setOptimizerPreview(null); setSelectedSections({}); studioToast('Prévia rejeitada.'); }}>Rejeitar prévia</button>
                      <button className="tb-btn primary" onClick={applyOptimizer}>Aplicar selecionadas</button>
                    </div>
                  </div>
                  {optimizerPreview.warning && <div className="toast bad">Aviso: {optimizerPreview.warning}</div>}
                  <ReportList title="Resumo das mudanças" items={optimizerPreview.change_summary}/>
                  <div className="optimizer-patches">
                    {patchEntries.map(([key, value]) => {
                      const current = selectedAgent?.raw?.[key];
                      const reason = optimizerPreview.patch_reasons?.[key];
                      return (
                        <label className="patch-card optimizer-patch-card" key={key}>
                          <input type="checkbox" checked={!!selectedSections[key]} onChange={e => setSelectedSections(prev => ({ ...prev, [key]: e.target.checked }))}/>
                          <div className="optimizer-patch-body">
                            <div className="optimizer-patch-title">
                              <strong>{PATCH_LABELS[key] || key}</strong>
                              <span>{selectedSections[key] ? 'Será aplicado' : 'Ignorado'}</span>
                            </div>
                            {reason && <p className="optimizer-patch-reason">{reason}</p>}
                            <div className="optimizer-diff">
                              <div className="optimizer-diff-side old">
                                <span className="optimizer-diff-label">Atual</span>
                                <pre>{currentPatchPreview(current)}</pre>
                              </div>
                              <div className="optimizer-diff-side new">
                                <span className="optimizer-diff-label">Proposto</span>
                                <pre>{patchPreview(value)}</pre>
                              </div>
                            </div>
                          </div>
                        </label>
                      );
                    })}
                    {!patchEntries.length && <div className="empty">Nenhuma alteração proposta.</div>}
                  </div>
                  <div className="optimizer-context">
                    <ReportList title="Motivos" items={optimizerPreview.rationale}/>
                    <ReportList title="Riscos" items={optimizerPreview.risk_notes}/>
                  </div>
                  <VersionHistory versions={agentVersions} onRestore={restoreVersion}/>
                </>
              )}
            </div>
          </div>
        )}
      </div>
      {testerHistoryDetail && (
        <TesterHistoryDetailModal
          detail={testerHistoryDetail}
          onClose={() => setTesterHistoryDetail(null)}
          onUseReport={() => {
            if (testerHistoryDetail.output) {
              setTesterReport(testerHistoryDetail.output);
              setTab('tester');
              setTesterHistoryDetail(null);
              studioToast('Diagnóstico anterior reaberto.');
            }
          }}
        />
      )}
    </>
  );
};

function TesterHistoryModule({ history, loading, open, onToggle, onOpenDetail, onRefresh, onLoadMore, detailLoading }) {
  const items = Array.isArray(history?.items) ? history.items : [];
  const total = Number(history?.total || 0);
  return (
    <section className="tester-history-card">
      <button className="tester-history-head" onClick={onToggle}>
        <span className="tester-history-title">
          <Icon name="logs" size={14}/>
          <span>Testes anteriores</span>
        </span>
        <span className="tester-history-count">{loading ? '...' : total}</span>
      </button>
      {open && (
        <div className="tester-history-body">
          <div className="tester-history-toolbar">
            <span>{items.length ? `${items.length} de ${total}` : 'Sem registros'}</span>
            <button className="tb-btn ghost" onClick={onRefresh} disabled={loading}>Atualizar</button>
          </div>
          <div className="tester-history-list">
            {loading && !items.length && <div className="empty tiny">Carregando testes...</div>}
            {!loading && !items.length && (
              <EmptyState icon="logs" title="Nenhum teste salvo" description="Quando você rodar o Testador, os diagnósticos aparecerão aqui sem ocupar a conversa principal."/>
            )}
            {items.map(item => (
              <article key={item.id} className="tester-history-row">
                <span className="tester-history-row-top">
                  <strong>{item.agent_name}</strong>
                  <span className={`badge ${testerHistoryStatusClass(item.status)}`}>{item.status || 'registrado'}</span>
                </span>
                <span className="tester-history-row-meta">
                  {testerHistoryDate(item.created_at)} - {item.mode || 'quick'} - {testerHistoryScore(item)}
                </span>
                <span className="tester-history-row-preview">{item.first_message || item.summary || 'Teste registrado.'}</span>
                <span className="tester-history-row-result">{item.quality_label || item.result || 'Resultado pendente'}</span>
                <span className="tester-history-row-actions">
                  <button type="button" className="tb-btn ghost mini" onClick={() => onOpenDetail(item)} disabled={detailLoading}>Detalhes</button>
                </span>
              </article>
            ))}
          </div>
          {items.length < total && (
            <button className="tb-btn ghost tester-history-more" onClick={onLoadMore} disabled={loading}>Carregar mais</button>
          )}
        </div>
      )}
    </section>
  );
}

function TesterHistoryDetailModal({ detail, onClose, onUseReport }) {
  const messages = testerHistoryMessages(detail);
  const meta = detail.metadata || {};
  return (
    <div className="modal-backdrop open">
      <div className="tester-history-modal">
        <div className="tester-history-modal-head">
          <div>
            <div className="panel-title">Detalhes do teste</div>
            <div className="muted">{detail.agent_name} - {testerHistoryDate(detail.created_at)} - {detail.mode}</div>
          </div>
          <div className="row-actions compact-actions">
            <button className="tb-btn ghost" onClick={onUseReport}>Reabrir diagnóstico</button>
            <button className="tb-btn" onClick={onClose}>Fechar</button>
          </div>
        </div>
        <div className="tester-history-detail-grid">
          <aside className="tester-history-detail-side">
            <ScoreRing value={scoreValue(detail.score)} size={70}/>
            <dl className="rt-kv compact">
              <dt>Status</dt><dd><span className={`badge ${testerHistoryStatusClass(detail.status)}`}>{detail.status}</span></dd>
              <dt>Resultado</dt><dd>{detail.quality_label || '--'}</dd>
              <dt>Latência</dt><dd>{detail.latency_ms != null ? `${detail.latency_ms} ms` : '--'}</dd>
              <dt>Cenários</dt><dd>{detail.scenarios_count || meta.transcript_count || 0}</dd>
              <dt>Erros</dt><dd>{detail.errors_count || 0}</dd>
              <dt>Modelo</dt><dd>{meta.model || '--'}</dd>
            </dl>
            {detail.objective && <div className="tester-history-objective"><span>Objetivo</span><p>{detail.objective}</p></div>}
            <div className="tester-history-metadata">
              <span>Metadados</span>
              <dl className="rt-kv compact">
                <dt>Run</dt><dd>#{detail.run_id || detail.id}</dd>
                <dt>Agente</dt><dd>{detail.agent_id ? `#${detail.agent_id}` : '--'}</dd>
                <dt>Assistente</dt><dd>{meta.assistant_kind || 'tester'}</dd>
                <dt>Análise</dt><dd>{meta.analysis_mode || detail.mode || '--'}</dd>
              </dl>
            </div>
          </aside>
          <main className="tester-history-detail-main">
            <div className="tester-history-summary">
              <span>Resumo</span>
              <p>{detail.summary || 'Sem resumo registrado.'}</p>
            </div>
            <div className="tester-history-transcript">
              <div className="rt-label">Conversa completa</div>
              {messages.map((message, idx) => (
                <ChatBubble
                  key={`${message.role}-${idx}`}
                  role={message.role === 'user' ? 'tester' : message.role === 'assistant' ? 'agent' : 'system'}
                  text={message.content}
                  avatar={message.role === 'assistant' ? <Icon name="agents" size={13}/> : message.role === 'system' ? null : 'T'}
                  meta={<span>{message.scenario || ''}{message.latency_ms ? ` - ${message.latency_ms} ms` : ''}</span>}
                />
              ))}
              {!messages.length && <div className="empty">Nenhuma mensagem registrada neste teste.</div>}
            </div>
            {!!asList(detail.output?.issues).length && <ReportList title="Erros e alertas" tone="risk" icon="x" items={detail.output.issues}/>}
          </main>
        </div>
      </div>
    </div>
  );
}

function ReportList({ title, items, icon = 'logs', tone = 'neutral', empty = 'Sem itens.' }) {
  const rawList = reportItems(items);
  const list = rawList.length ? rawList : [empty];
  const isEmpty = !rawList.length;
  return (
    <div className={`report-list report-section ${tone}`}>
      <div className="report-section-head">
        <span className="report-section-icon"><Icon name={icon} size={14}/></span>
        <div>
          <div className="rt-label">{title}</div>
          <span>{rawList.length} {rawList.length === 1 ? 'item' : 'itens'}</span>
        </div>
      </div>
      <div className="report-section-items">
        {list.map((item, idx) => {
          const parts = reportItemParts(item, tone);
          const priority = isEmpty ? '' : parts.priority;
          return (
            <div className={`report-item ${isEmpty ? 'report-item-empty' : ''}`} key={idx}>
              <span className="report-item-index"><Icon name={isEmpty ? 'logs' : reportToneIcon(tone)} size={12}/></span>
              <span className="report-item-copy">
                <span className="report-item-title-row">
                  <strong>{parts.title}</strong>
                  {priority && <span className={`report-priority ${reportPriorityClass(priority)}`}>{priority}</span>}
                </span>
                {parts.body.map((line, lineIdx) => <em key={lineIdx}>{line}</em>)}
              </span>
            </div>
          );
        })}
      </div>
    </div>
  );
}

function VersionHistory({ versions, onRestore }) {
  const list = Array.isArray(versions) ? versions : [];
  return (
    <div className="version-history">
      <div className="report-head compact">
        <div>
          <div className="panel-title">Histórico reversível</div>
          <div className="muted">Cada aplicação salva a versão anterior do agente.</div>
        </div>
      </div>
      {list.length ? list.slice(0, 6).map(version => (
        <div className="version-row" key={version.id}>
          <div>
            <strong>{version.label || `Versão ${version.id}`}</strong>
            <span>{version.source} - {window.fmtShortDate ? window.fmtShortDate(version.created_at) : version.created_at}</span>
          </div>
          <button className="tb-btn ghost" onClick={() => onRestore(version)}>Restaurar</button>
        </div>
      )) : <div className="empty tiny">Nenhuma versão salva ainda.</div>}
    </div>
  );
}

window.ChannelsPage = function ChannelsPage() {
  const [q, setQ] = useExtraState('');
  const [qrByChannel, setQrByChannel] = useExtraState({});
  const [connectingId, setConnectingId] = useExtraState(null);
  const data = studioData();
  const channels = (data.channels || []).filter(item => `${item.name} ${item.instance_name} ${item.agent_name || ''}`.toLowerCase().includes(q.toLowerCase()));
  const online = channels.filter(item => channelStatus(item.instance_name) === 'online').length;
  const agentOptions = [{ value: '', label: 'Selecione depois' }, ...(data.agents || []).map(agent => ({ value: String(agent.id), label: agent.name }))];

  async function createChannel() {
    const values = await studioForm({
      title: 'Novo canal',
      description: 'Escolha a instância WhatsApp, o agente responsável e o delay antes de conectar.',
      submitLabel: 'Criar canal',
      fields: [
        { name: 'name', label: 'Nome do canal', required: true },
        { name: 'instance_name', label: 'Identificador WhatsApp', helper: 'Vazio usa o nome do canal.' },
        { name: 'agent_id', label: 'Agente responsável', type: 'select', options: agentOptions },
        { name: 'description', label: 'Descrição', type: 'textarea' },
        { name: 'custom_prompt', label: 'Orientação específica', type: 'textarea' },
        { name: 'reply_delay', label: 'Delay em segundos', type: 'number', defaultValue: '0' },
      ],
    });
    if (!values) return;
    const name = values.name.trim();
    runAction(() => API.createChannel({
      name,
      instance_name: values.instance_name?.trim() || name,
      description: values.description || '',
      custom_prompt: values.custom_prompt || '',
      reply_delay: Number(values.reply_delay || 0),
      agent_id: values.agent_id ? Number(values.agent_id) : null,
    }));
  }

  async function editChannel(channel) {
    const values = await studioForm({
      title: 'Alterar canal',
      submitLabel: 'Salvar canal',
      fields: [
        { name: 'name', label: 'Nome do canal', required: true, defaultValue: channel.name || '' },
        { name: 'instance_name', label: 'Identificador WhatsApp', defaultValue: channel.instance_name || '' },
        { name: 'agent_id', label: 'Agente responsável', type: 'select', defaultValue: channel.agent_id ? String(channel.agent_id) : '', options: agentOptions },
        { name: 'description', label: 'Descrição', type: 'textarea', defaultValue: channel.description || '' },
        { name: 'custom_prompt', label: 'Orientação específica', type: 'textarea', defaultValue: channel.custom_prompt || '' },
        { name: 'reply_delay', label: 'Delay em segundos', type: 'number', defaultValue: String(channel.reply_delay || 0) },
      ],
    });
    if (!values) return;
    runAction(() => API.updateChannel(channel.id, {
      name: values.name.trim(),
      instance_name: values.instance_name?.trim() || values.name.trim(),
      description: values.description || '',
      custom_prompt: values.custom_prompt || '',
      agent_id: values.agent_id ? Number(values.agent_id) : null,
      reply_delay: Number(values.reply_delay || 0),
    }));
  }

  async function connectChannel(channel) {
    setConnectingId(channel.id);
    try {
      const result = await API.connectChannel(channel.id);
      setQrByChannel(prev => ({ ...prev, [channel.id]: result }));
      await refreshStudio();
      studioToast('QR do canal gerado.');
    } catch (err) {
      setQrByChannel(prev => ({ ...prev, [channel.id]: { error: err.message || String(err) } }));
      studioToast(err.message || String(err), 'bad');
    } finally {
      setConnectingId(null);
    }
  }

  return (
    <>
      <PageTitle
        eyebrow={`Orquestração - ${channels.length} canais`}
        title="Canais WhatsApp"
        sub="Status, QR inline, agente responsável, orientação e delay por canal."
        action={<button className="tb-btn primary" onClick={createChannel}><Icon name="plus" size={12}/> Novo canal</button>}
      />
      <div className="page">
        <div className="module-grid-4">
          <MiniKpi label="Canais" value={String((data.channels || []).length)}/>
          <MiniKpi label="Conectados" value={String(online)}/>
          <MiniKpi label="Instâncias" value={String((data.instances || []).length)}/>
          <MiniKpi label="Agentes ligados" value={String(channels.filter(c => c.agent_id).length)}/>
        </div>
        <div className="panel">
          <div className="panel-head">
            <div className="toolbar-wrap">
              <div className="topbar-search local-search">
                <Icon name="search" size={13}/>
                <input value={q} onChange={e => setQ(e.target.value)} placeholder="Buscar canal ou instância..."/>
              </div>
            </div>
          </div>
          <div className="channel-card-grid">
            {channels.map(channel => {
              const st = channelStatusInfo(channel.instance_name);
              const qr = qrByChannel[channel.id] || {};
              const qrImage = qr.base64 || qr.qrcode || qr.qrCode || qr.code;
              return (
                <div className={`channel-card ${st.tag}`} key={channel.id}>
                  <div className="channel-card-head">
                    <div className="av"><span className="av-mark">W</span><span className="av-name">{channel.name}</span></div>
                    <span className={`badge ${st.tag}`} title="Status da conexão WhatsApp"><span className={`sw ${st.tag}`}/> {st.label}</span>
                  </div>
                  <div className="channel-meta">
                    <div><span>Instância</span><strong className="mono">{channel.instance_name}</strong></div>
                    <div><span>Responsável</span><strong>{channel.agent_name || agentName(channel.agent_id) || 'Não atribuído'}</strong></div>
                    <div><span>Delay</span><strong>{channel.reply_delay || 0}s</strong></div>
                  </div>
                  <div className="channel-qr-inline">
                    {qrImage && String(qrImage).startsWith('data:image')
                      ? <img alt="QR Code WhatsApp" src={qrImage}/>
                      : <div className="empty tiny">{qr.error || (st.status === 'online' ? 'Conectado. QR não necessário.' : 'Gere o QR para conectar este canal.')}</div>}
                  </div>
                  <div className="field-helper mono">{channel.webhook}</div>
                  <div className="row-actions">
                    <button className="tb-btn ghost" onClick={() => editChannel(channel)}>Alterar</button>
                    <button className="tb-btn ghost" onClick={() => connectChannel(channel)} disabled={connectingId === channel.id}>{connectingId === channel.id ? 'Gerando...' : 'QR inline'}</button>
                    <button className="tb-btn ghost" onClick={() => runAction(() => API.disconnectChannel(channel.id))}>Desconectar WhatsApp</button>
                    <button className="tb-btn danger" onClick={async () => (await studioConfirm({ title:'Excluir canal', message:`Excluir ${channel.name}?`, confirmLabel:'Excluir', danger:true })) && runAction(() => API.deleteChannel(channel.id))}>Excluir</button>
                  </div>
                </div>
              );
            })}
            {!channels.length && <div className="empty-cta"><strong>Nenhum canal encontrado.</strong><span>Crie um canal e vincule a um agente para receber mensagens reais.</span><button className="tb-btn primary" onClick={createChannel}>Novo canal</button></div>}
          </div>
        </div>
      </div>
    </>
  );
};

window.KnowledgePage = function KnowledgePage() {
  const [q, setQ] = useExtraState('');
  const [agentFilter, setAgentFilter] = useExtraState('');
  const [selected, setSelected] = useExtraState(null);
  const [kbSources, setKbSources] = useExtraState([]);
  const [testQuery, setTestQuery] = useExtraState('');
  const [testResult, setTestResult] = useExtraState(null);
  const [testLoading, setTestLoading] = useExtraState(false);
  const data = studioData();
  const agentOptions = [{ value: '', label: 'Global / sem agente' }, ...(data.agents || []).map(agent => ({ value: String(agent.id), label: agent.name }))];
  const knowledge = (data.knowledge || [])
    .filter(item => !agentFilter || (agentFilter === '__global' ? !item.agent_id : String(item.agent_id || '') === agentFilter))
    .filter(item => `${item.name} ${item.description || ''} ${item.tenant_id || ''} ${agentName(item.agent_id)}`.toLowerCase().includes(q.toLowerCase()));
  const selectedKb = knowledge.find(item => String(item.id) === String(selected)) || knowledge[0] || null;

  useExtraEffect(() => {
    setTestResult(null);
    if (!selectedKb?.id) { setKbSources([]); return; }
    API.getKnowledgeBaseSources(selectedKb.id).then(setKbSources).catch(() => setKbSources([]));
  }, [selectedKb?.id]);

  async function createBase() {
    const values = await studioForm({
      title: 'Nova base de conhecimento',
      description: 'Cria uma base geral. Vinculos por agente ficam no perfil do agente.',
      submitLabel: 'Criar base',
      fields: [
        { name: 'name', label: 'Nome da base', required: true },
        { name: 'agent_id', label: 'Vincular ao agente', type: 'select', options: agentOptions },
        { name: 'description', label: 'Descrição', type: 'textarea' },
        { name: 'tenant_id', label: 'Tenant', helper: 'Opcional.' },
      ],
    });
    if (!values) return;
    runAction(() => API.createKnowledgeBase({
      name: values.name.trim(),
      description: values.description || 'Base geral criada pelo Studio',
      agent_id: values.agent_id ? Number(values.agent_id) : null,
      tenant_id: values.tenant_id || undefined,
    }));
  }

  async function editBase(item) {
    const values = await studioForm({
      title: 'Alterar base de conhecimento',
      submitLabel: 'Salvar base',
      fields: [
        { name: 'name', label: 'Nome da base', required: true, defaultValue: item.name || '' },
        { name: 'agent_id', label: 'Vincular ao agente', type: 'select', defaultValue: item.agent_id ? String(item.agent_id) : '', options: agentOptions },
        { name: 'description', label: 'Descrição', type: 'textarea', defaultValue: item.description || '' },
        { name: 'tenant_id', label: 'Tenant', defaultValue: item.tenant_id || '' },
      ],
    });
    if (!values) return;
    runAction(() => API.updateKnowledgeBase(item.id, {
      name: values.name.trim(),
      description: values.description || '',
      agent_id: values.agent_id ? Number(values.agent_id) : null,
      tenant_id: values.tenant_id || null,
    }));
  }

  async function deleteBase(item) {
    return (await studioConfirm({ title:'Excluir base', message:`Excluir ${item.name}? Fontes e chunks tambem seráo removidos.`, confirmLabel:'Excluir', danger:true })) && runAction(() => API.deleteKnowledgeBase(item.id));
  }

  async function runKbTest() {
    if (!selectedKb || !testQuery.trim() || testLoading) return;
    setTestLoading(true);
    setTestResult(null);
    try {
      setTestResult(await API.testKnowledgeBase(selectedKb.id, { query: testQuery.trim() }));
    } catch (err) {
      setTestResult({ error: err.message || String(err), chunks: [] });
    } finally {
      setTestLoading(false);
    }
  }

  return (
    <>
      <PageTitle
        eyebrow="Inteligência - base de conhecimento"
        title="Conhecimento do sistema"
        sub="Bases separadas por agente, com acesso rápido para alterar, ver fontes e excluir."
        action={<button className="tb-btn primary" onClick={createBase}><Icon name="plus" size={12}/> Nova base</button>}
      />
      <div className="page">
        <div className="module-grid-4">
          <MiniKpi label="Bases" value={String(data.knowledge?.length || 0)}/>
          <MiniKpi label="Com agente" value={String((data.knowledge || []).filter(k => k.agent_id).length)}/>
          <MiniKpi label="Gerais" value={String((data.knowledge || []).filter(k => !k.agent_id).length)}/>
          <MiniKpi label="Agentes" value={String(new Set((data.knowledge || []).map(k => k.agent_id).filter(Boolean)).size)}/>
        </div>
        <div className="profile-workbench">
          <div className="panel profile-list-panel">
            <div className="panel-head">
              <div className="toolbar-wrap">
                <div className="topbar-search local-search">
                  <Icon name="search" size={13}/>
                  <input value={q} onChange={e => setQ(e.target.value)} placeholder="Buscar base, agente..."/>
                </div>
                <select className="input compact-select" value={agentFilter} onChange={e => { setAgentFilter(e.target.value); setSelected(null); }}>
                  <option value="">Todos agentes</option>
                  <option value="__global">Somente globais</option>
                  {(data.agents || []).map(agent => <option key={agent.id} value={String(agent.id)}>{agent.name}</option>)}
                </select>
              </div>
            </div>
            <div className="stack-list">
              {knowledge.map(item => (
                <button key={item.id} className={`entity-card selectable ${String(selectedKb?.id) === String(item.id) ? 'active' : ''}`} onClick={() => setSelected(item.id)}>
                  <span className="entity-copy">
                    <strong className="entity-title">{item.name}</strong>
                    <span className="entity-sub">{item.agent_id ? agentName(item.agent_id) : 'Sistema'} - {item.description || 'Sem descrição'}</span>
                  </span>
                  <span className="badge accent">{item.agent_id ? 'agente' : 'global'}</span>
                </button>
              ))}
              {!knowledge.length && <div className="empty">Nenhuma base encontrada.</div>}
            </div>
          </div>
          <div className="panel profile-detail-panel">
            <div className="panel-head">
              <div><div className="panel-title">Perfil da KB</div><div className="panel-eyebrow">{selectedKb ? selectedKb.name : 'selecione uma base'}</div></div>
              {selectedKb && <div className="row-actions"><button className="tb-btn ghost" onClick={() => editBase(selectedKb)}>Alterar</button><button className="tb-btn danger" onClick={() => deleteBase(selectedKb)}>Excluir</button></div>}
            </div>
            {selectedKb ? (
              <div className="profile-detail-body">
                <div className="detail-metrics">
                  <MiniKpi label="Escopo" value={selectedKb.agent_id ? 'agente' : 'global'} sub={selectedKb.agent_id ? agentName(selectedKb.agent_id) : 'Sistema'}/>
                  <MiniKpi label="Tenant" value={selectedKb.tenant_id || '--'}/>
                  <MiniKpi label="Criada" value={window.fmtShortDate ? window.fmtShortDate(selectedKb.created_at) : '--'}/>
                </div>
                <div className="soft-row"><span>Descrição</span><strong>{selectedKb.description || 'Sem descrição'}</strong></div>
                <div className="panel-subtitle">Fontes</div>
                <table className="dt compact-table">
                  <thead><tr><th>Fonte</th><th>Tipo</th><th>Status</th><th>Chunks</th></tr></thead>
                  <tbody>
                    {kbSources.map(src => <tr key={src.id}><td className="mono truncate-cell">{src.uri}</td><td>{src.source_type}</td><td>{src.status}</td><td>{src.chunk_count || 0}</td></tr>)}
                    {!kbSources.length && <EmptyRow cols="4" text="Nenhuma fonte indexada."/>}
                  </tbody>
                </table>
                <div className="kb-test-panel">
                  <div className="panel-subtitle">Teste de busca</div>
                  <div className="kb-test-row">
                    <input className="input" value={testQuery} onChange={e => setTestQuery(e.target.value)} onKeyDown={e => { if (e.key === 'Enter') runKbTest(); }} placeholder="Digite uma pergunta para testar a recuperação da KB..."/>
                    <button className="tb-btn primary" onClick={runKbTest} disabled={testLoading || !testQuery.trim()}>{testLoading ? 'Testando...' : 'Testar KB'}</button>
                  </div>
                  {testResult?.error && <div className="inline-error">{testResult.error}</div>}
                  {testResult && !testResult.error && (
                    <div className="kb-test-results">
                      <div className="field-helper">Modo: {testResult.retrieval_mode || 'keyword_fallback'} - confiança {Math.round(Number(testResult.confidence || 0) * 100)}%</div>
                      {(testResult.chunks || []).map(chunk => (
                        <div className="kb-result-card" key={chunk.chunk_id || chunk.title}>
                          <div className="entity-title">{chunk.title || 'Fonte'}</div>
                          <div className="entity-sub">{chunk.uri || 'base interna'} {chunk.score != null ? `- score ${Number(chunk.score).toFixed(2)}` : ''}</div>
                          <p>{chunk.snippet || 'Sem trecho retornado.'}</p>
                        </div>
                      ))}
                      {!(testResult.chunks || []).length && <div className="empty tiny">Nenhum trecho retornado para esta pergunta.</div>}
                    </div>
                  )}
                </div>
              </div>
            ) : <div className="empty">Selecione uma KB.</div>}
          </div>
        </div>
      </div>
    </>
  );
};

window.ToolsPage = function ToolsPage() {
  const [q, setQ] = useExtraState('');
  const [selectedScope, setSelectedScope] = useExtraState('all');
  const data = studioData();
  const allTools = data.tools || [];
  const systemTools = allTools.filter(item => !item.agent_id);
  const agentScopes = (data.agents || [])
    .map(agent => ({
      id: `agent:${agent.id}`,
      label: agent.name,
      sub: agent.role || agent.channel || 'Agente',
      count: allTools.filter(tool => String(tool.agent_id) === String(agent.id)).length,
      agentId: agent.id,
    }))
    .filter(item => item.count > 0 || `${item.label} ${item.sub}`.toLowerCase().includes(q.toLowerCase()));
  const scopes = [
    { id: 'all', label: 'Todas ferramentas', sub: 'Globais e por agente', count: allTools.length },
    { id: 'system', label: 'Sistema', sub: 'Ferramentas globais', count: systemTools.length },
    ...agentScopes,
  ];
  const scopedTools = selectedScope === 'all'
    ? allTools
    : selectedScope === 'system'
      ? systemTools
      : selectedScope?.startsWith('agent:')
        ? allTools.filter(item => String(item.agent_id) === selectedScope.slice(6))
        : [];
  const tools = scopedTools.filter(item => `${item.name} ${item.tool_type} ${item.description || ''} ${agentName(item.agent_id)}`.toLowerCase().includes(q.toLowerCase()));
  const selectedLabel = scopes.find(item => item.id === selectedScope)?.label || 'Selecione um escopo';

  async function createTool() {
    const values = await studioForm({
      title: 'Nova ferramenta do sistema',
      description: 'Cria uma ferramenta global. Ferramentas usadas por agente ficam no perfil do agente.',
      submitLabel: 'Criar ferramenta',
      fields: [
        { name: 'name', label: 'Nome', required: true },
        { name: 'agent_id', label: 'Agente que pode usar', type: 'select', required: true, options: (data.agents || []).map(agent => ({ value: String(agent.id), label: agent.name })) },
        { name: 'tool_type', label: 'Tipo', type: 'select', defaultValue: 'knowledge_base', options: [
          { value: 'web_search', label: 'web_search' },
          { value: 'knowledge_base', label: 'knowledge_base' },
          { value: 'data_table', label: 'data_table' },
          { value: 'http_api', label: 'http_api' },
          { value: 'python_runtime', label: 'python_runtime' },
          { value: 'ticket_creation', label: 'ticket_creation' },
          { value: 'contextual_memory', label: 'contextual_memory' },
        ]},
        { name: 'description', label: 'Descrição', type: 'textarea' },
      ],
    });
    if (!values) return;
    runAction(() => API.createTool({
      name: values.name.trim(),
      agent_id: Number(values.agent_id),
      tool_type: values.tool_type,
      description: values.description || '',
      enabled: true,
    }));
  }

  async function editTool(tool) {
    const values = await studioForm({
      title: 'Alterar ferramenta',
      submitLabel: 'Salvar ferramenta',
      fields: [
        { name: 'name', label: 'Nome', required: true, defaultValue: tool.name || '' },
        { name: 'tool_type', label: 'Tipo', type: 'select', defaultValue: tool.tool_type || 'knowledge_base', options: [
          { value: 'web_search', label: 'web_search' },
          { value: 'knowledge_base', label: 'knowledge_base' },
          { value: 'data_table', label: 'data_table' },
          { value: 'http_api', label: 'http_api' },
          { value: 'python_runtime', label: 'python_runtime' },
          { value: 'ticket_creation', label: 'ticket_creation' },
          { value: 'contextual_memory', label: 'contextual_memory' },
        ]},
        { name: 'description', label: 'Descrição', type: 'textarea', defaultValue: tool.description || '' },
      ],
    });
    if (!values) return;
    runAction(() => API.updateTool(tool.id, {
      name: values.name.trim(),
      tool_type: values.tool_type || tool.tool_type,
      description: values.description || '',
    }));
  }

  return (
    <>
      <PageTitle
        eyebrow="Inteligência - ferramentas"
        title="Ferramentas do sistema"
        sub="Catalogo completo: ferramentas globais e ferramentas usadas por cada agente."
        action={<button className="tb-btn primary" onClick={createTool}><Icon name="plus" size={12}/> Nova ferramenta</button>}
      />
      <div className="page">
        <div className="module-grid-4 tool-summary-grid">
          {[
            ['knowledge_base', 'Busca em documentos, URLs e textos indexados.'],
            ['http_api', 'Chama CRM, ERP ou sistemas externos com parametros controlados.'],
            ['data_table', 'Consulta e grava dados nas tabelas internas.'],
            ['python_runtime', 'Executa logica e calculos customizados quando hábilitado.'],
          ].map(([type, description]) => (
            <div className="panel tool-tile metric-tile" key={type}>
              <div><div className="metric-title mono">{type}</div><div className="metric-value">{(data.tools || []).filter(t => t.tool_type === type).length}</div><div className="muted">{description}</div></div>
              <span className="badge accent">catalogo</span>
            </div>
          ))}
        </div>
        <div className="profile-workbench tools-scope-workbench">
          <div className="panel profile-list-panel">
            <div className="panel-head">
              <div className="topbar-search local-search">
                <Icon name="search" size={13}/>
                <input value={q} onChange={e => setQ(e.target.value)} placeholder="Buscar agente ou ferramenta..."/>
              </div>
            </div>
            <div className="stack-list">
              {scopes.map(scope => (
                <button key={scope.id} className={`entity-card selectable ${selectedScope === scope.id ? 'active' : ''}`} onClick={() => setSelectedScope(scope.id)}>
                  <span className="entity-copy">
                    <strong className="entity-title">{scope.label}</strong>
                    <span className="entity-sub">{scope.sub}</span>
                  </span>
                  <span className="badge accent">{scope.count}</span>
                </button>
              ))}
            </div>
          </div>
          <div className="panel profile-detail-panel">
            <div className="panel-head">
              <div><div className="panel-title">Ferramentas</div><div className="panel-eyebrow">{selectedLabel}</div></div>
              {selectedScope && <span className="badge accent">{tools.length} visiveis</span>}
            </div>
            {selectedScope ? (
              <div className="tool-card-grid">
                {tools.map(tool => (
                  <div className="tool-catalog-card" key={tool.id}>
                    <div className="tool-card-top">
                      <span className="badge accent">{tool.tool_type}</span>
                      <span className={`badge ${tool.enabled ? 'ok' : ''}`}><span className={`sw ${tool.enabled ? 'ok' : ''}`}/> {tool.enabled ? 'ativa' : 'inativa'}</span>
                    </div>
                    <strong className="mono">{tool.name}</strong>
                    <span className="entity-sub">{tool.description || 'Sem descrição'}</span>
                    <div className="soft-row"><span>Escopo</span><strong>{tool.agent_id ? agentName(tool.agent_id) : 'Sistema'}</strong></div>
                    <div className="soft-row"><span>Aprovação</span><strong>{tool.requires_approval ? 'sim' : 'não'}</strong></div>
                    <div className="row-actions">
                      <button className="tb-btn ghost" onClick={() => editTool(tool)}>Alterar</button>
                      <button className="tb-btn ghost" onClick={() => runAction(() => API.updateTool(tool.id, { enabled: !tool.enabled }))}>{tool.enabled ? 'Pausar' : 'Ativar'}</button>
                      <button className="tb-btn danger" onClick={async () => (await studioConfirm({ title:'Excluir ferramenta', message:`Excluir ${tool.name}?`, confirmLabel:'Excluir', danger:true })) && runAction(() => API.deleteTool(tool.id))}>Excluir</button>
                    </div>
                  </div>
                ))}
                {!tools.length && <div className="empty">Nenhuma ferramenta neste escopo.</div>}
              </div>
            ) : (
              <div className="empty">Escolha um agente, Sistema ou Todas ferramentas para ver detalhes.</div>
            )}
          </div>
        </div>
      </div>
    </>
  );
};

const SQUAD_TEMPLATES = {
  suporte: { name: 'Suporte Escalonado', mode: 'hierarchical', config: { template: 'suporte', expected_roles: ['triagem', 'especialista', 'supervisor'] } },
  vendas: { name: 'Vendas Consultivas', mode: 'hierarchical', config: { template: 'vendas', expected_roles: ['qualificador', 'consultor', 'closer'] } },
  geral: { name: 'Atendimento Geral', mode: 'horizontal', config: { template: 'geral', expected_roles: ['suporte', 'vendas', 'técnico'] } },
};

window.SquadsPage = function SquadsPage() {
  const data = studioData();
  const [selected, setSelected] = useExtraState(null);
  const [detail, setDetail] = useExtraState(null);

  useExtraEffect(() => {
    if (!selected) { setDetail(null); return; }
    API.get(`/api/squads/${selected}`).then(setDetail).catch(() => setDetail(null));
  }, [selected]);

  async function createSquad() {
    const values = await studioForm({
      title: 'Novo squad',
      submitLabel: 'Criar squad',
      fields: [
        { name: 'template', label: 'Template', type: 'select', defaultValue: 'geral', options: [
          { value: 'suporte', label: 'Suporte Escalonado' },
          { value: 'vendas', label: 'Vendas Consultivas' },
          { value: 'geral', label: 'Atendimento Geral' },
        ]},
        { name: 'name', label: 'Nome do squad', required: true },
        { name: 'mode', label: 'Modo', type: 'select', defaultValue: 'hierarchical', options: [
          { value: 'hierarchical', label: 'Hierarquico' },
          { value: 'horizontal', label: 'Horizontal' },
        ]},
        { name: 'manager_agent_id', label: 'Gerente', type: 'select', options: [{ value:'', label:'Selecione depois' }, ...(data.agents || []).map(agent => ({ value:String(agent.id), label:agent.name }))] },
        { name: 'fallback_agent_id', label: 'Fallback', type: 'select', options: [{ value:'', label:'Selecione depois' }, ...(data.agents || []).map(agent => ({ value:String(agent.id), label:agent.name }))] },
      ],
    });
    if (!values) return;
    const template = SQUAD_TEMPLATES[values.template] || SQUAD_TEMPLATES.geral;
    runAction(() => API.createSquad({
      name: values.name.trim() || template.name,
      mode: values.mode || template.mode,
      manager_agent_id: values.manager_agent_id ? Number(values.manager_agent_id) : null,
      fallback_agent_id: values.fallback_agent_id ? Number(values.fallback_agent_id) : null,
      config: template.config,
    }));
  }

  function openSquadProfile(id) {
    setSelected(id);
  }

  function deleteSquad(id) {
    return runAction(() => API.deleteSquad(id));
  }

  async function editSquad() {
    if (!detail) return;
    const values = await studioForm({
      title: 'Alterar squad',
      submitLabel: 'Salvar squad',
      fields: [
        { name: 'name', label: 'Nome do squad', required: true, defaultValue: detail.name || '' },
        { name: 'mode', label: 'Modo', type: 'select', defaultValue: detail.mode || 'hierarchical', options: [
          { value: 'hierarchical', label: 'Hierarquico' },
          { value: 'horizontal', label: 'Horizontal' },
        ]},
        { name: 'manager_agent_id', label: 'Gerente', type: 'select', defaultValue: detail.manager_agent_id ? String(detail.manager_agent_id) : '', options: [{ value:'', label:'Sem gerente' }, ...(data.agents || []).map(agent => ({ value:String(agent.id), label:agent.name }))] },
        { name: 'fallback_agent_id', label: 'Fallback', type: 'select', defaultValue: detail.fallback_agent_id ? String(detail.fallback_agent_id) : '', options: [{ value:'', label:'Sem fallback' }, ...(data.agents || []).map(agent => ({ value:String(agent.id), label:agent.name }))] },
      ],
    });
    if (!values) return;
    runAction(async () => {
      await API.updateSquad(selected, {
        name: values.name.trim(),
        mode: values.mode || 'hierarchical',
        manager_agent_id: values.manager_agent_id ? Number(values.manager_agent_id) : null,
        fallback_agent_id: values.fallback_agent_id ? Number(values.fallback_agent_id) : null,
      });
      setDetail(await API.get(`/api/squads/${selected}`));
    });
  }

  function addMember() {
    if (!selected) return;
    const agentId = firstAgentId();
    if (!agentId) {
      studioToast('Crie um agente antes.', 'bad');
      return;
    }
    runAction(async () => {
      await API.post(`/api/squads/${selected}/members`, { agent_id: agentId, role: 'specialist', priority: 100 });
      setDetail(await API.get(`/api/squads/${selected}`));
    });
  }

  window.openSquadProfile = openSquadProfile;
  window.deleteSquad = deleteSquad;

  return (
    <>
      <PageTitle
        eyebrow="Inteligência - squads"
        title="Squads de agentes"
        sub="Hierarquia, fallback e membros para roteamento multiagente."
        action={<button className="tb-btn primary" onClick={createSquad}><Icon name="plus" size={12}/> Novo squad</button>}
      />
      <div className="page">
        <div className="module-grid-2">
          <div className="panel">
            <div className="panel-head"><div className="panel-title">Squads</div></div>
            <div className="stack-list">
              {(data.squads || []).map(squad => (
                <button key={squad.id} className={`entity-card selectable ${selected === squad.id ? 'active' : ''}`} onClick={() => openSquadProfile(squad.id)}>
                  <span className="entity-copy">
                    <strong className="entity-title">{squad.name}</strong>
                    <span className="entity-sub">{squad.mode} - {squad.member_count || 0} membros - manager {squad.manager_agent_name || '--'}</span>
                  </span>
                  <span className="badge accent">{squad.fallback_agent_name || 'sem fallback'}</span>
                </button>
              ))}
              {!(data.squads || []).length && <div className="empty">Nenhum squad criado.</div>}
            </div>
          </div>
          <div className="panel">
            <div className="panel-head">
              <div className="panel-title">Perfil do squad</div>
              {selected && <div className="row-actions">
                <button className="tb-btn ghost" onClick={editSquad}>Alterar</button>
                <button className="tb-btn danger" onClick={async () => (await studioConfirm({ title:'Excluir squad', message:'Excluir este squad?', confirmLabel:'Excluir', danger:true })) && deleteSquad(selected)}>Excluir</button>
              </div>}
            </div>
            {detail ? (
              <div className="stack-list">
                <div className="soft-row"><span>Modo</span><strong>{detail.mode}</strong></div>
                <div className="soft-row"><span>Manager</span><strong>{detail.manager_agent_name || '--'}</strong></div>
                <div className="soft-row"><span>Fallback</span><strong>{detail.fallback_agent_name || '--'}</strong></div>
                <div className="squad-flow">
                  <div className="squad-node manager"><span>Gerente</span><strong>{detail.manager_agent_name || 'Não definido'}</strong></div>
                  <div className="squad-arrow">distribui para</div>
                  <div className="squad-members-grid">
                    {(detail.members || []).map(member => (
                      <div className="squad-node" key={member.id}>
                        <span>{member.role || 'specialist'} - P{member.priority || 100}</span>
                        <strong>{member.agent_name || `Agente ${member.agent_id}`}</strong>
                        <small>{member.routing_description || 'Sem regra de roteamento.'}</small>
                      </div>
                    ))}
                    {!(detail.members || []).length && <div className="squad-node muted-node"><span>Membros</span><strong>Nenhum agente</strong></div>}
                  </div>
                  <div className="squad-node fallback"><span>Fallback</span><strong>{detail.fallback_agent_name || 'Não definido'}</strong></div>
                </div>
                <div className="checklist squad-checklist">
                  {[
                    [!!detail.manager_agent_id, 'Tem gerente'],
                    [(detail.members || []).length >= 2, 'Tem 2+ membros'],
                    [!!detail.fallback_agent_id, 'Tem fallback'],
                    [(detail.members || []).every(member => member.routing_description), 'Membros tem roteamento'],
                  ].map(([done, label]) => (
                    <span className={`check-item ${done ? 'done' : ''}`} key={label}><span className="check-dot"></span><span>{label}</span></span>
                  ))}
                </div>
                <select id="squad-member-agent" className="input" onChange={e => e.target.value && runAction(async () => {
                  await API.addMember(selected, { agent_id: Number(e.target.value), role: 'specialist', priority: 100 });
                  setDetail(await API.get(`/api/squads/${selected}`));
                  e.target.value = '';
                })}>
                  <option value="">Adicionar agente ao Squad</option>
                  {(data.agents || []).map(agent => <option key={agent.id} value={agent.id}>{agent.name}</option>)}
                </select>
                <button className="tb-btn primary" onClick={addMember}><Icon name="plus" size={11}/> Adicionar primeiro agente disponível</button>
                {(detail.members || []).map(member => (
                  <div className="entity-card" key={member.id}>
                    <span className="entity-copy"><strong className="entity-title">{member.agent_name}</strong><span className="entity-sub">{member.role} - prioridade {member.priority}</span></span>
                    <button className="tb-btn danger" onClick={() => runAction(async () => {
                      await API.del(`/api/squad-members/${member.id}`);
                      setDetail(await API.get(`/api/squads/${selected}`));
                    })}>Remover</button>
                  </div>
                ))}
              </div>
            ) : <div className="empty">Selecione um squad.</div>}
          </div>
        </div>
      </div>
    </>
  );
};

const TABLE_TEMPLATES = {
  clients: { name: 'Cadastro de Clientes', fields: ['nome', 'telefone', 'email', 'empresa', 'data_cadastro'] },
  orders: { name: 'Registro de Pedidos', fields: ['cliente', 'produto', 'valor', 'status', 'data'] },
  faq: { name: 'FAQ', fields: ['pergunta', 'resposta', 'categoria'] },
  support: { name: 'Controle de Atendimentos', fields: ['protocolo', 'assunto', 'status', 'responsável', 'data'] },
};

window.TablesPage = function TablesPage() {
  const data = studioData();
  const [selected, setSelected] = useExtraState(null);
  const [detail, setDetail] = useExtraState(null);
  const [fullscreen, setFullscreen] = useExtraState(false);

  useExtraEffect(() => {
    if (!selected && (data.tables || []).length) setSelected((data.tables || [])[0].id);
  }, [(data.tables || []).length, selected]);

  useExtraEffect(() => {
    if (!selected) { setDetail(null); return; }
    API.get(`/api/data-tables/${selected}`).then(setDetail).catch(() => setDetail(null));
  }, [selected]);

  useExtraEffect(() => {
    setFullscreen(false);
  }, [selected]);

  async function createTable() {
    const values = await studioForm({
      title: 'Nova tabela',
      submitLabel: 'Criar tabela',
      fields: [
        { name: 'template', label: 'Template', type: 'select', defaultValue: 'clients', options: [
          { value: 'clients', label: 'Cadastro de Clientes' },
          { value: 'orders', label: 'Registro de Pedidos' },
          { value: 'faq', label: 'FAQ / Perguntas Frequentes' },
          { value: 'support', label: 'Controle de Atendimentos' },
        ]},
        { name: 'name', label: 'Nome da tabela', required: true },
        { name: 'description', label: 'Descrição', type: 'textarea' },
      ],
    });
    if (!values) return;
    const template = TABLE_TEMPLATES[values.template] || TABLE_TEMPLATES.clients;
    runAction(() => API.createTable({
      name: values.name.trim() || template.name,
      description: values.description || template.name,
      schema_json: { description: values.description || template.name, fields: template.fields.map(name => ({ name, type: name === 'valor' ? 'number' : 'text' })) },
      records: [],
    }));
  }

  function openTableCreateModal() {
    createTable();
  }

  async function deleteSelectedTable() {
    if (!selected || !(await studioConfirm({ title:'Excluir tabela', message:'Excluir tabela selecionada?', confirmLabel:'Excluir', danger:true }))) return Promise.resolve();
    return runAction(async () => {
      await API.deleteTable(selected);
      setSelected(null);
      setDetail(null);
    });
  }

  async function editSelectedTable() {
    if (!selected || !detail) return;
    const values = await studioForm({
      title: 'Alterar tabela',
      submitLabel: 'Salvar tabela',
      fields: [
        { name:'name', label:'Nome da tabela', required:true, defaultValue: detail.name || '' },
        { name:'description', label:'Descrição', type:'textarea', defaultValue: detail.schema_json?.description || detail.description || '' },
        { name:'tenant_id', label:'Tenant', defaultValue: detail.tenant_id || '' },
      ],
    });
    if (!values) return;
    runAction(async () => {
      await API.updateTable(selected, { name: values.name.trim(), description: values.description || '', tenant_id: values.tenant_id || null });
      setDetail(await API.get(`/api/data-tables/${selected}`));
    });
  }

  async function addColumn() {
    if (!selected) return;
    const values = await studioForm({ title:'Adicionar coluna', submitLabel:'Adicionar', fields:[
      { name:'name', label:'Nome da coluna', required:true },
      { name:'type', label:'Tipo', type:'select', defaultValue:'text', options:[
        { value:'text', label:'Texto' },
        { value:'number', label:'Número' },
        { value:'date', label:'Data' },
        { value:'boolean', label:'Booleano' },
      ]},
    ]});
    if (!values) return;
    runAction(async () => {
      await API.addColumn(selected, { name: values.name.trim(), type: values.type || 'text' });
      setDetail(await API.get(`/api/data-tables/${selected}`));
    });
  }

  async function addRecord() {
    if (!selected) return;
    const values = await studioForm({ title:'Adicionar linha', description:'Informe JSON simples para criar a linha.', submitLabel:'Adicionar linha', fields:[
      { name:'data', label:'Dados da linha', type:'textarea', rows:8, defaultValue:'{"nome": "Novo registro"}', required:true },
    ]});
    if (!values) return;
    runAction(async () => {
      await API.addRecord(selected, { data: JSON.parse(values.data) });
      setDetail(await API.get(`/api/data-tables/${selected}`));
    });
  }

  const columns = fieldNames(detail);
  const displayColumns = pickDisplayColumns(columns);
  const hiddenColumnCount = Math.max(0, columns.length - displayColumns.length);
  const tableDescription = detail?.schema_json?.description || detail?.description || 'Sem descricao registrada.';
  window.openTableCreateModal = openTableCreateModal;
  window.deleteSelectedTable = deleteSelectedTable;

  return (
    <>
      <PageTitle
        eyebrow="Dados - tabelas"
        title="Tabelas operacionais"
        sub="Perfis de tabelas para abrir, revisar e manter os dados usados pelos agentes."
        action={<button className="tb-btn primary" onClick={openTableCreateModal}><Icon name="plus" size={12}/> Nova tabela</button>}
      />
      <div className="page">
        <span id="table-create-modal" hidden></span>
        <div className="tables-workbench">
          <div className="panel table-list-panel">
            <div className="panel-head"><div><div className="panel-title">Perfis de tabelas</div><div className="panel-eyebrow">{(data.tables || []).length} tabelas cadastradas</div></div></div>
            <div className="table-profile-list">
              {(data.tables || []).map(table => {
                const count = fieldNames(table).length;
                const active = String(selected) === String(table.id);
                return (
                  <button key={table.id} className={`table-profile-card ${active ? 'active' : ''}`} onClick={() => setSelected(table.id)}>
                    <span className="table-profile-kicker">Tabela</span>
                    <strong className="mono">{table.name}</strong>
                    <span>{table.description || table.schema_json?.description || 'Dados operacionais'}</span>
                    <em>{count} colunas · {table.record_count || 0} linhas</em>
                  </button>
                );
              })}
              {!(data.tables || []).length && <div className="empty">Nenhuma tabela criada.</div>}
            </div>
          </div>
          <div className={`panel table-detail-panel table-profile-panel ${fullscreen ? 'table-profile-fullscreen' : ''}`}>
            <div className="panel-head">
              <div><div className="panel-title">{detail ? detail.name : 'Tabela'}</div><div className="panel-eyebrow">{detail ? `${columns.length} colunas - ${(detail.records || []).length} linhas carregadas` : 'selecione uma tabela'}</div></div>
              {detail && <div className="row-actions"><button className="tb-btn ghost" onClick={() => setFullscreen(!fullscreen)}>{fullscreen ? 'Sair da tela cheia' : 'Tela cheia'}</button><button className="tb-btn ghost" onClick={editSelectedTable}>Alterar tabela</button><button className="tb-btn danger" onClick={deleteSelectedTable}>Excluir tabela</button><button className="tb-btn" onClick={addColumn}>Adicionar coluna</button><button className="tb-btn primary" onClick={addRecord}>Adicionar linha</button></div>}
            </div>
            {detail ? (
              <>
                <div className="table-profile-summary">
                  <div><span>Descricao</span><strong>{tableDescription}</strong></div>
                  <div><span>Colunas</span><strong>{columns.length}</strong></div>
                  <div><span>Linhas</span><strong>{(detail.records || []).length}</strong></div>
                  <div><span>Campos visiveis</span><strong>{displayColumns.length}{hiddenColumnCount ? ` + ${hiddenColumnCount}` : ''}</strong></div>
                </div>
                <div className="data-table-wrap table-profile-records">
                  <table className="dt">
                    <thead><tr>{displayColumns.map(col => <th key={col}>{col}</th>)}{hiddenColumnCount > 0 && <th>Extras</th>}<th></th></tr></thead>
                    <tbody>
                      {(detail.records || []).map(record => (
                        <tr key={record.id}>
                          {displayColumns.map(col => {
                            const raw = (record.data || {})[col];
                            return <td key={col} data-label={col} className={recordCellClass(col)} title={String(raw ?? '')}><span className="cell-preview">{truncateText(raw, fullscreen ? 900 : 260)}</span></td>;
                          })}
                          {hiddenColumnCount > 0 && <td data-label="Extras"><span className="record-count-pill">+{hiddenColumnCount} colunas</span></td>}
                          <td data-label="" className="actions-cell"><button className="tb-btn danger" onClick={async () => (await studioConfirm({ title:'Excluir linha', message:'Excluir esta linha?', confirmLabel:'Excluir', danger:true })) && runAction(async () => {
                            await API.deleteRecord(record.id);
                            setDetail(await API.get(`/api/data-tables/${selected}`));
                          })}>Excluir</button></td>
                        </tr>
                      ))}
                      {!(detail.records || []).length && <EmptyRow cols={Math.max(displayColumns.length + 2, 1)} text="Sem registros."/>}
                    </tbody>
                  </table>
                </div>
              </>
            ) : <div className="empty">Selecione uma tabela para editar.</div>}
          </div>
        </div>
      </div>
    </>
  );
};

window.LogsPage = function LogsPage() {
  const [mode, setMode] = useExtraState('runs');
  const data = studioData();
  const runs = data.runs || [];
  const events = data.events || [];

  return (
    <>
      <PageTitle
        eyebrow="Telemetria - auditoria"
        title="Logs & execucoes"
        sub="Eventos Evolution e execucoes de IA com latencia, erro e conversa."
        meta={<span className="badge accent">{runs.length + events.length} registros</span>}
      />
      <div className="page">
        <div className="panel">
          <div className="panel-head">
            <div className="filter-row">
              <button className={`fp ${mode === 'runs' ? 'active' : ''}`} onClick={() => setMode('runs')}>Runs <span className="count">{runs.length}</span></button>
              <button className={`fp ${mode === 'events' ? 'active' : ''}`} onClick={() => setMode('events')}>Eventos <span className="count">{events.length}</span></button>
            </div>
          </div>
          {mode === 'runs' ? (
            <table className="dt">
              <thead><tr><th>Hora</th><th>Agente</th><th>Conversa</th><th>Status</th><th className="num">Latência</th><th>Erro</th></tr></thead>
              <tbody>
                {runs.slice(0, 200).map(run => (
                  <tr key={run.id}>
                    <td data-label="Hora" className="mono">{window.fmtTime ? window.fmtTime(run.created_at) : '--'}</td>
                    <td data-label="Agente">{agentName(run.agent_id)}</td>
                    <td data-label="Conversa" className="mono">{run.conversation_id || '--'}</td>
                    <td data-label="Status"><span className={`badge ${statusTag(run.status)}`}><span className={`sw ${statusTag(run.status)}`}/> {run.status || 'ok'}</span></td>
                    <td data-label="Latência" className="num mono">{run.latency_ms ? `${run.latency_ms} ms` : '--'}</td>
                    <td data-label="Erro" className="muted">{run.error || '--'}</td>
                  </tr>
                ))}
                {!runs.length && <EmptyRow cols="6" text="Sem execucoes registradas."/>}
              </tbody>
            </table>
          ) : (
            <table className="dt">
              <thead><tr><th>Hora</th><th>Instância</th><th>Evento</th><th>Cliente</th><th>Status</th><th>Mensagem</th></tr></thead>
              <tbody>
                {events.slice(0, 200).map(event => (
                  <tr key={event.id}>
                    <td data-label="Hora" className="mono">{window.fmtTime ? window.fmtTime(event.created_at) : '--'}</td>
                    <td data-label="Instância" className="mono">{event.instance || '--'}</td>
                    <td data-label="Evento">{event.event || '--'}</td>
                    <td data-label="Cliente" className="mono">{event.customer_phone || '--'}</td>
                    <td data-label="Status"><span className={`badge ${statusTag(event.status)}`}><span className={`sw ${statusTag(event.status)}`}/> {event.status || 'ok'}</span></td>
                    <td data-label="Mensagem" className="muted">{event.error || event.message_text || event.audio_transcription || '--'}</td>
                  </tr>
                ))}
                {!events.length && <EmptyRow cols="6" text="Sem eventos registrados."/>}
              </tbody>
            </table>
          )}
        </div>
      </div>
    </>
  );
};

window.TeamPage = function TeamPage() {
  const data = studioData();
  const [selectedType, setSelectedType] = useExtraState('team');
  const [selectedId, setSelectedId] = useExtraState(null);
  const teams = data.teams || [];
  const attendants = data.attendants || [];
  const selectedTeam = teams.find(team => String(team.id) === String(selectedId)) || teams[0] || null;
  const selectedAttendant = attendants.find(att => String(att.id) === String(selectedId)) || attendants[0] || null;
  const profile = selectedType === 'attendant' ? selectedAttendant : selectedTeam;
  const profileTeamAttendants = selectedType === 'attendant' ? attendants.filter(att => att.team_id === profile?.team_id) : [];
  const profileTeamWeight = profileTeamAttendants.reduce((sum, att) => sum + Number(att.weight || 1), 0) || 1;
  const profileWeightShare = selectedType === 'attendant' && profile ? Math.round((Number(profile.weight || 1) / profileTeamWeight) * 100) : 0;

  useExtraEffect(() => {
    if (selectedId) return;
    if (teams[0]) { setSelectedType('team'); setSelectedId(teams[0].id); return; }
    if (attendants[0]) { setSelectedType('attendant'); setSelectedId(attendants[0].id); }
  }, [teams.length, attendants.length]);

  async function createTeam() {
    const values = await studioForm({ title:'Novo time', submitLabel:'Criar time', fields:[
      { name:'name', label:'Nome do time', required:true },
      { name:'description', label:'Descrição', type:'textarea' },
    ]});
    if (!values) return;
    runAction(() => API.createTeam({ name: values.name.trim(), description: values.description || 'Time criado pelo Studio' }));
  }

  async function editTeam(team) {
    const values = await studioForm({ title:'Alterar time', submitLabel:'Salvar time', fields:[
      { name:'name', label:'Nome do time', required:true, defaultValue: team.name || '' },
      { name:'description', label:'Descrição', type:'textarea', defaultValue: team.description || '' },
    ]});
    if (!values) return;
    runAction(() => API.updateTeam(team.id, { name: values.name.trim(), description: values.description || '' }));
  }

  async function createAttendant() {
    const team = (data.teams || [])[0];
    if (!team) return studioToast('Crie um time antes.', 'bad');
    const values = await studioForm({ title:'Novo atendente', submitLabel:'Criar atendente', fields:[
      { name:'name', label:'Nome do atendente', required:true },
      { name:'email', label:'Email' },
      { name:'team_id', label:'Time', type:'select', defaultValue:String(team.id), options:(data.teams || []).map(t => ({ value:String(t.id), label:t.name })) },
      { name:'weight', label:'Peso', type:'number', defaultValue:'1' },
    ]});
    if (!values) return;
    runAction(() => API.createAttendant({ name: values.name.trim(), email: values.email || undefined, team_id: Number(values.team_id), available: true, weight: Number(values.weight || 1) }));
  }

  async function editAttendant(att) {
    const values = await studioForm({ title:'Alterar atendente', submitLabel:'Salvar atendente', fields:[
      { name:'name', label:'Nome do atendente', required:true, defaultValue: att.name || '' },
      { name:'email', label:'Email', defaultValue: att.email || '' },
      { name:'team_id', label:'Time', type:'select', defaultValue:String(att.team_id || (data.teams || [])[0]?.id || ''), options:(data.teams || []).map(t => ({ value:String(t.id), label:t.name })) },
      { name:'weight', label:'Peso', type:'number', defaultValue:String(att.weight || 1) },
    ]});
    if (!values) return;
    runAction(() => API.updateAttendant(att.id, { name: values.name.trim(), email: values.email || undefined, team_id: Number(values.team_id), weight: Number(values.weight || 1) }));
  }

  async function deleteAttendant(id) {
    return (await studioConfirm({ title:'Excluir atendente', message:'Excluir atendente?', confirmLabel:'Excluir', danger:true })) && runAction(() => API.deleteAttendant(id));
  }

  window.deleteAttendant = deleteAttendant;

  return (
    <>
      <PageTitle
        eyebrow="CRM - times"
        title="Atendentes & Times"
        sub="Distribuicao round-robin ponderada e disponibilidade de atendimento humano."
        action={<div className="row-actions"><button className="tb-btn" onClick={createTeam}>Novo time</button><button className="tb-btn primary" onClick={createAttendant}>Novo atendente</button></div>}
      />
      <div className="page">
        <div className="profile-workbench crm-profile">
          <div className="panel profile-list-panel">
            <div className="panel-head"><div className="panel-title">Times</div><span className="badge accent">{teams.length}</span></div>
            <div className="stack-list">
              {teams.map(team => (
                <button className={`entity-card selectable ${selectedType === 'team' && String(selectedId) === String(team.id) ? 'active' : ''}`} key={team.id} onClick={() => { setSelectedType('team'); setSelectedId(team.id); }}>
                  <span className="entity-copy">
                    <strong className="entity-title">{team.name}</strong>
                    <span className="entity-sub">{team.description || 'Sem descrição'}</span>
                  </span>
                  <span className="badge accent">{attendants.filter(a => a.team_id === team.id).length} atendentes</span>
                </button>
              ))}
              {!teams.length && <div className="empty">Nenhum time criado.</div>}
            </div>
            <div className="panel-head sub-head"><div className="panel-title">Atendentes</div><span className="badge accent">{attendants.length}</span></div>
            <div className="stack-list compact-stack">
              {attendants.map(att => (
                <button className={`entity-card selectable ${selectedType === 'attendant' && String(selectedId) === String(att.id) ? 'active' : ''}`} key={att.id} onClick={() => { setSelectedType('attendant'); setSelectedId(att.id); }}>
                  <span className="entity-copy"><strong className="entity-title">{att.name}</strong><span className="entity-sub">{att.team_name || '--'} - peso {att.weight}</span></span>
                  <span className={`badge ${att.available ? 'ok' : ''}`}>{att.available ? 'disponível' : 'pausado'}</span>
                </button>
              ))}
              {!attendants.length && <div className="empty">Nenhum atendente criado.</div>}
            </div>
          </div>
          <div className="panel profile-detail-panel">
            <div className="panel-head">
              <div><div className="panel-title">{selectedType === 'attendant' ? 'Perfil do atendente' : 'Perfil do time'}</div><div className="panel-eyebrow">{profile?.name || 'selecione um item'}</div></div>
              {profile && <div className="row-actions">
                {selectedType === 'attendant'
                  ? <><button className="tb-btn ghost" onClick={() => editAttendant(profile)}>Alterar</button><button className="tb-btn ghost" onClick={() => runAction(() => API.updateAttendant(profile.id, { available: !profile.available }))}>{profile.available ? 'Pausar' : 'Ativar'}</button><button className="tb-btn danger" onClick={() => deleteAttendant(profile.id)}>Excluir</button></>
                  : <button className="tb-btn ghost" onClick={() => editTeam(profile)}>Alterar</button>}
              </div>}
            </div>
            {profile ? selectedType === 'attendant' ? (
              <div className="profile-detail-body">
                <div className="detail-metrics">
                  <MiniKpi label="Status" value={profile.available ? 'disponível' : 'pausado'}/>
                  <MiniKpi label="Peso" value={String(profile.weight || 1)}/>
                  <MiniKpi label="Time" value={profile.team_name || '--'}/>
                </div>
                <div className="soft-row"><span>Email</span><strong>{profile.email || '--'}</strong></div>
                <div className="weight-visual">
                  <div className="soft-row"><span>Distribuicao round-robin</span><strong>{profileWeightShare}% estimado</strong></div>
                  <div className="weight-bar"><span style={{width: `${profileWeightShare}%`}}></span></div>
                  <div className="field-helper">Peso {profile.weight || 1} dentro do time {profile.team_name || '--'}.</div>
                </div>
                <div className="soft-row"><span>ID</span><strong className="mono">{profile.id}</strong></div>
              </div>
            ) : (
              <div className="profile-detail-body">
                <div className="detail-metrics">
                  <MiniKpi label="Atendentes" value={String(attendants.filter(a => a.team_id === profile.id).length)}/>
                  <MiniKpi label="Disponiveis" value={String(attendants.filter(a => a.team_id === profile.id && a.available).length)}/>
                  <MiniKpi label="ID" value={String(profile.id)}/>
                </div>
                <div className="soft-row"><span>Descrição</span><strong>{profile.description || 'Sem descrição'}</strong></div>
                <div className="panel-subtitle">Atendentes do time</div>
                <div className="stack-list compact-stack">
                  {attendants.filter(a => a.team_id === profile.id).map(att => <button className="entity-card selectable" key={att.id} onClick={() => { setSelectedType('attendant'); setSelectedId(att.id); }}><span className="entity-copy"><strong className="entity-title">{att.name}</strong><span className="entity-sub">{att.email || '--'}</span></span><span className={`badge ${att.available ? 'ok' : ''}`}>{att.available ? 'online' : 'pausado'}</span></button>)}
                  {!attendants.filter(a => a.team_id === profile.id).length && <div className="empty">Time sem atendentes.</div>}
                </div>
              </div>
            ) : <div className="empty">Selecione um time ou atendente.</div>}
          </div>
        </div>
      </div>
    </>
  );
};

window.TagsPage = function TagsPage() {
  const data = studioData();

  async function createTag() {
    const values = await studioForm({ title:'Nova tag', submitLabel:'Criar tag', fields:[
      { name:'name', label:'Nome da tag', required:true },
      { name:'color', label:'Cor hex', defaultValue:'#1d4ed8' },
      { name:'description', label:'Descrição', type:'textarea' },
    ]});
    if (!values) return;
    runAction(() => API.createTag({ name: values.name.trim(), color: values.color || '#1d4ed8', description: values.description || 'Tag criada pelo Studio' }));
  }

  async function editTag(tag) {
    const values = await studioForm({ title:'Alterar tag', submitLabel:'Salvar tag', fields:[
      { name:'name', label:'Nome da tag', required:true, defaultValue: tag.name || '' },
      { name:'color', label:'Cor hex', defaultValue: tag.color || '#1d4ed8' },
      { name:'description', label:'Descrição', type:'textarea', defaultValue: tag.description || '' },
    ]});
    if (!values) return;
    runAction(() => API.updateTag(tag.id, { name: values.name.trim(), color: values.color || '#1d4ed8', description: values.description || '' }));
  }

  async function deleteTag(id) {
    return (await studioConfirm({ title:'Excluir tag', message:'Excluir tag?', confirmLabel:'Excluir', danger:true })) && runAction(() => API.deleteTag(id));
  }

  window.deleteTag = deleteTag;

  return (
    <>
      <PageTitle
        eyebrow="CRM - classificação"
        title="Tags & contexto"
        sub="Tags com cor e descrição para tickets e filtros operacionais."
        action={<button className="tb-btn primary" onClick={createTag}><Icon name="plus" size={12}/> Nova tag</button>}
      />
      <div className="page">
        <div className="module-grid-even">
          {(data.tags || []).map(tag => (
            <div className="panel tag-card" key={tag.id}>
              <div className="tag-swatch" style={{ background: tag.color || 'var(--accent)' }}/>
              <div>
                <div className="panel-title">{tag.name}</div>
                <div className="muted">{tag.description || 'Sem descrição'}</div>
              </div>
              <div className="row-actions">
                <button className="tb-btn ghost" onClick={() => editTag(tag)}>Alterar</button>
                <button className="tb-btn danger" onClick={() => deleteTag(tag.id)}>Excluir</button>
              </div>
            </div>
          ))}
          {!(data.tags || []).length && <div className="panel empty">Nenhuma tag criada.</div>}
        </div>
      </div>
    </>
  );
};

