/* global React, Icon, Button, Badge, Avatar, Card, StatusDot, BarChart, LineChart, ProgressBar, Modal, SectionTitle, selectStyle, Segmented, PageHead, Toolbar, Table, Th, Td, RowActions, DATA */
// ============================================================
// Admin — Tasks / SOP + Analytics
// ============================================================
const { useState: useStateB } = React;

const lab = { fontSize: 12.5, fontWeight: 600, color: "var(--muted)" };
const taskTone = { done: ["green", "Faite"], todo: ["gray", "À faire"], overdue: ["red", "En retard"] };

// store des SOP — PERSISTÉ sur Cloudflare D1 (plus d'exemples fictifs, survit au refresh)
const SopStore = (function () {
  let sops = [], loaded = false; const ls = new Set(); const emit = () => ls.forEach(f => f());
  return {
    sub(cb) { ls.add(cb); return () => ls.delete(cb); },
    list() { return sops; },
    isLoaded() { return loaded; },
    async reload() { const d = await window.Backend.sops(); if (d) { sops = d; loaded = true; emit(); } return sops; },
    async add({ title, steps }) { const s = await window.Backend.createSop({ title, steps }); if (s) { sops = [s, ...sops]; emit(); } return s; },
    async remove(id) { await window.Backend.delSop(id); sops = sops.filter(s => s.id !== id); emit(); },
  };
})();
function useSops() { const [, f] = React.useReducer(x => x + 1, 0); React.useEffect(() => { const u = SopStore.sub(f); SopStore.reload(); return u; }, []); return SopStore; }

// store des tâches — PERSISTÉ sur Cloudflare D1 (basé uniquement sur tes tâches, survit au refresh)
const TaskStore = (function () {
  let tasks = [], loaded = false; const ls = new Set(); const emit = () => ls.forEach(f => f());
  return {
    sub(cb) { ls.add(cb); return () => ls.delete(cb); },
    list() { return tasks; },
    isLoaded() { return loaded; },
    async reload() { const d = await window.Backend.tasks(); if (d) { tasks = d; loaded = true; emit(); } return tasks; },
    async add(t) { const nt = await window.Backend.createTask(t); if (nt) { tasks = [nt, ...tasks]; emit(); } return nt; },
    async remove(id) { await window.Backend.delTask(id); tasks = tasks.filter(t => t.id !== id); emit(); },
  };
})();
function useTasks() { const [, f] = React.useReducer(x => x + 1, 0); React.useEffect(() => { const u = TaskStore.sub(f); TaskStore.reload(); return u; }, []); return TaskStore; }

function AdminTasks() {
  const [tab, setTab] = useStateB("missions");
  const [modal, setModal] = useStateB(null); // null | { sopMode?, preset? }
  useTasks(); useSops();   // charge les deux depuis le cloud (dispo pour le modal + compteurs)
  const closeAndRefresh = () => { setModal(null); TaskStore.reload(); SopStore.reload(); };
  return (
    <div>
      <PageHead title="Tasks / SOP" sub="tâches assignées aux opérateurs + procédures réutilisables">
        <Button variant="outline" icon="clipboard" onClick={() => setModal({ sopMode: true })}>Nouvelle SOP</Button>
        <Button variant="primary" icon="plus" onClick={() => setModal({})}>Ajouter une nouvelle tâche</Button>
      </PageHead>

      <div style={{ display: "inline-flex", background: "var(--surface-2)", border: "1px solid var(--border)", borderRadius: 10, padding: 3, gap: 2, marginBottom: 18 }}>
        {[["missions", "Missions du jour"], ["sop", "Bibliothèque SOP"]].map(([v, l]) => (
          <button key={v} onClick={() => setTab(v)} style={{ padding: "8px 16px", fontSize: 13, fontWeight: 600, borderRadius: 7, border: "none", background: tab === v ? "var(--surface-3)" : "transparent", color: tab === v ? "var(--text)" : "var(--muted)" }}>{l}</button>
        ))}
      </div>

      {tab === "missions" ? <Missions onAdd={() => setModal({})} /> : <SopLibrary onUse={(sop) => setModal({ preset: sop })} />}
      {modal && <TaskModal sopMode={modal.sopMode} preset={modal.preset} onClose={closeAndRefresh} />}
    </div>
  );
}

function Missions({ onAdd }) {
  const store = useTasks();
  const byStatus = { overdue: [], todo: [], done: [] };
  store.list().forEach(t => byStatus[t.status].push(t));
  const cols = [["overdue", "En retard", "red"], ["todo", "À faire", "gray"], ["done", "Faites", "green"]];
  return (
    <div style={{ display: "grid", gridTemplateColumns: "repeat(3,1fr)", gap: 16, alignItems: "start" }} className="kanban">
      {cols.map(([key, label, tone]) => (
        <div key={key}>
          <div style={{ display: "flex", alignItems: "center", gap: 8, marginBottom: 12, padding: "0 2px" }}>
            <span style={{ width: 8, height: 8, borderRadius: 99, background: tone === "red" ? "var(--danger)" : tone === "green" ? "var(--accent)" : "var(--faint)" }} />
            <span style={{ fontSize: 13, fontWeight: 700 }}>{label}</span>
            <span className="num" style={{ fontSize: 11, color: "var(--faint)" }}>{byStatus[key].length}</span>
          </div>
          <div style={{ display: "grid", gap: 11 }}>
            {byStatus[key].map(t => {
              const op = DATA.opById(t.assignee);
              const devLabel = t.device_tag || "—";
              return (
                <Card key={t.id} pad={15} hover>
                  <div style={{ display: "flex", justifyContent: "space-between", alignItems: "flex-start", gap: 8 }}>
                    <div style={{ fontWeight: 600, fontSize: 13.5, lineHeight: 1.35, flex: 1 }}>{t.title}</div>
                    <Badge tone={taskTone[t.status][0]}>{taskTone[t.status][1]}</Badge>
                    <button onClick={(e) => { e.stopPropagation(); store.remove(t.id); }} title="Supprimer la tâche"
                      style={{ display: "grid", placeItems: "center", width: 24, height: 24, borderRadius: 7, background: "var(--surface-2)", border: "1px solid var(--border)", color: "var(--faint)", flex: "none", cursor: "pointer" }}
                      onMouseEnter={e => { e.currentTarget.style.color = "var(--danger)"; e.currentTarget.style.borderColor = "var(--danger)"; }}
                      onMouseLeave={e => { e.currentTarget.style.color = "var(--faint)"; e.currentTarget.style.borderColor = "var(--border)"; }}>
                      {React.createElement(Icon.x, { size: 13 })}
                    </button>
                  </div>
                  <div className="mono" style={{ fontSize: 11, color: "var(--faint)", margin: "8px 0 12px", display: "flex", alignItems: "center", gap: 6 }}>
                    {React.createElement(Icon.clock, { size: 12 })}{t.due} · {devLabel}
                  </div>
                  <ProgressBar value={t.progress} total={t.total} tone={t.status === "done" ? "green" : t.status === "overdue" ? "red" : "amber"} />
                  <div style={{ display: "flex", alignItems: "center", justifyContent: "space-between", marginTop: 12 }}>
                    <div style={{ display: "flex", alignItems: "center", gap: 7 }}>{op ? <><Avatar user={op} size={22} /><span style={{ fontSize: 12, color: "var(--muted)" }}>{op.name.split(" ")[0]}</span></> : <span style={{ fontSize: 12, color: "var(--faint)" }}>—</span>}</div>
                    <span className="num" style={{ fontSize: 11.5, color: "var(--faint)" }}>{t.progress}/{t.total}{t.completedAt ? ` · ${t.completedAt}` : ""}</span>
                  </div>
                </Card>
              );
            })}
            <button onClick={() => onAdd && onAdd(key)} style={{ display: "flex", alignItems: "center", justifyContent: "center", gap: 7, padding: "11px", borderRadius: 12, background: "transparent", border: "1px dashed var(--border-2)", color: "var(--faint)", fontSize: 12.5 }}>
              {React.createElement(Icon.plus, { size: 14 })} Ajouter
            </button>
          </div>
        </div>
      ))}
    </div>
  );
}

function SopLibrary({ onUse }) {
  const store = useSops();
  const sops = store.list();
  return (
    <div style={{ display: "grid", gridTemplateColumns: "repeat(auto-fill, minmax(300px,1fr))", gap: 16 }}>
      {sops.map(s => (
        <Card key={s.id} pad={18} hover onClick={() => onUse && onUse(s)}>
          <div style={{ display: "flex", justifyContent: "space-between", alignItems: "flex-start" }}>
            <div style={{ width: 38, height: 38, borderRadius: 11, background: "var(--cyan-soft)", color: "var(--accent-2)", display: "grid", placeItems: "center" }}>{React.createElement(Icon.clipboard, { size: 19 })}</div>
            <RowActions items={[{ icon: "plus", label: "Créer une tâche", onClick: () => onUse && onUse(s) }, { icon: "copy", label: "Dupliquer" }, { icon: "x", label: "Supprimer", danger: true, onClick: () => store.remove(s.id) }]} />
          </div>
          <div style={{ fontWeight: 700, fontSize: 15, marginTop: 13 }}>{s.title}</div>
          <div className="mono" style={{ fontSize: 11, color: "var(--faint)", marginTop: 4 }}>{s.steps.length} étapes · utilisée {s.uses}×</div>
          <div style={{ display: "grid", gap: 7, marginTop: 14 }}>
            {s.steps.map((st, i) => (
              <div key={i} style={{ display: "flex", alignItems: "center", gap: 10, fontSize: 12.5, color: "var(--muted)" }}>
                <span className="num" style={{ width: 18, height: 18, borderRadius: 5, background: "var(--surface-2)", border: "1px solid var(--border)", display: "grid", placeItems: "center", fontSize: 10.5, color: "var(--faint)", flex: "none" }}>{i + 1}</span>
                {st}
              </div>
            ))}
          </div>
          <div className="mono" style={{ fontSize: 10.5, color: "var(--accent-2)", marginTop: 13, display: "flex", alignItems: "center", gap: 6 }}>{React.createElement(Icon.plus, { size: 12 })} cliquer pour créer une tâche</div>
        </Card>
      ))}
      <button onClick={() => onUse && onUse(null)} style={{ display: "grid", placeItems: "center", gap: 10, minHeight: 220, borderRadius: "var(--r-lg)", background: "transparent", border: "1px dashed var(--border-2)", color: "var(--faint)" }}>
        {React.createElement(Icon.plus, { size: 26 })}<span style={{ fontSize: 13, fontWeight: 600 }}>Nouvelle procédure</span>
      </button>
    </div>
  );
}

const DEFAULT_TASK_TYPES = [
  { label: "Warm-up", icon: "bolt" },
  { label: "Story", icon: "play" },
  { label: "Engagement", icon: "users" },
];
const PRIORITIES = [["low", "Basse"], ["mid", "Moyenne"], ["high", "Haute"]];
const WEEKDAYS = [["L", 1], ["M", 2], ["M", 3], ["J", 4], ["V", 5], ["S", 6], ["D", 0]];
const DAY_NAMES = { 0: "dim", 1: "lun", 2: "mar", 3: "mer", 4: "jeu", 5: "ven", 6: "sam" };

function TaskModal({ onClose, sopMode, preset }) {
  const fld = { width: "100%", padding: "11px 13px", background: "var(--bg-2)", border: "1px solid var(--border-2)", borderRadius: 9, color: "var(--text)", fontSize: 13.5, outline: "none" };
  const [types, setTypes] = useStateB(DEFAULT_TASK_TYPES);
  const [type, setType] = useStateB(DEFAULT_TASK_TYPES[0].label);
  const [addingType, setAddingType] = useStateB(false);
  const [newType, setNewType] = useStateB("");
  const [presetSop, setPresetSop] = useStateB(preset ? preset.id : null);
  const [title, setTitle] = useStateB(preset ? preset.title : "");
  const [steps, setSteps] = useStateB(preset ? [...preset.steps] : ["", ""]);
  const [assignees, setAssignees] = useStateB([]);
  const [devices, setDevices] = useStateB([]);
  const [recurrence, setRecurrence] = useStateB("recurring"); // "once" | "recurring"
  const [date, setDate] = useStateB("");
  const [days, setDays] = useStateB([1, 3, 5]);
  const [time, setTime] = useStateB("18:00");
  const [prio, setPrio] = useStateB("mid");
  const [note, setNote] = useStateB("");
  const [saveAsSop, setSaveAsSop] = useStateB(!!sopMode);
  const ops = DATA.realTeam().filter(o => o.role === "Opérateur" && o.status === "active");
  // iPhones RÉELS du parc (backend) — plus de devices fictifs dans le sélecteur
  const farm = useLiveDevices();
  const devList = (farm.online && farm.list) ? farm.list : [];

  const [saving, setSaving] = useStateB(false);
  const saveSop = async () => { setSaving(true); await SopStore.add({ title, steps }); onClose(); };

  const loadSop = (sop) => {
    if (presetSop === sop.id) { setPresetSop(null); return; }
    setPresetSop(sop.id); setTitle(sop.title); setSteps([...sop.steps]);
  };
  const addType = () => {
    const v = newType.trim(); if (!v) return;
    if (!types.some(t => t.label === v)) setTypes(t => [...t, { label: v, icon: "clipboard" }]);
    setType(v); setNewType(""); setAddingType(false);
  };
  const toggleDay = (d) => setDays(ds => ds.includes(d) ? ds.filter(x => x !== d) : [...ds, d]);
  const toggleAssignee = (id) => setAssignees(a => a.includes(id) ? a.filter(x => x !== id) : [...a, id]);
  const toggleDevice = (id) => setDevices(a => a.includes(id) ? a.filter(x => x !== id) : [...a, id]);
  const whoSummary = assignees.length === 0 ? "tous les opérateurs"
    : assignees.length === 1 ? DATA.opById(assignees[0]).name.split(" ")[0]
    : assignees.length + " opérateurs";
  const daysSummary = days.length === 7 ? "tous les jours"
    : days.length === 5 && [1, 2, 3, 4, 5].every(d => days.includes(d)) ? "en semaine (lun→ven)"
    : days.length ? [1, 2, 3, 4, 5, 6, 0].filter(d => days.includes(d)).map(d => DAY_NAMES[d]).join(", ")
    : "aucun jour";

  const createTask = async () => {
    setSaving(true);
    if (saveAsSop) await SopStore.add({ title, steps });
    const due = recurrence === "recurring" ? `Récurrent · ${daysSummary} ${time}` : (date ? `${date.split("-").reverse().join("/")} ${time}` : `Aujourd'hui ${time}`);
    const total = steps.filter(Boolean).length || 1;
    const devId = devices[0] || (devList[0] && devList[0].id) || null;
    const devObj = devList.find(d => d.id === devId);
    await TaskStore.add({
      title: title.trim() || "Nouvelle tâche", sop_id: presetSop || null,
      assignee: assignees[0] || (ops[0] && ops[0].id) || null,
      device_udid: devId, device_tag: devObj ? devObj.tag : null,
      due, status: "todo", progress: 0, total, note: note || null,
    });
    onClose();
  };

  return (
    <Modal title={sopMode ? "Nouvelle procédure (SOP)" : "Ajouter une nouvelle tâche"} onClose={onClose} width={600}
      footer={<><Button variant="ghost" onClick={onClose}>Annuler</Button>
        <Button variant="outline" icon="clipboard" disabled={!title.trim() || saving} onClick={saveSop}>{saving ? "…" : "Enregistrer la SOP"}</Button>
        <Button variant="primary" icon="check" disabled={!title.trim() || saving} onClick={createTask}>{saving ? "…" : (sopMode ? "Créer la procédure" : "Créer la tâche" + (saveAsSop ? " + SOP" : ""))}</Button></>}>
      <div style={{ display: "grid", gap: 18 }}>

        {/* PRESET — partir d'une SOP */}
        <div>
          <label style={lab}>Partir d'une SOP <span className="mono" style={{ color: "var(--faint)", fontWeight: 400 }}>· remplit titre + étapes automatiquement</span></label>
          <div style={{ display: "flex", flexWrap: "wrap", gap: 8, marginTop: 9 }}>
            <button onClick={() => { setPresetSop(null); setTitle(""); setSteps(["", ""]); }} style={presetChip(presetSop === null)}>
              {React.createElement(Icon.plus, { size: 14 })} Vierge
            </button>
            {SopStore.list().map(s => (
              <button key={s.id} onClick={() => loadSop(s)} style={presetChip(presetSop === s.id)}>
                {React.createElement(Icon.clipboard, { size: 14 })} {s.title}
                <span className="mono" style={{ fontSize: 10, opacity: .7 }}>· {s.steps.length} ét.</span>
              </button>
            ))}
          </div>
        </div>

        {/* TYPE — personnalisable */}
        <div>
          <label style={lab}>Type de tâche <span className="mono" style={{ color: "var(--faint)", fontWeight: 400 }}>· personnalisable</span></label>
          <div style={{ display: "flex", flexWrap: "wrap", gap: 8, marginTop: 9, alignItems: "center" }}>
            {types.map(t => {
              const on = type === t.label;
              return (
                <button key={t.label} onClick={() => setType(t.label)} style={{ display: "flex", alignItems: "center", gap: 7, padding: "8px 13px", borderRadius: 9, fontSize: 12.5, fontWeight: 600,
                  background: on ? "var(--accent-soft)" : "var(--surface-2)", border: "1px solid " + (on ? "var(--accent-line)" : "var(--border)"), color: on ? "var(--accent)" : "var(--text)" }}>
                  {React.createElement(Icon[t.icon] || Icon.clipboard, { size: 15 })}{t.label}
                </button>
              );
            })}
            {addingType
              ? <span style={{ display: "inline-flex", gap: 6 }}>
                  <input value={newType} onChange={e => setNewType(e.target.value)} onKeyDown={e => e.key === "Enter" && addType()} placeholder="Nom du type…" autoFocus
                    style={{ width: 140, padding: "8px 11px", background: "var(--bg-2)", border: "1px solid var(--accent-line)", borderRadius: 9, color: "var(--text)", fontSize: 12.5, outline: "none" }} />
                  <button onClick={addType} style={{ display: "grid", placeItems: "center", width: 34, borderRadius: 9, background: "var(--accent)", color: "#06281c", border: "none" }}>{React.createElement(Icon.check, { size: 16 })}</button>
                </span>
              : <button onClick={() => setAddingType(true)} style={{ display: "flex", alignItems: "center", gap: 6, padding: "8px 13px", borderRadius: 9, fontSize: 12.5, fontWeight: 600, background: "transparent", border: "1px dashed var(--border-2)", color: "var(--muted)" }}>
                  {React.createElement(Icon.plus, { size: 14 })} Type
                </button>}
          </div>
        </div>

        <div><label style={lab}>Titre de la tâche</label>
          <input value={title} onChange={e => setTitle(e.target.value)} placeholder="ex. Story quotidienne" style={{ ...fld, marginTop: 7 }} autoFocus /></div>

        {/* checklist */}
        <div>
          <label style={lab}>Étapes (checklist à cocher par l'opérateur)</label>
          <div style={{ display: "grid", gap: 8, marginTop: 9 }}>
            {steps.map((s, i) => (
              <div key={i} style={{ display: "flex", alignItems: "center", gap: 9 }}>
                <span className="num" style={{ width: 24, height: 24, borderRadius: 6, background: "var(--surface-2)", border: "1px solid var(--border)", display: "grid", placeItems: "center", fontSize: 11, color: "var(--faint)", flex: "none" }}>{i + 1}</span>
                <input value={s} onChange={e => setSteps(st => st.map((x, j) => j === i ? e.target.value : x))} placeholder={`Étape ${i + 1}…`} style={fld} />
                <button onClick={() => setSteps(st => st.filter((_, j) => j !== i))} style={{ background: "none", border: "none", color: "var(--faint)", display: "grid", padding: 4 }}>{React.createElement(Icon.x, { size: 16 })}</button>
              </div>
            ))}
          </div>
          <button onClick={() => setSteps(st => [...st, ""])} style={{ display: "flex", alignItems: "center", gap: 7, marginTop: 10, background: "none", border: "1px dashed var(--border-2)", borderRadius: 8, padding: "8px 12px", color: "var(--muted)", fontSize: 12.5 }}>{React.createElement(Icon.plus, { size: 14 })} Ajouter une étape</button>
        </div>

        {/* RÉCURRENCE */}
        <div style={{ padding: 15, borderRadius: 12, background: "var(--surface-2)", border: "1px solid var(--border)" }}>
          <label style={lab}>Récurrence</label>
          <div style={{ display: "flex", gap: 8, margin: "9px 0 14px" }}>
            {[["recurring", "Récurrente", "calendar"], ["once", "Ponctuelle", "bolt"]].map(([v, l, ic]) => {
              const on = recurrence === v;
              return <button key={v} onClick={() => setRecurrence(v)} style={{ flex: 1, display: "flex", alignItems: "center", justifyContent: "center", gap: 8, padding: "10px", borderRadius: 9, fontSize: 13, fontWeight: 600,
                background: on ? "var(--accent-soft)" : "var(--surface)", border: "1px solid " + (on ? "var(--accent-line)" : "var(--border)"), color: on ? "var(--accent)" : "var(--text)" }}>{React.createElement(Icon[ic], { size: 16 })}{l}</button>;
            })}
          </div>

          {recurrence === "recurring" ? (
            <div>
              <div style={{ display: "flex", alignItems: "center", justifyContent: "space-between", marginBottom: 9 }}>
                <span style={{ fontSize: 12, color: "var(--muted)" }}>Jours où la tâche revient</span>
                <div style={{ display: "flex", gap: 6 }}>
                  <button onClick={() => setDays([1, 2, 3, 4, 5, 6, 0])} style={miniBtn}>Tous</button>
                  <button onClick={() => setDays([1, 2, 3, 4, 5])} style={miniBtn}>Jours ouvrés</button>
                </div>
              </div>
              <div style={{ display: "grid", gridTemplateColumns: "repeat(7,1fr)", gap: 6 }}>
                {WEEKDAYS.map(([letter, d]) => {
                  const on = days.includes(d);
                  return <button key={d} onClick={() => toggleDay(d)} title={DAY_NAMES[d]} style={{ aspectRatio: "1", borderRadius: 9, fontSize: 13, fontWeight: 700,
                    background: on ? "var(--accent)" : "var(--surface)", color: on ? "#06281c" : "var(--muted)", border: "1px solid " + (on ? "var(--accent)" : "var(--border)") }}>{letter}</button>;
                })}
              </div>
              <div style={{ display: "flex", alignItems: "center", gap: 9, marginTop: 12 }}>
                <span style={{ fontSize: 12, color: "var(--muted)" }}>à</span>
                <input type="time" value={time} onChange={e => setTime(e.target.value)} style={{ ...fld, width: 130 }} />
                <span className="mono" style={{ fontSize: 11, color: "var(--accent)" }}>↻ {daysSummary}</span>
              </div>
            </div>
          ) : (
            <div><span style={{ fontSize: 12, color: "var(--muted)" }}>Date d'échéance</span>
              <input type="date" value={date} onChange={e => setDate(e.target.value)} style={{ ...fld, marginTop: 6 }} /></div>
          )}
        </div>

        {/* affectation — multi-sélection */}
        <div>
          <label style={lab}>Assigner à <span className="mono" style={{ color: "var(--faint)", fontWeight: 400 }}>· {assignees.length ? assignees.length + " sélectionné(s)" : "tous les opérateurs"}</span></label>
          <div style={{ display: "grid", gridTemplateColumns: "repeat(2,1fr)", gap: 8, marginTop: 9 }}>
            {ops.map(o => {
              const on = assignees.includes(o.id);
              return (
                <button key={o.id} onClick={() => toggleAssignee(o.id)} style={{ display: "flex", alignItems: "center", gap: 9, padding: "9px 11px", borderRadius: 10, textAlign: "left",
                  background: on ? "var(--accent-soft)" : "var(--surface-2)", border: "1px solid " + (on ? "var(--accent-line)" : "var(--border)") }}>
                  <Avatar user={o} size={26} /><span style={{ fontSize: 12.5, fontWeight: 600, flex: 1 }}>{o.name}</span>
                  {on && <span style={{ color: "var(--accent)", display: "grid" }}>{React.createElement(Icon.check, { size: 15 })}</span>}
                </button>
              );
            })}
          </div>
        </div>

        <div>
          <label style={lab}>iPhones <span className="mono" style={{ color: "var(--faint)", fontWeight: 400 }}>· {devices.length ? devices.length + " sélectionné(s)" : "tous les devices assignés"}</span></label>
          {devList.length === 0
            ? <div style={{ marginTop: 9, padding: "12px 14px", borderRadius: 10, background: "var(--surface-2)", border: "1px dashed var(--border-2)", color: "var(--faint)", fontSize: 12.5 }}>
                {farm.online ? "Aucun iPhone détecté dans le parc — branche/déverrouille un iPhone." : "Parc non synchronisé — la tâche sera créée sans iPhone ciblé."}
              </div>
            : <div style={{ display: "grid", gridTemplateColumns: "repeat(3,1fr)", gap: 8, marginTop: 9, maxHeight: 168, overflow: "auto", paddingRight: 2 }}>
                {devList.map(d => {
                  const on = devices.includes(d.id);
                  return (
                    <button key={d.id} onClick={() => toggleDevice(d.id)} title={d.udid} style={{ display: "flex", alignItems: "center", gap: 8, padding: "8px 10px", borderRadius: 9, textAlign: "left",
                      background: on ? "var(--accent-soft)" : "var(--surface-2)", border: "1px solid " + (on ? "var(--accent-line)" : "var(--border)") }}>
                      <StatusDot status={d.status} /><span style={{ fontSize: 12, fontWeight: 600, flex: 1, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }}>{d.tag}</span>
                      {on && <span style={{ color: "var(--accent)", display: "grid", flex: "none" }}>{React.createElement(Icon.check, { size: 14 })}</span>}
                    </button>
                  );
                })}
              </div>}
        </div>

        <div><label style={lab}>Priorité</label>
          <div style={{ display: "flex", gap: 7, marginTop: 7 }}>
            {PRIORITIES.map(([v, l]) => {
              const on = prio === v;
              const c = v === "high" ? "var(--danger)" : v === "mid" ? "var(--busy)" : "var(--faint)";
              return <button key={v} onClick={() => setPrio(v)} style={{ flex: 1, padding: "10px", borderRadius: 9, fontSize: 12.5, fontWeight: 600,
                background: on ? "color-mix(in srgb," + c + " 15%, transparent)" : "var(--surface-2)", border: "1px solid " + (on ? c : "var(--border)"), color: on ? c : "var(--text)" }}>{l}</button>;
            })}
          </div></div>

        <div><label style={lab}>Note / consigne <span className="mono" style={{ color: "var(--faint)", fontWeight: 400 }}>· optionnel</span></label>
          <textarea value={note} onChange={e => setNote(e.target.value)} rows={2} placeholder="Précisions pour l'opérateur (ton, do/don't, lien…)" style={{ ...fld, marginTop: 7, resize: "vertical", fontFamily: "inherit" }} /></div>

        {/* enregistrer comme SOP */}
        <label style={{ display: "flex", alignItems: "center", gap: 12, padding: "13px 15px", borderRadius: 12, cursor: "pointer",
          background: saveAsSop ? "var(--cyan-soft)" : "var(--surface-2)", border: "1px solid " + (saveAsSop ? "rgba(34,211,238,.32)" : "var(--border)") }}>
          <span style={{ display: "grid", placeItems: "center", width: 34, height: 34, borderRadius: 9, background: saveAsSop ? "var(--accent-2)" : "var(--surface-3)", color: saveAsSop ? "#06281c" : "var(--muted)", flex: "none" }}>{React.createElement(Icon.clipboard, { size: 17 })}</span>
          <div style={{ flex: 1 }}>
            <div style={{ fontSize: 13.5, fontWeight: 600 }}>Enregistrer aussi comme SOP</div>
            <div style={{ fontSize: 11.5, color: "var(--faint)" }}>Réutilisable comme preset : la prochaine fois, 1 clic remplit tout, reste à assigner.</div>
          </div>
          <Toggle on={saveAsSop} onClick={() => setSaveAsSop(s => !s)} />
        </label>

        {recurrence === "recurring" && (
          <div style={{ display: "flex", alignItems: "center", gap: 9, padding: "10px 13px", borderRadius: 10, background: "var(--accent-soft)", border: "1px solid var(--accent-line)", fontSize: 12.5, color: "var(--accent)" }}>
            {React.createElement(Icon.calendar, { size: 16 })} Revient {daysSummary} à {time} · {whoSummary}.
          </div>
        )}
      </div>
    </Modal>
  );
}
const presetChip = (on) => ({ display: "flex", alignItems: "center", gap: 6, padding: "8px 12px", borderRadius: 9, fontSize: 12, fontWeight: 600,
  background: on ? "var(--accent-soft)" : "var(--surface-2)", border: "1px solid " + (on ? "var(--accent-line)" : "var(--border)"), color: on ? "var(--accent)" : "var(--text)" });
const miniBtn = { padding: "4px 10px", fontSize: 11, fontWeight: 600, borderRadius: 7, background: "var(--surface)", border: "1px solid var(--border)", color: "var(--muted)" };

function SopModal({ onClose }) {
  const [steps, setSteps] = useStateB(["", ""]);
  const field = { width: "100%", padding: "11px 13px", background: "var(--bg-2)", border: "1px solid var(--border-2)", borderRadius: 9, color: "var(--text)", fontSize: 13.5, outline: "none" };
  return (
    <Modal title="Nouvelle SOP" onClose={onClose} width={520}
      footer={<><Button variant="ghost" onClick={onClose}>Annuler</Button><Button variant="primary" icon="check" onClick={onClose}>Enregistrer la SOP</Button></>}>
      <div style={{ display: "grid", gap: 16 }}>
        <div><label style={{ fontSize: 12.5, fontWeight: 600, color: "var(--muted)" }}>Titre</label>
          <input placeholder="ex. Warm-up nouveau compte" style={{ ...field, marginTop: 7 }} autoFocus /></div>
        <div>
          <label style={{ fontSize: 12.5, fontWeight: 600, color: "var(--muted)" }}>Étapes (checklist ordonnée)</label>
          <div style={{ display: "grid", gap: 8, marginTop: 9 }}>
            {steps.map((s, i) => (
              <div key={i} style={{ display: "flex", alignItems: "center", gap: 9 }}>
                <span className="num" style={{ width: 24, height: 24, borderRadius: 6, background: "var(--surface-2)", border: "1px solid var(--border)", display: "grid", placeItems: "center", fontSize: 11, color: "var(--faint)", flex: "none" }}>{i + 1}</span>
                <input value={s} onChange={e => setSteps(st => st.map((x, j) => j === i ? e.target.value : x))} placeholder={`Étape ${i + 1}…`} style={field} />
                <button onClick={() => setSteps(st => st.filter((_, j) => j !== i))} style={{ background: "none", border: "none", color: "var(--faint)", display: "grid", padding: 4 }}>{React.createElement(Icon.x, { size: 16 })}</button>
              </div>
            ))}
          </div>
          <button onClick={() => setSteps(st => [...st, ""])} style={{ display: "flex", alignItems: "center", gap: 7, marginTop: 10, background: "none", border: "1px dashed var(--border-2)", borderRadius: 8, padding: "8px 12px", color: "var(--muted)", fontSize: 12.5 }}>{React.createElement(Icon.plus, { size: 14 })} Ajouter une étape</button>
        </div>
      </div>
    </Modal>
  );
}

// Construit des séries RÉELLES sur N jours : minutes connectées/jour (uptime du parc)
// + tâches assignées/faites par jour (depuis les vraies tâches D1).
function useRealDays(rangeDays) {
  const { useState, useEffect } = React;
  const [uptime, setUptime] = useState([]);
  const taskStore = useTasks();
  useEffect(() => { window.Backend.uptimeAll(rangeDays).then(d => { if (d) setUptime(d); }); }, [rangeDays]);
  const tasks = taskStore.list();
  const days = [];
  for (let i = rangeDays - 1; i >= 0; i--) {
    const dt = new Date(); dt.setDate(dt.getDate() - i);
    const iso = `${dt.getFullYear()}-${String(dt.getMonth() + 1).padStart(2, "0")}-${String(dt.getDate()).padStart(2, "0")}`;
    const idx = rangeDays - 1 - i;                 // position dans series (plus ancien en premier)
    let sec = 0; uptime.forEach(dev => { sec += (dev.series && dev.series[idx]) || 0; });
    const dayTasks = tasks.filter(t => (t.created || "").slice(0, 10) === iso);
    days.push({
      label: `${String(dt.getDate()).padStart(2, "0")}/${String(dt.getMonth() + 1).padStart(2, "0")}`,
      active: Math.round(sec / 60),
      tasksAssigned: dayTasks.length,
      tasksDone: dayTasks.filter(t => t.status === "done").length,
    });
  }
  return days;
}

// ---------- ANALYTICS ----------
function AdminAnalytics({ onWatch, onMessage }) {
  const [range, setRange] = useStateB("14j");
  const [selected, setSelected] = useStateB(null);
  const rangeDays = { "7j": 7, "14j": 14, "30j": 30 }[range] || 14;
  const days = useRealDays(rangeDays);
  const hasData = days.some(d => d.active > 0 || d.tasksAssigned > 0);

  if (selected) return <OperatorDetail id={selected} onBack={() => setSelected(null)} onWatch={onWatch} onMessage={onMessage} />;

  return (
    <div>
      <PageHead title="Analytics" sub="usage réel & complétion des tâches — clique une personne pour son suivi détaillé">
        <Segmented value={range} onChange={setRange} options={[["7j", "7 j"], ["14j", "14 j"], ["30j", "30 j"]]} />
        <Button variant="outline" icon="download">Export CSV</Button>
      </PageHead>

      {!hasData && <div style={{ marginBottom: 16, padding: "11px 14px", borderRadius: 10, background: "var(--surface-2)", border: "1px dashed var(--border-2)", color: "var(--faint)", fontSize: 12.5 }}>
        Les courbes se rempliront au fil de l'activité réelle (temps de connexion des iPhones + tâches créées/faites). Rien encore sur cette période.
      </div>}

      <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 16, marginBottom: 16 }} className="ov-grid">
        <Card pad={20}>
          <ChartHead title="Activité (minutes/jour)" legend={[["var(--accent)", "minutes connectées"]]} />
          <LineChart data={days} dkey="active" color="var(--accent)" h={196} />
          <Axis days={days} />
        </Card>
        <Card pad={20}>
          <ChartHead title="Tâches faites vs assignées" legend={[["var(--accent)", "faites"], ["var(--accent-2)", "assignées"]]} />
          <BarChart data={days} keys={["tasksDone", "tasksAssigned"]} colors={["var(--accent)", "var(--accent-2)"]} h={196} />
          <Axis days={days} />
        </Card>
      </div>

      {/* connectivité RÉELLE des iPhones */}
      <Connectivity />

      {/* récap par opérateur — RÉEL : uniquement l'équipe inscrite (stats à 0 tant que le suivi d'activité n'enregistre pas) */}
      <Table head={<><Th>Opérateur</Th><Th>Engagement</Th><Th>Tâches du jour</Th><Th>% fait</Th><Th>Temps d'usage</Th><Th>Dernier login</Th><Th></Th></>}>
        {DATA.realTeam().filter(o => o.role === "Opérateur").map(op => {
          const u = DATA.USAGE.find(x => x.id === op.id) || { id: op.id, today: { done: 0, assigned: 0 }, minutes: 0, lastLogin: "—" };
          const pct = u.today.assigned ? Math.round((u.today.done / u.today.assigned) * 100) : 0;
          const eng = DATA.USAGE.some(x => x.id === op.id) ? DATA.opStats(op.id).engagement : 0;
          return (
            <tr key={u.id} onClick={() => setSelected(u.id)} style={{ cursor: "pointer" }}
              onMouseEnter={e => e.currentTarget.style.background = "var(--surface-2)"} onMouseLeave={e => e.currentTarget.style.background = "transparent"}>
              <Td><div style={{ display: "flex", alignItems: "center", gap: 11 }}><Avatar user={op} size={32} /><div><div style={{ fontWeight: 600 }}>{op.name}</div><div className="mono" style={{ fontSize: 10.5, color: "var(--faint)" }}>{op.email}</div></div></div></Td>
              <Td><span className="num" style={{ fontWeight: 700, fontSize: 14, color: engColor(eng) }}>{eng}%</span></Td>
              <Td><span className="num" style={{ fontWeight: 700 }}>{u.today.done}</span><span style={{ color: "var(--faint)" }}>/{u.today.assigned}</span></Td>
              <Td><div style={{ display: "flex", alignItems: "center", gap: 10, minWidth: 130 }}><div style={{ flex: 1 }}><ProgressBar value={u.today.done} total={u.today.assigned} tone={pct >= 80 ? "green" : pct >= 40 ? "amber" : "red"} /></div><span className="num" style={{ fontSize: 12, color: pct >= 80 ? "var(--accent)" : pct === 0 ? "var(--danger)" : "var(--busy)", width: 34 }}>{pct}%</span></div></Td>
              <Td><span className="num">{Math.floor(u.minutes / 60)}h{String(u.minutes % 60).padStart(2, "0")}</span></Td>
              <Td><span className="mono" style={{ fontSize: 12, color: u.minutes === 0 ? "var(--danger)" : "var(--muted)" }}>{u.lastLogin}</span></Td>
              <Td><span style={{ display: "grid", placeItems: "center", color: "var(--faint)" }}>{React.createElement(Icon.chevRight, { size: 17 })}</span></Td>
            </tr>
          );
        })}
      </Table>
    </div>
  );
}

const engColor = (e) => e >= 70 ? "var(--accent)" : e >= 40 ? "var(--busy)" : "var(--danger)";

function OperatorDetail({ id, onBack, onWatch, onMessage }) {
  const op = DATA.opById(id);
  const st = DATA.opStats(id);
  useTasks();
  const tasks = TaskStore.list().filter(t => t.assignee === id);
  const overdue = tasks.filter(t => t.status === "overdue").length;
  const devices = DATA.DEVICES.filter(d => d.operator && d.operator.id === id);
  const logs = DATA.LOGS.filter(l => l.who === id);
  const ec = engColor(st.engagement);

  return (
    <div>
      <button onClick={onBack} style={{ display: "flex", alignItems: "center", gap: 7, background: "var(--surface-2)", border: "1px solid var(--border)", borderRadius: 9, padding: "8px 13px", color: "var(--text)", fontSize: 13, fontWeight: 600, marginBottom: 18 }}>
        {React.createElement(Icon.back, { size: 17 })} Analytics
      </button>

      {/* en-tête personne */}
      <div style={{ display: "flex", alignItems: "center", gap: 16, flexWrap: "wrap", marginBottom: 22 }}>
        <Avatar user={op} size={56} />
        <div style={{ flex: 1, minWidth: 180 }}>
          <div style={{ display: "flex", alignItems: "center", gap: 10 }}>
            <h1 style={{ margin: 0, fontSize: 23, fontWeight: 700 }}>{op.name}</h1>
            <Badge tone={op.role === "Admin" ? "green" : op.role === "Manager" ? "cyan" : "amber"}>{op.role}</Badge>
          </div>
          <div className="mono" style={{ fontSize: 12, color: "var(--faint)", marginTop: 4 }}>{op.email} · suivi sur {st.totalDays} jours</div>
        </div>
        <div style={{ display: "flex", gap: 8 }}>
          {devices.length > 0 && <Button variant="outline" icon="eye" onClick={() => onWatch && onWatch(id)}>Voir l'écran</Button>}
          <Button variant="outline" icon="send" onClick={() => onMessage && onMessage(id)}>Message</Button>
          <WhatsAppBtn user={op} variant="icon" />
          <TelegramBtn user={op} variant="icon" />
        </div>
      </div>

      {/* engagement hero + KPIs */}
      <div style={{ display: "grid", gridTemplateColumns: "260px 1fr", gap: 16, marginBottom: 16 }} className="ov-grid">
        <Card pad={22}>
          <div style={{ fontSize: 11.5, fontWeight: 700, letterSpacing: ".05em", textTransform: "uppercase", color: "var(--muted)", marginBottom: 14 }}>Taux d'engagement</div>
          <div style={{ display: "grid", placeItems: "center", gap: 12 }}>
            <Gauge value={st.engagement} color={ec} />
            <Badge tone={st.engagement >= 70 ? "green" : st.engagement >= 40 ? "amber" : "red"}>
              {st.engagement >= 70 ? "Très engagé" : st.engagement >= 40 ? "À surveiller" : "Décrochage"}
            </Badge>
          </div>
        </Card>

        <div style={{ display: "grid", gridTemplateColumns: "repeat(3,1fr)", gap: 12, alignContent: "start" }} className="kpi-grid">
          <MiniStat icon="check"   tone="green" label="Complétion tâches" value={st.completion + "%"} sub={`${st.totalDone}/${st.totalAssigned} étapes`} />
          <MiniStat icon="clock"   tone="cyan"  label="Temps moyen / jour" value={`${Math.floor(st.avgMin / 60)}h${String(st.avgMin % 60).padStart(2, "0")}`} sub={`${st.totalMin} min cumulées`} />
          <MiniStat icon="bolt"    tone="green" label="Actions totales" value={st.actions.toLocaleString("fr")} sub="taps, swipes, saisies" />
          <MiniStat icon="calendar" tone={st.activeDays >= st.totalDays * 0.7 ? "green" : "amber"} label="Jours actifs" value={`${st.activeDays}/${st.totalDays}`} sub="régularité" />
          <MiniStat icon="play"    tone={st.streak >= 3 ? "green" : "amber"} label="Série en cours" value={`${st.streak} j`} sub="jours consécutifs" />
          <MiniStat icon="x"       tone={overdue ? "red" : "green"} label="Tâches en retard" value={overdue} sub={overdue ? "à relancer" : "à jour"} />
        </div>
      </div>

      {/* courbes perso */}
      <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 16, marginBottom: 16 }} className="ov-grid">
        <Card pad={20}>
          <ChartHead title="Engagement / jour" legend={[[ec, "engagement %"]]} />
          <LineChart data={st.series} dkey="engagement" color={ec} h={186} />
          <Axis />
        </Card>
        <Card pad={20}>
          <ChartHead title="Tâches faites vs assignées" legend={[["var(--accent)", "faites"], ["var(--accent-2)", "assignées"]]} />
          <BarChart data={st.series} keys={["tasksDone", "tasksAssigned"]} colors={["var(--accent)", "var(--accent-2)"]} h={186} />
          <Axis />
        </Card>
      </div>

      {/* tâches + devices + actions */}
      <div style={{ display: "grid", gridTemplateColumns: "1.3fr 1fr", gap: 16 }} className="ov-grid">
        <Card pad={20}>
          <div style={{ fontSize: 14, fontWeight: 700, marginBottom: 14 }}>Ses tâches</div>
          <div style={{ display: "grid", gap: 9 }}>
            {tasks.length === 0 && <div style={{ color: "var(--faint)", fontSize: 13 }}>Aucune tâche assignée.</div>}
            {tasks.map(t => (
              <div key={t.id} style={{ display: "flex", alignItems: "center", gap: 11, padding: "10px 12px", borderRadius: 10, background: "var(--surface-2)", border: "1px solid var(--border)" }}>
                <span style={{ width: 8, height: 8, borderRadius: 99, flex: "none", background: t.status === "done" ? "var(--accent)" : t.status === "overdue" ? "var(--danger)" : "var(--faint)" }} />
                <div style={{ flex: 1, minWidth: 0 }}>
                  <div style={{ fontSize: 13, fontWeight: 600 }}>{t.title}</div>
                  <div className="mono" style={{ fontSize: 10.5, color: "var(--faint)" }}>{t.due} · {DATA.devById(t.device)?.tag || "—"}</div>
                </div>
                <Badge tone={taskTone[t.status][0]}>{taskTone[t.status][1]}</Badge>
                <span className="num" style={{ fontSize: 11.5, color: "var(--faint)", width: 32, textAlign: "right" }}>{t.progress}/{t.total}</span>
              </div>
            ))}
          </div>
        </Card>

        <div style={{ display: "grid", gap: 16, alignContent: "start" }}>
          <Card pad={20}>
            <div style={{ fontSize: 14, fontWeight: 700, marginBottom: 14 }}>iPhones pilotés <span className="num" style={{ color: "var(--faint)", fontWeight: 400 }}>· {devices.length}</span></div>
            <div style={{ display: "grid", gap: 8 }}>
              {devices.length === 0 && <div style={{ color: "var(--faint)", fontSize: 13 }}>Aucun device assigné.</div>}
              {devices.map(d => (
                <div key={d.id} style={{ display: "flex", alignItems: "center", gap: 10 }}>
                  <StatusDot status={d.status} />
                  <span style={{ fontSize: 13, fontWeight: 600, flex: 1 }}>{d.tag}</span>
                  <span className="mono" style={{ fontSize: 11, color: "var(--faint)" }}>{d.model}</span>
                </div>
              ))}
            </div>
          </Card>
          <Card pad={20}>
            <div style={{ fontSize: 14, fontWeight: 700, marginBottom: 14 }}>Actions récentes</div>
            <div style={{ display: "grid", gap: 0 }}>
              {logs.length === 0 && <div style={{ color: "var(--faint)", fontSize: 13 }}>Aucune action récente.</div>}
              {logs.map((l, i) => (
                <div key={l.id} style={{ display: "flex", alignItems: "center", gap: 10, padding: "8px 0", borderTop: i ? "1px solid var(--border)" : "none" }}>
                  <span className="num" style={{ fontSize: 10.5, color: "var(--faint)", flex: "none" }}>{l.at}</span>
                  <span style={{ fontSize: 12.5, fontWeight: 600, flex: 1 }}>{l.action}</span>
                  <span className="mono" style={{ fontSize: 10.5, color: "var(--faint)" }}>{l.meta}</span>
                </div>
              ))}
            </div>
          </Card>
        </div>
      </div>
    </div>
  );
}

function Gauge({ value, color }) {
  const r = 52, c = 2 * Math.PI * r;
  return (
    <div style={{ position: "relative", width: 132, height: 132 }}>
      <svg width="132" height="132" viewBox="0 0 132 132">
        <circle cx="66" cy="66" r={r} fill="none" stroke="var(--surface-3)" strokeWidth="11" />
        <circle cx="66" cy="66" r={r} fill="none" stroke={color} strokeWidth="11" strokeLinecap="round"
          strokeDasharray={c} strokeDashoffset={c * (1 - value / 100)} transform="rotate(-90 66 66)" style={{ transition: "stroke-dashoffset .6s ease" }} />
      </svg>
      <div style={{ position: "absolute", inset: 0, display: "grid", placeItems: "center" }}>
        <div className="num" style={{ fontSize: 30, fontWeight: 700, color, lineHeight: 1 }}>{value}<span style={{ fontSize: 15 }}>%</span></div>
      </div>
    </div>
  );
}

function MiniStat({ icon, tone, label, value, sub }) {
  const c = { green: "var(--accent)", cyan: "var(--accent-2)", amber: "var(--busy)", red: "var(--danger)" }[tone];
  return (
    <Card pad={16}>
      <div style={{ display: "flex", alignItems: "center", gap: 8, marginBottom: 10 }}>
        <span style={{ width: 30, height: 30, borderRadius: 9, background: "color-mix(in srgb," + c + " 14%, transparent)", color: c, display: "grid", placeItems: "center", flex: "none" }}>{React.createElement(Icon[icon], { size: 16 })}</span>
        <span style={{ fontSize: 11.5, color: "var(--muted)", fontWeight: 600, lineHeight: 1.2 }}>{label}</span>
      </div>
      <div className="num" style={{ fontSize: 23, fontWeight: 700, letterSpacing: "-.01em" }}>{value}</div>
      <div className="mono" style={{ fontSize: 10.5, color: "var(--faint)", marginTop: 2 }}>{sub}</div>
    </Card>
  );
}
function ChartHead({ title, legend }) {
  return (
    <div style={{ display: "flex", justifyContent: "space-between", alignItems: "center", marginBottom: 16 }}>
      <div style={{ fontSize: 14, fontWeight: 700 }}>{title}</div>
      <div style={{ display: "flex", gap: 13, fontSize: 11.5 }}>
        {legend.map(([c, l]) => <span key={l} style={{ display: "inline-flex", alignItems: "center", gap: 6, color: "var(--muted)" }}><span style={{ width: 9, height: 9, borderRadius: 3, background: c }} />{l}</span>)}
      </div>
    </div>
  );
}
function Axis({ days }) {
  const d = days || DATA.days;
  return (
    <div style={{ display: "flex", justifyContent: "space-between", marginTop: 8 }}>
      {d.filter((_, i) => i % 3 === 0).map((x, i) => <span key={i} className="mono" style={{ fontSize: 9.5, color: "var(--faint)" }}>{x.label}</span>)}
    </div>
  );
}

// ============================================================
// Connectivité des iPhones (uptime réel) — combien de temps connecté/jour + plage horaire de fiabilité
// ============================================================
function fmtUp(s) {
  s = Math.round(s || 0);
  const h = Math.floor(s / 3600), m = Math.floor((s % 3600) / 60);
  if (h) return `${h}h${String(m).padStart(2, "0")}`;
  if (m) return `${m} min`;
  return s > 0 ? `${s}s` : "—";
}
const shortDay = (iso) => { const p = iso.split("-"); return `${p[2]}/${p[1]}`; };

function Connectivity() {
  const { useState, useEffect } = React;
  const [days, setDays] = useState(7);
  const [list, setList] = useState(null);   // null = chargement, [] = vide
  const [online, setOnline] = useState(false);
  const [open, setOpen] = useState(null);   // udid déplié

  const load = async () => {
    const d = await window.Backend.uptimeAll(days);
    if (d === null) { setOnline(false); setList([]); return; }
    setOnline(true); setList(d);
  };
  useEffect(() => { load(); const id = setInterval(load, 8000); return () => clearInterval(id); }, [days]);

  return (
    <Card pad={20} style={{ marginBottom: 16 }}>
      <div style={{ display: "flex", alignItems: "center", justifyContent: "space-between", flexWrap: "wrap", gap: 12, marginBottom: 14 }}>
        <div>
          <div style={{ display: "flex", alignItems: "center", gap: 9 }}>
            {React.createElement(Icon.bolt, { size: 17, color: "var(--accent)" })}
            <div style={{ fontSize: 14.5, fontWeight: 700 }}>Connectivité des iPhones</div>
            <Badge tone={online ? "green" : "amber"}>{online ? "● réel" : "hors-ligne"}</Badge>
          </div>
          <div className="mono" style={{ fontSize: 11, color: "var(--faint)", marginTop: 4 }}>temps de connexion par jour + plage horaire de fiabilité · mesuré toutes les 4 s</div>
        </div>
        <Segmented value={String(days)} onChange={(v) => setDays(+v)} options={[["7", "7 j"], ["14", "14 j"], ["30", "30 j"]]} />
      </div>

      {list === null
        ? <div style={{ color: "var(--faint)", fontSize: 13, padding: "20px 0", textAlign: "center" }}>Chargement…</div>
        : !online
          ? <div style={{ color: "var(--faint)", fontSize: 13, padding: "20px 0", textAlign: "center" }}>Backend non synchronisé — l'historique de connectivité apparaîtra une fois le parc relié.</div>
          : list.length === 0
            ? <div style={{ color: "var(--faint)", fontSize: 13, padding: "20px 0", textAlign: "center" }}>Aucun iPhone enregistré pour l'instant.</div>
            : <div style={{ display: "grid", gap: 8 }}>
                {list.map(d => <UptimeRow key={d.udid} d={d} days={days} open={open === d.udid} onToggle={() => setOpen(o => o === d.udid ? null : d.udid)} />)}
              </div>}
    </Card>
  );
}

function UptimeRow({ d, days, open, onToggle }) {
  const { useState, useEffect } = React;
  const [detail, setDetail] = useState(null);
  useEffect(() => {
    if (!open) return;
    let on = true;
    window.Backend.uptime(d.udid, days).then(h => { if (on) setDetail(h || []); });
    return () => { on = false; };
  }, [open, days, d.udid]);

  const maxSeries = Math.max(1, ...(d.series || [0]));
  return (
    <div style={{ border: "1px solid var(--border)", borderRadius: 12, background: "var(--surface-2)", overflow: "hidden" }}>
      <button onClick={onToggle} style={{ width: "100%", display: "flex", alignItems: "center", gap: 12, padding: "11px 13px", background: "none", border: "none", cursor: "pointer", textAlign: "left" }}>
        <StatusDot status={d.status} />
        <div style={{ minWidth: 130, flex: "0 0 auto" }}>
          <div style={{ fontSize: 13.5, fontWeight: 600 }}>{d.label || "iPhone"}</div>
          <div className="mono" style={{ fontSize: 10, color: "var(--faint)" }}>{d.status === "online" ? "en ligne" : "hors-ligne"}</div>
        </div>
        {/* mini barres des N derniers jours */}
        <div style={{ flex: 1, display: "flex", alignItems: "flex-end", gap: 2, height: 30 }}>
          {(d.series || []).map((s, i) => (
            <div key={i} title={`${fmtUp(s)}`} style={{ flex: 1, height: `${Math.max(3, (s / maxSeries) * 100)}%`, background: i === d.series.length - 1 ? "var(--accent)" : "var(--accent-soft)", borderRadius: 2, minWidth: 3 }} />
          ))}
        </div>
        <div style={{ textAlign: "right", minWidth: 90, flex: "0 0 auto" }}>
          <div style={{ fontSize: 13.5, fontWeight: 700, color: "var(--accent)" }}>{fmtUp(d.today_sec)}</div>
          <div className="mono" style={{ fontSize: 10, color: "var(--faint)" }}>aujourd'hui · moy {fmtUp(d.avg_sec)}/j</div>
        </div>
        <span style={{ display: "grid", color: "var(--faint)", transform: open ? "rotate(180deg)" : "none", transition: "transform .16s" }}>{React.createElement(Icon.chevDown, { size: 16 })}</span>
      </button>

      {open && (
        <div style={{ padding: "4px 14px 16px", borderTop: "1px solid var(--border)" }}>
          {detail === null
            ? <div style={{ color: "var(--faint)", fontSize: 12.5, padding: "14px 0" }}>Chargement…</div>
            : <UptimeDetail detail={detail} />}
        </div>
      )}
    </div>
  );
}

function UptimeDetail({ detail }) {
  const today = detail[detail.length - 1] || { hours: [], first_seen: null, last_seen: null };
  const maxDay = Math.max(1, ...detail.map(x => x.online_sec));
  const maxHour = Math.max(1, ...(today.hours || [0]));
  // plage de fiabilité : 1ère et dernière heure avec activité aujourd'hui
  const activeHours = (today.hours || []).map((s, h) => (s > 30 ? h : -1)).filter(h => h >= 0);
  const range = activeHours.length ? `${String(activeHours[0]).padStart(2, "0")}h → ${String(activeHours[activeHours.length - 1]).padStart(2, "0")}h` : "—";
  const coverage = activeHours.length;

  return (
    <div style={{ display: "grid", gap: 18, marginTop: 12 }}>
      {/* barres par jour */}
      <div>
        <div style={{ fontSize: 12, fontWeight: 600, color: "var(--muted)", marginBottom: 8 }}>Temps connecté par jour</div>
        <div style={{ display: "flex", alignItems: "flex-end", gap: 6, height: 90 }}>
          {detail.map((x, i) => (
            <div key={i} style={{ flex: 1, display: "grid", gap: 4, justifyItems: "center" }} title={`${shortDay(x.day)} : ${fmtUp(x.online_sec)}`}>
              <div style={{ width: "100%", display: "flex", alignItems: "flex-end", height: 64 }}>
                <div style={{ width: "100%", height: `${Math.max(3, (x.online_sec / maxDay) * 100)}%`, background: i === detail.length - 1 ? "var(--accent)" : "var(--surface-3)", border: "1px solid " + (i === detail.length - 1 ? "var(--accent)" : "var(--border-2)"), borderRadius: "4px 4px 0 0" }} />
              </div>
              <span className="mono" style={{ fontSize: 8.5, color: "var(--faint)" }}>{shortDay(x.day).slice(0, 5)}</span>
            </div>
          ))}
        </div>
      </div>

      {/* plage horaire de fiabilité (aujourd'hui) */}
      <div>
        <div style={{ display: "flex", alignItems: "center", justifyContent: "space-between", marginBottom: 8 }}>
          <span style={{ fontSize: 12, fontWeight: 600, color: "var(--muted)" }}>Plage de fiabilité aujourd'hui</span>
          <span className="mono" style={{ fontSize: 11, color: "var(--accent)" }}>{range} · {coverage}h couvertes</span>
        </div>
        <div style={{ display: "grid", gridTemplateColumns: "repeat(24, 1fr)", gap: 2 }}>
          {Array.from({ length: 24 }, (_, h) => {
            const s = (today.hours || [])[h] || 0;
            const op = Math.min(1, s / 1800);  // 30 min = pleine intensité
            return <div key={h} title={`${String(h).padStart(2, "0")}h : ${fmtUp(s)}`}
              style={{ height: 26, borderRadius: 4, background: s > 0 ? `color-mix(in srgb, var(--accent) ${Math.round(20 + op * 80)}%, var(--surface-3))` : "var(--surface-3)", border: "1px solid var(--border)" }} />;
          })}
        </div>
        <div style={{ display: "flex", justifyContent: "space-between", marginTop: 5 }}>
          {["00h", "06h", "12h", "18h", "23h"].map(l => <span key={l} className="mono" style={{ fontSize: 8.5, color: "var(--faint)" }}>{l}</span>)}
        </div>
      </div>
    </div>
  );
}

Object.assign(window, { AdminTasks, Missions, SopLibrary, SopModal, TaskModal, AdminAnalytics, Connectivity });
