const { useState, useEffect, useCallback } = React;

const api = {
  async get(url) {
    const r = await fetch(url);
    if (r.status === 401) { location.href = '/login.html'; throw new Error('401'); }
    if (!r.ok) throw new Error((await r.json()).error || 'erreur');
    return r.json();
  },
  async send(url, method, body) {
    const r = await fetch(url, {
      method,
      headers: { 'Content-Type': 'application/json' },
      body: body ? JSON.stringify(body) : undefined,
    });
    if (!r.ok) throw new Error((await r.json()).error || 'erreur');
    return r.json();
  },
};

const STATUS_LABEL = { open: 'Ouvert', pending: 'En attente', resolved: 'Résolu', closed: 'Fermé' };
const initials = (s) => (s || '?').split(/[ @.]/).filter(Boolean).slice(0, 2).map((x) => x[0].toUpperCase()).join('');
const fmt = (d) => new Date(d).toLocaleString('fr-FR', { day: 'numeric', month: 'short', hour: '2-digit', minute: '2-digit' });
const fmtTime = (d) => new Date(d).toLocaleTimeString('fr-FR', { hour: '2-digit', minute: '2-digit' });

function App() {
  const [me, setMe] = useState(null);
  const [filter, setFilter] = useState('open');
  const [tickets, setTickets] = useState([]);
  const [selId, setSelId] = useState(null);
  const [ticket, setTicket] = useState(null);
  const [showInvites, setShowInvites] = useState(false);
  const [showSenders, setShowSenders] = useState(false);
  const [showNotifs, setShowNotifs] = useState(false);
  const [showSettings, setShowSettings] = useState(false);
  const [showReimport, setShowReimport] = useState(false);
  const [detailsOpen, setDetailsOpen] = useState(false); // tiroir Détails (mobile)

  useEffect(() => { api.get('/api/me').then(setMe).catch(() => {}); }, []);

  // Lien profond depuis les emails de notification : #ticket-123 sélectionne le ticket.
  useEffect(() => {
    const applyHash = () => {
      const m = location.hash.match(/^#ticket-(\d+)$/);
      if (m) setSelId(parseInt(m[1], 10));
    };
    applyHash();
    window.addEventListener('hashchange', applyHash);
    return () => window.removeEventListener('hashchange', applyHash);
  }, []);

  const loadTickets = useCallback(() => {
    const q = filter === 'all' ? '' : `?status=${filter}`;
    api.get(`/api/tickets${q}`).then(setTickets).catch(() => {});
  }, [filter]);
  useEffect(loadTickets, [loadTickets]);

  useEffect(() => {
    setDetailsOpen(false);
    if (selId == null) { setTicket(null); return; }
    api.get(`/api/tickets/${selId}`).then(setTicket).catch(() => {});
  }, [selId]);

  const refreshAll = () => { loadTickets(); if (selId != null) api.get(`/api/tickets/${selId}`).then(setTicket); };

  const deleteTicket = async (id) => {
    await api.send(`/api/tickets/${id}`, 'DELETE');
    setSelId(null);
    loadTickets();
  };

  if (!me) return <div className="empty">Chargement…</div>;
  const mailboxOff = !me.enterprise.mailbox_connected;

  return (
    <div className="app">
      <header>
        <div className="logo">Solvio Support<span className="ent-name"> · {me.enterprise.name}</span></div>
        <div className="right-head">
          <button className="hdr-btn" aria-label="Paramètres" title="Paramètres" onClick={() => setShowSettings(true)}>
            ⚙
            {me.agent.role === 'admin' && me.enterprise.mailbox_connected && me.enterprise.mailbox_token_valid === false && (
              <span className="hdr-dot" title="Action requise" />
            )}
          </button>
          <button className="avatar" title="Paramètres" onClick={() => setShowSettings(true)}>{initials(me.agent.name || me.agent.email)}</button>
        </div>
      </header>

      {mailboxOff && (
        <div className="banner">
          <span>La boîte de support n'est pas encore connectée.{me.agent.role !== 'admin' && ' Demandez à un admin de la connecter.'}</span>
          {me.agent.role === 'admin' && <button onClick={() => { location.href = '/api/mailbox/connect'; }}>Connecter Gmail</button>}
        </div>
      )}

      <div className={`cols${selId != null ? ' has-selection' : ''}`}>
        <div className="list">
          <div className="tabs">
            {['open', 'pending', 'resolved', 'all'].map((s) => (
              <button key={s} className={`tab ${filter === s ? 'active' : ''}`} onClick={() => setFilter(s)}>
                {s === 'all' ? 'Tous' : STATUS_LABEL[s]}
              </button>
            ))}
          </div>
          {tickets.length === 0 && <div style={{ padding: 20, color: 'var(--faint)' }}>Aucun ticket.</div>}
          {tickets.map((t) => (
            <div key={t.id} className={`tk ${selId === t.id ? 'sel' : ''}`} onClick={() => setSelId(t.id)}>
              <div className="tk-top">
                <span className="tk-name">{t.customer_name || t.customer_email}</span>
                <span className="tk-id">#{t.id}</span>
              </div>
              <div className="tk-sub">{t.subject}</div>
              <div className="tk-prev">{t.last_message || '—'}</div>
              <div style={{ marginTop: 4 }}>
                <span className={`pill p-${t.status}`}>{STATUS_LABEL[t.status]}</span>
                <span style={{ fontSize: 10, color: 'var(--faint)', marginLeft: 6 }}>{fmt(t.updated_at)}</span>
              </div>
            </div>
          ))}
        </div>

        {ticket ? <Conversation ticket={ticket} onReply={refreshAll} disabled={mailboxOff} onBack={() => setSelId(null)} onShowDetails={() => setDetailsOpen(true)} /> : <div className="conv"><div className="empty">Sélectionnez un ticket</div></div>}

        {ticket ? <Details ticket={ticket} onChange={refreshAll} isAdmin={me.agent.role === 'admin'} onDelete={deleteTicket} open={detailsOpen} onClose={() => setDetailsOpen(false)} /> : <div className="details" />}
      </div>

      {showSettings && (
        <SettingsModal
          me={me}
          onClose={() => setShowSettings(false)}
          onOpenNotifs={() => { setShowSettings(false); setShowNotifs(true); }}
          onOpenSenders={() => { setShowSettings(false); setShowSenders(true); }}
          onOpenInvites={() => { setShowSettings(false); setShowInvites(true); }}
          onOpenReimport={() => { setShowSettings(false); setShowReimport(true); }}
        />
      )}
      {showInvites && <InvitesModal onClose={() => setShowInvites(false)} />}
      {showSenders && <SendersModal onClose={() => setShowSenders(false)} />}
      {showNotifs && <NotificationsModal onClose={() => setShowNotifs(false)} />}
      {showReimport && <ReimportModal onClose={() => setShowReimport(false)} onDone={loadTickets} />}
    </div>
  );
}

function SettingsModal({ me, onClose, onOpenNotifs, onOpenSenders, onOpenInvites, onOpenReimport }) {
  const admin = me.agent.role === 'admin';
  const tokenInvalid = me.enterprise.mailbox_connected && me.enterprise.mailbox_token_valid === false;
  const logout = async () => { await api.send('/auth/logout', 'POST'); location.href = '/login.html'; };
  const reconnect = () => {
    if (confirm('Reconnecter la boîte Gmail ? Vous allez repasser par le consentement Google ; un nouveau jeton sera enregistré.')) {
      location.href = '/api/mailbox/connect';
    }
  };
  return (
    <div className="modal-bg" onClick={onClose}>
      <div className="modal" onClick={(e) => e.stopPropagation()}>
        <h3>Paramètres</h3>

        <div className="set-acct">
          <div className="avatar lg">{initials(me.agent.name || me.agent.email)}</div>
          <div style={{ minWidth: 0 }}>
            <div style={{ fontWeight: 600, overflow: 'hidden', textOverflow: 'ellipsis' }}>{me.agent.name || me.agent.email}</div>
            <div style={{ color: 'var(--muted)', fontSize: 12, overflow: 'hidden', textOverflow: 'ellipsis' }}>
              {me.agent.email} · {admin ? 'Admin' : 'Agent'} · {me.enterprise.name}
            </div>
          </div>
        </div>

        <div className="dl">Préférences</div>
        <button className="set-row" onClick={onOpenNotifs}>
          <span>Notifications de nouveaux tickets</span><span className="chev">›</span>
        </button>

        {admin && (
          <>
            <div className="dl">Administration</div>
            <button className="set-row" onClick={onOpenSenders}>
              <span>Adresses d’expéditeur</span><span className="chev">›</span>
            </button>
            <button className="set-row" onClick={onOpenInvites}>
              <span>Agents &amp; invitations</span><span className="chev">›</span>
            </button>
            <button className="set-row" onClick={onOpenReimport}>
              <span>Réimporter des emails…</span><span className="chev">›</span>
            </button>
            <button className="set-row" onClick={reconnect}>
              <span>Reconnecter la boîte Gmail</span>
              <span>{tokenInvalid && <span className="pill p-open" style={{ marginRight: 8 }}>action requise</span>}<span className="chev">›</span></span>
            </button>
          </>
        )}

        <div className="dl">Session</div>
        <button className="set-row danger" onClick={logout}>
          <span>Déconnexion</span><span className="chev">›</span>
        </button>

        <div style={{ textAlign: 'right', marginTop: 16 }}>
          <button className="ghost" onClick={onClose}>Fermer</button>
        </div>
      </div>
    </div>
  );
}

function Conversation({ ticket, onReply, disabled, onBack, onShowDetails }) {
  const editorRef = React.useRef(null);
  const [sending, setSending] = useState(false);
  const [empty, setEmpty] = useState(true);
  const [collapsed, setCollapsed] = useState(() => new Set());
  const [focused, setFocused] = useState(false);
  const [maximized, setMaximized] = useState(false);
  const [draftSaved, setDraftSaved] = useState(false);
  const [draftAt, setDraftAt] = useState(null);
  const saveTimer = React.useRef(null);

  // Sauvegarde du brouillon (serveur). Debounced via scheduleSave.
  const doSave = (ticketId) => {
    const el = editorRef.current;
    if (!el) return;
    api.send(`/api/tickets/${ticketId}/draft`, 'PUT', { bodyHtml: el.innerHTML, bodyText: el.innerText })
      .then((r) => { setDraftSaved(!!r?.saved); setDraftAt(r?.saved ? (r.updated_at || null) : null); })
      .catch(() => {});
  };

  const discardDraft = async () => {
    if (!confirm('Supprimer le brouillon ?')) return;
    if (saveTimer.current) { clearTimeout(saveTimer.current); saveTimer.current = null; }
    if (editorRef.current) editorRef.current.innerHTML = '';
    setEmpty(true);
    setDraftSaved(false);
    setDraftAt(null);
    try { await api.send(`/api/tickets/${ticket.id}/draft`, 'DELETE'); } catch (e) { /* ignore */ }
  };
  const scheduleSave = () => {
    if (saveTimer.current) clearTimeout(saveTimer.current);
    const id = ticket.id;
    saveTimer.current = setTimeout(() => { saveTimer.current = null; doSave(id); }, 800);
  };

  const toggleMsg = (id) => setCollapsed((s) => {
    const n = new Set(s);
    n.has(id) ? n.delete(id) : n.add(id);
    return n;
  });

  // Charge le brouillon de l'agent à l'ouverture du ticket ; à la sortie, sauvegarde
  // immédiatement le brouillon du ticket qu'on quitte (avant d'écraser l'éditeur).
  useEffect(() => {
    const id = ticket.id;
    setDraftSaved(false);
    setDraftAt(null);
    api.get(`/api/tickets/${id}/draft`)
      .then((d) => {
        if (editorRef.current) editorRef.current.innerHTML = d?.body_html || '';
        refreshEmpty();
        const has = !!(d && (d.body_text || d.body_html));
        setDraftSaved(has);
        setDraftAt(has ? (d.updated_at || null) : null);
      })
      .catch(() => { if (editorRef.current) editorRef.current.innerHTML = ''; refreshEmpty(); });
    return () => {
      if (saveTimer.current) { clearTimeout(saveTimer.current); saveTimer.current = null; }
      doSave(id); // l'éditeur contient encore le contenu du ticket qu'on quitte
    };
  }, [ticket.id]);

  // Façon Gmail : à l'ouverture d'un ticket et à chaque nouveau message,
  // on ne garde déplié que le DERNIER message (les autres sont repliés).
  const msgIds = ticket.messages.map((m) => m.id);
  const lastId = msgIds[msgIds.length - 1] ?? null;
  useEffect(() => {
    setCollapsed(new Set(msgIds.slice(0, -1)));
  }, [lastId]);

  const refreshEmpty = () => {
    const el = editorRef.current;
    setEmpty(!el || (el.textContent.trim() === '' && !el.querySelector('img')));
  };

  // Mémorise la sélection courante (les contrôles de la barre d'outils volent le focus).
  const savedRange = React.useRef(null);
  const saveSel = () => {
    const sel = window.getSelection();
    if (sel && sel.rangeCount && editorRef.current?.contains(sel.anchorNode)) {
      savedRange.current = sel.getRangeAt(0).cloneRange();
    }
  };
  const restoreSel = () => {
    const el = editorRef.current;
    el?.focus();
    const r = savedRange.current;
    if (r) { const sel = window.getSelection(); sel.removeAllRanges(); sel.addRange(r); }
  };
  // Applique une commande de mise en forme à la sélection.
  const exec = (cmd, val) => {
    restoreSel();
    document.execCommand('styleWithCSS', false, true); // styles inline (compatibles email)
    document.execCommand(cmd, false, val);
    saveSel();
    refreshEmpty();
    scheduleSave();
  };
  const addLink = () => {
    const url = prompt('URL du lien :', 'https://');
    if (url) exec('createLink', url);
  };

  const onPaste = (e) => {
    const items = Array.from(e.clipboardData?.items || []);
    const img = items.find((it) => it.type.startsWith('image/'));
    if (!img) return; // texte : collage natif
    e.preventDefault();
    const file = img.getAsFile();
    const reader = new FileReader();
    reader.onload = () => { document.execCommand('insertImage', false, reader.result); refreshEmpty(); scheduleSave(); };
    reader.readAsDataURL(file);
  };

  const submit = async () => {
    const el = editorRef.current;
    if (!el) return;
    // Extrait les images collées (data:URI) -> pièces jointes inline avec cid.
    const attachments = [];
    el.querySelectorAll('img').forEach((img, i) => {
      const m = (img.getAttribute('src') || '').match(/^data:([^;]+);base64,(.*)$/);
      if (m) {
        const cid = `img_${Date.now()}_${i}@solvio`;
        const ext = (m[1].split('/')[1] || 'png').split('+')[0];
        attachments.push({ cid, mime: m[1], contentBase64: m[2], filename: `image_${i + 1}.${ext}` });
        img.setAttribute('src', `cid:${cid}`);
      }
    });
    const bodyHtml = el.innerHTML;
    const bodyText = el.innerText;
    if (!bodyText.trim() && attachments.length === 0) return;
    setSending(true);
    try {
      await api.send(`/api/tickets/${ticket.id}/reply`, 'POST', { bodyText, bodyHtml, attachments });
      if (saveTimer.current) { clearTimeout(saveTimer.current); saveTimer.current = null; }
      el.innerHTML = '';
      setEmpty(true);
      setFocused(false);
      setMaximized(false);
      setDraftSaved(false);
      onReply();
    } catch (e) { alert('Échec de l’envoi : ' + e.message); }
    setSending(false);
  };

  return (
    <div className={`conv${maximized ? ' maxed' : ''}`}>
      <div className="conv-head">
        <button className="icon-btn mobile-only" aria-label="Retour" onClick={onBack}>←</button>
        <div className="conv-head-main">
          <div style={{ fontWeight: 600 }}>{ticket.subject} <span className="tk-id">#{ticket.id}</span></div>
          <div style={{ fontSize: 12, color: 'var(--muted)' }}>{ticket.customer_email}</div>
        </div>
        <span className={`pill p-${ticket.status}`}>{STATUS_LABEL[ticket.status]}</span>
        <button className="icon-btn mobile-only" aria-label="Détails" onClick={onShowDetails}>☰</button>
      </div>
      <div className="thread">
        {ticket.messages.map((m) => {
          const files = (m.attachments || []).filter((a) => !a.is_inline);
          const who = m.direction === 'in' ? (ticket.customer_name || ticket.customer_email) : 'Vous';
          const isCollapsed = collapsed.has(m.id);
          const preview = (m.body_text || '').replace(/\s+/g, ' ').trim();
          return (
            <div key={m.id} className={`msg ${m.direction}${isCollapsed ? ' collapsed' : ''}`}>
              <div className="msg-head" onClick={() => toggleMsg(m.id)} title={isCollapsed ? 'Déplier' : 'Replier'}>
                <span className="msg-who">
                  <span className="msg-chevron">{isCollapsed ? '▸' : '▾'}</span>
                  <span className="msg-av">{m.direction === 'in' ? initials(who) : 'Vo'}</span>
                  {who}
                </span>
                <span className="msg-meta">{m.direction === 'in' ? 'reçu' : 'envoyé'} · {fmt(m.created_at)}</span>
              </div>
              {isCollapsed ? (
                <div className="msg-preview" onClick={() => toggleMsg(m.id)}>
                  {preview || '(contenu)'}{files.length > 0 ? ` · ${files.length} pièce(s) jointe(s)` : ''}
                </div>
              ) : (
                <>
                  <div className="msg-body">
                    {m.body_html
                      ? <div className="rich" dangerouslySetInnerHTML={{ __html: m.body_html }} />
                      : (m.body_text || '(vide)')}
                  </div>
                  {files.length > 0 && (
                    <div className="atts">
                      {files.map((a) => (
                        <a key={a.id} className="att" href={`/api/attachments/${a.id}`} target="_blank" rel="noreferrer">
                          📎 {a.filename || 'fichier'}
                        </a>
                      ))}
                    </div>
                  )}
                </>
              )}
            </div>
          );
        })}
      </div>
      <div className={`composer${focused || maximized ? ' focused' : ''}`}>
        {!disabled && (
          <div className="toolbar">
            <button title="Gras" style={{ fontWeight: 700 }} onClick={() => exec('bold')}>B</button>
            <button title="Italique" style={{ fontStyle: 'italic' }} onClick={() => exec('italic')}>I</button>
            <button title="Souligné" style={{ textDecoration: 'underline' }} onClick={() => exec('underline')}>U</button>
            <button title="Barré" style={{ textDecoration: 'line-through' }} onClick={() => exec('strikeThrough')}>S</button>
            <span className="tb-sep" />
            <select title="Police" defaultValue="" onChange={(e) => { exec('fontName', e.target.value); e.target.value = ''; }}>
              <option value="" disabled>Police</option>
              <option value="system-ui, sans-serif">Système</option>
              <option value="Arial, sans-serif">Arial</option>
              <option value="Georgia, serif">Georgia</option>
              <option value="'Times New Roman', serif">Times</option>
              <option value="'Courier New', monospace">Courier</option>
            </select>
            <select title="Taille" defaultValue="" onChange={(e) => { exec('fontSize', e.target.value); e.target.value = ''; }}>
              <option value="" disabled>Taille</option>
              <option value="2">Petite</option>
              <option value="3">Normale</option>
              <option value="5">Grande</option>
              <option value="6">Très grande</option>
            </select>
            <label className="tb-color" title="Couleur du texte">
              A
              <input type="color" defaultValue="#1a1a18" onChange={(e) => exec('foreColor', e.target.value)} />
            </label>
            <span className="tb-sep" />
            <button title="Liste à puces" onClick={() => exec('insertUnorderedList')}>•≡</button>
            <button title="Liste numérotée" onClick={() => exec('insertOrderedList')}>1.</button>
            <button title="Insérer un lien" onClick={addLink}>🔗</button>
            <button title="Effacer la mise en forme" onClick={() => exec('removeFormat')}>✕</button>
          </div>
        )}
        <div
          ref={editorRef}
          className="editor"
          contentEditable={!disabled}
          data-placeholder={disabled ? 'Connectez la boîte Gmail pour répondre…' : 'Répondre au client (mise en forme + collage d’images)…'}
          onInput={() => { refreshEmpty(); scheduleSave(); }}
          onPaste={onPaste}
          onKeyUp={saveSel}
          onMouseUp={saveSel}
          onFocus={() => setFocused(true)}
          onBlur={(e) => {
            saveSel();
            // Ne rétrécit pas si le focus part vers un contrôle de la zone (barre d'outils, boutons).
            const composer = editorRef.current?.closest('.composer');
            if (!composer || !composer.contains(e.relatedTarget)) setFocused(false);
          }}
          suppressContentEditableWarning
        />
        <div className="composer-bar">
          <span style={{ display: 'flex', alignItems: 'center', gap: 10 }}>
            <button
              className="ghost expand-btn"
              title={maximized ? 'Réduire' : 'Plein écran'}
              onClick={() => setMaximized((v) => !v)}
            >
              {maximized ? '⤡ Réduire' : '⤢ Plein écran'}
            </button>
            {draftSaved && !empty && (
              <span style={{ fontSize: 11, color: 'var(--faint)', display: 'flex', alignItems: 'center', gap: 8 }}>
                ✓ Brouillon enregistré{draftAt ? ` à ${fmtTime(draftAt)}` : ''}
                <a onClick={discardDraft} style={{ color: 'var(--warn-fg)', cursor: 'pointer' }}>Supprimer</a>
              </span>
            )}
          </span>
          <button className="send" disabled={disabled || sending || empty} onClick={submit}>
            {sending ? 'Envoi…' : 'Envoyer'}
          </button>
        </div>
      </div>
    </div>
  );
}

function Details({ ticket, onChange, isAdmin, onDelete, open, onClose }) {
  const setStatus = async (status) => { await api.send(`/api/tickets/${ticket.id}`, 'PATCH', { status }); onChange(); };
  const del = async () => {
    if (!confirm(`Supprimer définitivement le ticket #${ticket.id} ?\nLes messages et pièces jointes associés seront aussi supprimés. Cette action est irréversible.`)) return;
    try { await onDelete(ticket.id); }
    catch (e) { alert('Échec de la suppression : ' + e.message); }
  };
  return (
    <div className={`details${open ? ' open' : ''}`}>
      <div className="details-head">
        <h4>Détails</h4>
        <button className="icon-btn details-close" aria-label="Fermer" onClick={onClose}>✕</button>
      </div>
      <div className="dl">Client</div>
      <div>{ticket.customer_name || '—'}</div>
      <div style={{ fontSize: 12, color: 'var(--muted)' }}>{ticket.customer_email}</div>
      <div className="dl">Statut</div>
      <select value={ticket.status} onChange={(e) => setStatus(e.target.value)}>
        {Object.entries(STATUS_LABEL).map(([v, l]) => <option key={v} value={v}>{l}</option>)}
      </select>
      <div className="dl">Créé</div>
      <div>{fmt(ticket.created_at)}</div>
      <div className="dl">Dernière activité</div>
      <div>{fmt(ticket.updated_at)}</div>
      {isAdmin && (
        <>
          <div className="dl" style={{ marginTop: 18 }}>Zone de danger</div>
          <button
            className="ghost"
            style={{ color: 'var(--warn-fg)', borderColor: 'var(--warn-fg)' }}
            onClick={del}
          >
            Supprimer le ticket
          </button>
        </>
      )}
    </div>
  );
}

function InvitesModal({ onClose }) {
  const [list, setList] = useState([]);
  const [email, setEmail] = useState('');
  const [role, setRole] = useState('agent');
  const load = () => api.get('/api/invitations').then(setList).catch(() => {});
  useEffect(() => { load(); }, []);
  const invite = async () => {
    try { await api.send('/api/invitations', 'POST', { email, role }); setEmail(''); load(); }
    catch (e) { alert(e.message); }
  };
  return (
    <div className="modal-bg" onClick={onClose}>
      <div className="modal" onClick={(e) => e.stopPropagation()}>
        <h3>Inviter un agent</h3>
        <div className="inv-row">
          <input placeholder="email@exemple.com" value={email} onChange={(e) => setEmail(e.target.value)} />
          <select style={{ width: 110 }} value={role} onChange={(e) => setRole(e.target.value)}>
            <option value="agent">Agent</option>
            <option value="admin">Admin</option>
          </select>
          <button className="send" onClick={invite}>Inviter</button>
        </div>
        <div className="inv-list">
          {list.map((i) => (
            <div key={i.id} className="inv-item">
              <span>{i.email} <span style={{ color: 'var(--faint)' }}>· {i.role}</span></span>
              <span style={{ color: 'var(--muted)' }}>{i.status}</span>
            </div>
          ))}
          {list.length === 0 && <div style={{ color: 'var(--faint)', fontSize: 13 }}>Aucune invitation.</div>}
        </div>
        <div style={{ textAlign: 'right', marginTop: 16 }}>
          <button className="ghost" onClick={onClose}>Fermer</button>
        </div>
      </div>
    </div>
  );
}

function SendersModal({ onClose }) {
  const [mode, setMode] = useState('received');
  const [list, setList] = useState([]);
  const [email, setEmail] = useState('');
  const [name, setName] = useState('');

  const load = () => api.get('/api/senders').then((d) => { setMode(d.mode || 'received'); setList(d.addresses); }).catch(() => {});
  useEffect(() => { load(); }, []);

  const add = async () => {
    try { await api.send('/api/senders', 'POST', { email, name }); setEmail(''); setName(''); load(); }
    catch (e) { alert(e.message); }
  };
  const makeDefault = async (id) => { try { await api.send(`/api/senders/${id}/default`, 'POST'); load(); } catch (e) { alert(e.message); } };
  const remove = async (id) => { try { await api.send(`/api/senders/${id}`, 'DELETE'); load(); } catch (e) { alert(e.message); } };
  const changeMode = async (m) => { setMode(m); try { await api.send('/api/senders/mode', 'PATCH', { mode: m }); } catch (e) { alert(e.message); load(); } };

  return (
    <div className="modal-bg" onClick={onClose}>
      <div className="modal" onClick={(e) => e.stopPropagation()}>
        <h3>Adresses d’expéditeur</h3>

        <div className="dl">Choix de l’adresse d’envoi des réponses</div>
        <label style={{ display: 'flex', gap: 8, alignItems: 'flex-start', margin: '8px 0' }}>
          <input type="radio" name="mode" checked={mode === 'received'} onChange={() => changeMode('received')} />
          <span>Depuis l’adresse à laquelle le client a écrit<br />
            <span style={{ color: 'var(--muted)', fontSize: 12 }}>Repli sur l’adresse par défaut si elle n’est pas dans la liste.</span>
          </span>
        </label>
        <label style={{ display: 'flex', gap: 8, alignItems: 'flex-start', margin: '8px 0' }}>
          <input type="radio" name="mode" checked={mode === 'fixed'} onChange={() => changeMode('fixed')} />
          <span>Toujours depuis l’adresse par défaut</span>
        </label>

        <div className="dl" style={{ marginTop: 14 }}>Liste des adresses</div>
        <div className="inv-row">
          <input placeholder="adresse@domaine.com" value={email} onChange={(e) => setEmail(e.target.value)} />
          <input style={{ width: 130 }} placeholder="Nom (option.)" value={name} onChange={(e) => setName(e.target.value)} />
          <button className="send" onClick={add}>Ajouter</button>
        </div>
        <div className="inv-list">
          {list.map((s) => (
            <div key={s.id} className="inv-item">
              <span>
                {s.name ? `${s.name} ` : ''}<span style={{ color: s.name ? 'var(--muted)' : 'inherit' }}>{s.email}</span>
                {s.is_default && <span className="pill p-pending" style={{ marginLeft: 8 }}>défaut</span>}
              </span>
              <span style={{ display: 'flex', gap: 10 }}>
                {!s.is_default && <a style={{ color: 'var(--accent)', cursor: 'pointer', fontSize: 12 }} onClick={() => makeDefault(s.id)}>définir défaut</a>}
                {!s.is_default && <a style={{ color: 'var(--warn-fg)', cursor: 'pointer', fontSize: 12 }} onClick={() => remove(s.id)}>supprimer</a>}
              </span>
            </div>
          ))}
          {list.length === 0 && <div style={{ color: 'var(--faint)', fontSize: 13 }}>Aucune adresse.</div>}
        </div>

        <div style={{ color: 'var(--faint)', fontSize: 12, marginTop: 10 }}>
          Chaque adresse doit être un alias d’envoi autorisé du compte Gmail connecté, sinon Gmail réécrit l’expéditeur.
        </div>
        <div style={{ textAlign: 'right', marginTop: 16 }}>
          <button className="ghost" onClick={onClose}>Fermer</button>
        </div>
      </div>
    </div>
  );
}

function NotificationsModal({ onClose }) {
  const [list, setList] = useState([]);
  const load = () => api.get('/api/notifications/prefs').then(setList).catch(() => {});
  useEffect(() => { load(); }, []);

  const toggle = async (address, enabled) => {
    setList((l) => l.map((x) => (x.address === address ? { ...x, enabled } : x)));
    try { await api.send('/api/notifications/prefs', 'PUT', { address, enabled }); }
    catch (e) { alert(e.message); load(); }
  };

  return (
    <div className="modal-bg" onClick={onClose}>
      <div className="modal" onClick={(e) => e.stopPropagation()}>
        <h3>Notifications de nouveaux tickets</h3>
        <div className="dl">
          Recevez un email à <strong>chaque nouveau ticket</strong>, selon l’adresse de support sur laquelle il arrive.
          Décochez une adresse pour ne plus en être notifié.
        </div>
        <div className="inv-list">
          {list.map((p) => (
            <div key={p.address} className="inv-item">
              <span>
                {p.name ? `${p.name} ` : ''}
                <span style={{ color: p.name ? 'var(--muted)' : 'inherit' }}>{p.address}</span>
                {p.isDefault && <span className="pill p-pending" style={{ marginLeft: 8 }}>défaut</span>}
              </span>
              <label style={{ display: 'flex', alignItems: 'center', gap: 6, fontSize: 12, cursor: 'pointer' }}>
                <input type="checkbox" checked={p.enabled} onChange={(e) => toggle(p.address, e.target.checked)} />
                Me notifier
              </label>
            </div>
          ))}
          {list.length === 0 && <div style={{ color: 'var(--faint)', fontSize: 13 }}>Aucune adresse de support configurée.</div>}
        </div>
        <div style={{ color: 'var(--faint)', fontSize: 12, marginTop: 10 }}>
          Les notifications partent de la boîte Gmail connectée vers votre adresse ({' '}celle de votre compte agent{' '}).
        </div>
        <div style={{ textAlign: 'right', marginTop: 16 }}>
          <button className="ghost" onClick={onClose}>Fermer</button>
        </div>
      </div>
    </div>
  );
}

function ReimportModal({ onClose, onDone }) {
  const today = new Date().toISOString().slice(0, 10);
  const weekAgo = new Date(Date.now() - 7 * 86400000).toISOString().slice(0, 10);
  const [since, setSince] = useState(weekAgo);
  const [busy, setBusy] = useState(false);
  const [result, setResult] = useState(null);

  const run = async () => {
    if (!since) return;
    setBusy(true); setResult(null);
    try {
      const r = await api.send('/api/mailbox/reimport', 'POST', { since });
      setResult(r);
      if (!r.error) onDone && onDone();
    } catch (e) {
      setResult({ error: e.message });
    }
    setBusy(false);
  };

  return (
    <div className="modal-bg" onClick={onClose}>
      <div className="modal" onClick={(e) => e.stopPropagation()}>
        <h3>Réimporter des emails</h3>
        <div className="dl">
          Récupère les emails de la boîte de support reçus <strong>depuis la date choisie</strong> et crée
          ou complète les tickets correspondants. Les emails déjà présents sont ignorés (pas de doublons),
          et aucune notification n’est envoyée aux agents.
        </div>
        <div className="inv-row" style={{ marginTop: 12, alignItems: 'center' }}>
          <input type="date" value={since} max={today} onChange={(e) => setSince(e.target.value)} />
          <button className="send" disabled={busy || !since} onClick={run}>
            {busy ? 'Import en cours…' : 'Réimporter'}
          </button>
        </div>

        {result && result.error && (
          <div style={{ marginTop: 12, fontSize: 13, color: 'var(--danger)' }}>
            Échec : {result.error}
            {result.tokenInvalid && ' — reconnectez la boîte Gmail.'}
          </div>
        )}
        {result && !result.error && (
          <div style={{ marginTop: 12, fontSize: 13 }}>
            ✓ {result.created || 0} ticket(s) créé(s), {result.appended || 0} message(s) ajouté(s)
            {' '}sur {result.scanned || 0} email(s) analysé(s).
            {result.capped && (
              <div style={{ color: 'var(--warn-fg)', marginTop: 6 }}>
                Limite atteinte (volume trop important) : relancez avec une date plus récente pour récupérer le reste.
              </div>
            )}
          </div>
        )}

        <div style={{ color: 'var(--faint)', fontSize: 12, marginTop: 10 }}>
          Astuce : choisissez une date proche pour récupérer les emails manqués (ex. pendant une panne).
          Les très anciens réimports peuvent être longs.
        </div>
        <div style={{ textAlign: 'right', marginTop: 16 }}>
          <button className="ghost" onClick={onClose}>Fermer</button>
        </div>
      </div>
    </div>
  );
}

ReactDOM.createRoot(document.getElementById('root')).render(<App />);
