/* Messages — bubbles, agentic step viz, thinking accordion, actions */

/* ─── Mapa de labels e ícones para todas as skills registradas ─── */
const TOOL_LABELS = {
  /* Prazos */
  calcular_prazo_processual:           ['Calculando prazo',          'clock'],
  calcular_prazo:                      ['Calculando prazo',          'clock'],
  /* Súmulas / Precedentes */
  consultar_sumulas:                   ['Consultando súmulas',       'book'],
  verificar_sumula:                    ['Verificando súmula',        'book'],
  pesquisar_jurisprudencia_local:      ['Jurisprudência local',      'book'],
  pesquisa_jurisprudencial_profunda:   ['Deep Research jurídico',    'scale'],
  validar_jurisprudencia_local:        ['Validando julgado',         'check'],
  buscar_jurisprudencia_local:         ['Buscando julgado',          'book'],
  precedentes_qualificados:            ['Precedentes qualificados',  'scale'],
  /* Processos */
  extrair_inteiro_teor:                ['Inteiro teor',              'process'],
  extrair_dados_processo:              ['Extração de dados',         'process'],
  importar_processo_synapia:           ['Importando processo',       'process'],
  consultar_processo_datajud:          ['DataJud',                   'process'],
  consultar_comunicacoes_pje:          ['Comunicações PJe',          'process'],
  /* Peças / Redação */
  estrutura_peca:                      ['Estruturando peça',         'edit'],
  redigir_peca_completa:               ['Redigindo peça',            'edit'],
  auditar_minuta:                      ['Auditoria de minuta',       'check'],
  gerar_quesitos_pericia:              ['Quesitos periciais',        'book'],
  aplicar_filtro_qualidade:            ['Filtro de qualidade',       'check'],
  analisar_ortografia:                 ['Revisão ortográfica',       'check'],
  traduzir_juridiques:                 ['Traduzindo linguagem',      'globe'],
  estilo_juridico_profissional:        ['Análise de estilo',         'scale'],
  /* Superskills de peças */
  superskill_contestacao:              ['Pacote contestação',        'edit'],
  superskill_aresp:                    ['AREsp / REsp',              'edit'],
  superskill_apelacao:                 ['Pacote apelação',           'edit'],
  superskill_agravo_instrumento:       ['Agravo de instrumento',     'edit'],
  superskill_agravo_interno:           ['Agravo interno',            'edit'],
  superskill_recurso_ordinario_trab:   ['Recurso ordinário trabalhista','edit'],
  superskill_recurso_revista:          ['Recurso de revista',        'edit'],
  superskill_embargos_declaracao:      ['Embargos de declaração',    'edit'],
  superskill_embargos_tst:             ['Embargos TST',              'edit'],
  superskill_rext:                     ['RE / Repercussão geral',    'edit'],
  superskill_memorial_dialetico:       ['Memorial dialético',        'edit'],
  superskill_impugnacao_cumprimento:   ['Impugnação cumprimento',    'edit'],
  /* Cálculos */
  calcular_rescisao_contratual:        ['Rescisão contratual',       'calc'],
  calcular_horas_extras:               ['Horas extras',              'calc'],
  calcular_adicional:                  ['Adicional NR',              'calc'],
  aplicar_correcao_adc58:              ['Correção ADC 58',           'calc'],
  liquidar_sentenca_trabalhista:       ['Liquidação de sentença',    'calc'],
  consultar_serie_bcb:                 ['Índices BCB',               'calc'],
  atualizar_bifasico_adc58:            ['Bifásico ADC 58',           'calc'],
  calcular_correcao_monetaria:         ['Correção monetária',        'calc'],
  calcular_juros:                      ['Cálculo de juros',          'calc'],
  /* APIs públicas */
  consultar_cnpj:                      ['Consultando CNPJ',          'globe'],
  consultar_sancoes:                   ['Sanções administrativas',   'scale'],
  buscar_dados_gov:                    ['Dados.gov.br',              'globe'],
  /* Legal Tools BR */
  gerar_resposta_padronizada:          ['Resposta padronizada',      'edit'],
  gerar_ata_reuniao_juridica:          ['Ata de reunião',            'edit'],
  gerar_revisao_tabular:               ['Revisão tabular Excel',     'calc'],
  /* Office Tools */
  excel_criar:                         ['Gerando planilha',          'calc'],
  pdf_extrair_texto:                   ['Extraindo texto PDF',       'process'],
  pdf_mesclar:                         ['Mesclando PDFs',            'process'],
  pdf_dividir:                         ['Dividindo PDF',             'process'],
  word_criar:                          ['Gerando Word',              'edit'],
  /* Security */
  analisar_seguranca_codigo:           ['Análise de segurança',      'check'],
  /* Meta-skills */
  listar_skills:                       ['Listando skills',           'bolt'],
  criar_skill:                         ['Criando skill',             'bolt'],
  otimizar_skill:                      ['Otimizando skill',          'bolt'],
  /* Pesquisa / Legislação */
  buscar_legislacao_planalto:          ['Legislação Planalto',       'book'],
  buscar_lexml:                        ['LexML',                     'book'],
  pesquisar_camara:                    ['Câmara dos Deputados',      'book'],
  pesquisar_senado:                    ['Senado Federal',            'book'],
  buscar_wiki_juridica:                ['Wiki jurídica',             'book'],
  /* Ratio / Lancedb */
  consultar_ratio_synap:               ['Ratio — 471k decisões',     'scale'],
  status_ratio_synap:                  ['Status Ratio',              'bolt'],
  /* Dosimetria / Estratégia */
  calcular_dano_moral:                 ['Dosimetria dano moral',     'scale'],
  elaborar_estrategia_processual:      ['Estratégia processual',     'scale'],
  linha_tempo_processual:              ['Linha do tempo',            'process'],
  calcular_prazo_master:               ['Prazo master',              'clock'],
  /* Outros */
  solicitar_dados_calculo:             ['Solicitando dados',         'bolt'],
};

/* ─── Mapa de ícone → componente (fallback bolt) ─── */
const ICON_MAP = {
  clock:   () => <I.clock   size={13}/>,
  book:    () => <I.book    size={13}/>,
  check:   () => <I.check   size={13} sw={2.2}/>,
  edit:    () => <I.edit    size={13}/>,
  scale:   () => <I.scale   size={13}/>,
  process: () => <I.process size={13}/>,
  globe:   () => <I.globe   size={13}/>,
  bolt:    () => <I.bolt    size={13}/>,
  calc:    () => <I.calc    size={13}/>,
};
const SkillIcon = ({ key: k }) => {
  const C = ICON_MAP[k] || ICON_MAP.bolt;
  return <C/>;
};

const toolDisplay = (name) => {
  if (name && name.startsWith('skill:')) {
    const raw = name.slice(6);
    return [`Skill: ${raw.replace(/-/g, ' ')}`, 'bolt'];
  }
  return TOOL_LABELS[name] || [(name || 'skill').replace(/_/g, ' '), 'bolt'];
};

/* ─── ToolStep — estilo Claude: pill header + body colapsável ─── */
const ToolStep = ({ tool, idx }) => {
  const [open, setOpen] = React.useState(false);
  const [label, iconKey] = toolDisplay(tool.name);
  const IconC = ICON_MAP[iconKey] || ICON_MAP.bolt;
  const running = tool.status === 'running';
  const done = tool.status === 'done';

  return (
    <div className={`tool-step ts-${tool.status || 'done'} ${open ? 'ts-open' : ''}`}>
      <button className="ts-head" onClick={() => setOpen(o => !o)} title={tool.name}>
        <span className={`ts-dot ${running ? 'ts-dot-spin' : ''}`}>
          {done ? <I.check size={9} sw={2.5}/> : <IconC/>}
        </span>
        <span className="ts-label">{label}</span>
        <span className="ts-name-raw">{tool.name}</span>
        {tool.status === 'running' && <span className="ts-running-badge">em execução</span>}
        <span className="ts-chev"><I.arrowR size={10} sw={2}/></span>
      </button>
      {open && (
        <div className="ts-body">
          {tool.args && Object.keys(tool.args).length > 0 && (
            <div className="ts-row">
              <span className="ts-row-k">entrada</span>
              <pre>{JSON.stringify(tool.args, null, 2)}</pre>
            </div>
          )}
          {tool.result && (
            <div className="ts-row">
              <span className="ts-row-k">resultado</span>
              <pre>{typeof tool.result === 'string' ? tool.result.slice(0, 2000) : JSON.stringify(tool.result, null, 2).slice(0, 2000)}</pre>
            </div>
          )}
        </div>
      )}
    </div>
  );
};

/* ─── Skills usado header — tipo Claude ─── */
const ToolsUsedHeader = ({ tools, latencyMs }) => {
  const [expanded, setExpanded] = React.useState(false);
  const done = tools.filter(t => t.status !== 'running').length;
  const running = tools.length - done;

  return (
    <div className={`tools-block ${expanded ? 'tb-open' : ''}`}>
      <button className="tb-head" onClick={() => setExpanded(o => !o)}>
        <span className="tb-icon-wrap">
          {running > 0
            ? <span className="tb-spin"><I.bolt size={11}/></span>
            : <I.check size={11} sw={2.5}/>}
        </span>
        <span className="tb-summary">
          {running > 0
            ? `Executando ${running} skill${running > 1 ? 's' : ''}…`
            : `${tools.length} skill${tools.length > 1 ? 's' : ''} usada${tools.length > 1 ? 's' : ''}`}
        </span>
        <span className="tb-pills">
          {tools.slice(0, 4).map((t, i) => {
            const [lbl, iconKey] = toolDisplay(t.name);
            const C = ICON_MAP[iconKey] || ICON_MAP.bolt;
            return (
              <span key={i} className={`tb-pill ${t.status === 'running' ? 'tb-pill-run' : ''}`}>
                <C/> {lbl}
              </span>
            );
          })}
          {tools.length > 4 && <span className="tb-pill tb-pill-more">+{tools.length - 4}</span>}
        </span>
        {latencyMs && done === tools.length && <span className="tb-time">{(latencyMs/1000).toFixed(1)}s</span>}
        <span className="tb-chev"><I.arrowR size={10} sw={2}/></span>
      </button>
      {expanded && (
        <div className="tb-steps">
          {tools.map((t, i) => <ToolStep key={i} tool={t} idx={i}/>)}
        </div>
      )}
    </div>
  );
};

const Thinking = ({ text }) => {
  const [open, setOpen] = React.useState(false);
  return (
    <div className={`thinking ${open ? 'open' : ''}`}>
      <button className="th-head" onClick={() => setOpen(o => !o)}>
        <span className="th-dot"/>
        <span className="th-label">Cadeia de raciocínio</span>
        <span className="th-time">3,2s</span>
        <span className="th-chev"><I.arrowR size={11} sw={2}/></span>
      </button>
      {open && <div className="th-body">{text}</div>}
    </div>
  );
};

const SourceCard = ({ source, idx }) => (
  <a href={source.url} target="_blank" rel="noopener noreferrer" className="source-card">
    <div className="sc-top">
      <div className="sc-idx">{idx + 1}</div>
      <div className="sc-domain">{new URL(source.url).hostname.replace('www.', '')}</div>
    </div>
    <div className="sc-title">{source.title}</div>
  </a>
);

const SourceGrid = ({ sources }) => {
  if (!sources || sources.length === 0) return null;
  return (
    <div className="sources-block">
      <div className="sources-head">
        <I.book size={13}/>
        <span>{sources.length} {sources.length === 1 ? 'fonte' : 'fontes'}</span>
      </div>
      <div className="sources-grid">
        {sources.slice(0, 4).map((s, i) => <SourceCard key={i} source={s} idx={i}/>)}
        {sources.length > 4 && (
          <div className="source-card more">
            <div className="sc-title">+{sources.length - 4} mais</div>
          </div>
        )}
      </div>
    </div>
  );
};

const GenerationStatus = ({ status, mode }) => {
  const steps = mode === 'pecas'
    ? ['Lendo anexos', 'Separando fatos', 'Montando tese', 'Redigindo peça']
    : ['Lendo contexto', 'Planejando', 'Redigindo', 'Verificando'];
  return (
    <div className="generation-status">
      <div className="gs-orbit" aria-hidden="true">
        <span/><span/><span/>
      </div>
      <div className="gs-copy">
        <strong>{status || 'Pensando'}</strong>
        <div className="gs-steps">
          {steps.map((step, i) => <span key={step} style={{ animationDelay: `${i * .18}s` }}>{step}</span>)}
        </div>
      </div>
    </div>
  );
};

const Markdown = ({ text, streaming }) => {
  const html = React.useMemo(() => {
    let t = (text || '');
    // Fenced code blocks primeiro (antes do escape geral)
    const blocks = [];
    t = t.replace(/```([\s\S]*?)```/g, (_, code) => {
      const idx = blocks.length;
      blocks.push(`<pre class="md-pre"><code>${code.replace(/[&<>"]/g, c => ({'&':'&amp;','<':'&lt;','>':'&gt;','"':'&quot;'}[c]))}</code></pre>`);
      return `\x00BLOCK${idx}\x00`;
    });
    // Escape o restante
    t = t.replace(/[&<>"]/g, c => ({'&':'&amp;','<':'&lt;','>':'&gt;','"':'&quot;'}[c]));
    // Links markdown [texto](url) → <a> clicáveis
    t = t.replace(/\[([^\]]+)\]\(([^)]+)\)/g, '<a href="$2" target="_blank" rel="noopener noreferrer" style="color: var(--accent); text-decoration: underline; cursor: pointer;">$1</a>');
    // Inline code
    t = t.replace(/`([^`]+)`/g, '<code>$1</code>');
    // Headers
    t = t.replace(/^### (.+)$/gm, '<h4>$1</h4>');
    t = t.replace(/^## (.+)$/gm, '<h3>$1</h3>');
    t = t.replace(/^# (.+)$/gm, '<h3>$1</h3>');
    // Bold / Italic
    t = t.replace(/\*\*([^*]+)\*\*/g, '<strong>$1</strong>');
    t = t.replace(/\*([^*\n]+)\*/g, '<em>$1</em>');
    // Lists
    t = t.replace(/^- (.+)$/gm, '<li>$1</li>');
    t = t.replace(/(<li>.*<\/li>\n?)+/g, m => `<ul>${m.replace(/\n/g,'')}</ul>`);
    t = t.replace(/^(\d+)\. (.+)$/gm, '<oli>$2</oli>');
    t = t.replace(/(<oli>.*<\/oli>\n?)+/g, m => `<ol>${m.replace(/<\/?oli>/g, m2 => m2 === '<oli>' ? '<li>' : '</li>')}</ol>`);
    // Paragraphs
    t = t.split(/\n{2,}/).map(p => p.match(/^<(ul|ol|h\d|pre|div|a)/) ? p : `<p>${p.replace(/\n/g,'<br/>')}</p>`).join('');
    // Restore code blocks
    t = t.replace(/\x00BLOCK(\d+)\x00/g, (_, i) => blocks[+i]);
    
    // Perplexity-style citations [1], [2]...
    // Como Markdown não tem acesso direto ao array de fontes aqui,
    // Message.jsx cuidará de injetar os links ou usaremos uma classe clicável.
    t = t.replace(/\[(\d+)\]/g, '<a class="cit" data-idx="$1"> $1 </a>');
    
    return t;
  }, [text]);
  return (
    <div className="md">
      <div dangerouslySetInnerHTML={{ __html: html }} style={{ display: 'inline' }} />
      {streaming && <span className="streaming-cursor" />}
    </div>
  );
};

const LEGAL_MARKERS = /EXCELENT[ÍI]SSIMO|MERIT[ÍI]SSIMO|EMBARGOS|CONTESTA[ÇC][ÃA]O|APELA[ÇC][ÃA]O|RECURSO|PETI[ÇC][ÃA]O|INICIAL|DIREITO L[ÍI]QUIDO|ANTECIPA[ÇC]|[ÁA] TEMA|[ÁA] DISPOSI[ÇC][ÃA]O|VEM, RESPEITOSAMENTE|PEDI-SE|REQUER-SE|TERMOS EM QUE/i;
const isLegalPieceHeuristic = (text) => text && text.length > 500 && (LEGAL_MARKERS.test(text));

const Message = ({ m, onCopy, onRegen, onOpenCanvas }) => {
  const bodyRef = React.useRef(null);

  const handleCiteClick = (e) => {
    const cit = e.target.closest('.cit');
    if (cit && m.sources) {
      e.preventDefault();
      const idx = parseInt(cit.getAttribute('data-idx')) - 1;
      const src = m.sources[idx];
      if (src && src.url) window.open(src.url, '_blank');
    }
  };

  if (m.role === 'user') {
    return (
      <div className="msg msg-user">
        <div className="msg-bubble">{m.content}</div>
      </div>
    );
  }
  return (
    <div className="msg msg-assistant">
      <div className="msg-avatar" style={{background: 'transparent', padding: 0, overflow: 'visible', color: 'var(--accent)'}}>
        <I.synapse size={22} />
      </div>
      <div className="msg-body" ref={bodyRef} onClick={handleCiteClick}>
        <div className="msg-name">
          SynapIA
          {m.mode === 'agent' && <span className="badge badge-agent">agêntico</span>}
          {m.mode === 'deepresearch' && <span className="badge badge-research">deep research</span>}
          {(m.mode === 'pecas' || m.mode === 'recursos') && m.latencyMs && !m.streaming && (
            <span className="badge badge-speed" title="Tempo de geração">
              {(m.latencyMs / 1000).toFixed(1)}s
              {m.content && m.content.length > 100 && (
                <> · {Math.round(m.content.length / (m.latencyMs / 1000))} car/s</>
              )}
            </span>
          )}
        </div>
        {m.thinking && <Thinking text={m.thinking}/>}
        
        {m.mode === 'deepresearch' && <SourceGrid sources={m.sources}/>}

        {Array.isArray(m.tools) && m.tools.length > 0 && (
          <ToolsUsedHeader tools={m.tools} latencyMs={m.latencyMs}/>
        )}
        
        <div className="msg-content-wrap">
          {m.streaming && !m.content
            ? <GenerationStatus status={m.status} mode={m.mode}/>
            : <Markdown text={m.content} streaming={m.streaming}/>
          }
          {/* Popover de Fonte (simplificado via CSS/Hover ou clicável) */}
        </div>

        <div className="msg-actions">
          <button onClick={() => onCopy(m)}><I.copy size={12}/> Copiar</button>
          <button onClick={() => onRegen(m)}><I.redo size={12}/> Regenerar</button>
          {onOpenCanvas && isLegalPieceHeuristic(m.content) && (
            <button className="canvas-open-btn" onClick={() => onOpenCanvas(m)}><I.edit size={12}/> Abrir no Canvas</button>
          )}
          <button><I.thumbsUp size={12}/></button>
          <button><I.thumbsDn size={12}/></button>
          {m.latencyMs && !m.streaming && m.mode !== 'pecas' && m.mode !== 'recursos' && (
            <span className="msg-ts">{(m.latencyMs / 1000).toFixed(1)}s</span>
          )}
          {m.ts && <span className="msg-ts">{new Date(m.ts).toLocaleTimeString('pt-BR',{hour:'2-digit',minute:'2-digit'})}</span>}
        </div>
      </div>
    </div>
  );
};

const Typing = () => (
  <div className="msg msg-assistant">
    <div className="msg-avatar loading" style={{background: 'transparent', padding: 0, overflow: 'visible'}}>
      <I.synapse size={24} />
    </div>
    <div className="msg-body">
      <div className="msg-name">SynapIA</div>
      <div className="typing-text">pensando<span className="typing-dots"><span>.</span><span>.</span><span>.</span></span></div>
    </div>
  </div>
);

window.Message = Message;
window.Typing = Typing;
