/* Digi AI SP Marketing — dock global do Marketing.
   Uma conversa por utilizador em todos os módulos; o sub-agente muda com o ecrã.
   Só aparece quando /api/marketing/digi/sp/config diz activo para o utilizador.
   Nos ecrãs com chat próprio (config.ocultar_em) não se mostra. */
(function () {
  const API = '/api/marketing/digi/sp';
  const PISCAR_PAINEL_MS = 4000;
  const VERIFICAR_MS = 5 * 60 * 1000;

  const LABELS = {
    inicio: 'Início', objectivos: 'Objectivos', marcas: 'Marcas e Estratégia', estrategia: 'Marcas e Estratégia',
    'plano-comunicacao': 'Plano de Comunicação', briefings: 'Briefings', campanhas: 'Campanhas',
    conteudos: 'Produção de Conteúdos', producao: 'Produção de Conteúdos', publicacao: 'Activação', activacao: 'Activação',
    'open-houses': 'Open Houses', audiencias: 'Audiências', crm: 'Audiências',
    'leads-outbound': 'Outbound', 'leads-campanhas': 'Outbound', 'leads-inbound': 'Inbound', sdr: 'SDR',
    resultados: 'Resultados', 'performance-ads': 'Resultados', budget: 'Budget', clipping: 'Clipping', seo: 'SEO', ligacoes: 'Ligações',
  };
  const QUICK = ['O que está pendente aqui?', 'Qual é o estado deste módulo?', 'Como uso este ecrã?'];

  function qs(email, extra) {
    const p = new URLSearchParams(window.location.search || '');
    const e = email || window.currentUser?.email || '';
    if (e && !p.get('email')) p.set('email', e);
    Object.entries(extra || {}).forEach(([k, v]) => { if (v != null && v !== '') p.set(k, v); });
    const s = p.toString();
    return s ? `?${s}` : '';
  }

  function hashParams() {
    try { return new URLSearchParams((window.location.hash || '').replace(/^#/, '')); } catch { return new URLSearchParams(); }
  }

  function marcaActual() {
    return hashParams().get('marca') || 'todas';
  }

  function ecraActual() {
    const h = hashParams();
    const out = {};
    ['lista', 'tab', 'vista', 'periodo', 'camp'].forEach(k => { const v = h.get(k); if (v) out[k] = v; });
    return out;
  }

  function irPara(link) {
    if (!link) return;
    if (link.hash) window.location.hash = link.hash;
    else if (link.sub && window.mktNavToSub) window.mktNavToSub(link.sub);
  }

  // Som curto gerado no browser; só toca depois de o utilizador ter interagido com a página.
  let interagiu = false;
  let audioCtx = null;
  ['pointerdown', 'keydown'].forEach(ev => window.addEventListener(ev, () => { interagiu = true; }, { once: true, capture: true }));
  function tocarSom() {
    if (!interagiu) return;
    try {
      audioCtx = audioCtx || new (window.AudioContext || window.webkitAudioContext)();
      const t0 = audioCtx.currentTime;
      [[880, 0], [1320, 0.12]].forEach(([freq, dt]) => {
        const o = audioCtx.createOscillator();
        const g = audioCtx.createGain();
        o.type = 'sine';
        o.frequency.value = freq;
        g.gain.setValueAtTime(0.0001, t0 + dt);
        g.gain.exponentialRampToValueAtTime(0.08, t0 + dt + 0.02);
        g.gain.exponentialRampToValueAtTime(0.0001, t0 + dt + 0.22);
        o.connect(g).connect(audioCtx.destination);
        o.start(t0 + dt);
        o.stop(t0 + dt + 0.25);
      });
    } catch {}
  }

  const IconeDigi = ({ size = 18, color = 'currentColor' }) => (
    <svg width={size} height={size} viewBox="0 0 24 24" fill="none" stroke={color} strokeWidth="1.8">
      <path d="M9.5 2A2.5 2.5 0 0 1 12 4.5v15a2.5 2.5 0 0 1-4.96-.46 2.5 2.5 0 0 1-2.96-3.08 3 3 0 0 1-.34-5.58 2.5 2.5 0 0 1 1.32-4.24 2.5 2.5 0 0 1 4.44-1.14Z"/>
      <path d="M14.5 2A2.5 2.5 0 0 0 12 4.5v15a2.5 2.5 0 0 0 4.96-.46 2.5 2.5 0 0 0 2.96-3.08 3 3 0 0 0 .34-5.58 2.5 2.5 0 0 0-1.32-4.24 2.5 2.5 0 0 0-4.44-1.14Z"/>
    </svg>
  );

  const semMarkdown = (t) => String(t || '')
    .replace(/\*\*(.+?)\*\*/g, '$1')
    .replace(/(^|\n)#{1,6}\s+/g, '$1')
    .replace(/(^|\n)[*-]\s+/g, '$1');

  const corPrioridade = (p) => p === 'p0' ? 'var(--danger, #dc2626)' : p === 'p1' ? 'var(--warning, #d97706)' : 'var(--text-muted)';

  const Pendente = ({ p }) => (
    <button onClick={() => irPara(p.link)} title="Abrir no ecrã" style={{
      display: 'flex', alignItems: 'flex-start', gap: 8, width: '100%', textAlign: 'left', padding: '7px 10px', marginTop: 6,
      borderRadius: 8, border: '1px solid var(--border)', background: 'var(--bg)', color: 'var(--text)', cursor: 'pointer', fontSize: 12, lineHeight: 1.4,
    }}>
      <span style={{ width: 7, height: 7, borderRadius: '50%', background: corPrioridade(p.prioridade), marginTop: 5, flexShrink: 0 }} />
      <span style={{ flex: 1 }}>{p.titulo}</span>
    </button>
  );

  const Mensagem = ({ m, mostrarCabecalho, labelAgente }) => {
    const user = m.role === 'user';
    return (
      <div style={{ display: 'flex', flexDirection: 'column', alignItems: user ? 'flex-end' : 'flex-start', marginBottom: 10, animation: 'mkt-digi-dock-msg-in .2s ease-out' }}>
        {!user && mostrarCabecalho && (
          <div style={{ fontSize: 10, fontFamily: 'var(--font-mono)', color: 'var(--text-dim)', marginBottom: 4, letterSpacing: '.04em' }}>
            Digi AI{labelAgente ? ` · ${labelAgente}` : ''}
          </div>
        )}
        <div style={{
          maxWidth: '88%', padding: '9px 12px', borderRadius: user ? '12px 12px 4px 12px' : '12px 12px 12px 4px',
          background: user ? 'var(--ai-500)' : (m.tipo === 'aviso' ? 'color-mix(in oklch, var(--warning, #d97706) 10%, var(--bg))' : 'var(--bg)'),
          color: user ? 'var(--text-on-ai, #fff)' : 'var(--text)',
          border: user ? 'none' : `1px solid ${m.tipo === 'aviso' ? 'color-mix(in oklch, var(--warning, #d97706) 40%, transparent)' : 'var(--border)'}`,
          fontSize: 12.5, lineHeight: 1.55, whiteSpace: 'pre-wrap', wordBreak: 'break-word',
        }}>
          {user ? m.content : semMarkdown(m.content)}
          {Array.isArray(m.pendentes) && m.pendentes.map((p, i) => <Pendente key={i} p={p} />)}
        </div>
      </div>
    );
  };

  const MktDigiDockInner = ({ sub, userName, userEmail }) => {
    const [cfg, setCfg] = React.useState(null);
    const [open, setOpen] = React.useState(false);
    const [expanded, setExpanded] = React.useState(false);
    const [msgs, setMsgs] = React.useState([]);
    const [pendentes, setPendentes] = React.useState([]);
    const [inp, setInp] = React.useState('');
    const [loading, setLoading] = React.useState(false);
    const [piscar, setPiscar] = React.useState(false);
    const [agenteResp, setAgenteResp] = React.useState(null);
    const bodyRef = React.useRef(null);
    const panelRef = React.useRef(null);
    const fabRef = React.useRef(null);
    const email = userEmail || window.currentUser?.email || '';

    React.useEffect(() => {
      let cancel = false;
      fetch(`${API}/config${qs(email)}`)
        .then(r => r.ok ? r.json() : null)
        .then(d => { if (!cancel) setCfg(d || { activo: false }); })
        .catch(() => { if (!cancel) setCfg({ activo: false }); });
      return () => { cancel = true; };
    }, [email]);

    const activo = !!cfg?.activo;
    const oculto = !activo || (cfg.ocultar_em || []).includes(sub);

    React.useEffect(() => {
      if (!activo) return;
      let cancel = false;
      fetch(`${API}/sessao${qs(email)}`)
        .then(r => r.ok ? r.json() : null)
        .then(d => { if (!cancel && d?.messages) setMsgs(d.messages); })
        .catch(() => {});
      return () => { cancel = true; };
    }, [activo, email]);

    React.useEffect(() => {
      if (oculto) return;
      let cancel = false;
      const verificar = async () => {
        const marca = marcaActual();
        try {
          const r = await fetch(`${API}/pendentes${qs(email, { modulo: sub, marca })}`);
          if (!r.ok || cancel) return;
          const d = await r.json();
          if (cancel) return;
          setPendentes(d.pendentes || []);
          if (!(d.novos || []).length) return;
          const a = await fetch(`${API}/pendentes/avisado${qs(email)}`, {
            method: 'POST', headers: { 'Content-Type': 'application/json' },
            body: JSON.stringify({ modulo: sub, marca, hashes: d.novos }),
          });
          const av = a.ok ? await a.json() : null;
          if (cancel || !av?.mensagem) return;
          setMsgs(m => [...m, av.mensagem]);
          if (cfg.som !== false) tocarSom();
          setPiscar(true);
        } catch {}
      };
      verificar();
      const t = setInterval(verificar, VERIFICAR_MS);
      return () => { cancel = true; clearInterval(t); };
    }, [sub, oculto, email]);

    React.useEffect(() => {
      if (!piscar || !open) return;
      const t = setTimeout(() => setPiscar(false), PISCAR_PAINEL_MS);
      return () => clearTimeout(t);
    }, [piscar, open]);

    React.useEffect(() => {
      if (open && bodyRef.current) bodyRef.current.scrollTop = bodyRef.current.scrollHeight;
    }, [msgs, open, loading]);

    React.useEffect(() => {
      if (!open) return;
      const onKey = (e) => { if (e.key === 'Escape') { if (expanded) setExpanded(false); else setOpen(false); } };
      const onClick = (e) => {
        if (expanded) return;
        if (panelRef.current && !panelRef.current.contains(e.target) && fabRef.current && !fabRef.current.contains(e.target)) setOpen(false);
      };
      document.addEventListener('keydown', onKey);
      document.addEventListener('mousedown', onClick);
      return () => { document.removeEventListener('keydown', onKey); document.removeEventListener('mousedown', onClick); };
    }, [open, expanded]);

    const enviar = async (texto) => {
      const t = String(texto ?? inp).trim();
      if (!t || loading) return;
      const marca = marcaActual();
      const ts = new Date().toISOString();
      setMsgs(m => [...m, { role: 'user', content: t, ts, modulo: sub }, { role: 'assistant', content: '', ts, modulo: sub, _stream: true }]);
      setInp('');
      setLoading(true);
      const actualizar = (fn) => setMsgs(m => {
        const i = m.length - 1;
        if (i < 0 || !m[i]._stream) return m;
        const c = m.slice();
        c[i] = fn(c[i]);
        return c;
      });
      try {
        const resp = await fetch(`${API}/chat${qs(email)}`, {
          method: 'POST', headers: { 'Content-Type': 'application/json' },
          body: JSON.stringify({ message: t, canal: 'portal', modulo: sub, marca, ecra: ecraActual() }),
        });
        if (!resp.ok || !resp.body) throw new Error(`HTTP ${resp.status}`);
        const reader = resp.body.getReader();
        const decoder = new TextDecoder();
        let buf = '';
        for (;;) {
          const { done, value } = await reader.read();
          if (done) break;
          buf += decoder.decode(value, { stream: true });
          const linhas = buf.split('\n');
          buf = linhas.pop() || '';
          for (const l of linhas) {
            if (!l.startsWith('data: ')) continue;
            let ev;
            try { ev = JSON.parse(l.slice(6)); } catch { continue; }
            if (ev.type === 'agente') { setAgenteResp(ev.label); actualizar(x => ({ ...x, agente: ev.agente, agenteLabel: ev.label })); }
            else if (ev.type === 'delta') actualizar(x => ({ ...x, content: x.content + ev.text }));
            else if (ev.type === 'error') actualizar(x => ({ ...x, content: x.content || `Erro: ${ev.message}` }));
          }
        }
      } catch {
        actualizar(x => ({ ...x, content: x.content || 'Sem ligação ao servidor.' }));
      } finally {
        actualizar(x => { const { _stream, ...rest } = x; return rest; });
        setLoading(false);
      }
    };

    if (oculto) return null;

    const label = LABELS[sub] || 'Marketing';
    const labelDeAgente = (id) => (cfg.agentes || []).find(a => a.id === id)?.label || '';
    const nPend = pendentes.length;
    const primeiroNome = String(userName || '').split(' ')[0];

    const cabecalho = (
      <div style={{ padding: expanded ? '14px 20px 12px' : '12px 16px 10px', borderBottom: '1px solid var(--border)', background: 'var(--bg-elev)', flexShrink: 0, display: 'flex', alignItems: 'center', gap: 10 }}>
        <div style={{ width: 32, height: 32, borderRadius: 10, background: 'var(--ai-500)', display: 'flex', alignItems: 'center', justifyContent: 'center', flexShrink: 0 }}>
          <IconeDigi size={16} color="var(--text-on-ai, #fff)" />
        </div>
        <div style={{ flex: 1, minWidth: 0 }}>
          <div style={{ fontSize: 13, fontWeight: 700, color: 'var(--text)', display: 'flex', alignItems: 'center', gap: 6 }}>
            Digi AI
            <span style={{ fontSize: 9, fontWeight: 700, fontFamily: 'var(--font-mono)', padding: '2px 7px', borderRadius: 4, background: 'color-mix(in oklch, var(--ai-500) 14%, transparent)', color: 'var(--ai-500)', letterSpacing: '.08em', textTransform: 'uppercase' }}>{label}</span>
          </div>
          <div style={{ fontSize: 10, color: 'var(--text-muted)', fontFamily: 'var(--font-mono)', marginTop: 1 }}>
            SP Marketing{agenteResp && agenteResp !== label ? ` · última resposta: ${agenteResp}` : ''}
          </div>
        </div>
        <button title={expanded ? 'Reduzir' : 'Expandir'} onClick={() => setExpanded(e => !e)} style={{ width: 28, height: 28, borderRadius: 6, border: '1px solid var(--border)', background: 'transparent', color: 'var(--text-dim)', cursor: 'pointer' }}>
          {expanded ? '–' : '⤢'}
        </button>
        <button title="Fechar" onClick={() => { setOpen(false); setExpanded(false); }} style={{ width: 28, height: 28, borderRadius: 6, border: '1px solid var(--border)', background: 'transparent', color: 'var(--text-dim)', cursor: 'pointer' }}>×</button>
      </div>
    );

    const corpo = (
      <>
        <div ref={bodyRef} className="scrollbar" style={{ flex: 1, overflowY: 'auto', padding: expanded ? '18px 20px 8px' : '14px 14px 6px', minHeight: 0 }}>
          {nPend > 0 && (
            <div style={{ marginBottom: 12, padding: '8px 10px', borderRadius: 10, border: '1px solid var(--border)', background: 'var(--bg-elev)' }}>
              <div style={{ fontSize: 10, fontWeight: 700, fontFamily: 'var(--font-mono)', color: 'var(--text-dim)', textTransform: 'uppercase', letterSpacing: '.06em' }}>
                {nPend} pendente{nPend === 1 ? '' : 's'} em {label}
              </div>
              {pendentes.map(p => <Pendente key={p.hash} p={p} />)}
            </div>
          )}
          {msgs.length === 0 && (
            <div style={{ fontSize: 12.5, color: 'var(--text-muted)', lineHeight: 1.55 }}>
              {primeiroNome ? `Olá ${primeiroNome}. ` : 'Olá. '}Estou contigo em todos os módulos do Marketing. Pergunta-me o que está pendente, o estado de {label} ou como usar este ecrã.
            </div>
          )}
          {msgs.map((m, i) => (
            <Mensagem key={`${m.ts}-${i}`} m={m}
              mostrarCabecalho={m.role !== 'user' && (i === 0 || msgs[i - 1].role === 'user' || msgs[i - 1].agente !== m.agente)}
              labelAgente={m.agenteLabel || labelDeAgente(m.agente) || LABELS[m.modulo] || ''} />
          ))}
          {loading && msgs[msgs.length - 1]?.content === '' && (
            <div style={{ display: 'flex', gap: 4, margin: '-4px 0 10px 4px' }}>
              {[0, 1, 2].map(i => <div key={i} style={{ width: 6, height: 6, borderRadius: '50%', background: 'var(--ai-500)', opacity: 0.5, animation: `mkt-digi-dock-dot ${0.7 + i * 0.18}s ease-in-out infinite alternate` }} />)}
            </div>
          )}
        </div>
        <div style={{ padding: expanded ? '6px 20px 0' : '6px 14px 0', display: 'flex', gap: 5, flexWrap: 'wrap', flexShrink: 0 }}>
          {QUICK.map(q => (
            <button key={q} onClick={() => enviar(q)} disabled={loading} style={{ fontSize: 11, padding: '4px 10px', borderRadius: 999, border: '1px solid var(--border)', background: 'var(--bg-elev)', color: 'var(--text-muted)', cursor: loading ? 'default' : 'pointer' }}>{q}</button>
          ))}
        </div>
        <div style={{ padding: expanded ? '8px 20px 16px' : '8px 14px 14px', display: 'flex', gap: 8, alignItems: 'flex-end', flexShrink: 0 }}>
          <textarea value={inp} onChange={e => setInp(e.target.value)} rows={2}
            onKeyDown={e => { if (e.key === 'Enter' && !e.shiftKey) { e.preventDefault(); enviar(); } }}
            placeholder={`Pergunta sobre ${label}... (Enter envia)`}
            style={{ flex: 1, resize: 'none', padding: '8px 12px', borderRadius: 10, border: '1px solid var(--border)', background: 'var(--bg)', color: 'var(--text)', fontSize: 12, fontFamily: 'var(--font-body)', lineHeight: 1.5, outline: 'none' }} />
          <button onClick={() => enviar()} disabled={!inp.trim() || loading} style={{
            width: 38, height: 38, borderRadius: 10, border: 'none', cursor: inp.trim() && !loading ? 'pointer' : 'default',
            background: inp.trim() && !loading ? 'var(--ai-500)' : 'var(--bg-sunken)', color: inp.trim() && !loading ? 'var(--text-on-ai, #fff)' : 'var(--text-dim)',
            display: 'flex', alignItems: 'center', justifyContent: 'center', flexShrink: 0,
          }}>
            <svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2"><path d="m22 2-7 20-4-9-9-4 20-7z"/></svg>
          </button>
        </div>
      </>
    );

    return (
      <>
        {!expanded && (
          <div ref={fabRef} style={{ position: 'fixed', bottom: 28, right: 28, zIndex: 200 }}>
            {nPend > 0 && !open && (
              <div style={{ position: 'absolute', top: -5, right: -5, zIndex: 201, minWidth: 19, height: 19, padding: '0 4px', borderRadius: 10, background: 'var(--warning, #d97706)', color: '#fff', border: '2px solid var(--bg)', fontSize: 10, fontWeight: 700, display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
                {nPend > 9 ? '9+' : nPend}
              </div>
            )}
            <button onClick={() => { setOpen(o => !o); setPiscar(false); }} title={`Digi AI · ${label}`}
              className={piscar && !open ? 'mkt-digi-dock-piscar' : ''}
              style={{
                width: 52, height: 52, borderRadius: '50%', border: 'none', cursor: 'pointer',
                background: open ? 'var(--brand-900)' : 'var(--ai-500)', color: 'var(--text-on-ai, #fff)',
                display: 'flex', alignItems: 'center', justifyContent: 'center',
                boxShadow: '0 4px 18px color-mix(in oklch, var(--ai-500) 38%, transparent)',
              }}>
              {open ? <span style={{ fontSize: 20, lineHeight: 1 }}>×</span> : <IconeDigi size={21} />}
            </button>
          </div>
        )}
        {open && !expanded && (
          <div ref={panelRef} className={piscar ? 'mkt-digi-dock-piscar-painel' : ''} style={{
            position: 'fixed', bottom: 92, right: 28, width: 420, height: 620, maxHeight: 'calc(100vh - 120px)', zIndex: 199,
            background: 'var(--bg-elev)', border: '1px solid var(--border)', borderRadius: 16,
            boxShadow: '0 20px 60px color-mix(in oklch, var(--ai-500) 14%, transparent)',
            display: 'flex', flexDirection: 'column', overflow: 'hidden', animation: 'mkt-digi-dock-in .22s ease-out',
          }}>
            {cabecalho}
            {corpo}
          </div>
        )}
        {open && expanded && ReactDOM.createPortal(
          <>
            <div onClick={() => setExpanded(false)} style={{ position: 'fixed', inset: 0, background: 'color-mix(in oklch, var(--text) 54%, transparent)', zIndex: 298 }} />
            <div style={{
              position: 'fixed', top: '50%', left: '50%', transform: 'translate(-50%,-50%)', width: 'min(1040px, 92vw)', height: '82vh', zIndex: 299,
              background: 'var(--bg-elev)', border: '1px solid var(--border)', borderRadius: 18, boxShadow: 'var(--shadow-lg)',
              display: 'flex', flexDirection: 'column', overflow: 'hidden',
            }}>
              {cabecalho}
              {corpo}
            </div>
          </>,
          document.body
        )}
        <style>{`
          @keyframes mkt-digi-dock-in { from { opacity:0; transform:translateY(12px) scale(.96); } to { opacity:1; transform:none; } }
          @keyframes mkt-digi-dock-msg-in { from { opacity:0; transform:translateY(6px); } to { opacity:1; transform:none; } }
          @keyframes mkt-digi-dock-dot { from { opacity:.3; transform:translateY(0); } to { opacity:1; transform:translateY(-3px); } }
          @keyframes mkt-digi-dock-piscar {
            0%, 100% { box-shadow: 0 0 0 0 color-mix(in oklch, var(--warning, #d97706) 70%, transparent); transform: scale(1); }
            50% { box-shadow: 0 0 0 12px color-mix(in oklch, var(--warning, #d97706) 0%, transparent); transform: scale(1.08); }
          }
          .mkt-digi-dock-piscar { animation: mkt-digi-dock-piscar 1s ease-in-out infinite; }
          @keyframes mkt-digi-dock-piscar-painel { 0%, 100% { border-color: var(--border); } 50% { border-color: var(--warning, #d97706); } }
          .mkt-digi-dock-piscar-painel { animation: mkt-digi-dock-piscar-painel .8s ease-in-out 5; }
        `}</style>
      </>
    );
  };

  class MktDigiDockBoundary extends React.Component {
    constructor(props) { super(props); this.state = { erro: false }; }
    static getDerivedStateFromError() { return { erro: true }; }
    componentDidCatch(error) { console.error('[MktDigiDock]', error); }
    render() { return this.state.erro ? null : this.props.children; }
  }

  window.MktDigiDock = (props) => (
    <MktDigiDockBoundary>
      <MktDigiDockInner {...props} />
    </MktDigiDockBoundary>
  );
})();
