/* global React, lecygne */
// Commandes — liste filtrable + saisie d'une commande (lignes + totaux).

function CommandeForm({ ctx, onClose, onSaved }) {
  const articles = lecygne.useArticles();
  const services = lecygne.useServices();
  const clients = lecygne.useClients({});
  const [codeClient, setCodeClient] = React.useState("");
  const [dateCmd, setDateCmd] = React.useState(new Date().toISOString().slice(0, 10));
  const [aLivrer, setALivrer] = React.useState("");
  const [lignes, setLignes] = React.useState([]);
  const [err, setErr] = React.useState("");
  const [busy, setBusy] = React.useState(false);
  const cur = (ctx.company && ctx.company.currency) || "XOF";
  const vat = Number((ctx.company && ctx.company.vat_rate) || 18);

  function addLine() {
    setLignes([...lignes, { ref_article: "", code_service: "", quantite: 1, prix_unitaire: 0 }]);
  }
  function setLine(i, k, v) {
    const next = lignes.slice();
    next[i] = { ...next[i], [k]: v };
    setLignes(next);
  }
  async function onArticleOrService(i, k, v) {
    setLine(i, k, v);
    const l = { ...lignes[i], [k]: v };
    if (l.ref_article && l.code_service) {
      const p = await lecygne.tarifs.price(Number(l.ref_article), Number(l.code_service));
      if (p) setLignes((prev) => prev.map((x, idx) => idx === i ? { ...x, [k]: v, prix_unitaire: p } : x));
    }
  }
  function rmLine(i) { setLignes(lignes.filter((_, idx) => idx !== i)); }

  const ht = lignes.reduce((s, l) => s + (Number(l.quantite) || 0) * (Number(l.prix_unitaire) || 0), 0);
  const tva = ht * vat / 100;
  const ttc = ht + tva;

  async function save(statut) {
    setErr("");
    if (!codeClient) { setErr("Sélectionner un client."); return; }
    setBusy(true);
    const no = await lecygne.commandes.nextNo();
    const res = await lecygne.commandes.upsert({
      no_commande: no, code_client: Number(codeClient),
      date_commande: dateCmd || null, a_livrer_avant: aLivrer || null, statut,
    }, ctx.company.id);
    if (res.error) { setErr(res.error.message); setBusy(false); return; }
    const valid = lignes.filter((l) => l.ref_article && l.code_service);
    if (valid.length) {
      await lecygne.commandes.replaceLignes(no, valid.map((l) => ({
        ref_article: Number(l.ref_article), code_service: Number(l.code_service),
        quantite: Number(l.quantite) || 1, prix_unitaire: Number(l.prix_unitaire) || 0,
      })));
    }
    setBusy(false);
    window.lcToast("Commande #" + no + " enregistrée", "success");
    onSaved(); onClose();
  }

  return (
    <div className="card">
      <h2>Nouvelle commande
        <button className="btn sm" onClick={onClose}>✕ Fermer</button>
      </h2>
      <div className="grid3">
        <div><label>Client</label>
          <select className="field" value={codeClient} onChange={(e) => setCodeClient(e.target.value)}>
            <option value="">— Sélectionner —</option>
            {(clients.data || []).map((c) =>
              <option key={c.code_client} value={c.code_client}>{c.societe || c.nom_client}</option>)}
          </select></div>
        <div><label>Date dépôt</label>
          <input className="field" type="date" value={dateCmd} onChange={(e) => setDateCmd(e.target.value)} /></div>
        <div><label>À livrer avant</label>
          <input className="field" type="date" value={aLivrer} onChange={(e) => setALivrer(e.target.value)} /></div>
      </div>

      <div className="tbl-wrap">
        <table>
          <thead><tr>
            <th style={{ width: "30%" }}>Article</th><th style={{ width: "24%" }}>Service</th>
            <th style={{ width: "10%" }}>Qté</th><th style={{ width: "16%" }} className="right">P.U. ({cur})</th>
            <th style={{ width: "16%" }} className="right">Montant</th><th></th>
          </tr></thead>
          <tbody>
            {lignes.map((l, i) => (
              <tr key={i}>
                <td><select className="field" value={l.ref_article}
                  onChange={(e) => onArticleOrService(i, "ref_article", e.target.value)}>
                  <option value="">—</option>
                  {(articles.data || []).map((a) => <option key={a.ref_article} value={a.ref_article}>{a.nom_article}</option>)}
                </select></td>
                <td><select className="field" value={l.code_service}
                  onChange={(e) => onArticleOrService(i, "code_service", e.target.value)}>
                  <option value="">—</option>
                  {(services.data || []).map((s) => <option key={s.code_service} value={s.code_service}>{s.nom_service}</option>)}
                </select></td>
                <td><input className="field num" type="number" value={l.quantite}
                  onChange={(e) => setLine(i, "quantite", e.target.value)} /></td>
                <td><input className="field num" type="number" value={l.prix_unitaire}
                  onChange={(e) => setLine(i, "prix_unitaire", e.target.value)} /></td>
                <td className="num">{lecygne.fmtAmount((Number(l.quantite) || 0) * (Number(l.prix_unitaire) || 0))}</td>
                <td><button className="btn sm danger" onClick={() => rmLine(i)}>✕</button></td>
              </tr>
            ))}
            {!lignes.length && <tr><td colSpan="6" className="empty">Ajoutez une ligne pour commencer.</td></tr>}
          </tbody>
        </table>
      </div>
      <button className="addline" onClick={addLine}>＋ Ajouter une ligne</button>

      <div className="totals"><div className="box">
        <div className="row"><span>Total HT</span><span>{lecygne.fmtAmount(ht, cur)}</span></div>
        <div className="row"><span>TVA {vat} %</span><span>{lecygne.fmtAmount(tva, cur)}</span></div>
        <div className="grand"><span>Total TTC</span><span>{lecygne.fmtAmount(ttc, cur)}</span></div>
      </div></div>

      {err && <div className="auth-err">{err}</div>}
      <div className="actions">
        <button className="btn" onClick={() => save("brouillon")} disabled={busy}>Enregistrer brouillon</button>
        <button className="btn primary" onClick={() => save("deposee")} disabled={busy}>✓ Valider la commande</button>
      </div>
    </div>
  );
}

function CommandeDetail({ ctx, no, onClose, onChanged }) {
  const [cmd, setCmd] = React.useState(undefined);
  const [busy, setBusy] = React.useState(false);
  const [edit, setEdit] = React.useState(false);
  const [draft, setDraft] = React.useState([]);
  const articles = lecygne.useArticles();
  const services = lecygne.useServices();
  const cur = (ctx.company && ctx.company.currency) || "XOF";
  const vat = Number((ctx.company && ctx.company.vat_rate) || 18);

  const reload = React.useCallback(() => lecygne.commandes.get(no).then(setCmd), [no]);
  React.useEffect(() => { reload(); }, [reload]);

  if (cmd === undefined) return (
    <div className="modal-overlay" onClick={onClose}><div className="modal"><div className="spinner">Chargement…</div></div></div>
  );

  const lignes = cmd.lignes || [];
  const srcLignes = edit ? draft : lignes;
  const ht = srcLignes.reduce((s, l) => s + Number(l.quantite || 0) * Number(l.prix_unitaire || 0), 0) + Number(cmd.port || 0);
  const tva = ht * vat / 100, ttc = ht + tva;
  const clientName = (cmd.client && (cmd.client.societe || cmd.client.nom_client)) || `#${cmd.code_client}`;
  const facturee = !!cmd.no_facture;

  function startEdit() {
    setDraft(lignes.map((l) => ({ ref_article: l.ref_article, code_service: l.code_service,
      quantite: l.quantite, prix_unitaire: l.prix_unitaire })));
    setEdit(true);
  }
  function setLine(i, k, v) { setDraft((d) => d.map((x, idx) => idx === i ? { ...x, [k]: v } : x)); }
  async function pickAS(i, k, v) {
    setLine(i, k, v);
    const l = { ...draft[i], [k]: v };
    if (l.ref_article && l.code_service) {
      const p = await lecygne.tarifs.price(Number(l.ref_article), Number(l.code_service));
      if (p) setDraft((d) => d.map((x, idx) => idx === i ? { ...x, [k]: v, prix_unitaire: p } : x));
    }
  }
  function addLine() { setDraft((d) => [...d, { ref_article: "", code_service: "", quantite: 1, prix_unitaire: 0 }]); }
  function rmLine(i) { setDraft((d) => d.filter((_, idx) => idx !== i)); }

  async function saveLines() {
    setBusy(true);
    const valid = draft.filter((l) => l.ref_article && l.code_service).map((l) => ({
      ref_article: Number(l.ref_article), code_service: Number(l.code_service),
      quantite: Number(l.quantite) || 1, prix_unitaire: Number(l.prix_unitaire) || 0,
    }));
    const res = await lecygne.commandes.replaceLignes(no, valid);
    setBusy(false);
    if (res.error) { window.lcToast(res.error.message, "error"); return; }
    setEdit(false); await reload(); onChanged && onChanged();
    window.lcToast("Lignes mises à jour", "success");
  }

  function printBL() {
    printDocument({ kind: "bl", company: ctx.company, client: cmd.client, lignes, port: cmd.port, commande: cmd });
  }
  async function facturer() {
    setBusy(true);
    const res = await lecygne.factures.generateFromCommande(no, ctx.company);
    setBusy(false);
    if (res.error) window.lcToast(res.error.message, "error");
    else { window.lcToast("Facture " + res.data.no_facture + " générée", "success"); reload(); onChanged && onChanged(); }
  }

  return (
    <div className="modal-overlay" onClick={onClose}>
      <div className="modal" style={{ width: 720 }} onClick={(e) => e.stopPropagation()}>
        <h2>Commande #{cmd.no_commande}
          <span className={"pill " + ((lecygne.STATUTS[cmd.statut] || {}).cls || "gray")}>
            {(lecygne.STATUTS[cmd.statut] || {}).fr || cmd.statut}</span>
        </h2>
        <div className="grid3">
          <div><label>Client</label><div className="field read">{clientName}</div></div>
          <div><label>Date dépôt</label><div className="field read">{lecygne.fmtDate(cmd.date_commande)}</div></div>
          <div><label>À livrer avant</label><div className="field read">{lecygne.fmtDate(cmd.a_livrer_avant)}</div></div>
        </div>

        <div className="tbl-wrap"><table>
          <thead><tr><th>Article</th><th>Service</th><th className="right">Qté</th><th className="right">P.U.</th><th className="right">Montant</th>{edit && <th></th>}</tr></thead>
          <tbody>
            {edit ? draft.map((l, i) => (
              <tr key={i}>
                <td><select className="field" value={l.ref_article} onChange={(e) => pickAS(i, "ref_article", e.target.value)}>
                  <option value="">—</option>
                  {(articles.data || []).map((a) => <option key={a.ref_article} value={a.ref_article}>{a.nom_article}</option>)}
                </select></td>
                <td><select className="field" value={l.code_service} onChange={(e) => pickAS(i, "code_service", e.target.value)}>
                  <option value="">—</option>
                  {(services.data || []).map((s) => <option key={s.code_service} value={s.code_service}>{s.nom_service}</option>)}
                </select></td>
                <td><input className="field num" type="number" value={l.quantite} onChange={(e) => setLine(i, "quantite", e.target.value)} /></td>
                <td><input className="field num" type="number" value={l.prix_unitaire} onChange={(e) => setLine(i, "prix_unitaire", e.target.value)} /></td>
                <td className="num">{lecygne.fmtAmount((Number(l.quantite) || 0) * (Number(l.prix_unitaire) || 0))}</td>
                <td><button className="btn sm danger" onClick={() => rmLine(i)}>✕</button></td>
              </tr>
            )) : lignes.map((l) => (
              <tr key={l.id}>
                <td>{l.article ? l.article.nom_article : "#" + l.ref_article}</td>
                <td>{l.service ? l.service.nom_service : "#" + l.code_service}</td>
                <td className="num">{l.quantite}</td>
                <td className="num">{lecygne.fmtAmount(l.prix_unitaire, cur)}</td>
                <td className="num">{lecygne.fmtAmount(l.montant, cur)}</td>
              </tr>
            ))}
            {!edit && !lignes.length && <tr><td colSpan="5" className="empty">Aucune ligne sur cette commande.</td></tr>}
          </tbody>
        </table></div>
        {edit && <button className="addline" onClick={addLine}>＋ Ajouter une ligne</button>}

        <div className="totals"><div className="box">
          <div className="row"><span>Total HT</span><span>{lecygne.fmtAmount(ht, cur)}</span></div>
          <div className="row"><span>TVA {vat} %</span><span>{lecygne.fmtAmount(tva, cur)}</span></div>
          <div className="grand"><span>Total TTC</span><span>{lecygne.fmtAmount(ttc, cur)}</span></div>
        </div></div>

        <div className="actions">
          {edit ? (<>
            <button className="btn" onClick={() => setEdit(false)}>Annuler</button>
            <button className="btn primary" onClick={saveLines} disabled={busy}>{busy ? "…" : "Enregistrer les lignes"}</button>
          </>) : (<>
            <button className="btn" onClick={onClose}>Fermer</button>
            <button className="btn" onClick={printBL}>Imprimer le BL</button>
            {!facturee && <button className="btn" onClick={startEdit}>Modifier les lignes</button>}
            {!facturee
              ? <button className="btn primary" onClick={facturer} disabled={busy}>{busy ? "…" : "Générer la facture"}</button>
              : <span className="pill green" style={{ alignSelf: "center" }}>Facturée · {cmd.no_facture}</span>}
          </>)}
        </div>
      </div>
    </div>
  );
}

function ScreenCommandes({ ctx }) {
  const [statut, setStatut] = React.useState("");
  const [search, setSearch] = React.useState("");
  const [creating, setCreating] = React.useState(false);
  const [detailNo, setDetailNo] = React.useState(null);
  React.useEffect(() => {
    if (ctx.seed && ctx.seed.route === "commandes") {
      setSearch(ctx.seed.term);
      if (/^\d+$/.test(ctx.seed.term)) setDetailNo(Number(ctx.seed.term));
    }
  }, [ctx.seed]);
  const list = lecygne.useCommandes({ statut: statut || undefined, search });
  const clientName = (c) => (c.client && (c.client.societe || c.client.nom_client)) || `#${c.code_client}`;

  async function changeStatut(no, s) {
    await lecygne.commandes.setStatut(no, s);
    list.reload();
  }

  return (
    <div>
      <div className="topbar"><h1>Commandes</h1>
        <input className="search" placeholder="Rechercher client, n°…"
          value={search} onChange={(e) => setSearch(e.target.value)} /></div>

      {creating
        ? <CommandeForm ctx={ctx} onClose={() => setCreating(false)} onSaved={() => list.reload()} />
        : (
          <div className="card">
            <div className="toolbar">
              <select className="field" style={{ width: 200 }} value={statut} onChange={(e) => setStatut(e.target.value)}>
                <option value="">Tous les statuts</option>
                {Object.entries(lecygne.STATUTS).map(([k, v]) => <option key={k} value={k}>{v.fr}</option>)}
              </select>
              <div className="grow" />
              <button className="btn" onClick={() => window.exportCsv("commandes.csv", list.data || [], [
                { key: "no_commande", label: "N°" },
                { label: "Client", map: clientName },
                { label: "Date dépôt", map: (c) => lecygne.fmtDate(c.date_commande) },
                { label: "À livrer", map: (c) => lecygne.fmtDate(c.a_livrer_avant) },
                { label: "Statut", map: (c) => (lecygne.STATUTS[c.statut] || {}).fr || c.statut },
                { key: "no_facture", label: "Facture" },
              ])}>⤓ Exporter</button>
              <button className="btn primary" onClick={() => setCreating(true)}>＋ Nouvelle commande</button>
            </div>
            {list.loading ? <div className="spinner">Chargement…</div> : (
              <div className="tbl-wrap">
                <table>
                  <thead><tr>
                    <th>N°</th><th>Client</th><th>Date dépôt</th><th>À livrer</th><th>Statut</th><th>Action</th>
                  </tr></thead>
                  <tbody>
                    {(list.data || []).map((c) => {
                      const st = lecygne.STATUTS[c.statut] || {};
                      return (
                        <tr key={c.no_commande} className="row-click" onClick={() => setDetailNo(c.no_commande)}>
                          <td>#{c.no_commande}</td>
                          <td>{clientName(c)}</td>
                          <td>{lecygne.fmtDate(c.date_commande)}</td>
                          <td>{lecygne.fmtDate(c.a_livrer_avant)}</td>
                          <td><span className={"pill " + (st.cls || "gray")}>{st.fr || c.statut}</span></td>
                          <td onClick={(e) => e.stopPropagation()}><select className="field sm" style={{ width: 150, height: 32 }}
                            value={c.statut} onChange={(e) => changeStatut(c.no_commande, e.target.value)}>
                            {Object.entries(lecygne.STATUTS).map(([k, v]) => <option key={k} value={k}>{v.fr}</option>)}
                          </select></td>
                        </tr>
                      );
                    })}
                    {!(list.data || []).length &&
                      <tr><td colSpan="6" className="empty">Aucune commande.</td></tr>}
                  </tbody>
                </table>
              </div>
            )}
          </div>
        )}

      {detailNo != null && (
        <CommandeDetail ctx={ctx} no={detailNo}
          onClose={() => setDetailNo(null)} onChanged={() => list.reload()} />
      )}
    </div>
  );
}
