/* ============================================================
   VT — Chat poseur ↔ supervision, par visite technique.
   Composants globaux :
   - window.VTChatPanel  : panneau de conversation (utilisé tel quel côté admin)
   - window.VTChatBubble : bulle flottante + overlay (côté poseur)
   API : vt_submit.php actions chat_list / chat_send (polling 5 s incrémental).
   ============================================================ */
(function () {
  const CAPI = (window.VT_CONFIG && window.VT_CONFIG.api) || {};

  async function chatCall(body) {
    const r = await window.VT_AUTH.authedFetch(CAPI.submit + '?action=' + body.action, {
      method: 'POST', headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify(Object.assign({ k: CAPI.key }, body)),
    });
    const j = await r.json().catch(() => null);
    if (!j || !j.ok) throw new Error((j && j.error) || ('HTTP ' + r.status));
    return j;
  }

  function fmtT(s) {
    if (!s) return '';
    const d = new Date(String(s).replace(' ', 'T'));
    return isNaN(d) ? '' : d.toLocaleTimeString('fr-FR', { hour: '2-digit', minute: '2-digit' });
  }
  function who(m) {
    const e = String(m.author || '');
    const mm = e.match(/^agence[.\-]?([^@]*)@/i);
    if (mm && mm[1]) return 'Agence ' + mm[1].replace(/[.\-_]+/g, ' ');
    return e.split('@')[0].replace(/[.\-_]+/g, ' ');
  }
  const seenKey = ref => 'vtchat_seen_' + ref;
  function getSeen(ref) { try { return parseInt(localStorage.getItem(seenKey(ref)) || '0', 10) || 0; } catch (e) { return 0; } }
  function setSeen(ref, id) { try { localStorage.setItem(seenKey(ref), String(id)); } catch (e) {} }

  /* hook de conversation : messages + envoi + non-lus */
  function useVTChat(vtRef, mySide, active) {
    const { useState, useEffect, useRef } = React;
    const [msgs, setMsgs] = useState([]);
    const msgsRef = useRef([]); msgsRef.current = msgs;
    const [unread, setUnread] = useState(0);

    useEffect(() => {
      if (!vtRef) return;
      let stop = false;
      async function poll() {
        try {
          const last = msgsRef.current.length ? msgsRef.current[msgsRef.current.length - 1].id : 0;
          const j = await chatCall({ action: 'chat_list', vt_ref: vtRef, since_id: last });
          if (stop || !j.msgs.length) return;
          const fresh = j.msgs.filter(nm => !msgsRef.current.some(m => m.id === nm.id));
          if (!fresh.length) return;
          const all = msgsRef.current.concat(fresh);
          setMsgs(all);
          const seen = getSeen(vtRef);
          setUnread(all.filter(m => m.id > seen && m.role !== mySide).length);
        } catch (e) {}
      }
      poll();
      const t = setInterval(poll, 5000);
      return () => { stop = true; clearInterval(t); };
    }, [vtRef]);

    function markSeen() {
      if (msgsRef.current.length) setSeen(vtRef, msgsRef.current[msgsRef.current.length - 1].id);
      setUnread(0);
    }
    async function send(text) {
      const t = String(text || '').trim();
      if (!t) return;
      const j = await chatCall({ action: 'chat_send', vt_ref: vtRef, text: t, side: mySide });
      const u = (window.VT_AUTH.user() || {});
      const mine = { id: j.id_msg, author: u.email || '', role: mySide, text: t, at: new Date().toISOString() };
      setMsgs(s => s.some(m => m.id === mine.id) ? s : s.concat([mine]));
      setSeen(vtRef, j.id_msg);
    }
    return { msgs, unread, send, markSeen };
  }

  function RoleChip({ role }) {
    const admin = role === 'admin';
    return <span style={{ fontSize: 10, fontWeight: 800, letterSpacing: '.3px', textTransform: 'uppercase',
      background: admin ? '#e8f0fb' : '#eaf6ee', color: admin ? '#1c3a8f' : '#1f8a5b',
      padding: '2px 8px', borderRadius: 99 }}>{admin ? '🖥️ Supervision' : '👷 Poseur'}</span>;
  }

  function Bubble({ m, mine }) {
    return (
      <div style={{ display: 'flex', flexDirection: 'column', alignItems: mine ? 'flex-end' : 'flex-start', marginBottom: 10 }}>
        <div style={{ display: 'flex', gap: 6, alignItems: 'center', marginBottom: 3, padding: '0 4px' }}>
          {!mine && <RoleChip role={m.role} />}
          <span style={{ fontSize: 11, fontWeight: 700, color: '#8792a8' }}>{mine ? 'Vous' : who(m)} · {fmtT(m.at)}</span>
          {mine && <RoleChip role={m.role} />}
        </div>
        <div style={{
          maxWidth: '82%', padding: '9px 13px', borderRadius: 14, fontSize: 14.5, lineHeight: 1.45,
          background: mine ? '#1c3a8f' : '#fff', color: mine ? '#fff' : '#22304d',
          border: mine ? 'none' : '1px solid #e2e7ef',
          boxShadow: mine ? 'none' : '0 2px 6px -4px rgba(13,28,77,.25)',
          borderTopRightRadius: mine ? 4 : 14, borderTopLeftRadius: mine ? 14 : 4,
          whiteSpace: 'pre-wrap', wordBreak: 'break-word',
        }}>
          {m.text}
        </div>
      </div>
    );
  }

  function VTChatPanel({ vtRef, mySide, height, autoFocus }) {
    const { useState, useEffect, useRef } = React;
    const chat = useVTChat(vtRef, mySide, true);
    const [txt, setTxt] = useState('');
    const [sending, setSending] = useState(false);
    const boxRef = useRef();

    useEffect(() => { chat.markSeen(); }, [chat.msgs.length]);
    useEffect(() => { if (boxRef.current) boxRef.current.scrollTop = boxRef.current.scrollHeight; }, [chat.msgs.length]);

    async function doSend() {
      if (!txt.trim() || sending) return;
      setSending(true);
      try { await chat.send(txt); setTxt(''); } catch (e) {}
      setSending(false);
    }
    return (
      <div style={{ display: 'flex', flexDirection: 'column', height: height || 340, minHeight: 0 }}>
        <div ref={boxRef} style={{ flex: 1, minHeight: 0, overflowY: 'auto', WebkitOverflowScrolling: 'touch', overscrollBehavior: 'contain', padding: '10px 8px', background: '#f4f6fa', borderRadius: 12 }}>
          {chat.msgs.length === 0 && <p className="muted" style={{ textAlign: 'center', marginTop: 20, fontSize: 13.5 }}>Aucun message — écrivez le premier 👋</p>}
          {chat.msgs.map(m => <Bubble key={m.id} m={m} mine={m.role === mySide} />)}
        </div>
        <div style={{ display: 'flex', gap: 8, paddingTop: 8, borderTop: '1px solid #eef1f5', flex: '0 0 auto' }}>
          <input value={txt} autoFocus={autoFocus} onChange={e => setTxt(e.target.value)}
            onKeyDown={e => { if (e.key === 'Enter') doSend(); }}
            onFocus={() => setTimeout(() => { if (boxRef.current) boxRef.current.scrollTop = boxRef.current.scrollHeight; }, 250)}
            placeholder="Votre message…"
            style={{ flex: 1, padding: '11px 14px', border: '1.5px solid #dfe4ec', borderRadius: 99, fontSize: 16, minWidth: 0 }} />
          <button className="btn btn-navy" disabled={sending || !txt.trim()} onClick={doSend} style={{ padding: '11px 18px', borderRadius: 99, flex: '0 0 auto' }}>➤</button>
        </div>
      </div>
    );
  }

  /* bulle flottante (poseur) : badge non-lus + bannière de notification + tiroir */
  function VTChatBubble({ vtRef, mySide }) {
    const { useState, useEffect, useRef } = React;
    const [open, setOpen] = useState(false);
    const [toast, setToast] = useState(null);
    const chat = useVTChat(vtRef, mySide, false);   // instance légère juste pour le badge
    const lastNotif = useRef(0);
    const openRef = useRef(open); openRef.current = open;

    /* tiroir ouvert = fond verrouillé (plus de scroll parasite derrière) */
    useEffect(() => {
      if (!open) return;
      const prev = document.body.style.overflow;
      document.body.style.overflow = 'hidden';
      return () => { document.body.style.overflow = prev; };
    }, [open]);

    /* nouveau message de l'autre côté + chat fermé -> bannière + vibration */
    useEffect(() => {
      const msgs = chat.msgs;
      if (!msgs.length) return;
      const last = msgs[msgs.length - 1];
      if (last.role !== mySide && last.id > lastNotif.current && chat.unread > 0 && !openRef.current) {
        lastNotif.current = last.id;
        setToast(last);
        try { if (navigator.vibrate) navigator.vibrate([180, 90, 180]); } catch (e) {}
        const t = setTimeout(() => setToast(null), 8000);
        return () => clearTimeout(t);
      }
    }, [chat.msgs.length]);

    if (!vtRef) return null;
    return (
      <>
        {toast && !open && (
          <div onClick={() => { setToast(null); setOpen(true); }} style={{
            position: 'fixed', top: 'calc(58px + env(safe-area-inset-top))', left: 10, right: 10, zIndex: 80,
            background: '#0d1c4d', color: '#fff', borderRadius: 14, padding: '12px 14px', cursor: 'pointer',
            boxShadow: '0 14px 34px rgba(13,28,77,.45)', display: 'flex', gap: 10, alignItems: 'center',
            animation: 'vtSlideIn .25s ease',
          }}>
            <span style={{ fontSize: 22 }}>💬</span>
            <div style={{ flex: 1, minWidth: 0 }}>
              <div style={{ fontSize: 12, fontWeight: 800, opacity: .75 }}>Message de la supervision</div>
              <div style={{ fontSize: 14.5, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>{toast.text}</div>
            </div>
            <span style={{ fontSize: 12.5, fontWeight: 800, background: 'rgba(255,255,255,.16)', padding: '6px 12px', borderRadius: 99 }}>Ouvrir</span>
          </div>
        )}
        {!open && (
          <button onClick={() => setOpen(true)} aria-label="Chat avec la supervision" style={{
            position: 'fixed', right: 14, bottom: 'calc(96px + env(safe-area-inset-bottom))', zIndex: 60, width: 56, height: 56, borderRadius: '50%',
            background: '#1c3a8f', color: '#fff', border: 'none', fontSize: 24, cursor: 'pointer',
            boxShadow: '0 10px 26px rgba(13,28,77,.35)',
          }}>💬
            {chat.unread > 0 && <span style={{ position: 'absolute', top: -3, right: -3, background: '#e11d33', color: '#fff', fontSize: 11.5, fontWeight: 800, minWidth: 20, height: 20, borderRadius: 99, display: 'flex', alignItems: 'center', justifyContent: 'center', padding: '0 4px' }}>{chat.unread}</span>}
          </button>
        )}
        {open && (
          <div style={{ position: 'fixed', inset: 0, zIndex: 70, background: 'rgba(13,28,77,.45)' }}
            onClick={e => { if (e.target === e.currentTarget) setOpen(false); }}>
            <div style={{ position: 'absolute', left: 0, right: 0, bottom: 0, margin: '0 auto', maxWidth: 560,
                          background: '#fff', borderRadius: '18px 18px 0 0',
                          padding: '10px 14px calc(10px + env(safe-area-inset-bottom))',
                          height: 'min(78dvh, 620px)', display: 'flex', flexDirection: 'column',
                          animation: 'vtSheetUp .22s ease' }}>
              <div style={{ width: 40, height: 4, borderRadius: 99, background: '#dfe4ec', margin: '0 auto 8px', flex: '0 0 auto' }} />
              <div style={{ display: 'flex', alignItems: 'center', marginBottom: 8, flex: '0 0 auto' }}>
                <strong style={{ fontSize: 16 }}>💬 Supervision</strong>
                <span className="muted" style={{ marginLeft: 8, fontSize: 12.5 }}>réponses en direct</span>
                <span style={{ flex: 1 }} />
                <button onClick={() => setOpen(false)} aria-label="Fermer" style={{ background: '#f0f2f6', border: 'none', width: 34, height: 34, borderRadius: '50%', fontSize: 18, cursor: 'pointer', color: '#40506b', lineHeight: 1 }}>×</button>
              </div>
              <div style={{ flex: 1, minHeight: 0, display: 'flex', flexDirection: 'column' }}>
                <VTChatPanel vtRef={vtRef} mySide={mySide} height={'100%'} autoFocus={false} />
              </div>
            </div>
          </div>
        )}
      </>
    );
  }

  window.VTChatPanel = VTChatPanel;
  window.VTChatBubble = VTChatBubble;
})();
