/* global React, Icon, API */

function initials(name) {
  return String(name || '?').split(' ').map(s => s[0]).slice(0, 2).join('').toUpperCase();
}

function conversationDisplayName(c) {
  const phone = c?.number || c?.customer_phone || '-';
  const name = c?.name || c?.customer_name || c?.state?.customer_name || '';
  return name ? `${phone} - ${name}` : phone;
}
window.conversationDisplayName = conversationDisplayName;

function conversationChannel(c) {
  const raw = c?.raw || c || {};
  const state = raw.state || c?.state || {};
  const phone = String(c?.number || raw.customer_phone || '').toLowerCase();
  const source = String(c?.channel || raw.channel || raw.source || state.source || '').toLowerCase();
  if (source === 'agent_test' || phone.startsWith('test-')) return 'agent_test';
  if (['public_test', 'public', 'shared_chat', 'shared_chat_demo', 'shared_chat_contact'].includes(source) || phone.startsWith('pub-')) return 'public';
  if (source === 'site' || phone.startsWith('site-')) return 'site';
  return 'whatsapp';
}

function conversationChannelLabel(c) {
  const channel = conversationChannel(c);
  if (channel === 'site') return 'Site';
  if (channel === 'public') return 'Chat Compartilhado';
  if (channel === 'agent_test') return 'Teste interno';
  return 'WhatsApp';
}

function studioToast(message, type = '') {
  if (window.STUDIO?.toast) window.STUDIO.toast(message, type);
}

function studioConfirm(config) {
  return window.STUDIO?.confirm ? window.STUDIO.confirm(config) : Promise.resolve(false);
}

function conversationAgentId(c) {
  return c?.agentId || c?.agent_id || c?.raw?.agent_id || c?.state?.agent_id || '';
}

function messageDir(role) {
  if (role === 'assistant') return 'out';
  if (role === 'human') return 'out human';
  if (role === 'system' || role === 'tool') return 'system';
  return 'in';
}

function runtimeBadgeClass(value) {
  const text = String(value || '').toLowerCase();
  if (text.includes('ok') || text.includes('ativo') || text.includes('done') || text.includes('resolvido') || text.includes('concluido')) return 'ok';
  if (text.includes('frustr') || text.includes('handoff') || text.includes('paus') || text.includes('erro')) return 'bad';
  if (text.includes('pend') || text.includes('wait') || text.includes('process') || text.includes('em andamento')) return 'warn';
  return '';
}

function runtimeText(value, fallback = '--') {
  if (value == null || value === '') return fallback;
  if (typeof value === 'string' || typeof value === 'number' || typeof value === 'boolean') return String(value);
  return value.summary || value.text || value.content || value.value || value.name || fallback;
}

function toolLine(item) {
  const latency = item.latency_ms ? `${item.latency_ms}ms` : '--ms';
  return `${item.tool || item.name || item.status || 'tool'} - ${latency}`;
}

function latestConversationPreview(preview) {
  return String(preview || '').split('\n').filter(Boolean).pop()?.replace(/^(user|assistant|human|system):\s*/i, '') || '';
}

function conversationFromApi(c) {
  const ticket = c.ticket ? `T-${c.ticket.id}` : null;
  const handoff = c.state?.human_handoff || {};
  const paused = Boolean(ticket) || Boolean(handoff.paused || handoff.requested || handoff.ticket_status === 'in_progress');
  const source = c.channel || c.source || c.state?.source || '';
  const phone = String(c.customer_phone || '');
  const channel = ['public_test', 'public', 'shared_chat', 'shared_chat_demo', 'shared_chat_contact'].includes(source) || phone.startsWith('pub-') ? 'public' : source || (phone.startsWith('site-') ? 'site' : 'whatsapp');
  return {
    id: c.id,
    name: c.customer_name || c.customer_phone || 'Contato',
    number: c.customer_phone || '--',
    agent: c.agent_name || `Agente #${c.agent_id || '-'}`,
    agentId: c.agent_id,
    channel,
    channelLabel: conversationChannelLabel({ channel }),
    last: latestConversationPreview(c.preview),
    time: window.fmtTime ? window.fmtTime(c.updated_at || c.created_at) : '--:--',
    unread: 0,
    paused,
    ticket,
    raw: c,
  };
}

function objectiveStatusText(status, note) {
  const text = String(status || '').toLowerCase();
  if (text.includes('conclu') || text.includes('done') || text.includes('ok')) return 'concluido';
  if (text.includes('process') || text.includes('andamento')) return 'em processo';
  return note || status || 'pendente';
}

window.ConversationsPage = function ConversationsPage({ agentId = null, embedded = false } = {}) {
  const data = window.MOCK || {};
  const agents = data.agents || [];
  const fixedAgentId = agentId == null ? null : String(agentId);
  const [liveConversations, setLiveConversations] = React.useState(null);
  const conversations = liveConversations || data.conversations || [];
  const [active, setActive] = React.useState(conversations.find(c => !fixedAgentId || String(conversationAgentId(c)) === fixedAgentId)?.id || null);
  const [detail, setDetail] = React.useState(null);
  const [q, setQ] = React.useState('');
  const [filter, setFilter] = React.useState('todas');
  const [channelFilter, setChannelFilter] = React.useState('all');
  const [agentFilter, setAgentFilter] = React.useState(fixedAgentId || 'all');
  const [showThread, setShowThread] = React.useState(false);
  const [draft, setDraft] = React.useState('');
  const [syncing, setSyncing] = React.useState(false);
  const [lastSync, setLastSync] = React.useState(null);
  const effectiveAgentFilter = fixedAgentId || agentFilter;
  const agentScoped = conversations.filter(c => effectiveAgentFilter === 'all' || String(conversationAgentId(c)) === String(effectiveAgentFilter));
  const channelScoped = agentScoped.filter(c => channelFilter === 'all' || conversationChannel(c) === channelFilter);
  const selected = channelScoped.find(c => String(c.id) === String(active)) || channelScoped[0] || null;
  const scopedAgent = fixedAgentId ? agents.find(agent => String(agent.id) === fixedAgentId) : null;
  const siteCount = agentScoped.filter(c => conversationChannel(c) === 'site').length;
  const publicCount = agentScoped.filter(c => conversationChannel(c) === 'public').length;
  const whatsappCount = agentScoped.filter(c => conversationChannel(c) === 'whatsapp').length;
  const agentCounts = conversations.reduce((acc, c) => {
    const id = String(conversationAgentId(c) || 'sem-agente');
    acc[id] = (acc[id] || 0) + 1;
    return acc;
  }, {});

  React.useEffect(() => {
    if (!channelScoped.length) { setActive(null); return; }
    if (!active || !channelScoped.some(c => String(c.id) === String(active))) setActive(channelScoped[0].id);
  }, [conversations.length, effectiveAgentFilter, channelFilter]);

  React.useEffect(() => {
    if (fixedAgentId && agentFilter !== fixedAgentId) setAgentFilter(fixedAgentId);
  }, [fixedAgentId]);

  React.useEffect(() => {
    if (!active) { setDetail(null); return; }
    let alive = true;
    API.getConversationDetail(active).then(item => { if (alive) setDetail(item); }).catch(() => { if (alive) setDetail(null); });
    return () => { alive = false; };
  }, [active]);

  React.useEffect(() => {
    if (!API?.getConversations) return undefined;
    let alive = true;
    let busy = false;
    async function syncLive() {
      if (busy || document.hidden) return;
      busy = true;
      if (alive) setSyncing(true);
      try {
        const rows = await API.getConversations(fixedAgentId || null);
        if (alive) setLiveConversations((rows || []).map(conversationFromApi));
        if (active) {
          const item = await API.getConversationDetail(active);
          if (alive) setDetail(item);
        }
        if (alive) setLastSync(new Date());
      } catch (err) {
        // A tela segue com os dados atuais; o toast global já cobre erros de backend.
      } finally {
        busy = false;
        if (alive) setSyncing(false);
      }
    }
    const timer = setInterval(syncLive, 2500);
    return () => { alive = false; clearInterval(timer); };
  }, [active, effectiveAgentFilter]);

  const list = channelScoped.filter(c => {
    const text = `${c.name} ${c.number} ${c.agent} ${c.last}`.toLowerCase();
    const okText = text.includes(q.toLowerCase());
    const okFilter = filter === 'todas' || (filter === 'pausadas' && c.paused) || (filter === 'ativas' && !c.paused);
    return okText && okFilter;
  });
  const paused = channelScoped.filter(c => c.paused).length;
  const messages = detail?.messages?.length ? detail.messages.map(m => ({
    id: m.id,
    dir: messageDir(m.role),
    text: m.content,
    time: window.fmtTime ? window.fmtTime(m.created_at) : '--',
    role: m.role,
  })) : [];
  const state = detail?.state || selected?.raw?.state || {};
  const handoff = state.human_handoff || {};
  const runtime = detail?.runtime || {};
  const runtimeStatus = runtime.status || {};
  const fallbackMemory = Object.entries(state.memory || state.context || {}).map(([key, value]) => ({ name: key, label: `@${key}`, value: runtimeText(value), filled: true }));
  const runtimeMemory = (runtime.memory?.entries || []).length ? runtime.memory.entries : fallbackMemory;
  const runtimeObjectives = runtime.objectives || [];
  const runtimeTools = (runtime.tools?.used || []).length
    ? runtime.tools.used
    : (data.runs || []).filter(r => String(r.conversation_id) === String(active)).slice(0, 4).map(r => ({ id: r.id, tool: r.output?.tool || r.input?.tool || r.status || 'run', latency_ms: r.latency_ms, status: r.status, output: r.output, input: r.input, error: r.error }));
  const runtimeConditionals = Array.isArray(runtime.conditionals?.matched) ? runtime.conditionals.matched : [];

  async function refreshDetail() {
    const rows = await API.getConversations(fixedAgentId || null);
    setLiveConversations((rows || []).map(conversationFromApi));
    if (active) setDetail(await API.getConversationDetail(active));
  }

  async function pauseAgent() {
    if (!active) return;
    await API.pauseAgent(active);
    await refreshDetail();
  }

  async function resumeAgent() {
    if (!active) return;
    await API.resumeAgent(active);
    await refreshDetail();
  }

  async function sendHumanMessage() {
    if (!active || !draft.trim()) return;
    await API.sendHumanMessage(active, draft.trim());
    setDraft('');
    await refreshDetail();
  }

  async function deleteSelectedConversation() {
    if (!active || !(await studioConfirm({ title: 'Apagar conversa', message: 'Apagar conversa selecionada?', confirmLabel: 'Apagar', danger: true }))) return;
    await API.deleteConversation(active);
    await window.STUDIO.refresh();
    setActive(null);
    setDetail(null);
  }

  async function deleteAgentConversations() {
    const agentId = conversationAgentId(selected);
    if (!agentId || !(await studioConfirm({ title: 'Apagar conversas do agente', message: 'Apagar todas as conversas deste agente?', confirmLabel: 'Apagar', danger: true }))) return;
    await API.deleteAgentConversations(agentId);
    await window.STUDIO.refresh();
    setActive(null);
    setDetail(null);
  }

  return (
    <>
      {!embedded && <div className="page-head">
        <div>
          <div className="page-eyebrow">Operação - {conversations.length} conversas - por agente e canal</div>
          <h1 className="page-title">Conversas</h1>
          <p className="page-sub">Threads reais do site, WhatsApp e chat compartilhado separadas por agente, canal, runtime, ticket e pausa humana.</p>
        </div>
        <div className="page-meta">
          <div className="meta-row"><span className={`sw ${syncing ? 'warn' : 'ok'}`}/> tempo real {syncing ? 'sincronizando' : lastSync ? lastSync.toLocaleTimeString('pt-BR', { hour: '2-digit', minute: '2-digit' }) : 'ativo'}</div>
          <div className="meta-row"><span className="sw bad"/> {paused} pausadas</div>
          <div className="meta-row"><span className="sw ok"/> {channelScoped.length - paused} ativas</div>
        </div>
      </div>}
      {embedded && <div className="agent-conv-toolbar">
        <div>
          <div className="panel-title">Conversas do agente</div>
          <div className="panel-subtitle">{scopedAgent?.name || 'Agente selecionado'} - {agentScoped.length} threads - {siteCount} site - {publicCount} chat compartilhado - {whatsappCount} WhatsApp</div>
        </div>
        <span className={`badge ${syncing ? 'warn' : 'ok'}`}><span className={`sw ${syncing ? 'warn' : 'ok'}`}/> tempo real</span>
      </div>}

      <div className={`page conv-page ${embedded ? 'agent-conv-page' : ''}`}>
        <div className="conv-shell">
          <div className={`conv-list ${showThread ? 'mobile-hidden' : ''}`}>
            <div className="conv-list-head">
              <div className="topbar-search" style={{ width: '100%', margin: 0}}>
                <Icon name="search" size={13}/>
                <input value={q} onChange={e => setQ(e.target.value)} placeholder="Buscar conversa..."/>
              </div>
              <div className="filter-row" style={{ marginTop: 10 }}>
                <button className={`fp ${filter === 'todas' ? 'active' : ''}`} onClick={() => setFilter('todas')}>Todas</button>
                <button className={`fp ${filter === 'pausadas' ? 'active' : ''}`} onClick={() => setFilter('pausadas')}>Pausadas <span className="count">{paused}</span></button>
            <button className={`fp ${filter === 'ativas' ? 'active' : ''}`} onClick={() => setFilter('ativas')}>Ativas</button>
          </div>
          <div className="filter-divider"><span>Status da conversa</span><i/><span>Canais</span></div>
          <div className="filter-row channel-filter-row">
            <button className={`fp ${channelFilter === 'all' ? 'active' : ''}`} onClick={() => setChannelFilter('all')}>Todos canais <span className="count">{agentScoped.length}</span></button>
            <button className={`fp ${channelFilter === 'site' ? 'active' : ''}`} onClick={() => setChannelFilter('site')}>Site <span className="count">{siteCount}</span></button>
            <button className={`fp ${channelFilter === 'public' ? 'active' : ''}`} onClick={() => setChannelFilter('public')}>Chat Compartilhado <span className="count">{publicCount}</span></button>
            <button className={`fp ${channelFilter === 'whatsapp' ? 'active' : ''}`} onClick={() => setChannelFilter('whatsapp')}>WhatsApp <span className="count">{whatsappCount}</span></button>
              </div>
              {!fixedAgentId && <div className="agent-scope-row">
                <button className={`agent-chip ${agentFilter === 'all' ? 'active' : ''}`} onClick={() => setAgentFilter('all')}>
                  <span className="av-mark">A</span><span>Todos</span><b>{conversations.length}</b>
                </button>
                {agents.map(agent => (
                  <button key={agent.id} className={`agent-chip ${String(agentFilter) === String(agent.id) ? 'active' : ''}`} onClick={() => setAgentFilter(agent.id)}>
                    <span className="av-mark">{initials(agent.name)}</span><span>{agent.name}</span><b>{agentCounts[String(agent.id)] || 0}</b>
                  </button>
                ))}
              </div>}
              {fixedAgentId && <div className="agent-scope-row compact">
                <span className="agent-chip active static"><span className="av-mark">{initials(scopedAgent?.name)}</span><span>{scopedAgent?.name || 'Agente'}</span><b>{agentScoped.length}</b></span>
              </div>}
            </div>
            {list.map(c => (
              <div key={c.id} className={`conv-row ${String(active) === String(c.id) ? 'active' : ''}`} onClick={() => { setActive(c.id); setShowThread(true); }}>
                <div className="conv-avatar" style={{ background: c.paused ? 'var(--bad)' : 'var(--accent)'}}>{initials(c.name)}</div>
                <div style={{ minWidth: 0 }}>
                  <div className="conv-name">{c.name}</div>
                  <div className="conv-snippet">{c.last || 'Sem mensagens ainda.'}</div>
                  <div className="conv-meta">
                    <span className={`badge ${['site', 'public'].includes(conversationChannel(c)) ? 'accent' : ''}`} style={{ fontSize: 10, padding:'1px 6px' }}>{conversationChannelLabel(c)}</span>
                    <span className="badge" style={{ fontSize: 10, padding:'1px 6px' }}>{c.agent}</span>
                    {c.paused && <span className="badge bad" style={{ fontSize: 10, padding:'1px 6px' }}>pausada</span>}
                    {c.ticket && <span className="badge accent" style={{ fontSize: 10, padding:'1px 6px' }}>{c.ticket}</span>}
                  </div>
                </div>
                <div><div className="conv-time">{c.time}</div></div>
              </div>
            ))}
            {!list.length && <div className="empty">Nenhuma conversa encontrada.</div>}
          </div>

          <div className={`conv-thread ${!showThread ? 'mobile-hidden' : ''}`}>
            {selected ? (
              <>
                <div className="conv-header">
                  <button className="tb-btn ghost" onClick={() => setShowThread(false)} style={{padding:'4px 8px'}}>voltar</button>
                  <div className="conv-avatar" style={{ background: selected.paused ? 'var(--bad)' : 'var(--accent)'}}>{initials(selected.name)}</div>
                  <div style={{ flex: 1, minWidth: 0 }}>
                    <div style={{ fontWeight:500, fontSize:14}}>{selected.name}</div>
                    <div style={{ fontSize: 11.5, color:'var(--ink-3)'}}>{conversationChannelLabel(selected)} - {selected.number} - agente {selected.agent}{selected.ticket ? ` - ${selected.ticket}` : ''}</div>
                  </div>
                  {selected.paused ? <span className="badge bad"><Icon name="pause" size={10}/> IA pausada</span> : <span className="badge ok"><Icon name="play" size={10}/> IA ativa</span>}
                </div>

                <div className="conv-msgs">
                  {messages.map(m => (
                    <div key={m.id} className={`msg ${m.dir}`}>
                      <div className="msg-bubble">{m.text}</div>
                      <div className="msg-meta">{m.role === 'human' ? 'humano - ' : ''}{m.time}</div>
                    </div>
                  ))}
                  {!messages.length && <div className="empty">Abra uma conversa com mensagens salvas no backend.</div>}
                </div>

                <div className="conv-composer">
                  <textarea value={draft} onChange={e => setDraft(e.target.value)} placeholder={selected.paused ? 'Responder como humano...' : 'IA ativa. Você pode pausar e responder.'}/>
                  <div className="conv-composer-actions">
                    {selected.paused
                      ? <button className="tb-btn primary" onClick={() => resumeAgent().catch(err => studioToast(err.message || String(err), 'bad'))}><Icon name="check" size={11}/> Devolver para IA</button>
                      : <button className="tb-btn" onClick={() => pauseAgent().catch(err => studioToast(err.message || String(err), 'bad'))}><Icon name="pause" size={11}/> Tomar posse</button>}
                    <button className="tb-btn ghost" onClick={() => deleteSelectedConversation().catch(err => studioToast(err.message || String(err), 'bad'))}>Apagar</button>
                    <button className="tb-btn ghost" onClick={() => deleteAgentConversations().catch(err => studioToast(err.message || String(err), 'bad'))}>Apagar do agente</button>
                    <button className="tb-btn primary" style={{marginLeft:'auto'}} onClick={() => sendHumanMessage().catch(err => studioToast(err.message || String(err), 'bad'))}>Enviar</button>
                  </div>
                </div>
              </>
            ) : <div className="empty">Selecione uma conversa.</div>}
          </div>

          <aside className="runtime">
            <div className="runtime-section">
              <div className="rt-label">Estado do runtime</div>
              <dl className="rt-kv">
                <dt>Estado</dt><dd><span className={`badge ${runtimeBadgeClass(runtimeStatus.state || (selected?.paused ? 'handoff' : 'ativo'))}`}>{runtimeStatus.state || (selected?.paused ? 'handoff' : 'ativo')}</span></dd>
                <dt>Memória</dt><dd>{runtimeStatus.memory_filled ?? runtimeMemory.filter(item => item.filled).length} / {runtimeStatus.memory_expected || runtimeMemory.length || 0} vars</dd>
                <dt>Ticket</dt><dd>{runtimeStatus.ticket?.id || selected?.ticket || '--'}</dd>
                <dt>Time alvo</dt><dd>{runtimeStatus.team_name || handoff.team_name || handoff.team || '--'}</dd>
              </dl>
            </div>
            <div className="runtime-section">
              <div className="rt-label">Objetivos</div>
              <div className="runtime-objectives">
                {runtimeObjectives.map(item => (
                  <div className="objective-row" key={`${item.order}-${item.label}`}>
                    <span className={`objective-dot ${runtimeBadgeClass(item.status)}`}></span>
                    <span>{item.label}</span>
                    <em>{objectiveStatusText(item.status, item.note)}</em>
                  </div>
                ))}
                {!runtimeObjectives.length && <div className="empty tiny">Objetivos não definidos no agente.</div>}
              </div>
            </div>
            <div className="runtime-section">
              <div className="rt-label">Memória contextual</div>
              <dl className="rt-kv compact">
                {runtimeMemory.slice(0, 8).map(item => (
                  <React.Fragment key={item.name || item.label}><dt>{item.label || `@${item.name}`}</dt><dd>{runtimeText(item.value, item.filled ? '' : '--')}</dd></React.Fragment>
                ))}
                {!runtimeMemory.length && <><dt>dados</dt><dd>sem memória salva</dd></>}
              </dl>
            </div>
            <div className="runtime-section">
              <div className="rt-label">Ferramentas usadas</div>
              <div className="rt-list">
                {runtimeTools.slice(0, 5).map(item => (
                  <div className="item runtime-card" key={item.id || toolLine(item)}>
                    <span className="t">{toolLine(item)}</span>
                    {item.error || runtimeText(item.output?.summary || item.output?.result || item.input?.query || item.input?.key, item.status || 'OK')}
                  </div>
                ))}
                {!runtimeTools.length && <div className="empty tiny">Nenhuma ferramenta registrada.</div>}
              </div>
            </div>
            <div className="runtime-section">
              <div className="rt-label">Condicionais ativadas</div>
              <div className="rt-list">
                {runtimeConditionals.slice(0, 4).map((item, idx) => (
                  <div className="item condition-card" key={item.id || item.name || idx}>
                    <span className="t">{runtimeText(item.name || item.prompt_name || item.type, 'condicional')}</span>
                    {runtimeText(item.reason || item.condition || item.action || item.prompt, 'ativada')}
                  </div>
                ))}
                {!runtimeConditionals.length && <div className="empty tiny">Nenhuma condicional ativa.</div>}
              </div>
            </div>
          </aside>
        </div>
      </div>
    </>
  );
};

window.ConversationWorkspace = window.ConversationsPage;

window.TicketsPage = function TicketsPage() {
  const data = window.MOCK || {};
  const tickets = data.tickets || [];
  const [filter, setFilter] = React.useState('Todos');
  const [typeFilter, setTypeFilter] = React.useState('Todos');
  const [sourceFilter, setSourceFilter] = React.useState('Todos');
  const [q, setQ] = React.useState('');
  const map = { 'Aberto': 'bad', 'Em andamento': 'warn', 'Resolvido': 'ok', 'Fechado': '' };
  const counts = tickets.reduce((acc, t) => { acc[t.status] = (acc[t.status] || 0) + 1; return acc; }, {});
  const requestTypes = ['Todos', ...Array.from(new Set(tickets.map(t => t.requestType).filter(Boolean)))];
  const sources = ['Todos', ...Array.from(new Set(tickets.map(t => t.source === 'shared_chat_contact' ? 'Chat Compartilhado' : t.source).filter(Boolean)))];
  function sourceLabel(ticket) {
    if (ticket.source === 'shared_chat_contact') return 'Chat Compartilhado';
    return ticket.source || '--';
  }
  const filtered = tickets.filter(t =>
    (filter === 'Todos' || t.status === filter) &&
    (typeFilter === 'Todos' || t.requestType === typeFilter) &&
    (sourceFilter === 'Todos' || sourceLabel(t) === sourceFilter) &&
    (q === '' || `${t.client} ${t.id} ${t.summary} ${t.team} ${t.attendant} ${t.requestType} ${sourceLabel(t)}`.toLowerCase().includes(q.toLowerCase()))
  );
  const open = tickets.filter(t => ['Aberto', 'Em andamento'].includes(t.status)).length;
  const resolved = tickets.filter(t => t.status === 'Resolvido').length;

  function setTicketStatus(ticket, status) {
    return API.updateTicket(ticket.realId || ticket.raw?.id, { status }).then(() => window.STUDIO.refresh());
  }

  async function deleteTicket(ticket) {
    if (!(await studioConfirm({ title: 'Excluir ticket', message: 'Excluir ticket?', confirmLabel: 'Excluir', danger: true }))) return;
    return API.deleteTicket(ticket.realId || ticket.raw?.id).then(() => window.STUDIO.refresh());
  }

  return (
    <>
      <div className="page-head">
        <div>
          <div className="page-eyebrow">Operação - fila humana</div>
          <h1 className="page-title">Tickets</h1>
          <p className="page-sub">Tickets reais criados por handoff humano, atualizaveis direto no backend.</p>
        </div>
        <div className="page-meta"><span className="badge accent">{tickets.length} tickets</span></div>
      </div>

      <div className="page">
        <div className="module-grid-4">
          <div className="kpi"><div className="kpi-label">Abertos</div><div className="kpi-value">{open}</div><div className="kpi-foot"><span>exigem humano</span><span/></div></div>
          <div className="kpi"><div className="kpi-label">Resolvidos</div><div className="kpi-value">{resolved}</div><div className="kpi-foot"><span>finalizados</span><span/></div></div>
          <div className="kpi"><div className="kpi-label">Sem atendente</div><div className="kpi-value">{tickets.filter(t => !t.raw?.assigned_attendant_id).length}</div><div className="kpi-foot"><span>round-robin pode assumir</span><span/></div></div>
          <div className="kpi"><div className="kpi-label">Tags</div><div className="kpi-value">{new Set(tickets.flatMap(t => t.tags || [])).size}</div><div className="kpi-foot"><span>classificações</span><span/></div></div>
        </div>

        <div className="panel">
          <div className="panel-head">
            <div style={{ flex: 1, display: 'flex', gap: 10, alignItems: 'center', flexWrap:'wrap'}}>
              <div className="topbar-search" style={{ width: 260, margin: 0}}>
                <Icon name="search" size={13}/>
                <input value={q} onChange={e => setQ(e.target.value)} placeholder="Cliente ou T-..."/>
              </div>
              {['Todos', 'Aberto', 'Em andamento', 'Resolvido', 'Fechado'].map(s => (
                <button key={s} className={`fp ${filter === s ? 'active' : ''}`} onClick={() => setFilter(s)}>
                  {s} <span className="count">{s === 'Todos' ? tickets.length : (counts[s] || 0)}</span>
                </button>
              ))}
              <select className="select-filter" value={typeFilter} onChange={e => setTypeFilter(e.target.value)} title="Tipo da solicitação">
                {requestTypes.map(item => <option key={item} value={item}>{item === 'Todos' ? 'Todos os tipos' : item}</option>)}
              </select>
              <select className="select-filter" value={sourceFilter} onChange={e => setSourceFilter(e.target.value)} title="Origem">
                {sources.map(item => <option key={item} value={item}>{item === 'Todos' ? 'Todas origens' : item}</option>)}
              </select>
            </div>
          </div>
          <table className="dt tickets-table">
            <thead>
              <tr><th>ID</th><th>Cliente</th><th>Origem</th><th>Tipo</th><th>Time</th><th>Atendente</th><th>Resumo</th><th>Tags</th><th>Status</th><th>Atualizado</th><th></th></tr>
            </thead>
            <tbody>
              {filtered.map(t => (
                <tr key={t.id}>
                  <td data-label="ID" className="mono">{t.id}</td>
                  <td data-label="Cliente"><div className="av"><span className="av-mark" style={{ width:24, height:24, fontSize:10}}>{initials(t.client)}</span><span className="av-name">{t.client}</span></div></td>
                  <td data-label="Origem"><span className="ticket-origin">{sourceLabel(t)}</span></td>
                  <td data-label="Tipo"><span className="ticket-type">{t.requestType || '--'}</span></td>
                  <td data-label="Time">{t.team}</td>
                  <td data-label="Atendente" className="muted">{t.attendant !== '--' ? t.attendant : <span className="badge bad" style={{fontSize:10}}>não atribuído</span>}</td>
                  <td data-label="Resumo" className="summary-cell"><span className="summary-text" title={t.summary}>{truncateTicketText(t.summary)}</span></td>
                  <td data-label="Tags" className="ticket-tags-cell">{(t.tags || []).map(g => <span key={g} className="ticket-tag">{g}</span>)}</td>
                  <td data-label="Status"><span className={`badge ${map[t.status] || ''}`}><span className={`sw ${map[t.status] || ''}`}/> {t.status}</span></td>
                  <td className="num muted" data-label="Atualizado">{t.updated}</td>
                  <td data-label="" className="actions-cell"><div className="row-actions">
                    {t.status !== 'Em andamento' && <button className="tb-btn ghost" onClick={() => setTicketStatus(t, 'in_progress').catch(err => studioToast(err.message || String(err), 'bad'))}>Assumir</button>}
                    {t.status !== 'Resolvido' && <button className="tb-btn ghost" onClick={() => setTicketStatus(t, 'finished').catch(err => studioToast(err.message || String(err), 'bad'))}>Resolver</button>}
                    <button className="tb-btn danger" onClick={() => deleteTicket(t).catch(err => studioToast(err.message || String(err), 'bad'))}>Excluir</button>
                  </div></td>
                </tr>
              ))}
              {filtered.length === 0 && <tr><td colSpan="11" className="empty">Nenhum ticket corresponde aos filtros.</td></tr>}
            </tbody>
          </table>
        </div>
      </div>
    </>
  );
};

window.PageConvTickets = { ConversationsPage: window.ConversationsPage, TicketsPage: window.TicketsPage };

function truncateTicketText(value) {
  const text = String(value || '');
  return text.length > 280 ? text.slice(0, 279).trimEnd() + '...' : text;
}
