// ============================================================
// Polycall — espace admin d'une opération :
//   suivi & stats · fiches · éditeur de codes conclusion
// ============================================================

const CODE_SWATCHES = ["#1f8a5b", "#36a572", "#b9760f", "#d7a13d", "#2a6fdb", "#5b8def", "#5b54d6", "#7a74e0", "#c0392b", "#dd7368", "#b0357a", "#9a948f"];
const NEEDS_OPTS = [
  { key: "", label: "Aucun champ" },
  { key: "rappel", label: "Date & heure (rappel / RDV)" },
  { key: "devis", label: "Référence (devis / étude / offre)" },
  { key: "sav", label: "Description (SAV)" },
];

/* ---------- modale d'édition d'un code conclusion ---------- */
function CodeEditorModal({ code, allCodes, onClose, onSave }) {
  const editing = !!code;
  const [f, setF] = useState(code || { label: "", sub: "", group: "", tone: "good", color: "#1f8a5b", flux: ["entrant", "sortant"], needs: "" });
  const set = (k, v) => setF((s) => ({ ...s, [k]: v }));
  const toggleFlux = (x) => setF((s) => ({ ...s, flux: s.flux.includes(x) ? s.flux.filter((y) => y !== x) : [...s.flux, x] }));
  const groups = groupsOf(allCodes);
  const valid = f.label.trim() && f.group.trim() && f.flux.length;

  const save = () => {
    const existing = allCodes.filter((c) => c.code !== (code && code.code)).map((c) => c.code);
    const out = { ...f, label: f.label.trim(), sub: f.sub.trim(), group: f.group.trim(),
      code: editing ? code.code : slugCode(f.label, existing) };
    if (!out.needs) delete out.needs;
    onSave(out);
  };

  return (
    <Modal title={editing ? "Modifier le code conclusion" : "Nouveau code conclusion"}
      sub={editing ? "Code interne : " + code.code : "Le code interne sera généré automatiquement."} onClose={onClose}
      footer={<>
        <button className="btn btn-ghost" onClick={onClose}>Annuler</button>
        <button className="btn btn-primary" disabled={!valid} onClick={save}><I.check s={16} /> {editing ? "Enregistrer" : "Ajouter le code"}</button>
      </>}>
      <div className="field-row c2">
        <Field label="Libellé" required><input value={f.label} placeholder="ex. Devis envoyé" onChange={(e) => set("label", e.target.value)} /></Field>
        <Field label="Sous-titre"><input value={f.sub} placeholder="ex. Proposition transmise" onChange={(e) => set("sub", e.target.value)} /></Field>
      </div>

      <div className="field-row c2">
        <Field label="Groupe / catégorie" required>
          <input value={f.group} placeholder="ex. À suivre" list="grp-list" onChange={(e) => set("group", e.target.value)} />
          <datalist id="grp-list">{groups.map((g) => <option key={g} value={g} />)}</datalist>
        </Field>
        <Field label="Champ complémentaire">
          <select value={f.needs} onChange={(e) => set("needs", e.target.value)}>
            {NEEDS_OPTS.map((o) => <option key={o.key} value={o.key}>{o.label}</option>)}
          </select>
        </Field>
      </div>

      <div className="field">
        <label>Tonalité</label>
        <div className="tone-pick">
          {TONES.map((t) => (
            <button key={t.key} className={"tone-opt tone-" + t.key + (f.tone === t.key ? " on" : "")}
              onClick={() => set("tone", t.key)}>{t.label}</button>
          ))}
        </div>
      </div>

      <div className="field-row c2">
        <div className="field">
          <label>Flux autorisé</label>
          <div className="flux-pick">
            <button className={"flux-opt" + (f.flux.includes("entrant") ? " on" : "")} onClick={() => toggleFlux("entrant")}><I.phoneIn s={15} w={2} /> Entrant</button>
            <button className={"flux-opt" + (f.flux.includes("sortant") ? " on" : "")} onClick={() => toggleFlux("sortant")}><I.phoneOut s={15} w={2} /> Sortant</button>
          </div>
        </div>
        <div className="field">
          <label>Couleur (graphiques)</label>
          <div className="swatch-row">
            {CODE_SWATCHES.map((c) => (
              <button key={c} className={"swatch sm" + (f.color === c ? " on" : "")} style={{ background: c }}
                onClick={() => set("color", c)}>{f.color === c && <I.check s={12} />}</button>
            ))}
          </div>
        </div>
      </div>

      <div className="code-preview">
        <span style={{ fontSize: 11, fontWeight: 700, color: "var(--ink-faint)", textTransform: "uppercase", letterSpacing: ".06em" }}>Aperçu</span>
        <div className="code-card on" style={{ pointerEvents: "none", marginTop: 8, maxWidth: 280, "--tc": f.color }}>
          <span className="ck" style={{ background: f.color, borderColor: f.color }}><I.checkBold s={13} /></span>
          <span className="ct"><b>{f.label || "Libellé du code"}</b><span>{f.sub || "Sous-titre"}</span></span>
        </div>
      </div>
    </Modal>
  );
}

/* ---------- éditeur de codes conclusion ---------- */
function CodesEditor({ op, onChange }) {
  const codes = op.codes;
  const [modal, setModal] = useState(null); // {} new, or code to edit
  const groups = groupsOf(codes);

  const move = (idx, dir) => {
    const j = idx + dir;
    if (j < 0 || j >= codes.length) return;
    const next = codes.slice(); const t = next[idx]; next[idx] = next[j]; next[j] = t;
    onChange(next);
  };
  const remove = (code) => onChange(codes.filter((c) => c.code !== code));
  const save = (data) => {
    if (codes.some((c) => c.code === data.code)) onChange(codes.map((c) => c.code === data.code ? data : c));
    else onChange([...codes, data]);
    setModal(null);
  };

  return (
    <div className="console-page">
      <div className="page-head">
        <div><h1>Codes conclusion</h1><p>Ajoutez, modifiez et réordonnez les codes. Les changements s'appliquent immédiatement à la qualification de {op.name}.</p></div>
        <button className="toolbtn accent" onClick={() => setModal({})}><I.plus s={17} /> Ajouter un code</button>
      </div>

      <div className="codes-editor">
        {groups.map((g) => (
          <div className="ce-group" key={g}>
            <div className="ce-group-h">{g}</div>
            {codes.map((c, i) => c.group === g ? (
              <div className="ce-row" key={c.code}>
                <span className="ce-grip"><I.grip s={16} /></span>
                <span className="ce-dot" style={{ background: codeColor(c) }} />
                <div className="ce-main">
                  <div className="ce-label"><b>{c.label}</b> <span className="ce-key">{c.code}</span></div>
                  <div className="ce-sub">{c.sub}</div>
                </div>
                <div className="ce-tags">
                  <ToneBadge tone={c.tone}>{TONES.find((t) => t.key === c.tone).label.split(" ")[0]}</ToneBadge>
                  <span className="ce-flux">{c.flux.includes("entrant") && <I.phoneIn s={13} w={2} title="Entrant" />}{c.flux.includes("sortant") && <I.phoneOut s={13} w={2} title="Sortant" />}</span>
                  {c.needs && <span className="ce-needs">{NEEDS_OPTS.find((n) => n.key === c.needs).label.split(" ")[0]}</span>}
                </div>
                <div className="ce-actions">
                  <button className="iconbtn sm" title="Monter" onClick={() => move(i, -1)} disabled={i === 0}><I.chevronD s={15} style={{ transform: "rotate(180deg)" }} /></button>
                  <button className="iconbtn sm" title="Descendre" onClick={() => move(i, 1)} disabled={i === codes.length - 1}><I.chevronD s={15} /></button>
                  <button className="iconbtn sm" title="Modifier" onClick={() => setModal(c)}><I.edit s={15} /></button>
                  <button className="iconbtn sm danger" title="Supprimer" onClick={() => remove(c.code)}><I.trash s={15} /></button>
                </div>
              </div>
            ) : null)}
          </div>
        ))}
        {codes.length === 0 && <div className="empty-q" style={{ background: "var(--surface)", border: "1px solid var(--line)", borderRadius: 12 }}>Aucun code conclusion. Ajoutez-en un pour démarrer.</div>}
      </div>

      {modal && <CodeEditorModal code={modal.code ? modal : null} allCodes={codes} onClose={() => setModal(null)} onSave={save} />}
    </div>
  );
}

/* ---------- table des fiches ---------- */
function FichesTable({ op, canDelete, onDelete }) {
  const [status, setStatus] = useState("toutes");
  const [flux, setFlux] = useState("tous");
  const [canal, setCanal] = useState("tous");
  const [q, setQ] = useState("");
  const byCode = (c) => findCode(op.codes, c);

  const list = op.fiches.filter((f) => {
    if (!isLive(f)) return false;
    if (status !== "toutes" && f.status !== status) return false;
    if (flux !== "tous" && f.type !== flux) return false;
    if (canal !== "tous" && (f.canal || DEFAULT_CHANNEL) !== canal) return false;
    if (q.trim()) {
      const hay = [f.fields.nom, f.fields.prenom, f.fields.societe, f.fields.ville, f.fields.tel, f.fields.clientNum, f.fields.motif].join(" ").toLowerCase();
      if (!hay.includes(q.trim().toLowerCase())) return false;
    }
    return true;
  });
  const stamp = () => new Date().toISOString().slice(0, 10);
  const totalLive = op.fiches.filter(isLive).length;

  return (
    <div className="console-page">
      <div className="page-head">
        <div><h1>Fiches</h1><p>{totalLive} fiches au total · {list.length} affichées</p></div>
        <button className="toolbtn accent" onClick={() => downloadFiches(list, op.codes, "polycall_" + op.id + "_fiches_" + stamp() + ".csv")}><I.download s={17} /> Exporter ({list.length})</button>
      </div>

      <div className="fiches-filters">
        <div className="seg">
          {[["toutes", "Toutes"], ["attente", "En attente"], ["traitee", "Traitées"]].map(([k, l]) => (
            <button key={k} className={status === k ? "on" : ""} onClick={() => setStatus(k)}>{l}</button>
          ))}
        </div>
        <div className="seg">
          {[["tous", "Tous flux"], ["entrant", "Entrants"], ["sortant", "Sortants"]].map(([k, l]) => (
            <button key={k} className={flux === k ? "on" : ""} onClick={() => setFlux(k)}>{l}</button>
          ))}
        </div>
        <select className="canal-filter" value={canal} onChange={(e) => setCanal(e.target.value)}>
          <option value="tous">Tous canaux</option>
          {CHANNELS.map((c) => <option key={c.key} value={c.key}>{c.label}</option>)}
        </select>
        <div className="mini-search">
          <I.search s={15} />
          <input value={q} placeholder="Rechercher…" onChange={(e) => setQ(e.target.value)} />
        </div>
      </div>

      <div className="fiches-table-wrap">
        <table className="qtable">
          <thead><tr><th>État</th><th>Client</th><th>Canal</th><th>Flux</th><th>Téléphone</th><th>Ville</th><th>Motif</th><th>Conclusion</th>{canDelete && <th></th>}</tr></thead>
          <tbody>
            {list.map((f) => {
              const c = f.conclusion ? byCode(f.conclusion.code) : null;
              return (
                <tr key={f.id}>
                  <td>{f.status === "traitee" ? <span className="status-pill on" style={{ background: "var(--good-tint)", color: "var(--good)" }}>{f.qualifiedAt}</span> : <span className="status-pill" style={{ background: "var(--warn-tint)", color: "var(--warn)" }}>En attente</span>}</td>
                  <td className="nm">{displayName(f)}</td>
                  <td><ChannelBadge canal={f.canal} size={12} /></td>
                  <td><FluxBadge type={f.type} /></td>
                  <td className="tm">{f.fields.tel}</td>
                  <td style={{ color: "var(--ink-soft)" }}>{f.fields.ville || "—"}</td>
                  <td style={{ color: "var(--ink-soft)", maxWidth: 240, whiteSpace: "nowrap", overflow: "hidden", textOverflow: "ellipsis" }}>{f.fields.motif}</td>
                  <td>{c ? <ToneBadge tone={c.tone}>{c.label}</ToneBadge> : <span style={{ color: "var(--ink-faint)" }}>—</span>}</td>
                  {canDelete && <td style={{ textAlign: "right" }}><button className="iconbtn sm danger" title="Mettre à la corbeille" onClick={() => onDelete(f.id)}><I.trash s={15} /></button></td>}
                </tr>
              );
            })}
            {list.length === 0 && <tr><td colSpan={canDelete ? 9 : 8} style={{ textAlign: "center", color: "var(--ink-faint)", padding: 32 }}>Aucune fiche ne correspond aux filtres.</td></tr>}
          </tbody>
        </table>
      </div>
    </div>
  );
}

/* ---------- corbeille (10 jours) ---------- */
function TrashView({ op, onRestore, onPurge, onEmpty }) {
  const [confirm, setConfirm] = useState(null); // { kind:"one"|"all", fiche }
  const byCode = (c) => findCode(op.codes, c);
  const trash = op.fiches.filter(inTrash).slice().sort((a, b) => (b.deletedAt || "").localeCompare(a.deletedAt || ""));

  return (
    <div className="console-page">
      <div className="page-head">
        <div>
          <h1>Corbeille</h1>
          <p>Les fiches supprimées sont conservées {TRASH_RETENTION_DAYS} jours, puis définitivement effacées. {trash.length} fiche{trash.length > 1 ? "s" : ""} dans la corbeille.</p>
        </div>
        {trash.length > 0 && (
          <button className="toolbtn danger-tool" onClick={() => setConfirm({ kind: "all" })}><I.trash s={16} /> Vider la corbeille</button>
        )}
      </div>

      {trash.length === 0 ? (
        <div className="trash-empty">
          <span className="te-ic"><I.trash s={30} /></span>
          <h2>La corbeille est vide</h2>
          <p>Les fiches que vous supprimez apparaîtront ici et pourront être restaurées pendant {TRASH_RETENTION_DAYS} jours.</p>
        </div>
      ) : (
        <div className="fiches-table-wrap">
          <table className="qtable">
            <thead><tr><th>Client</th><th>Canal</th><th>Flux</th><th>Motif</th><th>Supprimée le</th><th>Suppression définitive</th><th></th></tr></thead>
            <tbody>
              {trash.map((f) => {
                const left = trashDaysLeft(f.deletedAt);
                const dt = new Date(f.deletedAt);
                return (
                  <tr key={f.id}>
                    <td className="nm">{displayName(f)}</td>
                    <td><ChannelBadge canal={f.canal} size={12} /></td>
                    <td><FluxBadge type={f.type} /></td>
                    <td style={{ color: "var(--ink-soft)", maxWidth: 240, whiteSpace: "nowrap", overflow: "hidden", textOverflow: "ellipsis" }}>{f.fields.motif}</td>
                    <td className="tm">{dt.toLocaleDateString("fr-FR")}</td>
                    <td><span className={"ttl-pill" + (left <= 2 ? " soon" : "")}>{left === 0 ? "Aujourd'hui" : "J-" + left}</span></td>
                    <td style={{ textAlign: "right", whiteSpace: "nowrap" }}>
                      <button className="iconbtn sm" title="Restaurer" onClick={() => onRestore(f.id)}><I.restore s={15} /></button>
                      <button className="iconbtn sm danger" title="Supprimer définitivement" onClick={() => setConfirm({ kind: "one", fiche: f })}><I.x s={15} /></button>
                    </td>
                  </tr>
                );
              })}
            </tbody>
          </table>
        </div>
      )}

      {confirm && confirm.kind === "one" && (
        <ConfirmModal title="Supprimer définitivement ?" danger confirmLabel="Supprimer définitivement"
          message={<>La fiche de <b>{displayName(confirm.fiche)}</b> sera définitivement effacée. Cette action est irréversible.</>}
          onCancel={() => setConfirm(null)} onConfirm={() => { onPurge(confirm.fiche.id); setConfirm(null); }} />
      )}
      {confirm && confirm.kind === "all" && (
        <ConfirmModal title="Vider la corbeille ?" danger confirmLabel={"Tout supprimer (" + trash.length + ")"}
          message={<>Les <b>{trash.length} fiche{trash.length > 1 ? "s" : ""}</b> de la corbeille seront définitivement effacées. Cette action est irréversible.</>}
          onCancel={() => setConfirm(null)} onConfirm={() => { onEmpty(); setConfirm(null); }} />
      )}
    </div>
  );
}

/* ---------- espace admin / visiteur d'une opération ---------- */
function AdminWorkspace({ op, updateOp, user, onExit, onLogout, exitLabel }) {
  const canEdit = user.role === "admin" || user.role === "super";
  const [tab, setTab] = useState("suivi");
  useEffect(() => { applyAccent(op.accent); }, [op.accent]);
  useEffect(() => { if (!canEdit && (tab === "codes" || tab === "corbeille")) setTab("suivi"); }, [canEdit, tab]);
  const stamp = () => new Date().toISOString().slice(0, 10);

  const liveFiches = op.fiches.filter(isLive);
  const trashCount = op.fiches.filter(inTrash).length;
  const liveCount = liveFiches.length;

  const softDelete = (id) => {
    updateOp((o) => ({ ...o, fiches: o.fiches.map((f) => f.id === id ? { ...f, deletedAt: new Date().toISOString() } : f) }));
    PolycallAPI.deleteFiche(id);
  };
  const restoreFiche = (id) => {
    updateOp((o) => ({ ...o, fiches: o.fiches.map((f) => f.id === id ? { ...f, deletedAt: null } : f) }));
    PolycallAPI.restoreFiche(id);
  };
  const purgeFiche = (id) => {
    updateOp((o) => ({ ...o, fiches: o.fiches.filter((f) => f.id !== id) }));
    PolycallAPI.purgeFiche(id);
  };
  const emptyTrash = () => {
    updateOp((o) => ({ ...o, fiches: o.fiches.filter((f) => !f.deletedAt) }));
    PolycallAPI.emptyTrash(op.id);
  };

  return (
    <div className="app">
      <ConsoleBar user={user} onLogout={onLogout} opChip={op} onExit={onExit} exitLabel={exitLabel || "Changer d'opération"} sub={canEdit ? "Pilotage" : "Espace client"} />
      <div className="work-tabs">
        <button className={"wtab" + (tab === "suivi" ? " on" : "")} onClick={() => setTab("suivi")}><I.chart s={17} /> Suivi &amp; statistiques</button>
        <button className={"wtab" + (tab === "fiches" ? " on" : "")} onClick={() => setTab("fiches")}><I.flag s={17} /> Fiches <span className="wt-c">{liveCount}</span></button>
        {canEdit && <button className={"wtab" + (tab === "codes" ? " on" : "")} onClick={() => setTab("codes")}><I.sliders s={17} /> Codes conclusion <span className="wt-c">{op.codes.length}</span></button>}
        {canEdit && <button className={"wtab" + (tab === "corbeille" ? " on" : "")} onClick={() => setTab("corbeille")}><I.trash s={17} /> Corbeille {trashCount > 0 && <span className="wt-c">{trashCount}</span>}</button>}
        {!canEdit && <span className="readonly-pill"><I.eye s={14} /> Lecture seule</span>}
      </div>

      <div className="work-body">
        {tab === "suivi" && (
          <div className="console-page">
            <div className="page-head">
              <div><h1>Suivi &amp; statistiques</h1><p>{op.sector} · vue temps réel de la session</p></div>
              <div style={{ display: "flex", gap: 8 }}>
                <button className="toolbtn" onClick={() => downloadFiches(liveFiches.filter((f) => f.status === "traitee"), op.codes, "polycall_" + op.id + "_traitees_" + stamp() + ".csv")}><I.download s={16} /> Traitées</button>
                <button className="toolbtn accent" onClick={() => downloadFiches(liveFiches, op.codes, "polycall_" + op.id + "_toutes_" + stamp() + ".csv")}><I.download s={16} /> Tout exporter</button>
              </div>
            </div>
            <Dashboard fiches={liveFiches} codes={op.codes} op={op} embedded />
          </div>
        )}
        {tab === "fiches" && <FichesTable op={op} canDelete={canEdit} onDelete={softDelete} />}
        {tab === "codes" && canEdit && <CodesEditor op={op} onChange={(codes) => { updateOp((o) => ({ ...o, codes })); PolycallAPI.saveCodes(op.id, codes); }} />}
        {tab === "corbeille" && canEdit && <TrashView op={op} onRestore={restoreFiche} onPurge={purgeFiche} onEmpty={emptyTrash} />}
      </div>
    </div>
  );
}

Object.assign(window, { CodeEditorModal, CodesEditor, FichesTable, TrashView, AdminWorkspace });
