/* ============================================================
   KeS Metas — WhatsApp (estrutura REAL, pronta para o motor)
   ------------------------------------------------------------
   • Mensagens em tempo real no banco (1 doc por mensagem).
   • Envio = FILA: o app grava "pendente"; a PONTE (motor Evolution
     ou API oficial/Coexistência) envia e marca "enviada".
   • Caixa por usuário: cada um vê a sua; líder vê a equipe;
     adm/master vê todos. Supervisão = somente leitura.
   • AUTOMAÇÕES: config em state.config.whatsAuto (boas-vindas /
     fora de horário). A ponte lê essa config e responde sozinha
     gravando na mesma fila com origem:"auto".
   • Sem motor conectado: dá pra testar tudo no DEV com o botão
     "Receber msg de teste" (só aparece no ambiente de teste).
   ============================================================ */
function WhatsAppScreen({ state, dispatch, viewer, isOwner }) {
  const { useState, useEffect, useRef, useMemo } = React;
  const DB = window.KESDB;
  // Tenant em foco: empresa (multiempresa) OU equipe — bancos separados.
  const teamId = tenantIdAtual(state);
  const EMDEV = (typeof location !== "undefined") && (location.hostname === "localhost" || location.hostname === "127.0.0.1");

  // ---- Permissões ----
  const ehAdm = isOwner || viewer.papel === "admin";
  const ehLider = viewer.cargo === "lider";
  const donos = (state.users || []).filter((u) => u.cargo);
  const caixasVisiveis = (ehAdm || ehLider) ? donos : donos.filter((u) => u.id === viewer.id);
  const [caixaId, setCaixaId] = useState(() =>
    (caixasVisiveis.some((u) => u.id === viewer.id) ? viewer.id : (caixasVisiveis[0] || {}).id) || null);
  const caixaDona = donos.find((u) => u.id === caixaId) || null;
  const minhaCaixa = caixaId === viewer.id;

  // ---- Dados reais (tempo real) ----
  const [msgs, setMsgs] = useState([]);
  const [caixas, setCaixas] = useState({});          // { userId: {status, canal, numero, qr} }
  const [erroBanco, setErroBanco] = useState(false);
  useEffect(() => {
    if (!DB || !DB.waCaixasListen || !teamId) return;
    return DB.waCaixasListen(teamId, setCaixas);
  }, [teamId]);
  // ---- Atendimento por conversa: humano assumiu? (IA pausa naquela conversa) ----
  const [atend, setAtend] = useState({});                 // { contato: {assumido, por} }
  useEffect(() => {
    if (!DB || !DB.waAtendListen || !teamId) return;
    return DB.waAtendListen(teamId, setAtend);
  }, [teamId]);
  // ---- AVISOS "sem resposta": relógio das conversas + re-render por minuto ----
  const [fup, setFup] = useState({});                     // { contato: {ultimoTs, ultimaDir, pergunta} }
  useEffect(() => {
    if (!DB || !DB.waFupListen || !teamId) return;
    return DB.waFupListen(teamId, setFup);
  }, [teamId]);
  const [, setRelogio] = useState(0);
  useEffect(() => { const t = setInterval(() => setRelogio((n) => n + 1), 60000); return () => clearInterval(t); }, []);
  // Baseia-se na ÚLTIMA mensagem REAL da conversa → reseta na hora que respondemos.
  // Só avisa quando a mensagem PEDE resposta: abertura de conversa (oi, olá,
  // bom dia…) ou PERGUNTA. "ok", "obrigado" etc. não geram alerta.
  const ehAbertura = (t) => {
    const s = String(t || "").toLowerCase().normalize("NFD").replace(/[̀-ͯ]/g, "").trim();
    if (!s || s.length > 40) return false;
    return /(^|\b)(oi+|ola+|opa|hey|hello|alo+|e ?ai|bom dia|boa tarde|boa noite|tudo bem|td bem)(\b|[!,. ]|$)/.test(s);
  };
  const ehPergunta = (t) => {
    const s = String(t || "").toLowerCase().normalize("NFD").replace(/[̀-ͯ]/g, "").trim();
    if (s.indexOf("?") >= 0) return true;
    return /^(quanto|qual|quais|como|quando|onde|quem|por ?que|pq|sera|pode|podem|poderia|tem|teria|voces|vcs|consigo|da pra|queria saber|gostaria de saber)\b/.test(s);
  };
  const avisoDe = (contato) => {
    const key = String(contato || "").replace(/\D/g, "");
    const cv = conversas.find((x) => String(x.contato || "").replace(/\D/g, "") === key);
    if (!cv || !cv.msgs.length) return null;
    const ult = cv.msgs[cv.msgs.length - 1];
    if (ult.dir !== "in") return null;                    // respondemos → sem aviso
    const pergunta = ehPergunta(ult.texto);
    if (!pergunta && !ehAbertura(ult.texto)) return null; // não pede resposta → sem alerta
    const min = Math.floor((Date.now() - Number(ult.ts || 0)) / 60000);
    if (min < 30) return null;                            // aviso a partir de 30 minutos
    return { min: min, pergunta: pergunta };
  };
  useEffect(() => {
    setMsgs([]); setErroBanco(false);
    if (!DB || !DB.waListen || !teamId || !caixaId) return;
    return DB.waListen(teamId, { caixaId: caixaId }, (lista, err) => {
      if (err) { setErroBanco(true); return; }
      setMsgs(lista || []);
    });
  }, [teamId, caixaId]);

  const caixa = caixas[caixaId] || { status: "desconectado" };
  const conectado = caixa.status === "conectado";

  // ---- Conversas (agrupadas por contato) ----
  const conversas = useMemo(() => {
    const map = {};
    msgs.forEach((m) => {
      const key = String(m.contato || "").replace(/\D/g, "") || "?";
      if (!map[key]) map[key] = { contato: m.contato, nome: m.contatoNome || m.contato, msgs: [], naoLidas: 0 };
      map[key].msgs.push(m);
      if (m.contatoNome) map[key].nome = m.contatoNome;
      if (m.dir === "in" && !m.lida) map[key].naoLidas++;
    });
    return Object.keys(map).map((k) => map[k])
      .sort((a, b) => (b.msgs[b.msgs.length - 1].ts || 0) - (a.msgs[a.msgs.length - 1].ts || 0));
  }, [msgs]);

  const [convKey, setConvKey] = useState(null);
  const [texto, setTexto] = useState("");
  // CRM dentro do WhatsApp: ficha do lead (criar/editar) e tarefa
  const [leadModal, setLeadModal] = useState(null);   // null | prefill (novo) | lead (editar)
  const [tarefaLead, setTarefaLead] = useState(null); // { leadFixo }
  // Mensagens ricas: responder (quote), editar, reagir, áudio e arquivos
  const [replyTo, setReplyTo] = useState(null);       // msg sendo respondida
  const [editando, setEditando] = useState(null);     // msg própria sendo editada
  const [reagindo, setReagindo] = useState(null);     // msg alvo do seletor de emoji
  const [gravando, setGravando] = useState(false);    // gravador de áudio ativo?
  const gravRef = useRef(null);                       // MediaRecorder + chunks
  const fileRef = useRef(null);                       // input de arquivo escondido
  const MAX_ARQ = 15 * 1024 * 1024;                   // 15 MB via Storage (limite do WhatsApp)
  const MAX_B64 = 700 * 1024;                         // reserva sem Storage: base64 no banco
  const EMOJIS = ["👍", "❤️", "😂", "😮", "😢", "🙏"];
  const [emojiPicker, setEmojiPicker] = useState(false);  // seletor de emoji do composer
  const EMOJIS_TODOS = ["😀","😁","😂","🤣","😊","😍","😘","😎","🤔","😅","😉","🙃","😢","😭","😡","🥳","🤝","👍","👎","👏","🙏","💪","👌","✌️","🤞","❤️","💚","💙","💛","🖤","🔥","⭐","✅","❌","⚠️","🎉","🎯","📞","📅","💰","📦","🚀","☕","😴","🤯","😇","🫡","👀"];
  // envia uma mídia: tenta o STORAGE (arquivos grandes); sem Storage → base64 pequeno
  async function subirEEnviar(blob, nome, docBase) {
    const up = DB.waUpload ? await DB.waUpload(teamId, blob, nome) : { ok: false };
    if (up.ok) {
      DB.waSend(teamId, Object.assign({ mediaUrl: up.url }, docBase));
      return true;
    }
    if (blob.size > MAX_B64) {
      dispatch({ type: "TOAST", msg: "⚠ Armazenamento de mídia indisponível — sem ele, o limite é 700 KB. (Habilite o Storage no Firebase.)" });
      return false;
    }
    return await new Promise((res) => {
      const fr = new FileReader();
      fr.onload = () => { DB.waSend(teamId, Object.assign({ mediaB64: String(fr.result) }, docBase)); res(true); };
      fr.readAsDataURL(blob);
    });
  }
  const [threadAberta, setThreadAberta] = useState(false);
  const [qrModal, setQrModal] = useState(false);
  const [autoModal, setAutoModal] = useState(false);
  const [agenteModal, setAgenteModal] = useState(false);   // Agente de IA (prompt no banco)
  const [followModal, setFollowModal] = useState(false);   // Follow-up automático (régua por fase)
  const [crmAberto, setCrmAberto] = useState(false);           // popover CRM do cabeçalho
  const [confirmaApagar, setConfirmaApagar] = useState(false); // apagar a conversa (só admin)
  const [confirmaDesconexao, setConfirmaDesconexao] = useState(false); // desconectar o número (só admin)
  const fimRef = useRef(null);
  const conv = conversas.find((c) => String(c.contato || "").replace(/\D/g, "") === convKey) || null;

  useEffect(() => { setConvKey(null); setThreadAberta(false); }, [caixaId]);
  useEffect(() => { if (fimRef.current) fimRef.current.scrollIntoView({ block: "end" }); }, [msgs, convKey]);

  // Marca como lidas ao abrir (só na própria caixa)
  useEffect(() => {
    if (!conv || !minhaCaixa || !DB || !DB.waUpdateMsg) return;
    conv.msgs.filter((m) => m.dir === "in" && !m.lida && m._id)
      .forEach((m) => DB.waUpdateMsg(teamId, m._id, { lida: true }));
  }, [convKey, msgs.length]);

  // Respondeu manualmente → ASSUME a conversa (a IA não atropela o humano).
  function assumirAoResponder() {
    const chaveAt = String(conv.contato || "").replace(/\D/g, "");
    if (DB.waAtendSet && !(atend[chaveAt] || {}).assumido) {
      DB.waAtendSet(teamId, chaveAt, { assumido: true, por: viewer.nome, porId: viewer.id, em: new Date().toISOString(), auto: true });
      dispatch({ type: "TOAST", msg: "Você respondeu — conversa assumida (a IA pausa aqui). Use 'Devolver p/ IA' quando quiser." });
    }
  }

  function enviar() {
    const t = texto.trim();
    if (!t || !conv || !minhaCaixa || !DB || !DB.waSend) return;
    setTexto("");
    // EDITANDO uma mensagem própria: atualiza o doc + manda o comando pro motor
    if (editando) {
      const alvo = editando; setEditando(null);
      if (alvo._id && DB.waUpdateMsg) DB.waUpdateMsg(teamId, alvo._id, { texto: t.slice(0, 4000), editada: true });
      DB.waSend(teamId, { caixaId: caixaId, contato: conv.contato, contatoNome: conv.nome,
        dir: "out", tipo: "edicao", editarWaId: alvo.waId || "", novoTexto: t.slice(0, 4000),
        texto: "(edição)", ts: Date.now(), status: "pendente", origem: "app", de: viewer.id, lida: true });
      dispatch({ type: "TOAST", msg: "Mensagem editada." });
      return;
    }
    assumirAoResponder();
    const extra = replyTo ? { quotedWaId: replyTo.waId || "", quotedTexto: String(replyTo.texto || "").slice(0, 200) } : {};
    setReplyTo(null);
    DB.waSend(teamId, Object.assign(extra, {
      caixaId: caixaId, contato: conv.contato, contatoNome: conv.nome,
      dir: "out", tipo: "texto", texto: t.slice(0, 4000), ts: Date.now(),
      status: "pendente", origem: "app", de: viewer.id, lida: true,
    }));
  }
  function onKey(e) { if (e.key === "Enter" && !e.shiftKey) { e.preventDefault(); enviar(); } }

  // ---- REAGIR com emoji (o motor manda a reação pro WhatsApp) ----
  function reagir(m, emoji) {
    setReagindo(null);
    if (!m.waId) { dispatch({ type: "TOAST", msg: "Não dá para reagir a esta mensagem (antiga, sem id)." }); return; }
    DB.waSend(teamId, { caixaId: caixaId, contato: conv.contato, contatoNome: conv.nome,
      dir: "out", tipo: "reacao", alvoWaId: m.waId, alvoFromMe: !!m.waFromMe, emoji: emoji,
      texto: emoji + " (você reagiu)", ts: Date.now(), status: "pendente", origem: "app", de: viewer.id, lida: true });
  }

  // ---- ÁUDIO: grava no navegador e manda pela fila (base64) ----
  async function gravarAudio() {
    if (gravando) { try { gravRef.current && gravRef.current.rec.stop(); } catch (e) {} return; }
    try {
      const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
      const rec = new MediaRecorder(stream, MediaRecorder.isTypeSupported("audio/webm;codecs=opus") ? { mimeType: "audio/webm;codecs=opus" } : undefined);
      const chunks = [];
      rec.ondataavailable = (e) => { if (e.data && e.data.size) chunks.push(e.data); };
      rec.onstop = async () => {
        stream.getTracks().forEach((tr) => tr.stop());
        setGravando(false);
        const blob = new Blob(chunks, { type: rec.mimeType || "audio/webm" });
        if (blob.size > MAX_ARQ) { dispatch({ type: "TOAST", msg: "⚠ Áudio muito grande." }); return; }
        assumirAoResponder();
        const ok = await subirEEnviar(blob, "audio.webm", { caixaId: caixaId, contato: conv.contato, contatoNome: conv.nome,
          dir: "out", tipo: "audio", texto: "🎤 Áudio", ts: Date.now(),
          status: "pendente", origem: "app", de: viewer.id, lida: true });
        if (ok) dispatch({ type: "TOAST", msg: "🎤 Áudio na fila de envio." });
      };
      gravRef.current = { rec: rec };
      rec.start();
      setGravando(true);
      // trava de segurança: para sozinho em 60s
      setTimeout(() => { try { rec.state !== "inactive" && rec.stop(); } catch (e) {} }, 60000);
    } catch (e) { dispatch({ type: "TOAST", msg: "⚠ Microfone indisponível ou sem permissão." }); }
  }

  // ---- ARQUIVO/IMAGEM: sobe pro Storage e manda pela fila (até 15 MB) ----
  async function enviarArquivo(ev) {
    const arq = ev.target.files && ev.target.files[0];
    ev.target.value = "";
    if (!arq || !conv) return;
    if (arq.size > MAX_ARQ) { dispatch({ type: "TOAST", msg: "⚠ Arquivo acima de 15 MB (limite do WhatsApp)." }); return; }
    const ehImg = /^image\//.test(arq.type);
    assumirAoResponder();
    const legenda = texto.trim().slice(0, 500);
    const ok = await subirEEnviar(arq, arq.name, { caixaId: caixaId, contato: conv.contato, contatoNome: conv.nome,
      dir: "out", tipo: ehImg ? "imagem" : "documento", mediaNome: arq.name, legenda: legenda,
      texto: ehImg ? ("📷 Imagem" + (legenda ? ": " + legenda : "")) : ("📎 " + arq.name),
      ts: Date.now(), status: "pendente", origem: "app", de: viewer.id, lida: true });
    if (ok) { setTexto(""); dispatch({ type: "TOAST", msg: (ehImg ? "📷 Imagem" : "📎 Arquivo") + " na fila de envio." }); }
  }

  // (o botão "Receber msg de teste" foi removido — o motor real já espelha tudo)

  // Lead do CRM com o mesmo telefone (vínculo automático)
  const leadDe = (c) => {
    const dig = String(c && c.contato || "").replace(/\D/g, "");
    if (dig.length < 8) return null;
    return (state.leads || []).find((l) =>
      ((l.telefone || "") + (l.telefone2 || "") + (l.telefone3 || "")).replace(/\D/g, "").includes(dig.slice(-8)));
  };
  const hora = (ts) => { const d = new Date(ts || 0); const z = (n) => (n < 10 ? "0" : "") + n; return z(d.getHours()) + ":" + z(d.getMinutes()); };
  const tick = (m) => m.dir !== "out" ? "" : (m.status === "pendente" ? " 🕓" : m.status === "erro" ? " ⚠" : " ✓✓");

  // Automações (config da equipe — a ponte consome)
  const auto = (state.config && state.config.whatsAuto) || {};

  return (
    <div className="content content-fill">
      <div className="topbar">
        <div className="ttl">
          <h1 style={{ display: "flex", alignItems: "center", gap: 10, flexWrap: "wrap" }}>
            <Icon name="whatsapp" size={24} style={{ color: "#1FA855" }} />
            WhatsApp
            {conectado
              ? <span className="wa-status ok" style={{ fontSize: 11, padding: "4px 11px" }}><span className="wa-dot" /> Conectado</span>
              : <span className="wa-selo-sim">AGUARDANDO CONEXÃO</span>}
            {caixa.canal && <span className="wa-canal-tag">{caixa.canal === "cloudapi" ? "🅰️ Oficial" : "🅱️ Não-oficial"}</span>}
            {auto.ativo && <span className="wa-status ok" style={{ fontSize: 11, padding: "4px 11px", color: "var(--warn)", background: "rgba(242,169,59,.12)", borderColor: "rgba(242,169,59,.5)" }}>🤖</span>}
            {/* Ações compactas (só ícone) — economizam espaço de tela */}
            {(ehAdm || ehLider) && <button className="iconbtn" title="Automações do WhatsApp" onClick={() => setAutoModal(true)}><Icon name="sliders" size={18} /></button>}
            {ehAdm && <button className="iconbtn" title="Agente de IA (prompt, modos, limite)" onClick={() => setAgenteModal(true)} style={{ fontSize: 16 }}>🤖</button>}
            {(ehAdm || ehLider) && <button className="iconbtn" title="Follow-up automático (régua por fase)" onClick={() => setFollowModal(true)}><Icon name="clock" size={18} /></button>}
            {/* Conectar: o DONO da caixa, e também admin/líder (podem conectar
                qualquer caixa da equipe em foco — cada tenant tem instância própria) */}
            {!conectado && (minhaCaixa || ehAdm || ehLider) && <button className="iconbtn" title={"Conectar WhatsApp (QR)" + (minhaCaixa ? "" : " — caixa de " + (caixaDona ? caixaDona.nome : ""))} onClick={() => setQrModal(true)} style={{ background: "#1FA855", color: "#fff", borderRadius: 10 }}><Icon name="link" size={18} /></button>}
            {/* DESCONECTAR o número (só admin) — o motor faz o logout no Evolution */}
            {conectado && ehAdm && <button className="iconbtn" title={"Desconectar o número" + (caixaDona ? " de " + caixaDona.nome : "")} onClick={() => setConfirmaDesconexao(true)} style={{ color: "var(--kes-red-400)" }}><Icon name="logout" size={17} /></button>}
          </h1>
          <p>{ehAdm ? "Caixas de WhatsApp da equipe." : ehLider ? "WhatsApp da sua equipe." : "Suas conversas de WhatsApp."}</p>
        </div>
        <div className="actions">
          {caixasVisiveis.length > 1 && (
            <Field label={null}>
              <select className="field" value={caixaId || ""} onChange={(e) => setCaixaId(e.target.value)} style={{ minWidth: 190, fontWeight: 700 }}>
                {caixasVisiveis.map((u) => {
                  const st = (caixas[u.id] || {}).status === "conectado" ? " 🟢" : " ⚪";
                  return <option key={u.id} value={u.id}>{u.nome}{u.id === viewer.id ? " (você)" : ""}{st}</option>;
                })}
              </select>
            </Field>
          )}
        </div>
      </div>

      {erroBanco && (
        <div className="wa-supervisao" style={{ background: "rgba(224,60,49,.12)", borderColor: "var(--kes-red-400)", color: "var(--kes-red-400)" }}>
          <Icon name="alert" size={15} /> O banco recusou a leitura do WhatsApp — as regras precisam ser publicadas (fale com o suporte).
        </div>
      )}
      {!minhaCaixa && caixaDona && (
        <div className="wa-supervisao">
          <Icon name="eye" size={15} /> Caixa de <strong>&nbsp;{caixaDona.nome}&nbsp;</strong> — modo supervisão (somente leitura).
        </div>
      )}

      <div className={"chat-grid wa-grid" + (threadAberta ? " thread-open" : "")}>
        {/* Conversas */}
        <aside className="chat-side">
          <div className="chat-side-h">Conversas {caixaDona ? "· " + caixaDona.nome.split(" ")[0] : ""}</div>
          {(() => {
            const pendentes = conversas.filter((c) => avisoDe(c.contato)).length;
            return pendentes > 0 ? (
              <div style={{ margin: "6px 10px", padding: "7px 10px", background: "rgba(224,60,49,.14)", border: "1px solid var(--kes-red-400)", borderRadius: 8, fontSize: 12, color: "var(--kes-red-400)", fontWeight: 700 }}>
                ⚠ {pendentes} conversa{pendentes > 1 ? "s" : ""} aguardando resposta há 30min+
              </div>
            ) : null;
          })()}
          {conversas.length === 0 && (
            <div style={{ padding: 16, fontSize: 12.5, color: "var(--fg3)" }}>
              {conectado ? "Nenhuma conversa ainda." : "Conecte o WhatsApp para as conversas aparecerem aqui."}
            </div>
          )}
          {conversas.map((c) => {
            const key = String(c.contato || "").replace(/\D/g, "");
            const u = c.msgs[c.msgs.length - 1];
            return (
              <button key={key} className={"chat-conv" + (convKey === key ? " active" : "")} onClick={() => { setConvKey(key); setThreadAberta(true); setCrmAberto(false); }}>
                <span className="wa-avatar">{String(c.nome || "?").split(" ").map((p) => p[0]).slice(0, 2).join("").toUpperCase()}</span>
                <span className="chat-conv-tx">
                  <span className="chat-conv-ttl">{c.nome}</span>
                  <span className="chat-conv-sub">{u ? (u.dir === "out" ? "Você: " : "") + u.texto : c.contato}</span>
                  {(() => {
                    const av = avisoDe(c.contato);
                    if (!av) return null;
                    const txt = av.min >= 60 ? Math.floor(av.min / 60) + "h" + (av.min % 60 ? (av.min % 60) + "m" : "") : av.min + "min";
                    return <span style={{ fontSize: 10.5, color: "var(--kes-red-400)", fontWeight: 800 }}>
                      {av.pergunta ? "❓ Pergunta sem resposta há " + txt : "⏰ Sem resposta há " + txt}
                    </span>;
                  })()}
                </span>
                <span style={{ display: "flex", flexDirection: "column", alignItems: "flex-end", gap: 4, flexShrink: 0 }}>
                  <span style={{ fontSize: 10.5, color: "var(--fg3)" }}>{u ? hora(u.ts) : ""}</span>
                  {c.naoLidas > 0 && <span className="chat-badge wa-badge">{c.naoLidas}</span>}
                </span>
              </button>
            );
          })}
        </aside>

        {/* Conversa */}
        <section className="chat-main">
          {!conv ? (
            <div className="empty" style={{ margin: "auto" }}>
              <Icon name="message" size={40} />
              <div style={{ fontWeight: 700 }}>{conectado ? "Escolha uma conversa" : "WhatsApp ainda não conectado"}</div>
              <div style={{ fontSize: 13 }}>{conectado ? "As mensagens chegam em tempo real." : "Use o botão Conectar para vincular o número."}</div>
            </div>
          ) : (
            <>
              <div className="chat-main-h">
                <button className="chat-back iconbtn" onClick={() => setThreadAberta(false)} title="Voltar"><Icon name="chevronLeft" size={20} /></button>
                <span className="wa-avatar" style={{ width: 34, height: 34 }}>{String(conv.nome || "?").split(" ").map((p) => p[0]).slice(0, 2).join("").toUpperCase()}</span>
                <div style={{ minWidth: 0, flex: 1 }}>
                  <div className="chat-main-ttl">{conv.nome}</div>
                  <div className="chat-main-sub">{conv.contato}</div>
                </div>
                {(() => {
                  const lead = leadDe(conv);
                  // CRM vira um botão único no cabeçalho (abre o popover com as ações).
                  if (lead) return (
                    <div style={{ position: "relative" }}>
                      <button className="iconbtn" title="CRM — etapa, ficha, agendar, tarefa" onClick={() => setCrmAberto((v) => !v)}
                        style={{ width: "auto", padding: "0 12px", gap: 6, fontWeight: 700, fontSize: 13, background: crmAberto ? "var(--kes-navy-700)" : "transparent" }}>
                        <Icon name="funnel" size={15} /> CRM <Icon name="chevronDown" size={13} />
                      </button>
                    </div>
                  );
                  // Quem chamou no Whats ainda não é lead → vira lead em 1 clique,
                  // com nome/telefone/responsável já preenchidos (ajusta e salva).
                  const dig = String(conv.contato || "").replace(/\D/g, "");
                  return <Btn variant="primary" size="sm" icon="plus" onClick={() => setLeadModal({
                    nome: (conv.nome && conv.nome !== conv.contato) ? conv.nome : "",
                    empresa: "", telefone: (dig ? "+" + dig : String(conv.contato || "")), telefone2: "", telefone3: "",
                    email: "", socios: "", instagram: "", google: "", linkedin: "", porte: "", endereco: "",
                    origem: "WhatsApp", valor: "", responsavelId: (caixaDona && caixaDona.id) || viewer.id,
                    tags: [], observacoes: "", stageId: (state.stages[0] || {}).id,
                  })}>Criar lead</Btn>;
                })()}
                {/* APAGAR CONVERSA (só administradores) — com confirmação */}
                {ehAdm && (
                  <button className="iconbtn" title="Apagar esta conversa (admin)" onClick={() => setConfirmaApagar(true)} style={{ color: "var(--kes-red-400)" }}>
                    <Icon name="trash" size={16} />
                  </button>
                )}
                {/* ASSUMIR CONVERSA: humano assume → a IA para de responder AQUI.
                    "Devolver" religa a IA nesta conversa. O motor lê isso do banco. */}
                {(minhaCaixa || ehAdm || ehLider) && (() => {
                  const chave = String(conv.contato || "").replace(/\D/g, "");
                  const a = atend[chave] || {};
                  return a.assumido
                    ? <Btn variant="subtle" size="sm" icon="zap" title={"Assumida por " + (a.por || "alguém") + " — clique para devolver à IA"}
                        onClick={() => { DB.waAtendSet(teamId, chave, { assumido: false, devolvidaPor: viewer.nome }); dispatch({ type: "TOAST", msg: "Conversa devolvida — a IA volta a responder aqui. 🤖" }); }}>
                        Devolver p/ IA</Btn>
                    : <Btn variant="primary" size="sm" icon="user"
                        onClick={() => { DB.waAtendSet(teamId, chave, { assumido: true, por: viewer.nome, porId: viewer.id, em: new Date().toISOString() }); dispatch({ type: "TOAST", msg: "Você assumiu esta conversa — a IA não responde mais aqui." }); }}>
                        Assumir conversa</Btn>;
                })()}
              </div>
              {(() => {
                const chave = String(conv.contato || "").replace(/\D/g, "");
                const a = atend[chave] || {};
                return a.assumido ? (
                  <div className="wa-supervisao" style={{ margin: "8px 12px 0" }}>
                    <Icon name="user" size={14} /> 🤖 IA pausada nesta conversa — atendimento com <strong>&nbsp;{a.por || "a equipe"}</strong>
                  </div>
                ) : null;
              })()}
              {/* POPOVER CRM: funções do funil sem sair do WhatsApp — abre pelo
                  botão "CRM" do cabeçalho. Mover de etapa, ficha, agendar, tarefa. */}
              {crmAberto && (() => {
                const lead = leadDe(conv);
                if (!lead) return null;
                return (
                  <div style={{ display: "flex", alignItems: "center", gap: 8, flexWrap: "wrap", margin: "8px 12px 0", padding: "9px 12px", background: "var(--kes-navy-800)", border: "1px solid var(--border-dark)", borderRadius: "var(--radius-md)" }}>
                    <span style={{ fontSize: 11.5, color: "var(--fg3)", fontWeight: 700, letterSpacing: ".04em" }}>ETAPA</span>
                    <select className="field" style={{ width: "auto", padding: "5px 8px", fontSize: 12.5, fontWeight: 700 }}
                      value={lead.stageId || ""} title="Mover de etapa"
                      onChange={(e) => { const v = e.target.value; if (v && v !== lead.stageId) { dispatch({ type: "MOVE_LEAD", id: lead.id, stageId: v }); dispatch({ type: "TOAST", msg: "Lead movido de etapa pelo WhatsApp." }); } }}>
                      {state.stages.map((s) => <option key={s.id} value={s.id}>{s.nome}</option>)}
                    </select>
                    <Btn variant="subtle" size="sm" icon="edit" onClick={() => { setLeadModal(lead); setCrmAberto(false); }}>Ficha</Btn>
                    <Btn variant="subtle" size="sm" icon="calendar" onClick={() => { dispatch({ type: "AGENDAR_LEAD", lead: lead }); setCrmAberto(false); }}>Agendar reunião</Btn>
                    <Btn variant="subtle" size="sm" icon="checkCircle" onClick={() => { setTarefaLead({ leadFixo: lead }); setCrmAberto(false); }}>Tarefa</Btn>
                  </div>
                );
              })()}

              <div className="chat-msgs wa-msgs">
                {conv.msgs.map((m) => {
                  if (m.tipo === "edicao") return null;   // comando interno — não é bolha
                  if (m.tipo === "reacao") return (
                    <div key={m._id || m.ts} style={{ alignSelf: m.dir === "out" ? "flex-end" : "flex-start", fontSize: 12, color: "var(--fg3)", padding: "2px 10px" }}>{m.texto} · {hora(m.ts)}</div>
                  );
                  const minha = m.dir === "out";
                  return (
                    <div key={m._id || m.ts} className={"chat-bubble wa-bubble " + (minha ? "mine wa-out" : "theirs")}>
                      {m.origem === "auto" && <div className="chat-bubble-nome" style={{ color: "var(--warn)" }}>🤖 resposta automática</div>}
                      {m.quotedTexto && (
                        <div style={{ borderLeft: "3px solid var(--kes-red-400)", background: "rgba(255,255,255,.06)", borderRadius: 6, padding: "4px 8px", fontSize: 12, color: "var(--fg2)", marginBottom: 5, maxWidth: 320, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }}>↩ {m.quotedTexto}</div>
                      )}
                      {m.tipo === "audio" && (m.mediaUrl || m.mediaB64)
                        ? <audio controls src={m.mediaUrl || m.mediaB64} style={{ maxWidth: 240, height: 38 }} />
                        : m.tipo === "imagem" && (m.mediaUrl || m.mediaB64)
                          ? <img src={m.mediaUrl || m.mediaB64} alt="imagem" style={{ maxWidth: 240, maxHeight: 240, borderRadius: 8, display: "block" }} />
                          : m.tipo === "documento" && m.mediaUrl
                            ? <a href={m.mediaUrl} target="_blank" rel="noreferrer" style={{ color: "inherit", textDecoration: "underline" }}>📎 {m.mediaNome || "Arquivo"}</a>
                            : <div className="chat-bubble-tx">{m.texto}</div>}
                      <div className="chat-bubble-ts">{m.editada ? "(editada) " : ""}{hora(m.ts)}{tick(m)}</div>
                      {/* Ações da mensagem (aparecem no hover): responder, reagir, editar */}
                      {minhaCaixa && (
                        <div className="wa-acts">
                          <button className="wa-act" title="Responder" onClick={() => { setEditando(null); setReplyTo(m); }}>↩</button>
                          <button className="wa-act" title="Reagir" onClick={() => setReagindo(reagindo === (m._id || m.ts) ? null : (m._id || m.ts))}>🙂</button>
                          {minha && m.tipo !== "audio" && m.tipo !== "imagem" && m.tipo !== "documento" && m.origem !== "auto" && (
                            <button className="wa-act" title="Editar mensagem" onClick={() => { setReplyTo(null); setEditando(m); setTexto(m.texto || ""); }}>✏️</button>
                          )}
                        </div>
                      )}
                      {reagindo === (m._id || m.ts) && (
                        <div style={{ display: "flex", gap: 4, marginTop: 6, background: "var(--kes-navy-800)", border: "1px solid var(--border-dark)", borderRadius: 20, padding: "4px 8px", width: "fit-content" }}>
                          {EMOJIS.map((e) => <button key={e} className="wa-act" style={{ fontSize: 17 }} onClick={() => reagir(m, e)}>{e}</button>)}
                        </div>
                      )}
                    </div>
                  );
                })}
                <div ref={fimRef} />
              </div>

              {minhaCaixa ? (
                <div>
                  {replyTo && (
                    <div style={{ display: "flex", alignItems: "center", gap: 8, margin: "6px 12px 0", padding: "6px 10px", background: "var(--kes-navy-800)", borderLeft: "3px solid #1FA855", borderRadius: 6, fontSize: 12.5 }}>
                      <span style={{ color: "var(--fg2)", overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap", flex: 1 }}>↩ Respondendo: {String(replyTo.texto || "").slice(0, 90)}</span>
                      <button className="wa-act" onClick={() => setReplyTo(null)} title="Cancelar">✕</button>
                    </div>
                  )}
                  {editando && (
                    <div style={{ display: "flex", alignItems: "center", gap: 8, margin: "6px 12px 0", padding: "6px 10px", background: "rgba(242,169,59,.14)", borderLeft: "3px solid var(--warn)", borderRadius: 6, fontSize: 12.5 }}>
                      <span style={{ color: "var(--fg2)", flex: 1 }}>✏️ Editando mensagem — altere o texto e envie</span>
                      <button className="wa-act" onClick={() => { setEditando(null); setTexto(""); }} title="Cancelar edição">✕</button>
                    </div>
                  )}
                  {emojiPicker && (
                    <div style={{ display: "flex", flexWrap: "wrap", gap: 2, margin: "6px 12px 0", padding: 8, background: "var(--kes-navy-800)", border: "1px solid var(--border-dark)", borderRadius: 12, maxHeight: 130, overflowY: "auto" }}>
                      {EMOJIS_TODOS.map((e) => <button key={e} className="wa-act" style={{ fontSize: 20, padding: "3px 5px" }} onClick={() => setTexto((t) => t + e)}>{e}</button>)}
                    </div>
                  )}
                  <div className="chat-composer">
                    <input type="file" ref={fileRef} style={{ display: "none" }} onChange={enviarArquivo}
                      accept="image/*,application/pdf,.doc,.docx,.xls,.xlsx,.csv,.txt,.zip,video/*,audio/*" />
                    <button className="iconbtn" title="Emojis" onClick={() => setEmojiPicker(!emojiPicker)} style={{ fontSize: 17 }}>😊</button>
                    <button className="iconbtn" title="Enviar arquivo ou imagem (até 15 MB)" onClick={() => fileRef.current && fileRef.current.click()} disabled={!!editando}>
                      <Icon name="paperclip" size={19} />
                    </button>
                    <button className="iconbtn" title={gravando ? "Parar e enviar o áudio" : "Gravar áudio"} onClick={gravarAudio} disabled={!!editando}
                      style={gravando ? { background: "var(--kes-red-400)", color: "#fff", borderRadius: 10, animation: "pulse 1s infinite" } : {}}>
                      <Icon name={gravando ? "check" : "mic"} size={19} />
                    </button>
                    <textarea className="field chat-input" rows={1} placeholder={gravando ? "🔴 Gravando… clique no ✓ para enviar" : (editando ? "Novo texto da mensagem…" : "Mensagem…")}
                      value={texto} onChange={(e) => setTexto(e.target.value)} onKeyDown={onKey} />
                    <Btn variant="primary" icon="arrowRight" onClick={enviar} disabled={!texto.trim()} style={{ background: "#1FA855", borderColor: "#1FA855" }}>{editando ? "Salvar" : "Enviar"}</Btn>
                  </div>
                </div>
              ) : (
                <div className="chat-readonly">
                  <Icon name="eye" size={15} style={{ verticalAlign: "-2px", marginRight: 6 }} />
                  Modo supervisão — somente {caixaDona ? caixaDona.nome.split(" ")[0] : "o dono da caixa"} responde por este número.
                </div>
              )}
            </>
          )}
        </section>
      </div>

      {/* DESCONECTAR O NÚMERO — confirmação (o motor faz o logout em ~1 min) */}
      {confirmaDesconexao && (
        <Modal title="Desconectar o WhatsApp?" onClose={() => setConfirmaDesconexao(false)}
          footer={<><Btn variant="ghost" onClick={() => setConfirmaDesconexao(false)}>Cancelar</Btn>
            <Btn variant="primary" icon="logout" style={{ background: "var(--kes-red-400)", borderColor: "var(--kes-red-400)" }}
              onClick={() => {
                setConfirmaDesconexao(false);
                DB.waCaixaSet(teamId, caixaId, { status: "desconectar", solicitadoEm: new Date().toISOString() });
                dispatch({ type: "TOAST", msg: "Desconectando o número… (leva até 1 minuto)" });
              }}>Desconectar</Btn></>}>
          <p style={{ margin: 0, fontSize: 13.5, lineHeight: 1.6 }}>
            Desconectar o número {caixa.numero ? <strong>+{caixa.numero}</strong> : "desta caixa"}{caixaDona ? <> (caixa de <strong>{caixaDona.nome}</strong>)</> : ""}?<br />
            As conversas ficam guardadas no sistema; o número para de receber/enviar por aqui até alguém
            conectar de novo pelo QR. O agente de IA e o follow-up desta caixa também param.
          </p>
        </Modal>
      )}

      {/* APAGAR CONVERSA — confirmação (remove as mensagens e os controles;
          NÃO apaga nada no celular do cliente, só aqui no sistema) */}
      {confirmaApagar && conv && (
        <Modal title="Apagar conversa?" onClose={() => setConfirmaApagar(false)}
          footer={<><Btn variant="ghost" onClick={() => setConfirmaApagar(false)}>Cancelar</Btn>
            <Btn variant="primary" icon="trash" style={{ background: "var(--kes-red-400)", borderColor: "var(--kes-red-400)" }}
              onClick={async () => {
                const alvo = conv; setConfirmaApagar(false);
                let n = 0;
                for (const m of alvo.msgs) { if (m._id && DB.waMsgDelete) { await DB.waMsgDelete(teamId, m._id); n++; } }
                if (DB.waConversaLimpar) await DB.waConversaLimpar(teamId, alvo.contato);
                setConvKey(null); setThreadAberta(false);
                dispatch({ type: "TOAST", msg: "Conversa apagada (" + n + " mensagens)." });
              }}>Apagar de vez</Btn></>}>
          <p style={{ margin: 0, fontSize: 13.5, lineHeight: 1.6 }}>
            Apagar a conversa com <strong>{conv.nome}</strong> ({conv.msgs.length} mensagens)?<br />
            Isso remove o histórico <strong>do sistema</strong> (o celular do cliente não é afetado) e zera os controles de follow-up.
            <strong> Não dá para desfazer.</strong>
          </p>
        </Modal>
      )}

      {/* FICHA DO LEAD (criar/editar) — o mesmo modal do CRM, dentro do WhatsApp.
          Sem id = novo (vem pré-preenchido da conversa); com id = editar. */}
      {leadModal && window.LeadModal && (
        <window.LeadModal initial={leadModal} stages={state.stages} users={state.users} viewer={viewer}
          onClose={() => setLeadModal(null)}
          onSave={(data) => {
            if (leadModal.id) {
              dispatch({ type: "UPDATE_LEAD", id: leadModal.id, patch: data });
              dispatch({ type: "TOAST", msg: "Lead atualizado pelo WhatsApp." });
            } else {
              dispatch({ type: "ADD_LEAD", lead: data });
              dispatch({ type: "TOAST", msg: "Contato virou lead no CRM. ✅" });
            }
            setLeadModal(null);
          }}
          onAgendar={(l) => { setLeadModal(null); dispatch({ type: "AGENDAR_LEAD", lead: l }); }}
          onTarefa={(l) => { setLeadModal(null); setTarefaLead({ leadFixo: l }); }} />
      )}

      {/* TAREFA vinculada ao lead — o mesmo modal do CRM/Tarefas */}
      {tarefaLead && window.TarefaModal && (
        <window.TarefaModal state={state} viewer={viewer} dispatch={dispatch}
          leadFixo={tarefaLead.leadFixo || null} onClose={() => setTarefaLead(null)} />
      )}

      {/* Modal de conexão — ciente do canal (Oficial vs Não-oficial) */}
      {qrModal && (
        <ConexaoWhatsModal caixa={caixa} onClose={() => setQrModal(false)}
          onCanal={(canal) => {
            if (!DB || !DB.waCaixaSet) return;
            // Evolution: pede o PROVISIONAMENTO — o motor (n8n) cria a instância
            // e devolve o QR neste mesmo documento (aparece aqui em tempo real).
            if (canal === "evolution" && caixa.status !== "conectado") {
              DB.waCaixaSet(teamId, caixaId, { canal: canal, status: "provisionar", solicitadoEm: new Date().toISOString() });
            } else {
              DB.waCaixaSet(teamId, caixaId, { canal: canal, status: caixa.status || "desconectado" });
            }
          }} />
      )}

      {/* Modal do FOLLOW-UP — régua por fase do funil, com IA adaptando os modelos.
          Config em config.followupWhats — o motor lê do banco a cada rodada. */}
      {followModal && (
        <FollowupModal cfg={(state.config || {}).followupWhats || {}} state={state} onClose={() => setFollowModal(false)}
          onSave={(cfg) => { dispatch({ type: "SET_CONFIG", patch: { followupWhats: cfg } }); dispatch({ type: "TOAST", msg: "Follow-up salvo. O motor já segue a nova régua." }); setFollowModal(false); }} />
      )}

      {/* Modal do AGENTE DE IA — o prompt mora no BANCO (config.agenteWhats);
          o motor (n8n) lê a cada mensagem. Editar aqui vale na hora. */}
      {agenteModal && (
        <AgenteIAModal agente={(state.config || {}).agenteWhats || {}} onClose={() => setAgenteModal(false)}
          onSave={(cfg) => { dispatch({ type: "SET_CONFIG", patch: { agenteWhats: cfg } }); dispatch({ type: "TOAST", msg: "Agente de IA salvo. Já vale para as próximas mensagens." }); setAgenteModal(false); }} />
      )}

      {/* Modal de AUTOMAÇÕES — a ponte (motor) lê esta configuração */}
      {autoModal && (
        <AutoWhatsModal auto={auto} onClose={() => setAutoModal(false)}
          onSave={(cfg) => { dispatch({ type: "SET_CONFIG", patch: { whatsAuto: cfg } }); dispatch({ type: "TOAST", msg: "Automações do WhatsApp salvas." }); setAutoModal(false); }} />
      )}
    </div>
  );
}

/* ---- Modal de conexão: escolhe o CANAL e mostra o passo certo ----
   • cloudapi  = API Oficial (Meta Cloud API / Coexistência) — conexão feita no
     n8n/Meta; aqui não tem QR, o número "aparece" quando o webhook recebe.
   • evolution = não-oficial (Evolution/Baileys) — conexão por QR Code.
   Os TOKENS ficam no n8n (servidor) — nunca nesta tela. */
function ConexaoWhatsModal({ caixa, onClose, onCanal }) {
  const { useState } = React;
  const [canal, setCanal] = useState(caixa.canal || null);
  const escolher = (c) => { setCanal(c); onCanal(c); };

  return (
    <Modal title="Conectar WhatsApp" onClose={onClose} wide
      footer={<Btn variant="ghost" onClick={onClose}>Fechar</Btn>}>
      {!canal ? (
        <>
          <p style={{ margin: "0 0 12px", fontSize: 13.5 }}>Como este número vai conectar?</p>
          <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 12 }}>
            <button className="wa-canal-card" onClick={() => escolher("cloudapi")}>
              <div className="wa-canal-emoji">🅰️</div>
              <strong>API Oficial (Meta)</strong>
              <span>Número espelhado (Coexistência). Sem risco de bloqueio. Recomendado.</span>
            </button>
            <button className="wa-canal-card" onClick={() => escolher("evolution")}>
              <div className="wa-canal-emoji">🅱️</div>
              <strong>Não-oficial (QR)</strong>
              <span>Conecta por QR Code, como o WhatsApp Web. Mais barato, com risco.</span>
            </button>
          </div>
        </>
      ) : canal === "cloudapi" ? (
        <div style={{ fontSize: 13.5, lineHeight: 1.7 }}>
          <div className="wa-status ok" style={{ display: "inline-flex", marginBottom: 10 }}><span className="wa-dot" /> Canal: API Oficial</div>
          <p style={{ margin: "0 0 10px" }}>Este número usa a <strong>API Oficial da Meta (Coexistência)</strong>. A conexão e os <strong>tokens</strong> ficam no <strong>n8n</strong> (servidor) — nunca aqui.</p>
          <p style={{ margin: "0 0 10px" }}>As conversas aparecem <strong>automaticamente</strong> assim que o webhook receber a 1ª mensagem. {caixa.numero ? <>Número: <strong>{caixa.numero}</strong>.</> : <span className="muted">Aguardando o número ser vinculado no n8n.</span>}</p>
          <button className="bulk-link" onClick={() => escolher(null)}>← trocar o tipo de conexão</button>
        </div>
      ) : (
        <div style={{ fontSize: 13.5, lineHeight: 1.7 }}>
          <div className="wa-selo-sim" style={{ marginBottom: 10 }}>CANAL: NÃO-OFICIAL (QR)</div>
          {caixa.qr ? (
            <div style={{ display: "flex", gap: 18, flexWrap: "wrap", alignItems: "center" }}>
              <img src={caixa.qr} alt="QR Code" style={{ width: 190, height: 190, background: "#fff", borderRadius: 10, padding: 8 }} />
              <ol style={{ margin: 0, paddingLeft: 18, display: "grid", gap: 6, flex: 1, minWidth: 200 }}>
                <li>Abra o <strong>WhatsApp</strong> no celular</li>
                <li><strong>⋮ &gt; Dispositivos conectados</strong></li>
                <li><strong>Conectar dispositivo</strong> → aponte a câmera</li>
              </ol>
            </div>
          ) : (
            <p className="muted" style={{ margin: 0 }}>
              {caixa.status === "provisionar" || caixa.status === "conectando"
                ? <>⏳ <strong>Gerando o QR Code…</strong> o motor está criando a instância deste número (leva até 1 minuto). O código aparece aqui sozinho — não feche.</>
                : <>O <strong>motor (Evolution)</strong> ainda não gerou o QR desta caixa. Quando o n8n/Evolution ativar o número, o código aparece aqui.</>}
            </p>
          )}
          <div style={{ marginTop: 12 }}><button className="bulk-link" onClick={() => escolher(null)}>← trocar o tipo de conexão</button></div>
        </div>
      )}
    </Modal>
  );
}

/* ---- Configuração das respostas automáticas (estrutura p/ a ponte) ---- */
function AutoWhatsModal({ auto, onClose, onSave }) {
  const { useState } = React;
  const [f, setF] = useState({
    ativo: !!auto.ativo,
    msgBoasVindas: auto.msgBoasVindas || "",
    foraHorarioAtivo: !!auto.foraHorarioAtivo,
    msgForaHorario: auto.msgForaHorario || "",
    horaInicio: auto.horaInicio || "08:00",
    horaFim: auto.horaFim || "18:00",
  });
  const set = (k, v) => setF((s) => ({ ...s, [k]: v }));
  return (
    <Modal title="Automações do WhatsApp 🤖" onClose={onClose} wide
      footer={<><Btn variant="ghost" onClick={onClose}>Cancelar</Btn>
        <Btn variant="primary" icon="check" onClick={() => onSave(f)}>Salvar</Btn></>}>
      <label className="cfg-toggle" style={{ marginBottom: 10 }}>
        <input type="checkbox" checked={f.ativo} onChange={(e) => set("ativo", e.target.checked)} />
        <span><strong>Ativar respostas automáticas</strong> (passa a valer quando o motor estiver conectado)</span>
      </label>
      <Field label="Mensagem de boas-vindas" hint="Enviada 1x quando um contato NOVO chama pela primeira vez">
        <textarea className="field" style={{ minHeight: 60 }} value={f.msgBoasVindas} onChange={(e) => set("msgBoasVindas", e.target.value)}
          placeholder="Ex.: Olá! 👋 Aqui é da KeS Assessoria. Já vamos te atender!" />
      </Field>
      <label className="cfg-toggle" style={{ margin: "6px 0 10px" }}>
        <input type="checkbox" checked={f.foraHorarioAtivo} onChange={(e) => set("foraHorarioAtivo", e.target.checked)} />
        <span><strong>Responder fora do horário comercial</strong></span>
      </label>
      {f.foraHorarioAtivo && (
        <>
          <div className="form-row">
            <Field label="Início do expediente"><input type="time" className="field" value={f.horaInicio} onChange={(e) => set("horaInicio", e.target.value)} /></Field>
            <Field label="Fim do expediente"><input type="time" className="field" value={f.horaFim} onChange={(e) => set("horaFim", e.target.value)} /></Field>
          </div>
          <Field label="Mensagem fora do horário">
            <textarea className="field" style={{ minHeight: 60 }} value={f.msgForaHorario} onChange={(e) => set("msgForaHorario", e.target.value)}
              placeholder="Ex.: Recebemos sua mensagem! Nosso horário é das 8h às 18h — te respondemos assim que abrirmos. 😊" />
          </Field>
        </>
      )}
    </Modal>
  );
}

/* ---- AGENTE DE IA — o prompt fica no BANCO (config.agenteWhats do tenant).
   O motor (n8n) lê a cada mensagem recebida: mudou aqui, valeu na hora.
   Modos: sempre | fora do horário | desligado. Modelo: GPT (OpenAI). ---- */
function AgenteIAModal({ agente, onClose, onSave }) {
  const { useState, useRef, useEffect } = React;
  const PROMPT_EXEMPLO = "Você é o assistente comercial da {{empresa}}. Atenda com simpatia e objetividade, em português.\n\nSuas tarefas:\n1. Cumprimentar e entender o que o cliente precisa.\n2. Responder dúvidas sobre nossos serviços.\n3. Coletar nome e necessidade do cliente.\n4. Oferecer agendar uma conversa com a equipe comercial.\n\nRegras:\n- Nunca invente preços ou prazos; diga que a equipe confirma.\n- Se o cliente pedir um humano, diga que a equipe já vai assumir.\n- Respostas curtas (até 3 frases), tom cordial e profissional.";
  const [f, setF] = useState({
    ativo: !!agente.ativo,
    modo: agente.modo || "fora_horario",           // sempre | fora_horario
    prompt: agente.prompt || PROMPT_EXEMPLO,
    horaInicio: agente.horaInicio || "08:00",
    horaFim: agente.horaFim || "18:00",
    limiteDia: agente.limiteDia || 100,             // teto de respostas/dia (controle de custo)
  });
  const set = (k, v) => setF((s) => ({ ...s, [k]: v }));

  // ---- SIMULADOR: converse com o agente ANTES de ligar no WhatsApp real ----
  // Usa o prompt COMO ESTÁ NA TELA (nem precisa salvar). Nada é enviado ao
  // WhatsApp nem gravado nas conversas — é um ensaio de bancada.
  const [teste, setTeste] = useState([]);          // [{de:'cliente'|'agente', texto}]
  const [testeTxt, setTesteTxt] = useState("");
  const [testeBusy, setTesteBusy] = useState(false);
  const [testeErro, setTesteErro] = useState("");
  const fimRef = useRef(null);
  useEffect(() => { if (fimRef.current) fimRef.current.scrollIntoView({ behavior: "smooth" }); }, [teste, testeBusy]);
  async function testar() {
    const texto = testeTxt.trim();
    if (!texto || testeBusy) return;
    const novo = teste.concat([{ de: "cliente", texto }]);
    setTeste(novo); setTesteTxt(""); setTesteErro(""); setTesteBusy(true);
    try {
      const r = await Promise.race([
        fetch("https://webhook.kesassessoria.com/webhook/kes-agente-teste", {
          method: "POST", headers: { "Content-Type": "application/json" },
          body: JSON.stringify({ prompt: String(f.prompt || "").slice(0, 6000), historico: novo.slice(-12) }),
        }),
        new Promise((_, rej) => setTimeout(() => rej(new Error("timeout")), 30000)),
      ]);
      const d = await r.json();
      if (d && d.resposta) setTeste((t) => t.concat([{ de: "agente", texto: String(d.resposta) }]));
      else setTesteErro("O motor respondeu sem texto — tente de novo.");
    } catch (e) {
      setTesteErro("O motor de teste não respondeu. Ele precisa estar ativo no n8n (workflow “Teste do Agente”).");
    }
    setTesteBusy(false);
  }

  return (
    <Modal title="Agente de IA do WhatsApp 🤖" onClose={onClose} wide
      footer={<><Btn variant="ghost" onClick={onClose}>Cancelar</Btn>
        <Btn variant="primary" icon="check" onClick={() => onSave({ ...f, limiteDia: Number(f.limiteDia) || 100, modelo: "gpt-4o-mini" })}>Salvar agente</Btn></>}>
      <label className="cfg-toggle" style={{ marginBottom: 10 }}>
        <input type="checkbox" checked={f.ativo} onChange={(e) => set("ativo", e.target.checked)} />
        <span><strong>Ligar o agente</strong> — responde sozinho nas caixas conectadas desta {""}equipe</span>
      </label>
      <div className="form-row">
        <Field label="Quando responder">
          <select className="field" value={f.modo} onChange={(e) => set("modo", e.target.value)}>
            <option value="sempre">Sempre (24h, até um humano assumir)</option>
            <option value="fora_horario">Só fora do horário comercial</option>
          </select>
        </Field>
        <Field label="Limite de respostas por dia" hint="Trava de custo — o agente para ao atingir">
          <input type="number" className="field" min="1" max="2000" value={f.limiteDia} onChange={(e) => set("limiteDia", e.target.value)} />
        </Field>
      </div>
      {f.modo === "fora_horario" && (
        <div className="form-row">
          <Field label="Início do expediente"><input type="time" className="field" value={f.horaInicio} onChange={(e) => set("horaInicio", e.target.value)} /></Field>
          <Field label="Fim do expediente"><input type="time" className="field" value={f.horaFim} onChange={(e) => set("horaFim", e.target.value)} /></Field>
        </div>
      )}
      <Field label="Prompt do agente (a personalidade e as regras dele)"
        hint={'Variáveis: {{empresa}} {{equipe}} {{nome_cliente}}. Salvou, valeu — o motor lê o prompt do banco a cada mensagem.'}>
        <textarea className="field" style={{ minHeight: 220, fontFamily: "inherit", fontSize: 13, lineHeight: 1.55 }}
          value={f.prompt} onChange={(e) => set("prompt", e.target.value)} />
      </Field>
      <p className="muted" style={{ fontSize: 12, margin: 0 }}>
        Modelo: <strong>GPT (OpenAI)</strong>, com o histórico recente da conversa como contexto. As chaves ficam no servidor — nunca neste navegador.
      </p>

      <div className="section-label"><span className="eyebrow">🧪 Testar o agente (não envia nada ao WhatsApp)</span><span className="rule" /></div>
      <p className="muted" style={{ fontSize: 12, margin: "0 0 8px" }}>
        Converse como se fosse um cliente. Vale o prompt <strong>como está acima</strong> — dá pra ajustar e testar quantas vezes quiser antes de salvar/ligar.
      </p>
      <div style={{ border: "1px solid var(--border-dark)", borderRadius: "var(--radius-md)", padding: 10, maxHeight: 260, overflowY: "auto", display: "flex", flexDirection: "column", gap: 6, background: "var(--kes-navy-800)" }}>
        {teste.length === 0 && <div className="muted" style={{ fontSize: 12.5, textAlign: "center", padding: 14 }}>Escreva abaixo a primeira mensagem do "cliente" 👇</div>}
        {teste.map((m, i) => (
          <div key={i} style={{ alignSelf: m.de === "cliente" ? "flex-end" : "flex-start", maxWidth: "85%",
            background: m.de === "cliente" ? "var(--kes-red)" : "var(--kes-navy-700)", color: "#fff",
            borderRadius: 12, padding: "8px 12px", fontSize: 13.5, whiteSpace: "pre-wrap" }}>
            {m.de === "agente" && <div style={{ fontSize: 10.5, opacity: 0.75, marginBottom: 2 }}>🤖 agente</div>}
            {m.texto}
          </div>
        ))}
        {testeBusy && <div className="muted" style={{ fontSize: 12.5 }}>🤖 digitando…</div>}
        <div ref={fimRef} />
      </div>
      <div style={{ display: "flex", gap: 8, marginTop: 8 }}>
        <input className="field" style={{ flex: 1 }} placeholder="Escreva como cliente… (Enter envia)" value={testeTxt}
          onChange={(e) => setTesteTxt(e.target.value)}
          onKeyDown={(e) => { if (e.key === "Enter") { e.preventDefault(); testar(); } }} />
        <Btn variant="subtle" size="sm" onClick={testar} disabled={testeBusy || !testeTxt.trim()}>{testeBusy ? "…" : "Enviar"}</Btn>
        {teste.length > 0 && <Btn variant="ghost" size="sm" onClick={() => { setTeste([]); setTesteErro(""); }}>Limpar</Btn>}
      </div>
      {testeErro && <div className="form-err" style={{ marginTop: 6 }}><Icon name="alert" size={13} />{testeErro}</div>}
    </Modal>
  );
}

/* ---- FOLLOW-UP automático: régua por FASE do funil ----
   Gatilho: conversa PARADA (qualquer lado) há X tempo.
   Você escreve o MODELO de cada passo; a IA adapta ao contexto da conversa
   (se a IA falhar, vai o modelo puro). O motor lê config.followupWhats. ---- */
function FollowupModal({ cfg, state, onClose, onSave }) {
  const { useState } = React;
  // fases disponíveis: funil principal + funis extras (multifunis)
  const fases = [];
  (state.stages || []).forEach((s) => { if (s.tipo !== "won" && s.tipo !== "lost") fases.push({ id: s.id, rotulo: "Vendas · " + s.nome }); });
  (((state.config || {}).funis) || []).forEach((f) => (f.stages || []).forEach((s) => { if (s.tipo !== "won" && s.tipo !== "lost") fases.push({ id: s.id, rotulo: f.nome + " · " + s.nome }); }));
  const [f, setF] = useState({
    ativo: !!cfg.ativo,
    somenteHorario: cfg.somenteHorario !== false,
    horaInicio: cfg.horaInicio || "08:00",
    horaFim: cfg.horaFim || "19:00",
    porFase: JSON.parse(JSON.stringify(cfg.porFase || {})),
    semLead: JSON.parse(JSON.stringify(cfg.semLead || { ativo: false, passos: [] })),
  });
  const set = (k, v) => setF((s) => ({ ...s, [k]: v }));
  const faseCfg = (id) => f.porFase[id] || { ativo: false, passos: [] };
  const setFase = (id, patch) => set("porFase", { ...f.porFase, [id]: { ...faseCfg(id), ...patch } });
  const UN = [["h", "horas"], ["d", "dias"]];
  const PassoEditor = ({ dono, passos, onMudar }) => (
    <div style={{ display: "grid", gap: 6, marginTop: 6 }}>
      {passos.map((p, i) => (
        <div key={i} style={{ display: "flex", gap: 6, alignItems: "flex-start" }}>
          <span className="muted" style={{ fontSize: 12, marginTop: 9, whiteSpace: "nowrap" }}>{i + 1}º · após</span>
          <input type="number" className="field" style={{ width: 64 }} min="1" value={p.qtd}
            onChange={(e) => onMudar(passos.map((x, j) => j === i ? { ...x, qtd: Number(e.target.value) || 1 } : x))} />
          <select className="field" style={{ width: 84 }} value={p.un}
            onChange={(e) => onMudar(passos.map((x, j) => j === i ? { ...x, un: e.target.value } : x))}>
            {UN.map(([v, l]) => <option key={v} value={v}>{l}</option>)}
          </select>
          <textarea className="field" style={{ flex: 1, minHeight: 44, fontSize: 12.5 }} placeholder="Modelo da mensagem (a IA adapta ao contexto)… {{nome_cliente}}"
            value={p.modelo} onChange={(e) => onMudar(passos.map((x, j) => j === i ? { ...x, modelo: e.target.value } : x))} />
          <button className="iconbtn" title="Remover passo" onClick={() => onMudar(passos.filter((_, j) => j !== i))}><Icon name="x" size={14} /></button>
        </div>
      ))}
      <Btn variant="subtle" size="sm" icon="plus" onClick={() => onMudar([...passos, { qtd: passos.length ? 1 : 4, un: passos.length ? "d" : "h", modelo: "" }])}>Passo</Btn>
    </div>
  );
  return (
    <Modal title="Follow-up automático ⏰" onClose={onClose} wide
      footer={<><Btn variant="ghost" onClick={onClose}>Cancelar</Btn>
        <Btn variant="primary" icon="check" onClick={() => onSave(f)}>Salvar follow-up</Btn></>}>
      <label className="cfg-toggle" style={{ marginBottom: 8 }}>
        <input type="checkbox" checked={f.ativo} onChange={(e) => set("ativo", e.target.checked)} />
        <span><strong>Ligar o follow-up</strong> — quando a conversa fica parada, o sistema retoma sozinho</span>
      </label>
      <div style={{ display: "flex", gap: 10, alignItems: "center", flexWrap: "wrap", marginBottom: 12 }}>
        <label className="cfg-toggle" style={{ margin: 0 }}>
          <input type="checkbox" checked={f.somenteHorario} onChange={(e) => set("somenteHorario", e.target.checked)} />
          <span>Só em horário comercial</span>
        </label>
        {f.somenteHorario && (<>
          <input type="time" className="field" style={{ width: 110 }} value={f.horaInicio} onChange={(e) => set("horaInicio", e.target.value)} />
          <span className="muted">às</span>
          <input type="time" className="field" style={{ width: 110 }} value={f.horaFim} onChange={(e) => set("horaFim", e.target.value)} />
        </>)}
      </div>
      <p className="muted" style={{ fontSize: 12, margin: "0 0 10px" }}>
        A régua é <strong>por fase do funil</strong>: cliente parado na fase X segue os passos da fase X. Respondeu? O ciclo zera.
        Mudou de fase? Vale a régua nova. Conversa <strong>assumida por humano</strong> não recebe follow-up automático.
      </p>
      {fases.map((fase) => {
        const c = faseCfg(fase.id);
        return (
          <div key={fase.id} style={{ border: "1px solid var(--border-dark)", borderRadius: "var(--radius-md)", padding: "10px 12px", marginBottom: 8 }}>
            <label className="cfg-toggle" style={{ margin: 0 }}>
              <input type="checkbox" checked={!!c.ativo} onChange={(e) => setFase(fase.id, { ativo: e.target.checked })} />
              <span><strong>{fase.rotulo}</strong>{c.ativo ? "" : " — sem follow-up"}</span>
            </label>
            {c.ativo && <PassoEditor dono={fase.id} passos={c.passos || []} onMudar={(p) => setFase(fase.id, { passos: p })} />}
          </div>
        );
      })}
      <div style={{ border: "1px dashed var(--border-dark)", borderRadius: "var(--radius-md)", padding: "10px 12px", marginBottom: 4 }}>
        <label className="cfg-toggle" style={{ margin: 0 }}>
          <input type="checkbox" checked={!!f.semLead.ativo} onChange={(e) => set("semLead", { ...f.semLead, ativo: e.target.checked })} />
          <span><strong>Sem cadastro</strong> — quem chamou mas ainda não virou lead</span>
        </label>
        {f.semLead.ativo && <PassoEditor dono="semlead" passos={f.semLead.passos || []} onMudar={(p) => set("semLead", { ...f.semLead, passos: p })} />}
      </div>
    </Modal>
  );
}

window.WhatsAppScreen = WhatsAppScreen;
