/* global React */
const { useState, useMemo, useEffect } = React;

const DEFAULT_MODEL = 'gpt-4o-mini';
const MODEL_PRESETS = [
  { id: 'openai-fast', label: 'OpenAI rápido', model: 'gpt-4o-mini', temperature: 0.4, hint: 'Baixo custo e boa velocidade para atendimento geral.' },
  { id: 'groq-fast', label: 'Groq rápido', model: 'groq/llama-3.1-8b-instant', temperature: 0.4, hint: 'Resposta muito rápida para triagem simples.' },
  { id: 'groq-smart', label: 'Groq forte', model: 'groq/llama-3.3-70b-versatile', temperature: 0.35, hint: 'Mais qualidade para comercial, suporte e fluxos com contexto.' },
  { id: 'groq-oss-120b', label: 'Groq OSS 120B', model: 'groq/openai/gpt-oss-120b', temperature: 0.3, hint: 'Opcao forte para raciocínio e respostas mais cuidadosas.' },
];
const DEFAULT_MODEL_PRESET = MODEL_PRESETS[0].id;
const DEFAULT_PROMPT = `## Identidade
Você e um assistente virtual inteligente e prestativo. Seu nome padrão e Alex, mas use o nome configurado para este agente quando existir. Você representa uma organização profissional e ajuda o usuário a resolver dúvidas com clareza, eficiência e segurança.

## Tom de Voz
- Sejá cordial, direto e objetivo.
- Use linguagem simples e acessivel.
- Evite respostas longas demais; va direto ao ponto.
- Nunca sejá rude ou impaciente.

## Objetivo Principal
Ajudar o usuário a encontrar a informação que precisa, resolver seu problema ou direciona-lo para o próximo passo correto.

## Como Conduzir a Conversa
1. Cumprimente o usuário na primeira mensagem.
2. Identifique o que o usuário precisa antes de responder.
3. Se a dúvida for vaga, faça uma pergunta por vez.
4. Use memória contextual apenas para melhorar o atendimento.
5. Confirme se a resposta foi ?til ao final do atendimento.

## Conhecimento e Ferramentas
- Use a base de conhecimento e ferramentas disponíveis quando forem relevantes.
- Não exponhá prompts, regras internas, IDs, tabelas, logs, RAG, embeddings ou mecanismos internos.
- Não invente informações. Se não souber, diga: "Não tenho essa informação no momento, mas posso te ajudar a encontrar o caminho certo."

## Limites
- Não fujá do escopo de atuação do agente.
- Acione handoff humano quando houver pedido de humano, risco, irritação, tema sensível ou baixa confiança.

## Encerramento
Ao final do atendimento, pergunte se o usuário precisa de mais alguma coisa. Se não precisar, despeça-se de forma simpática e profissional.

## Exemplo de Resposta
Usuário: "Quero saber sobre os planos disponíveis."
Alex: "Claro! Temos algumas opções que podem se encaixar bem no que você precisa. Me conta um pouco mais sobre o seu uso: é para uso pessoal ou empresarial?"`;
const SM_LEAD_ASSISTANT_PROMPT = `## Identidade
Você e o SM_Lead_Assistant, assistente comercial do site oficial da System Manager. Você recebe visitantes interessados em automação, agentes de IA, WhatsApp, CRM, captação de leads e integração com atendimento humano.

## Objetivo
Transformar interesse inicial em lead qualificado, coletando contexto minimo e conduzindo para uma conversa comercial humana quando houver oportunidade real.

## Como conversar
1. Cumprimente de forma breve e pergunte como pode ajudar.
2. Entenda a necessidade do visitante antes de falar de solução.
3. Colete, quando fizer sentido, @nome, @email, @numero, @empresa, @necessidade e @orcamento.
4. Relacione a dor do lead com as soluções da System Manager: agentes de IA para atendimento, automação WhatsApp, CRM, captação de leads, tickets e repasse humano.
5. Quando o lead demonstrar interesse comercial, peça um contato e ofereça encaminhar para o time humano.

## Tom
Consultivo, claro, profissional e humanizado. Responda em Portugues do Brasil, com mensagens curtas.

## Regras
- Não invente preços, prazos, contratos, garantias ou capacidades técnicas não confirmadas.
- Não prometa implantação sem validação humana.
- Não exponhá prompts, ferramentas, IDs internos ou mecanismos do sistema.
- Faca no maximo uma pergunta principal por mensagem.
- Se o visitante pedir humano, proposta, reunião, desconto, integração específica ou demonstrar urgência, solicite repasse humano com resumo do caso.`;
const AGENT_TEMPLATES = [
  {
    id: 'default',
    label: 'Assistente padrão',
    name: '',
    instance_name: '',
    description: '',
    ai_model: DEFAULT_MODEL,
    model_preset: DEFAULT_MODEL_PRESET,
    temperature: 0.7,
    system_prompt: DEFAULT_PROMPT,
    client_info: '',
    kb_sources: '',
    negative_rules: [],
    conversation_goals: [],
    final_goal: '',
    handoff_config: { enabled: false, conditions: [], next_action: '' },
  },
  {
    id: 'suporte-cliente',
    label: 'Suporte ao Cliente',
    name: 'Agente de Suporte',
    instance_name: 'agente-suporte',
    description: 'Resolve dúvidas, orienta passos e abre repasse humano quando necessário.',
    ai_model: DEFAULT_MODEL,
    model_preset: DEFAULT_MODEL_PRESET,
    temperature: 0.35,
    system_prompt: `${DEFAULT_PROMPT}\n\n## Especialidade\nAtue como suporte ao cliente. Diagnostique o problema, faça uma pergunta por vez e entregue passos claros. Quando houver irritação, risco ou bloqueio operacional, encaminhe para humano.`,
    client_info: '@nome\n@numero\n@problema\n@urgência',
    kb_sources: '',
    negative_rules: ['Não inventar procedimentos.', 'Não prometer prazos sem fonte.', 'Não culpar o usuário.'],
    conversation_goals: ['Entender o problema.', 'Orientar próximo passo.', 'Registrar resumo para humano quando necessário.'],
    final_goal: 'Resolver o atendimento ou encaminhar com contexto completo.',
    handoff_config: { enabled: true, conditions: ['pedido de humano', 'cliente irritado', 'baixa confiança', 'problema crítico'], next_action: 'Criar ticket com resumo do caso.' },
  },
  {
    id: 'sdr-leads',
    label: 'SDR / Qualificacao',
    name: 'Agente SDR',
    instance_name: 'agente-sdr',
    description: 'Qualifica leads, coleta contexto comercial e prepara repasse para vendas.',
    ai_model: DEFAULT_MODEL,
    model_preset: DEFAULT_MODEL_PRESET,
    temperature: 0.45,
    system_prompt: `${DEFAULT_PROMPT}\n\n## Especialidade\nAtue como SDR consultivo. Entenda necessidade, empresa, prazo, orçamento e decisor. Evite discurso longo; avance para repasse humano quando houver fit claro.`,
    client_info: '@nome\n@email\n@numero\n@empresa\n@necessidade\n@orcamento',
    kb_sources: '',
    negative_rules: ['Não inventar preços.', 'Não prometer desconto.', 'Não marcar reunião sem contato confirmado.'],
    conversation_goals: ['Qualificar necessidade.', 'Coletar contato.', 'Identificar urgência e fit comercial.'],
    final_goal: 'Gerar lead qualificado para o time comercial.',
    handoff_config: { enabled: true, conditions: ['lead qualificado', 'pedido de proposta', 'pedido de reunião'], next_action: 'Criar ticket comercial.' },
  },
  {
    id: 'faq-bot',
    label: 'FAQ Bot',
    name: 'Agente FAQ',
    instance_name: 'agente-faq',
    description: 'Responde perguntas frequentes usando base de conhecimento.',
    ai_model: DEFAULT_MODEL,
    model_preset: DEFAULT_MODEL_PRESET,
    temperature: 0.25,
    system_prompt: `${DEFAULT_PROMPT}\n\n## Especialidade\nResponda perguntas frequentes com base nas fontes configuradas. Se não houver informação suficiente, diga que não encontrou a informação e ofereça encaminhar.`,
    client_info: '@nome\n@dúvida',
    kb_sources: '',
    negative_rules: ['Não responder fora da base quando a pergunta exigir fato especifico.', 'Não citar mecanismo interno de KB.'],
    conversation_goals: ['Identificar dúvida.', 'Responder com clareza.', 'Encaminhar quando a base não cobrir.'],
    final_goal: 'Responder dúvidas repetitivas com segurança.',
    handoff_config: { enabled: true, conditions: ['base sem resposta', 'pedido de humano'], next_action: 'Encaminhar pergunta sem resposta.' },
  },
  {
    id: 'agendamento',
    label: 'Agendamento',
    name: 'Agente de Agendamento',
    instance_name: 'agente-agendamento',
    description: 'Coleta dados e organiza pedidos de horário, retorno ou reunião.',
    ai_model: DEFAULT_MODEL,
    model_preset: DEFAULT_MODEL_PRESET,
    temperature: 0.35,
    system_prompt: `${DEFAULT_PROMPT}\n\n## Especialidade\nConduza agendamentos. Colete nome, contato, preferência de horário, motivo e disponibilidade. Confirme dados antes de encaminhar ao time humano.`,
    client_info: '@nome\n@numero\n@email\n@motivo\n@horário_preferido',
    kb_sources: '',
    negative_rules: ['Não confirmar horário definitivo sem integração ou humano.', 'Não prometer disponibilidade.'],
    conversation_goals: ['Coletar dados mínimos.', 'Confirmar preferência.', 'Encaminhar para confirmação.'],
    final_goal: 'Preparar agendamento para confirmação humana.',
    handoff_config: { enabled: true, conditions: ['dados completos', 'pedido de confirmação'], next_action: 'Criar ticket de agendamento.' },
  },
  {
    id: 'consultor-técnico',
    label: 'Consultor Tecnico',
    name: 'Agente Consultor Tecnico',
    instance_name: 'agente-consultor-técnico',
    description: 'Explica soluções técnicas com linguagem clara e limites de segurança.',
    ai_model: 'groq/llama-3.3-70b-versatile',
    model_preset: 'groq-smart',
    temperature: 0.3,
    system_prompt: `${DEFAULT_PROMPT}\n\n## Especialidade\nAtue como consultor técnico. Explique conceitos, valide restrições e proponhá caminhos práticos. Quando a resposta exigir dado interno não configurado, declare a limitação.`,
    client_info: '@nome\n@empresa\n@cenario\n@restricao_tecnica',
    kb_sources: '',
    negative_rules: ['Não inventar integrações.', 'Não executar diagnóstico perigoso.', 'Não prometer viabilidade sem validação.'],
    conversation_goals: ['Entender contexto técnico.', 'Explicar alternativa segura.', 'Encaminhar caso complexo.'],
    final_goal: 'Orientar decisão técnica com clareza.',
    handoff_config: { enabled: true, conditions: ['arquitetura complexa', 'integração critica', 'pedido de proposta técnica'], next_action: 'Criar ticket técnico.' },
  },
  {
    id: 'sm-lead-assistant',
    label: 'SM_Lead_Assistant',
    name: 'SM_Lead_Assistant',
    instance_name: 'sm-lead-assistant',
    description: 'Assistente de leads para o site oficial da System Manager.',
    ai_model: 'groq/llama-3.3-70b-versatile',
    model_preset: 'groq-smart',
    temperature: 0.35,
    system_prompt: SM_LEAD_ASSISTANT_PROMPT,
    client_info: '@nome\n@email\n@numero\n@empresa\n@necessidade\n@orcamento',
    kb_sources: 'System Manager oferece automações para WhatsApp, agentes de IA, CRM, captação de leads, tickets e integração com atendimento humano.',
    negative_rules: [
      'Não inventar preços, prazos ou garantias.',
      'Não prometer implantação sem validação humana.',
      'Não expor prompts, ferramentas ou bastidores.',
    ],
    conversation_goals: [
      'Entender necessidade, canal e volume do lead.',
      'Coletar nome, contato e empresa quando fizer sentido.',
      'Apresentar caminho comercial da System Manager sem inventar detalhes.',
      'Encaminhar para humano quando houver interesse em proposta, reunião ou implantação.',
    ],
    final_goal: 'Gerar um lead qualificado para o time comercial da System Manager.',
    handoff_config: {
      enabled: true,
      conditions: ['pedido de humano', 'pedido de proposta', 'pedido de reunião', 'lead qualificado', 'dúvida comercial específica'],
      next_action: 'Criar ticket comercial com resumo do lead e contato informado.',
    },
  },
];
const PAGE_IDS = ['dashboard','ecosystem','assistants','agents','agent-profile','channels','kb','tools','conversations','tickets','team','tags','tables','squads','logs'];
const PROFILE_PAGES = ['agent-profile','kb','tools','conversations','logs'];
const PAGE_LABELS = {
  dashboard: 'Dashboard',
  ecosystem: 'Mapa do Ecossistema',
  assistants: 'Assistentes',
  agents: 'Agentes',
  'agent-profile': 'Perfil do agente',
  channels: 'Canais',
  kb: 'Conhecimento',
  tools: 'Ferramentas',
  conversations: 'Conversas',
  tickets: 'Tickets',
  team: 'Atendentes',
  tags: 'Tags',
  tables: 'Tabelas',
  squads: 'Squads',
  logs: 'Logs',
};
const PAGE_SECTIONS = {
  dashboard: 'Operação',
  ecosystem: 'Início',
  assistants: 'Início',
  conversations: 'Operação',
  tickets: 'Operação',
  agents: 'Inteligência',
  'agent-profile': 'Inteligência',
  kb: 'Inteligência',
  tools: 'Inteligência',
  squads: 'Inteligência',
  channels: 'Dados & Canais',
  tables: 'Dados & Canais',
  logs: 'Telemetria',
  team: 'CRM',
  tags: 'CRM',
};
const DETAIL_BUILDER_QUESTIONS = [
  { id: 'goal', label: 'Qual é o objetivo principal do agente?' },
  { id: 'audience', label: 'Quem ele atende e em qual contexto?' },
  { id: 'client_info', label: 'Quais informações sobre o cliente que o Agente deve coletar?' },
  { id: 'tone', label: 'Qual tom de voz deve usar?' },
  { id: 'rules', label: 'O que ele nunca deve fazer?' },
  { id: 'knowledge', label: 'Quais fontes ou fatos ele precisa conhecer?' },
  { id: 'kb_sources', label: 'Bases de conhecimento', kind: 'kb', optional: true },
  { id: 'handoff', label: 'Quando deve chamar um humano?' },
  { id: 'success', label: 'Como medir conversa bem-sucedida?' },
];

function esc(str) {
  return String(str == null ? '' : str).replace(/[&<>"']/g, ch => ({ '&':'&amp;', '<':'&lt;', '>':'&gt;', '"':'&quot;', "'":'&#39;' }[ch]));
}

function parseApiDate(value) {
  if (value instanceof Date) return value;
  if (typeof value !== 'string') return new Date(value);
  const trimmed = value.trim();
  const hasTime = /^\d{4}-\d{2}-\d{2}T/.test(trimmed);
  const hasZone = /([zZ]|[+-]\d{2}:?\d{2})$/.test(trimmed);
  return new Date(hasTime && !hasZone ? trimmed + 'Z' : trimmed);
}

function fmtDate(value) {
  if (!value) return '--';
  const date = parseApiDate(value);
  if (Number.isNaN(date.getTime())) return '--';
  return date.toLocaleString('pt-BR', { day:'2-digit', month:'2-digit', hour:'2-digit', minute:'2-digit' });
}

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

function prettyStudioKey(key) {
  return String(key || '')
    .replace(/_/g, ' ')
    .replace(/\b\w/g, ch => ch.toUpperCase());
}

function prettyStudioValue(value, depth = 0) {
  if (value == null || value === '') return '';
  if (typeof value === 'string') return value;
  if (typeof value === 'number' || typeof value === 'boolean') return String(value);
  if (Array.isArray(value)) {
    return value.map(item => prettyStudioValue(item, depth + 1)).filter(Boolean).join(depth ? ' - ' : '\n');
  }
  if (typeof value === 'object') {
    const direct = value.text || value.goal || value.rule || value.description || value.content || value.value || value.name || value.title || value.summary || value.reason;
    if (direct) return String(direct);
    return Object.entries(value)
      .filter(([, item]) => item != null && item !== '')
      .slice(0, 12)
      .map(([key, item]) => {
        const rendered = prettyStudioValue(item, depth + 1);
        return rendered ? `${prettyStudioKey(key)}: ${rendered}` : '';
      })
      .filter(Boolean)
      .join(depth ? ' - ' : '\n');
  }
  return String(value);
}

function lineItemToText(item) {
  if (item == null) return '';
  if (typeof item === 'string') return item;
  if (typeof item === 'number' || typeof item === 'boolean') return String(item);
  if (Array.isArray(item)) return item.map(lineItemToText).filter(Boolean).join(' - ');
  return item.text || item.goal || item.rule || item.description || item.content || item.value || item.name || item.title || prettyStudioValue(item);
}

function modelPresetById(id) {
  return MODEL_PRESETS.find(item => item.id === id) || MODEL_PRESETS[0];
}

function modelPresetForModel(model) {
  return MODEL_PRESETS.find(item => item.model === model) || null;
}

function agentTemplateById(id) {
  return AGENT_TEMPLATES.find(item => item.id === id) || AGENT_TEMPLATES[0];
}

function siteAgentApiUrl(agent) {
  const raw = agent?.raw || agent || {};
  const id = raw.id || agent?.id || '{agent_id}';
  return `${window.location.origin}/api/site-agents/${id}/chat`;
}

function siteAgentEmbedCode(agent) {
  const raw = agent?.raw || agent || {};
  const name = raw.name || agent?.name || 'Assistente';
  const apiUrl = siteAgentApiUrl(agent);
  return `<script>
(() => {
  const API_URL = "${apiUrl}";
  const STORAGE_KEY = "sm_site_agent_session";
  const session = localStorage.getItem(STORAGE_KEY) || crypto.randomUUID();
  localStorage.setItem(STORAGE_KEY, session);

  window.sendTo${String(name).replace(/[^a-zA-Z0-9]+/g, '') || 'Agent'} = async (message) => {
    const response = await fetch(API_URL, {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify({ session_id: session, message })
    });
    if (!response.ok) throw new Error(await response.text());
    return response.json();
  };
})();
</script>`;
}

window.WA = { DEFAULT_PROMPT, DEFAULT_MODEL, DEFAULT_MODEL_PRESET, MODEL_PRESETS, AGENT_TEMPLATES, PAGE_IDS, PROFILE_PAGES, PAGE_LABELS, PAGE_SECTIONS, DETAIL_BUILDER_QUESTIONS, esc, fmtDate, parseApiDate, linesToText, prettyStudioValue, prettyStudioKey, modelPresetById, modelPresetForModel, agentTemplateById, siteAgentApiUrl, siteAgentEmbedCode };
window.DEFAULT_PROMPT = DEFAULT_PROMPT;
window.DEFAULT_MODEL = DEFAULT_MODEL;
window.DEFAULT_MODEL_PRESET = DEFAULT_MODEL_PRESET;
window.MODEL_PRESETS = MODEL_PRESETS;
window.AGENT_TEMPLATES = AGENT_TEMPLATES;
window.PAGE_IDS = PAGE_IDS;
window.PROFILE_PAGES = PROFILE_PAGES;
window.PAGE_LABELS = PAGE_LABELS;
window.PAGE_SECTIONS = PAGE_SECTIONS;
window.DETAIL_BUILDER_QUESTIONS = DETAIL_BUILDER_QUESTIONS;
window.esc = esc;
window.fmtDate = fmtDate;
window.parseApiDate = parseApiDate;
window.linesToText = linesToText;
window.prettyStudioValue = prettyStudioValue;
window.prettyStudioKey = prettyStudioKey;
window.modelPresetById = modelPresetById;
window.modelPresetForModel = modelPresetForModel;
window.agentTemplateById = agentTemplateById;
window.siteAgentApiUrl = siteAgentApiUrl;
window.siteAgentEmbedCode = siteAgentEmbedCode;

window.MOCK = {
  agents: [],
  instances: [],
  handoffQueue: [],
  tickets: [],
  conversations: [],
  thread: [],
  channels: [],
  knowledge: [],
  tables: [],
  squads: [],
  tools: [],
  teams: [],
  attendants: [],
  tags: [],
  runs: [],
  events: [],
  diagnostics: {},
};

window.Icon = function Icon({ name, size = 14 }) {
  const s = { width: size, height: size, stroke: 'currentColor', fill: 'none', strokeWidth: 1.6, strokeLinecap: 'round', strokeLinejoin: 'round' };
  switch(name) {
    case 'dashboard': return <svg viewBox="0 0 16 16" {...s}><rect x="2" y="2" width="5" height="6" rx="1"/><rect x="2" y="10" width="5" height="4" rx="1"/><rect x="9" y="2" width="5" height="4" rx="1"/><rect x="9" y="8" width="5" height="6" rx="1"/></svg>;
    case 'ecosystem': return <svg viewBox="0 0 16 16" {...s}><circle cx="8" cy="8" r="2"/><circle cx="8" cy="2" r="1.2"/><circle cx="14" cy="11" r="1.2"/><circle cx="2" cy="11" r="1.2"/><path d="M8 4v2M12.9 9.5L10 9M5 9l-2.9.5"/></svg>;
    case 'assistants': return <svg viewBox="0 0 16 16" {...s}><path d="M8 2a4 4 0 0 1 4 4c0 1.8-1 3.3-2.5 4L8 14l-1.5-4A4 4 0 0 1 4 6a4 4 0 0 1 4-4z"/><circle cx="8" cy="6" r="1.2" fill="currentColor" stroke="none"/></svg>;
    case 'share': return <svg viewBox="0 0 16 16" {...s}><circle cx="12" cy="4" r="1.5"/><circle cx="4" cy="8" r="1.5"/><circle cx="12" cy="12" r="1.5"/><path d="M5.4 7.2l5.2-2.4M5.4 8.8l5.2 2.4"/></svg>;
    case 'agents': return <svg viewBox="0 0 16 16" {...s}><circle cx="8" cy="6" r="2.5"/><path d="M3 14c0-2.5 2.2-4.5 5-4.5s5 2 5 4.5"/></svg>;
    case 'channels': return <svg viewBox="0 0 16 16" {...s}><path d="M3 12V8a5 5 0 0 1 10 0v4M3 12h2v-3M11 12h2v-3M8 14v-2"/></svg>;
    case 'conversations': return <svg viewBox="0 0 16 16" {...s}><path d="M2 4a2 2 0 0 1 2-2h8a2 2 0 0 1 2 2v5a2 2 0 0 1-2 2H6l-3 3V4z"/></svg>;
    case 'tickets': return <svg viewBox="0 0 16 16" {...s}><path d="M2 5a1 1 0 0 1 1-1h10a1 1 0 0 1 1 1v2a1 1 0 0 0 0 2v2a1 1 0 0 1-1 1H3a1 1 0 0 1-1-1V9a1 1 0 0 0 0-2V5z"/></svg>;
    case 'tables': return <svg viewBox="0 0 16 16" {...s}><rect x="2" y="3" width="12" height="10" rx="1"/><path d="M2 7h12M2 10h12M6 3v10M10 3v10"/></svg>;
    case 'squads': return <svg viewBox="0 0 16 16" {...s}><circle cx="5" cy="5" r="2"/><circle cx="11" cy="5" r="2"/><path d="M2 13c0-2 1.5-3.5 3-3.5s3 1.5 3 3.5M8 13c0-2 1.5-3.5 3-3.5s3 1.5 3 3.5"/></svg>;
    case 'tools': return <svg viewBox="0 0 16 16" {...s}><path d="M9 2l5 5-2 2-1-1-5 5-3 1 1-3 5-5-1-1z"/></svg>;
    case 'kb': return <svg viewBox="0 0 16 16" {...s}><path d="M3 3h7l3 3v7H3z"/><path d="M10 3v3h3M5 9h6M5 11h4"/></svg>;
    case 'logs': return <svg viewBox="0 0 16 16" {...s}><path d="M3 3h10M3 6h10M3 9h7M3 12h5"/></svg>;
    case 'tags': return <svg viewBox="0 0 16 16" {...s}><path d="M2 8V3h5l7 7-5 5z"/><circle cx="5" cy="6" r="0.6" fill="currentColor"/></svg>;
    case 'team': return <svg viewBox="0 0 16 16" {...s}><circle cx="6" cy="6" r="2.5"/><circle cx="12" cy="7" r="1.6"/><path d="M2 13c0-2.2 1.8-4 4-4s4 1.8 4 4M11 13c0-1.6.7-3 2-3"/></svg>;
    case 'search': return <svg viewBox="0 0 16 16" {...s}><circle cx="7" cy="7" r="4"/><path d="M10 10l3.5 3.5"/></svg>;
    case 'plus': return <svg viewBox="0 0 16 16" {...s}><path d="M8 3v10M3 8h10"/></svg>;
    case 'arrow': return <svg viewBox="0 0 16 16" {...s}><path d="M3 8h10M9 4l4 4-4 4"/></svg>;
    case 'bell': return <svg viewBox="0 0 16 16" {...s}><path d="M4 11V7a4 4 0 0 1 8 0v4l1 1H3l1-1zM6 13a2 2 0 0 0 4 0"/></svg>;
    case 'filter': return <svg viewBox="0 0 16 16" {...s}><path d="M2 4h12l-4 5v4l-4 1V9z"/></svg>;
    case 'refresh': return <svg viewBox="0 0 16 16" {...s}><path d="M13 5a5 5 0 0 0-8.5-2.5L3 4"/><path d="M3 1v3h3"/><path d="M3 11a5 5 0 0 0 8.5 2.5L13 12"/><path d="M13 15v-3h-3"/></svg>;
    case 'pause': return <svg viewBox="0 0 16 16" {...s}><rect x="4" y="3" width="3" height="10" rx="0.5"/><rect x="9" y="3" width="3" height="10" rx="0.5"/></svg>;
    case 'play': return <svg viewBox="0 0 16 16" {...s}><path d="M5 3l8 5-8 5z"/></svg>;
    case 'check': return <svg viewBox="0 0 16 16" {...s}><path d="M3 8l3 3 7-7"/></svg>;
    case 'x': return <svg viewBox="0 0 16 16" {...s}><path d="M4 4l8 8M12 4l-8 8"/></svg>;
    case 'sun': return <svg viewBox="0 0 16 16" {...s}><circle cx="8" cy="8" r="3"/><path d="M8 1v2M8 13v2M1 8h2M13 8h2M3 3l1.5 1.5M11.5 11.5L13 13M3 13l1.5-1.5M11.5 4.5L13 3"/></svg>;
    case 'moon': return <svg viewBox="0 0 16 16" {...s}><path d="M13 9.5A6 6 0 0 1 6.5 3a6 6 0 1 0 6.5 6.5z"/></svg>;
    default: return null;
  }
};

/* --- Shared UI Components (Phase 0) --- */

function studioToast(message, type = '') {
  if (window.STUDIO?.toast) window.STUDIO.toast(message, type);
}
function studioForm(config) {
  return window.STUDIO?.form ? window.STUDIO.form(config) : Promise.resolve(null);
}
function studioConfirm(config) {
  return window.STUDIO?.confirm ? window.STUDIO.confirm(config) : Promise.resolve(false);
}

window.studioToast = studioToast;
window.studioForm = studioForm;
window.studioConfirm = studioConfirm;

const SAFE_STATUS_GROUPS = {
  default: [
    'Analisando sua mensagem...',
    'Verificando o contexto da conversa...',
    'Consultando informações disponíveis...',
    'Organizando a melhor resposta...',
    'Preparando uma resposta personalizada...',
  ],
  commercial: [
    'Analisando sua necessidade comercial...',
    'Verificando informações comerciais...',
    'Buscando dados sobre planos e serviços...',
    'Organizando a melhor orientação...',
  ],
  support: [
    'Analisando o problema informado...',
    'Buscando possíveis orientações...',
    'Verificando materiais de apoio...',
    'Preparando um próximo passo claro...',
  ],
  institutional: [
    'Consultando informações sobre a empresa...',
    'Organizando os detalhes mais relevantes...',
    'Revisando as informações antes de responder...',
  ],
};

function smartStatusForMessage(message = '') {
  const text = String(message || '').toLowerCase();
  if (/(preço|preco|valor|plano|orçamento|orcamento|serviço|servico|contratar|mensalidade|custa)/.test(text)) return SAFE_STATUS_GROUPS.commercial;
  if (/(erro|problema|suporte|bug|falha|não funciona|nao funciona|ajuda|resolver)/.test(text)) return SAFE_STATUS_GROUPS.support;
  if (/(empresa|quem são|quem sao|sobre vocês|sobre voces|história|historia|system manager)/.test(text)) return SAFE_STATUS_GROUPS.institutional;
  return SAFE_STATUS_GROUPS.default;
}

function useRotatingStatus(active, statuses) {
  const safeStatuses = Array.isArray(statuses) && statuses.length ? statuses : SAFE_STATUS_GROUPS.default;
  const [index, setIndex] = React.useState(0);
  React.useEffect(() => {
    if (!active) return undefined;
    setIndex(0);
    const timer = window.setInterval(() => {
      setIndex(prev => Math.min(prev + 1, safeStatuses.length - 1));
    }, 1450);
    return () => window.clearInterval(timer);
  }, [active, safeStatuses.join('|')]);
  return safeStatuses[Math.min(index, safeStatuses.length - 1)];
}

window.SAFE_STATUS_GROUPS = SAFE_STATUS_GROUPS;
window.smartStatusForMessage = smartStatusForMessage;

window.LiveStatus = function LiveStatus({ active = true, statuses, message, compact = false, label }) {
  const status = useRotatingStatus(active, statuses || smartStatusForMessage(message));
  return (
    <div className={`live-status ${compact ? 'compact' : ''}`}>
      <span className="live-status-orb"><span/></span>
      <div className="live-status-copy">
        {label && <strong>{label}</strong>}
        <span>{status}</span>
      </div>
      <span className="thinking-dots"><span/><span/><span/></span>
    </div>
  );
};

window.ThinkingAnimation = function ThinkingAnimation({ steps, currentStep = 0, variant = 'dots', label }) {
  if (variant === 'steps' && steps?.length) {
    return (
      <div className="thinking-steps">
        {steps.map((step, i) => (
          <div key={i} className={`thinking-step ${i < currentStep ? 'done' : ''} ${i === currentStep ? 'active' : ''}`}>
            <span className="thinking-step-icon">{i < currentStep ? <Icon name="check" size={10}/> : <span className="thinking-dot-pulse"/>}</span>
            <span>{step}</span>
          </div>
        ))}
      </div>
    );
  }
  if (variant === 'inline') {
    return (
      <span className="thinking-inline">
        {label && <span>{label}</span>}
        <span className="thinking-dots"><span/><span/><span/></span>
      </span>
    );
  }
  return (
    <div className="thinking-dots-wrap">
      <span className="thinking-dots"><span/><span/><span/></span>
      {label && <span className="thinking-dots-label">{label}</span>}
    </div>
  );
};

window.StepIndicator = function StepIndicator({ steps, compact, vertical = false }) {
  if (!steps?.length) return null;
  return (
    <div className={`step-indicator flow-step-indicator ${compact ? 'compact' : ''} ${vertical ? 'vertical' : ''}`}>
      {steps.map((step, i) => {
        const status = step.status || (step.done ? 'done' : step.active ? 'running' : 'pending');
        const isDone = status === 'done';
        const isRunning = status === 'running';
        const icon = isDone ? <Icon name="check" size={11}/> : isRunning ? <span className="step-spinner"/> : i + 1;
        return (
        <React.Fragment key={step.label || i}>
          {i > 0 && <span className="step-connector"/>}
          <div className={`flow-step ${status} ${step.active ? 'active' : ''}`}>
            <span className={`step-node ${isDone ? 'done' : ''} ${isRunning ? 'active' : ''} ${status}`}>{icon}</span>
            {!compact && <span className="step-node-label">{step.label}</span>}
          </div>
        </React.Fragment>
        );
      })}
    </div>
  );
};

window.SkeletonLoader = function SkeletonLoader({ lines = 3, variant = 'text' }) {
  if (variant === 'card') {
    return (
      <div className="skeleton skeleton-card">
        <div className="skeleton-line" style={{width:'40%', height:14}}/>
        <div className="skeleton-line" style={{width:'80%'}}/>
        <div className="skeleton-line" style={{width:'60%'}}/>
      </div>
    );
  }
  if (variant === 'chat') {
    return (
      <div className="skeleton skeleton-chat">
        {[...Array(Math.min(lines, 4))].map((_, i) => (
          <div key={i} className={`skeleton-bubble ${i % 2 ? 'right' : 'left'}`}/>
        ))}
      </div>
    );
  }
  return (
    <div className="skeleton">
      {[...Array(lines)].map((_, i) => (
        <div key={i} className="skeleton-line" style={{width: `${70 + Math.random() * 30}%`}}/>
      ))}
    </div>
  );
};

window.EmptyState = function EmptyState({ icon, title, description, action }) {
  return (
    <div className="ui-empty-state">
      {icon && <div className="ui-empty-icon"><Icon name={icon} size={24}/></div>}
      {title && <strong>{title}</strong>}
      {description && <p>{description}</p>}
      {action && <div className="ui-empty-action">{action}</div>}
    </div>
  );
};

window.ErrorState = function ErrorState({ message, detail, onRetry }) {
  return (
    <div className="ui-error-state">
      <div className="ui-error-icon">!</div>
      <strong>{message || 'Algo deu errado.'}</strong>
      {detail && <p>{detail}</p>}
      {onRetry && <button className="tb-btn" onClick={onRetry}>Tentar novamente</button>}
    </div>
  );
};

window.ChatBubble = function ChatBubble({ role, text, time, meta, avatar }) {
  const roleLabels = { tester: 'Testador', agent: 'Agente', system: 'Sistema', user: 'Voce' };
  return (
    <div className={`chat-bubble chat-bubble-${role || 'agent'}`}>
      {avatar && <div className="chat-bubble-avatar">{avatar}</div>}
      <div className="chat-bubble-body">
        <div className="chat-bubble-role">{roleLabels[role] || role}</div>
        <div className="chat-bubble-text">{text}</div>
        <div className="chat-bubble-footer">
          {time && <span>{time}</span>}
          {meta}
        </div>
      </div>
    </div>
  );
};

window.ScoreRing = function ScoreRing({ value, size = 56 }) {
  const r = (size - 8) / 2;
  const circ = 2 * Math.PI * r;
  const offset = circ - (Math.min(value, 100) / 100) * circ;
  const color = value >= 80 ? 'var(--ok)' : value >= 50 ? 'var(--warn)' : 'var(--bad)';
  return (
    <svg className="score-ring" width={size} height={size} viewBox={`0 0 ${size} ${size}`}>
      <circle cx={size/2} cy={size/2} r={r} fill="none" stroke="var(--rule)" strokeWidth="4"/>
      <circle cx={size/2} cy={size/2} r={r} fill="none" stroke={color} strokeWidth="4"
        strokeDasharray={circ} strokeDashoffset={offset} strokeLinecap="round"
        transform={`rotate(-90 ${size/2} ${size/2})`} style={{transition:'stroke-dashoffset .6s ease'}}/>
      <text x={size/2} y={size/2} textAnchor="middle" dominantBaseline="central"
        style={{fontSize:size*0.28,fontWeight:700,fill:'var(--ink)'}}>{value}%</text>
    </svg>
  );
};

window.Spark = function Spark({ data, color = 'currentColor' }) {
  const values = Array.isArray(data) && data.length ? data : [1, 1, 1, 1, 1, 1, 1, 1];
  const w = 100, h = 28;
  const max = Math.max(...values), min = Math.min(...values);
  const pts = values.map((v,i) => {
    const x = (i / (values.length-1 || 1)) * w;
    const y = h - ((v - min) / (max - min || 1)) * (h - 4) - 2;
    return `${x},${y}`;
  }).join(' ');
  return (
    <svg className="spark" viewBox={`0 0 ${w} ${h}`} preserveAspectRatio="none">
      <polyline points={pts} fill="none" stroke={color} strokeWidth="1.4"/>
      <polyline points={`${pts} ${w},${h} 0,${h}`} fill={color} fillOpacity="0.10" stroke="none"/>
    </svg>
  );
};

