// ============================================================
// Polycall — export CSV + tableau de bord (par opération)
// ============================================================

const FLUX_HEX = { entrant: "#2a6fdb", sortant: "#6c6764" };

/* ---------------- Export CSV (Excel FR : séparateur ;) ---------------- */
function csvCell(v) {
  const s = (v == null ? "" : String(v));
  return /[";\n\r]/.test(s) ? '"' + s.replace(/"/g, '""') + '"' : s;
}
function buildCSV(list, codes) {
  const cols = [
    "Date/heure clôture", "Type d'appel", "Canal", "Civilité", "Nom", "Prénom", "Société",
    "Client n°", "Adresse", "Code postal", "Ville", "Téléphone", "Adresse mail",
    "Matricule fiscale", "Motif d'appel", "Commentaire", "Code conclusion", "Détail",
  ];
  const lines = [cols.join(";")];
  list.forEach((f) => {
    const x = f.fields, c = f.conclusion ? findCode(codes, f.conclusion.code) : null;
    let detail = "";
    if (f.conclusion) {
      if (f.conclusion.rappelDate) detail = "Rappel/RDV " + f.conclusion.rappelDate + " " + f.conclusion.rappelHeure;
      else if (f.conclusion.devis) detail = "Réf. " + f.conclusion.devis;
      else if (f.conclusion.sav) detail = "SAV : " + f.conclusion.sav;
    }
    lines.push([
      f.qualifiedAt || "", f.type === "entrant" ? "Entrant" : "Sortant",
      (findChannel(f.canal) || findChannel(DEFAULT_CHANNEL)).label,
      x.civilite, x.nom, x.prenom, x.societe, x.clientNum, x.adresse, x.cp, x.ville,
      x.tel, x.email, x.matricule, x.motif, x.commentaire, c ? c.label : (f.conclusion ? f.conclusion.code : ""), detail,
    ].map(csvCell).join(";"));
  });
  return lines.join("\r\n");
}
function downloadFiches(list, codes, name) {
  const csv = "\uFEFF" + buildCSV(list, codes);
  const blob = new Blob([csv], { type: "text/csv;charset=utf-8;" });
  const url = URL.createObjectURL(blob);
  const a = document.createElement("a");
  a.href = url; a.download = name; document.body.appendChild(a); a.click();
  document.body.removeChild(a); setTimeout(() => URL.revokeObjectURL(url), 1000);
}

/* ---------------- Donut SVG ---------------- */
function Donut({ segments, size = 184, thickness = 28, centerTop, centerSub }) {
  const total = segments.reduce((s, d) => s + d.value, 0) || 1;
  const r = (size - thickness) / 2;
  const c = 2 * Math.PI * r;
  let acc = 0;
  return (
    <div style={{ position: "relative", width: size, height: size, flexShrink: 0 }}>
      <svg width={size} height={size} style={{ transform: "rotate(-90deg)" }}>
        <circle cx={size / 2} cy={size / 2} r={r} fill="none" stroke="var(--line)" strokeWidth={thickness} />
        {segments.map((d, i) => {
          const len = (d.value / total) * c;
          const el = (
            <circle key={i} cx={size / 2} cy={size / 2} r={r} fill="none"
              stroke={d.color} strokeWidth={thickness}
              strokeDasharray={`${len} ${c - len}`} strokeDashoffset={-acc} strokeLinecap="butt" />
          );
          acc += len;
          return el;
        })}
      </svg>
      <div style={{ position: "absolute", inset: 0, display: "flex", flexDirection: "column", alignItems: "center", justifyContent: "center" }}>
        <b style={{ fontSize: 32, fontWeight: 800, lineHeight: 1, letterSpacing: "-.02em" }}>{centerTop}</b>
        <span style={{ fontSize: 11, color: "var(--ink-faint)", fontWeight: 600, marginTop: 4 }}>{centerSub}</span>
      </div>
    </div>
  );
}

/* ---------------- Tableau de bord ---------------- */
function Dashboard({ fiches, codes, op, onClose, embedded }) {
  const byCode = (c) => findCode(codes, c);
  const done = fiches.filter((f) => f.status === "traitee");
  const total = done.length;
  const isWon = (f) => { const c = byCode(f.conclusion.code); return c && c.tone === "good"; };
  const won = done.filter(isWon).length;
  const taux = total ? Math.round(won / total * 100) : 0;
  const attente = fiches.filter((f) => f.status === "attente").length;
  const devisCodes = codes.filter((c) => c.needs === "devis").map((c) => c.code);
  const rappelCodes = codes.filter((c) => c.needs === "rappel").map((c) => c.code);
  const devisN = done.filter((f) => devisCodes.includes(f.conclusion.code)).length;
  const rappelN = done.filter((f) => rappelCodes.includes(f.conclusion.code)).length;

  const byC = {};
  done.forEach((f) => { byC[f.conclusion.code] = (byC[f.conclusion.code] || 0) + 1; });
  const segs = codes.filter((c) => byC[c.code])
    .map((c) => ({ code: c.code, label: c.label, value: byC[c.code], color: codeColor(c) }))
    .sort((a, b) => b.value - a.value);

  const fluxStat = (type) => {
    const list = done.filter((f) => f.type === type);
    const w = list.filter(isWon).length;
    return { n: list.length, conc: w, taux: list.length ? Math.round(w / list.length * 100) : 0 };
  };
  const inS = fluxStat("entrant"), outS = fluxStat("sortant");

  const hours = {};
  done.forEach((f) => {
    const h = (f.qualifiedAt || "").slice(0, 2);
    if (!h) return;
    hours[h] = hours[h] || { entrant: 0, sortant: 0 };
    hours[h][f.type]++;
  });
  const hourKeys = Object.keys(hours).sort();
  const hourMax = Math.max(1, ...hourKeys.map((h) => hours[h].entrant + hours[h].sortant));

  // provenance par canal (tous statuts)
  const canalCounts = {};
  fiches.forEach((f) => { const k = f.canal || DEFAULT_CHANNEL; canalCounts[k] = (canalCounts[k] || 0) + 1; });
  const canalRows = CHANNELS.map((c) => ({ ...c, n: canalCounts[c.key] || 0 })).filter((r) => r.n > 0).sort((a, b) => b.n - a.n);
  const canalTotal = fiches.length;
  const canalMax = canalRows.length ? canalRows[0].n : 1;

  const journal = done.slice().sort((a, b) => (b.qualifiedAt || "").localeCompare(a.qualifiedAt || ""));
  const stamp = () => new Date().toISOString().slice(0, 10);

  const body = (
    <div className="dash-body">
      <div className="dash-kpis">
        <div className="dkpi"><span className="dk-ic"><I.flag s={18} /></span><b>{total}</b><span>Fiches qualifiées</span></div>
        <div className="dkpi hl"><span className="dk-ic"><I.check s={18} /></span><b>{won}</b><span>Issues positives</span><div className="dk-sub">{op.name}</div></div>
        <div className="dkpi"><span className="dk-ic"><I.target s={18} /></span><b style={{ color: "var(--good)" }}>{taux}%</b><span>Taux de conversion</span></div>
        <div className="dkpi"><span className="dk-ic"><I.doc s={18} /></span><b>{devisN}</b><span>Propositions envoyées</span><div className="dk-sub">à relancer</div></div>
        <div className="dkpi"><span className="dk-ic"><I.calendar s={18} /></span><b>{rappelN}</b><span>Rappels / RDV</span></div>
      </div>

      <div className="dash-grid">
        <div className="dash-card">
          <h3><I.pie s={16} /> Répartition par code conclusion</h3>
          <p className="ch-sub">Tous flux confondus · session du jour</p>
          <div className="donut-wrap">
            <Donut segments={segs} centerTop={total} centerSub="fiches" />
            <div className="donut-legend">
              {segs.map((s) => (
                <div className="leg-row" key={s.code}>
                  <span className="lg-dot" style={{ background: s.color }} />
                  <span className="lg-name">{s.label}</span>
                  <span className="lg-val">{s.value}</span>
                  <span className="lg-pct">{Math.round(s.value / (total || 1) * 100)}%</span>
                </div>
              ))}
              {segs.length === 0 && <div style={{ color: "var(--ink-faint)", fontSize: 12.5 }}>Aucune fiche qualifiée.</div>}
            </div>
          </div>
        </div>

        <div className="dash-card">
          <h3><I.trend s={16} /> Performance entrant / sortant</h3>
          <p className="ch-sub">Volume traité et taux de conversion par flux</p>
          {[["entrant", "Appels entrants", inS, I.phoneIn], ["sortant", "Appels sortants", outS, I.phoneOut]].map(([k, lbl, st, Icn]) => (
            <div className="flux-stat" key={k}>
              <div className="fs-top">
                <span className="fs-label" style={{ color: FLUX_HEX[k] }}><Icn s={16} w={2} /> {lbl}</span>
                <span className="fs-nums"><b>{st.n}</b> fiches · {st.conc} conclus · {st.taux}%</span>
              </div>
              <div className="gauge"><div className="gf" style={{ width: st.taux + "%", background: FLUX_HEX[k] }} /></div>
            </div>
          ))}
          <div style={{ marginTop: 18, paddingTop: 16, borderTop: "1px solid var(--line)", display: "flex", gap: 22 }}>
            <div><div style={{ fontSize: 22, fontWeight: 800 }}>{inS.n}</div><div style={{ fontSize: 11, color: "var(--ink-soft)", fontWeight: 600 }}>Entrants</div></div>
            <div><div style={{ fontSize: 22, fontWeight: 800 }}>{outS.n}</div><div style={{ fontSize: 11, color: "var(--ink-soft)", fontWeight: 600 }}>Sortants</div></div>
            <div style={{ marginLeft: "auto", textAlign: "right" }}><div style={{ fontSize: 22, fontWeight: 800, color: "var(--good)" }}>{taux}%</div><div style={{ fontSize: 11, color: "var(--ink-soft)", fontWeight: 600 }}>Conversion globale</div></div>
          </div>
        </div>
      </div>

      <div className="dash-card" style={{ marginBottom: 16 }}>
        <h3><I.inbox s={16} /> Provenance des contacts</h3>
        <p className="ch-sub">D'où viennent les fiches — tous statuts confondus · {canalTotal} fiche{canalTotal > 1 ? "s" : ""}</p>
        <div className="canal-bars">
          {canalRows.map((r) => {
            const Icn = I[r.icon] || I.dot;
            return (
              <div className="canal-bar-row" key={r.key}>
                <span className="cb-ic" style={{ color: r.color, background: r.color + "1c" }}><Icn s={14} /></span>
                <span className="cb-name">{r.label}</span>
                <span className="cb-track"><span className="cb-fill" style={{ width: (r.n / canalMax * 100) + "%", background: r.color }} /></span>
                <span className="cb-val">{r.n}</span>
                <span className="cb-pct">{Math.round(r.n / (canalTotal || 1) * 100)}%</span>
              </div>
            );
          })}
          {canalRows.length === 0 && <div style={{ color: "var(--ink-faint)", fontSize: 12.5 }}>Aucune fiche enregistrée.</div>}
        </div>
      </div>

      <div className="dash-card" style={{ marginBottom: 16 }}>
        <h3><I.clock s={16} /> Activité par tranche horaire</h3>
        <p className="ch-sub">Fiches qualifiées par heure — <span style={{ color: FLUX_HEX.entrant, fontWeight: 700 }}>entrants</span> / <span style={{ color: FLUX_HEX.sortant, fontWeight: 700 }}>sortants</span></p>
        <div className="hours-chart">
          {hourKeys.map((h) => {
            const d = hours[h], tot = d.entrant + d.sortant;
            return (
              <div className="hour-col" key={h}>
                <span className="hour-tot">{tot}</span>
                <div className="hour-bars" style={{ height: (tot / hourMax * 100) + "%" }}>
                  <div className="hour-seg" style={{ height: (d.sortant / tot * 100) + "%", background: FLUX_HEX.sortant }} />
                  <div className="hour-seg" style={{ height: (d.entrant / tot * 100) + "%", background: FLUX_HEX.entrant }} />
                </div>
                <span className="hour-x">{h}h</span>
              </div>
            );
          })}
          {hourKeys.length === 0 && <div style={{ color: "var(--ink-faint)", fontSize: 12.5, alignSelf: "center" }}>Aucune activité enregistrée.</div>}
        </div>
      </div>

      <div className="dash-table">
        <div className="dt-head">
          <h3>Journal des clôtures · {journal.length}</h3>
          <button className="toolbtn" onClick={() => downloadFiches(done, codes, "polycall_" + op.id + "_journal_" + stamp() + ".csv")}>
            <I.download s={16} /> CSV
          </button>
        </div>
        <div className="dt-scroll">
          <table className="qtable">
            <thead><tr><th>Heure</th><th>Client</th><th>Flux</th><th>Code conclusion</th><th>Motif</th></tr></thead>
            <tbody>
              {journal.map((f) => {
                const c = byCode(f.conclusion.code);
                return (
                  <tr key={f.id}>
                    <td className="tm">{f.qualifiedAt}</td>
                    <td className="nm">{displayName(f)}</td>
                    <td><FluxBadge type={f.type} /></td>
                    <td>{c ? <ToneBadge tone={c.tone}>{c.label}</ToneBadge> : f.conclusion.code}</td>
                    <td style={{ color: "var(--ink-soft)", maxWidth: 280, whiteSpace: "nowrap", overflow: "hidden", textOverflow: "ellipsis" }}>{f.fields.motif}</td>
                  </tr>
                );
              })}
            </tbody>
          </table>
        </div>
      </div>
    </div>
  );

  if (embedded) return body;

  return (
    <>
      <div className="overlay" onClick={onClose} />
      <div className="dash-modal" role="dialog" aria-label="Tableau de bord">
        <div className="dash-head">
          <span className="di" style={{ background: op.accent[0] }}><I.chart s={20} /></span>
          <div>
            <h2>Tableau de bord — {op.name}</h2>
            <p>{op.sector} · session du jour · {total} fiches qualifiées</p>
          </div>
          <div className="spacer" />
          <button className="toolbtn" onClick={() => downloadFiches(done, codes, "polycall_" + op.id + "_traitees_" + stamp() + ".csv")}>
            <I.download s={17} /> Exporter les traitées
          </button>
          <button className="toolbtn accent" onClick={() => downloadFiches(fiches, codes, "polycall_" + op.id + "_toutes_" + stamp() + ".csv")}>
            <I.download s={17} /> Tout exporter
          </button>
          <button className="iconbtn" onClick={onClose} style={{ marginLeft: 4 }}><I.x s={18} /></button>
        </div>
        {body}
      </div>
    </>
  );
}

Object.assign(window, { FLUX_HEX, buildCSV, downloadFiches, Donut, Dashboard });
