/* global React, Icon, Avatar, Button, StatusDot, DATA */
// ============================================================
// Messagerie in-app — store temps réel + admin chat + boîte opérateur
// ============================================================
const { useState: useMsgState, useEffect: useMsgEffect, useRef: useMsgRef, useReducer } = React;

const TempMsg = (function () {
  const threads = {
    u3: [
      { id: 1, from: "admin", text: "Salut Sofia 👋 pense à lancer le warm-up du lot du matin avant 10h.", at: "08:12", read: true },
      { id: 2, from: "u3",    text: "C'est en cours, 3/5 déjà fait 👍", at: "08:20", read: true },
      { id: 3, from: "admin", text: "Parfait, merci !", at: "08:21", read: true },
    ],
    u4: [
      { id: 4, from: "admin", text: "Tom, la story du jour est prête à publier ?", at: "10:05", read: true },
      { id: 5, from: "u4",    text: "Pas encore, je finis le warm-up d'abord", at: "10:09", read: false },
    ],
    u7: [
      { id: 6, from: "admin", text: "Yuki, ta tâche du lot du soir est en retard, tu peux la reprendre ?", at: "20:14", read: false },
    ],
  };
  const listeners = new Set();
  const emit = () => listeners.forEach((l) => l());
  const stamp = () => { const d = new Date(); return [d.getHours(), d.getMinutes()].map((n) => String(n).padStart(2, "0")).join(":"); };
  let seq = 100;
  return {
    subscribe(cb) { listeners.add(cb); return () => listeners.delete(cb); },
    get(opId) { return threads[opId] || []; },
    send(opId, from, text) {
      if (!text || !text.trim()) return;
      (threads[opId] = threads[opId] || []).push({ id: ++seq, from, text: text.trim(), at: stamp(), read: false });
      emit();
    },
    markRead(opId, viewer) {
      (threads[opId] || []).forEach((m) => {
        const fromAdmin = m.from === "admin";
        if ((viewer === "admin" && !fromAdmin) || (viewer === "op" && fromAdmin)) m.read = true;
      });
      emit();
    },
    unreadAdmin(opId) { return (threads[opId] || []).filter((m) => m.from !== "admin" && !m.read).length; },
    unreadOp(opId) { return (threads[opId] || []).filter((m) => m.from === "admin" && !m.read).length; },
    totalAdmin() { return Object.keys(threads).reduce((s, k) => s + this.unreadAdmin(k), 0); },
    last(opId) { const t = threads[opId] || []; return t[t.length - 1]; },
  };
})();

function useMsg() {
  const [, force] = useReducer((x) => x + 1, 0);
  useMsgEffect(() => TempMsg.subscribe(force), []);
  return TempMsg;
}

// signal partagé : ouvre/ferme la bulle de chat flottante (bas-droite) côté opérateur
const ChatUI = (function () {
  let open = false; const ls = new Set();
  return { sub(cb) { ls.add(cb); return () => ls.delete(cb); }, isOpen() { return open; }, set(v) { open = v; ls.forEach(f => f()); }, toggle() { open = !open; ls.forEach(f => f()); } };
})();
function useChatUI() { const [, f] = useReducer((x) => x + 1, 0); useMsgEffect(() => ChatUI.sub(f), []); return ChatUI; }

// ---- bulle de message ----
function Bubble({ m, mine }) {
  return (
    <div style={{ display: "flex", justifyContent: mine ? "flex-end" : "flex-start" }}>
      <div style={{ maxWidth: "78%", padding: "9px 13px", borderRadius: 14,
        borderBottomRightRadius: mine ? 4 : 14, borderBottomLeftRadius: mine ? 14 : 4,
        background: mine ? "var(--accent)" : "var(--surface-3)", color: mine ? "#06281c" : "var(--text)",
        fontSize: 13.5, lineHeight: 1.45 }}>
        {m.text}
        <span className="mono" style={{ display: "block", textAlign: "right", fontSize: 9.5, marginTop: 3, opacity: .7 }}>{m.at}</span>
      </div>
    </div>
  );
}

function Composer({ onSend, placeholder, disabled }) {
  const [text, setText] = useMsgState("");
  const go = () => { if (!text.trim()) return; onSend(text); setText(""); };
  return (
    <div style={{ display: "flex", gap: 9, padding: 14, borderTop: "1px solid var(--border)", background: "var(--surface-2)" }}>
      <input value={text} onChange={(e) => setText(e.target.value)} onKeyDown={(e) => e.key === "Enter" && go()}
        placeholder={placeholder || "Écrire un message…"} disabled={disabled}
        style={{ flex: 1, padding: "10px 13px", background: "var(--bg-2)", border: "1px solid var(--border-2)", borderRadius: 10, color: "var(--text)", fontSize: 13.5, outline: "none" }} />
      <Button variant="primary" icon="send" onClick={go} disabled={disabled}>Envoyer</Button>
    </div>
  );
}

function ThreadScroll({ thread, mineFrom }) {
  const ref = useMsgRef(null);
  useMsgEffect(() => { if (ref.current) ref.current.scrollTop = ref.current.scrollHeight; }, [thread.length]);
  return (
    <div ref={ref} style={{ flex: 1, overflow: "auto", padding: 18, display: "grid", gap: 10, alignContent: "start" }}>
      {thread.length === 0 && <div style={{ textAlign: "center", color: "var(--faint)", fontSize: 13, marginTop: 30 }}>Aucun message. Démarrez la conversation 👇</div>}
      {thread.map((m) => <Bubble key={m.id} m={m} mine={m.from === mineFrom} />)}
    </div>
  );
}

// ============================================================
// ADMIN — page Messages (liste opérateurs + chat)
// ============================================================
function AdminMessages({ initialOp, onWatch }) {
  const msg = useMsg();
  const ops = DATA.realTeam().filter((o) => o.role !== "Admin");   // équipe réelle uniquement
  const [sel, setSel] = useMsgState(initialOp || ops.find((o) => o.status === "active")?.id || ops[0].id);
  useMsgEffect(() => { if (initialOp) setSel(initialOp); }, [initialOp]);
  useMsgEffect(() => { msg.markRead(sel, "admin"); }, [sel, msg.get(sel).length]);

  const op = DATA.opById(sel);
  const thread = msg.get(sel);
  const online = op.status === "active";

  return (
    <div style={{ display: "grid", gap: 0 }}>
      <div style={{ marginBottom: 18 }}>
        <h1 style={{ margin: 0, fontSize: 22, fontWeight: 700, letterSpacing: "-.01em" }}>Messages</h1>
        <p style={{ margin: "5px 0 0", color: "var(--muted)", fontSize: 13.5 }}>Envoyez un message en direct à un opérateur pendant qu'il travaille.</p>
      </div>
      <div style={{ display: "grid", gridTemplateColumns: "290px 1fr", height: "calc(100vh - 190px)", minHeight: 460,
        background: "var(--surface)", border: "1px solid var(--border)", borderRadius: "var(--r-lg)", overflow: "hidden" }} className="msg-grid">
        {/* liste conversations */}
        <div style={{ borderRight: "1px solid var(--border)", overflow: "auto", background: "var(--bg-2)" }}>
          <div className="mono" style={{ fontSize: 10, color: "var(--faint)", letterSpacing: ".12em", padding: "16px 16px 8px" }}>OPÉRATEURS</div>
          {ops.map((o) => {
            const unread = msg.unreadAdmin(o.id);
            const last = msg.last(o.id);
            const act = o.id === sel;
            return (
              <button key={o.id} onClick={() => setSel(o.id)} style={{ display: "flex", alignItems: "center", gap: 11, width: "100%", padding: "11px 14px",
                background: act ? "var(--surface)" : "transparent", border: "none", borderLeft: "2px solid " + (act ? "var(--accent)" : "transparent"), textAlign: "left", cursor: "pointer" }}>
                <div style={{ position: "relative", flex: "none" }}>
                  <Avatar user={o} size={38} />
                  <span style={{ position: "absolute", bottom: -1, right: -1, width: 11, height: 11, borderRadius: 99, background: o.status === "active" ? "var(--online)" : o.status === "suspended" ? "var(--offline)" : "var(--locked)", border: "2px solid var(--bg-2)" }} />
                </div>
                <div style={{ flex: 1, minWidth: 0 }}>
                  <div style={{ display: "flex", justifyContent: "space-between", alignItems: "center", gap: 6 }}>
                    <span style={{ fontSize: 13, fontWeight: 600, color: "var(--text)" }}>{o.name}</span>
                    {last && <span className="mono" style={{ fontSize: 10, color: "var(--faint)" }}>{last.at}</span>}
                  </div>
                  <div style={{ display: "flex", justifyContent: "space-between", alignItems: "center", gap: 6, marginTop: 2 }}>
                    <span style={{ fontSize: 11.5, color: "var(--muted)", overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }}>{last ? (last.from === "admin" ? "Vous : " : "") + last.text : "—"}</span>
                    {unread > 0 && <span className="num" style={{ flex: "none", minWidth: 18, height: 18, padding: "0 5px", borderRadius: 99, background: "var(--accent)", color: "#06281c", fontSize: 11, fontWeight: 700, display: "grid", placeItems: "center" }}>{unread}</span>}
                  </div>
                </div>
              </button>
            );
          })}
        </div>
        {/* fil */}
        <div style={{ display: "flex", flexDirection: "column", minWidth: 0 }}>
          <div style={{ display: "flex", alignItems: "center", gap: 11, padding: "13px 18px", borderBottom: "1px solid var(--border)" }}>
            <Avatar user={op} size={36} />
            <div style={{ flex: 1 }}>
              <div style={{ fontSize: 14, fontWeight: 700 }}>{op.name}</div>
              <div style={{ fontSize: 11.5, color: online ? "var(--accent)" : "var(--faint)", display: "flex", alignItems: "center", gap: 6 }}>
                <StatusDot status={online ? "online" : "offline"} pulse={online} /> {online ? "en ligne · en train de travailler" : "hors ligne"}
              </div>
            </div>
            {online && <button onClick={() => onWatch && onWatch(sel)} title="Voir son écran en direct"
              style={{ display: "flex", alignItems: "center", gap: 7, padding: "8px 13px", borderRadius: 9, background: "var(--cyan-soft)", color: "var(--accent-2)", border: "1px solid rgba(34,211,238,.3)", fontSize: 12.5, fontWeight: 600 }}>
              {React.createElement(Icon.eye, { size: 16 })} Voir son écran</button>}
            {op.whatsapp && <a href={`https://wa.me/${op.whatsapp.replace(/[^\d]/g, "")}`} target="_blank" rel="noreferrer" title="WhatsApp"
              style={{ display: "grid", placeItems: "center", width: 34, height: 34, borderRadius: 9, background: "rgba(37,211,102,.13)", color: "#25D366", border: "1px solid rgba(37,211,102,.3)" }}>
              {React.createElement(Icon.whatsapp, { size: 17 })}</a>}
            {op.telegram && <a href={`https://t.me/${op.telegram.replace(/^@/, "")}`} target="_blank" rel="noreferrer" title="Telegram"
              style={{ display: "grid", placeItems: "center", width: 34, height: 34, borderRadius: 9, background: "rgba(42,171,238,.13)", color: "#2AABEE", border: "1px solid rgba(42,171,238,.3)" }}>
              {React.createElement(Icon.telegram, { size: 17 })}</a>}
          </div>
          <ThreadScroll thread={thread} mineFrom="admin" />
          <Composer onSend={(t) => msg.send(sel, "admin", t)} placeholder={`Message à ${op.name.split(" ")[0]}…`} />
        </div>
      </div>
    </div>
  );
}

// ============================================================
// OPÉRATEUR — cloche + boîte de réception + toast live
// ============================================================
function OperatorBell({ user }) {
  const msg = useMsg();
  const chat = useChatUI();
  const [toast, setToast] = useMsgState(null);
  const prev = useMsgRef(msg.unreadOp(user.id));
  const unread = msg.unreadOp(user.id);

  useMsgEffect(() => {
    if (unread > prev.current && !chat.isOpen()) {
      const last = msg.last(user.id);
      setToast(last);
      const t = setTimeout(() => setToast(null), 5000);
      prev.current = unread;
      return () => clearTimeout(t);
    }
    prev.current = unread;
  }, [unread]);

  return (
    <>
      <button onClick={() => chat.set(true)} title="Messages" style={{ position: "relative", background: "var(--surface-2)", border: "1px solid var(--border)", borderRadius: 10, width: 38, height: 38, display: "grid", placeItems: "center", color: chat.isOpen() ? "var(--accent)" : "var(--muted)" }}>
        {React.createElement(Icon.bell, { size: 18 })}
        {unread > 0 && <span className="num" style={{ position: "absolute", top: -6, right: -6, minWidth: 18, height: 18, padding: "0 4px", borderRadius: 99, background: "var(--accent)", color: "#06281c", fontSize: 10.5, fontWeight: 700, display: "grid", placeItems: "center", border: "2px solid var(--bg)" }}>{unread}</span>}
      </button>

      {toast && (
        <div onClick={() => { chat.set(true); setToast(null); }} style={{ position: "fixed", top: 70, right: 22, zIndex: 90, width: 320, maxWidth: "90vw",
          background: "var(--surface)", border: "1px solid var(--accent-line)", borderRadius: 13, boxShadow: "var(--shadow-lg)", padding: 14, cursor: "pointer", animation: "toastIn .26s ease" }}>
          <div style={{ display: "flex", alignItems: "center", gap: 9, marginBottom: 7 }}>
            <span style={{ width: 22, height: 22, borderRadius: 7, background: "linear-gradient(135deg,var(--accent),var(--accent-2))", display: "grid", placeItems: "center", color: "#06281c" }}>{React.createElement(Icon.send, { size: 13 })}</span>
            <span style={{ fontSize: 12.5, fontWeight: 700 }}>Message · ton manager</span>
            <span className="mono" style={{ marginLeft: "auto", fontSize: 10, color: "var(--faint)" }}>{toast.at}</span>
          </div>
          <div style={{ fontSize: 13, color: "var(--muted)", lineHeight: 1.45 }}>{toast.text}</div>
        </div>
      )}
    </>
  );
}

// ============================================================
// Bulle de chat flottante (bas-droite) — opérateur ET superviseur
// ============================================================
function FloatingChat({ opId, as, z = 80 }) {
  const msg = useMsg();
  const chat = useChatUI();
  const controlled = as === opId; // côté opérateur : piloté par la cloche
  const [localOpen, setLocalOpen] = useMsgState(false);
  const open = controlled ? chat.isOpen() : localOpen;
  const setOpen = controlled ? (v) => chat.set(typeof v === "function" ? v(chat.isOpen()) : v) : setLocalOpen;
  const thread = msg.get(opId);
  const isAdmin = as === "admin";
  const unread = isAdmin ? msg.unreadAdmin(opId) : msg.unreadOp(opId);
  const peer = isAdmin ? DATA.opById(opId) : null;

  useMsgEffect(() => { if (open) msg.markRead(opId, isAdmin ? "admin" : "op"); }, [open, thread.length]);

  return (
    <div style={{ position: "fixed", right: 22, bottom: 22, zIndex: z, display: "flex", flexDirection: "column", alignItems: "flex-end", gap: 12 }}>
      {open && (
        <div style={{ width: 348, maxWidth: "90vw", height: 440, display: "flex", flexDirection: "column",
          background: "var(--surface)", border: "1px solid var(--border-2)", borderRadius: 16, boxShadow: "var(--shadow-lg)", overflow: "hidden", animation: "toastIn .2s ease" }}>
          <div style={{ display: "flex", alignItems: "center", gap: 10, padding: "12px 14px", borderBottom: "1px solid var(--border)" }}>
            {isAdmin
              ? <Avatar user={peer} size={32} />
              : <div style={{ width: 32, height: 32, borderRadius: 9, background: "linear-gradient(135deg,var(--accent),var(--accent-2))", display: "grid", placeItems: "center", color: "#06281c" }}>{React.createElement(Icon.shield, { size: 17 })}</div>}
            <div style={{ flex: 1, minWidth: 0 }}>
              <div style={{ fontSize: 13.5, fontWeight: 700 }}>{isAdmin ? peer.name : "Agence NKReal"}</div>
              <div style={{ fontSize: 10.5, color: "var(--accent)", display: "flex", alignItems: "center", gap: 5 }}><StatusDot status="online" pulse /> {isAdmin ? "opérateur · en ligne" : "admin · en ligne"}</div>
            </div>
            <button onClick={() => setOpen(false)} style={{ background: "none", border: "none", color: "var(--muted)", display: "grid", padding: 4 }}>{React.createElement(Icon.chevDown, { size: 20 })}</button>
          </div>
          <ThreadScroll thread={thread} mineFrom={as} />
          <Composer onSend={(t) => msg.send(opId, as, t)} placeholder={isAdmin ? `Guider ${peer.name.split(" ")[0]}…` : "Répondre à l'agence…"} />
        </div>
      )}
      <button onClick={() => setOpen(o => !o)} style={{ position: "relative", width: 56, height: 56, borderRadius: 99, border: "none",
        background: open ? "var(--surface-3)" : "linear-gradient(135deg,var(--accent),var(--accent-2))", color: open ? "var(--text)" : "#06281c",
        display: "grid", placeItems: "center", boxShadow: "0 10px 28px rgba(0,224,138,.32)", cursor: "pointer", transition: "transform .14s" }}
        onMouseEnter={e => e.currentTarget.style.transform = "scale(1.06)"} onMouseLeave={e => e.currentTarget.style.transform = "none"}>
        {React.createElement(Icon[open ? "chevDown" : "send"], { size: 23 })}
        {!open && unread > 0 && <span className="num" style={{ position: "absolute", top: -2, right: -2, minWidth: 22, height: 22, padding: "0 5px", borderRadius: 99, background: "var(--danger)", color: "#fff", fontSize: 11.5, fontWeight: 700, display: "grid", placeItems: "center", border: "2px solid var(--bg)" }}>{unread}</span>}
      </button>
    </div>
  );
}

// ============================================================
// Supervision live — voir l'écran de l'opérateur + le guider
// ============================================================
function WatchOverlay({ opId, onClose, me }) {
  const { useState, useEffect } = React;
  const ld = window.useLiveDevices ? useLiveDevices(4000) : { list: null };
  const ru = window.useRegUsers ? useRegUsers(8000) : { users: [] };
  const list = Array.isArray(ld.list) ? ld.list : [];
  const op = (ru.users || []).find(u => u.id === opId) || (window.DATA && DATA.opById ? DATA.opById(opId) : null) || { name: "Opérateur", id: opId };
  const myDevs = list.filter(d => d.operator_id === opId);
  const [logs, setLogs] = useState([]);
  const [pickUdid, setPickUdid] = useState(null);
  // device courant : choisi, sinon celui de sa dernière action (logs), sinon 1er en ligne assigné
  const recentUdid = logs[0] && logs[0].udid;
  const dev = (pickUdid && list.find(d => d.udid === pickUdid))
    || (recentUdid && myDevs.find(d => d.udid === recentUdid))
    || myDevs.find(d => d.status === "online") || myDevs[0] || null;

  const loadLogs = async () => {
    if (!window.Backend.logs) return;
    try { await window.Backend.flushLogs(); } catch (e) {}
    setLogs(await window.Backend.logs({ user: opId, limit: "30" }));
  };
  useEffect(() => {
    loadLogs(); const t = setInterval(loadLogs, 6000);
    const k = (e) => e.key === "Escape" && onClose();
    window.addEventListener("keydown", k);
    return () => { clearInterval(t); window.removeEventListener("keydown", k); };
  }, [opId]);

  return (
    <div style={{ position: "fixed", inset: 0, zIndex: 110, background: "rgba(4,6,11,.9)", backdropFilter: "blur(8px)", animation: "appfade .18s ease", display: "flex", flexDirection: "column" }}>
      {/* top bar */}
      <div style={{ display: "flex", alignItems: "center", gap: 14, padding: "12px 20px", borderBottom: "1px solid var(--border)", background: "var(--bg-2)" }}>
        <span style={{ display: "inline-flex", alignItems: "center", gap: 8, padding: "5px 11px", borderRadius: 99, background: "rgba(255,92,108,.14)", border: "1px solid rgba(255,92,108,.35)", color: "var(--danger)", fontSize: 12, fontWeight: 700 }}>
          <span style={{ width: 8, height: 8, borderRadius: 99, background: "var(--danger)", animation: "streamPulse 1.1s infinite" }} /> LIVE
        </span>
        <Avatar user={op} size={34} />
        <div style={{ lineHeight: 1.2 }}>
          <div style={{ fontSize: 15, fontWeight: 700 }}>Supervision · {op.name}</div>
          <div className="mono" style={{ fontSize: 11, color: "var(--faint)" }}>écran réel en direct{dev ? ` · ${dev.tag}` : ""}</div>
        </div>
        {myDevs.length > 1 && (
          <select value={dev ? dev.udid : ""} onChange={e => setPickUdid(e.target.value)} style={{ background: "var(--surface-2)", border: "1px solid var(--border)", borderRadius: 8, padding: "7px 9px", color: "var(--text)", fontSize: 12.5 }}>
            {myDevs.map(d => <option key={d.udid} value={d.udid}>{d.tag} · {d.name}{d.status === "online" ? " ●" : ""}</option>)}
          </select>
        )}
        <button onClick={onClose} style={{ marginLeft: "auto", display: "flex", alignItems: "center", gap: 7, padding: "9px 14px", borderRadius: 9, background: "var(--surface-2)", border: "1px solid var(--border-2)", color: "var(--text)", fontSize: 13, fontWeight: 600 }}>
          {React.createElement(Icon.x, { size: 16 })} Fermer
        </button>
      </div>

      {/* corps : VRAI écran (DeviceView réelle, embedded) + dernières actions RÉELLES */}
      <div style={{ flex: 1, display: "grid", gridTemplateColumns: "1fr 320px", minHeight: 0 }}>
        <div style={{ overflow: "auto", minHeight: 0, padding: dev ? 16 : 0 }}>
          {dev
            ? <DeviceView device={dev} user={me || { role: "Owner", id: "sup" }} admin embedded onBack={onClose} />
            : <div style={{ display: "grid", placeItems: "center", height: "100%", color: "var(--faint)", textAlign: "center", gap: 10 }}>{React.createElement(Icon.phone, { size: 40 })}<div>Aucun iPhone assigné à {op.name}.<br /><span style={{ fontSize: 12 }}>Assigne-lui un téléphone dans Team pour le superviser.</span></div></div>}
        </div>
        {/* dernières actions RÉELLES (logs cloud) */}
        <div style={{ borderLeft: "1px solid var(--border)", background: "var(--bg-2)", display: "flex", flexDirection: "column", minHeight: 0 }}>
          <div style={{ display: "flex", alignItems: "center", gap: 8, padding: "13px 15px", borderBottom: "1px solid var(--border)" }}>
            {React.createElement(Icon.list, { size: 15, color: "var(--muted)" })}
            <span style={{ fontSize: 12, fontWeight: 700, letterSpacing: ".05em", textTransform: "uppercase", color: "var(--muted)" }}>Ses dernières actions</span>
            <span className="mono" style={{ marginLeft: "auto", fontSize: 11, color: "var(--accent)" }}>● live</span>
          </div>
          <div style={{ flex: 1, overflow: "auto", padding: "8px 10px" }}>
            {logs.length === 0 ? <div style={{ fontSize: 12, color: "var(--faint)", padding: "10px 4px" }}>Aucune action récente enregistrée.</div>
              : logs.map(l => (
                <div key={l.id} style={{ display: "flex", gap: 8, padding: "7px 4px", fontSize: 12, borderBottom: "1px solid var(--border)", flexWrap: "wrap", alignItems: "baseline" }}>
                  <span className="mono" style={{ fontSize: 10, color: "var(--faint)" }}>{(l.at || "").slice(11, 16)}</span>
                  <span style={{ color: "var(--muted)" }}>{l.label || (l.udid || "").slice(-5)}</span>
                  <span style={{ fontWeight: 600 }}>{l.action}</span>
                  {l.detail ? <span className="mono" style={{ fontSize: 10, color: "var(--faint)" }}>{l.detail}</span> : null}
                </div>
              ))}
          </div>
        </div>
      </div>

      {/* bulle de chat pour le guider */}
      <FloatingChat opId={opId} as="admin" z={130} />
    </div>
  );
}

Object.assign(window, { TempMsg, useMsg, AdminMessages, OperatorBell, FloatingChat, WatchOverlay });
