/* Kay Construction — Document generators (part 1): shared helpers + RAB, Penawaran, SPK. */

const RAB_CATEGORIES = ["Persiapan", "Pekerjaan Tanah", "Struktur/Beton", "Dinding", "Atap", "Finishing", "MEP", "Lainnya"];
const UNITS = ["m2", "m3", "m'", "unit", "ls", "titik", "bh", "kg", "set"];
const RAB_STATUSES = ["draft", "final", "disetujui"];
const QUO_STATUSES = ["draft", "terkirim", "disetujui", "ditolak", "kadaluarsa"];
const SPK_STATUSES = ["draft", "aktif", "selesai", "dibatalkan"];
const INV_STATUSES = ["draft", "terkirim", "lunas sebagian", "lunas", "jatuh tempo", "dibatalkan"];

/* save: generate number if new, then upsert. returns saved doc */
function saveDoc(coll, type, doc) {
  const d = { ...doc };
  if (!d.number) d.number = S.generateDocNumber(type);
  return S.upsert(coll, d);
}
function newItem() { return { id: S.uid("it"), category: "", description: "", volume: 1, unit: "ls", unitPrice: 0 }; }

/* ---------------- items editor ---------------- */
function ItemsEditor({ items, onChange, showCategory }) {
  const [picker, setPicker] = useState(false);
  const [savedId, setSavedId] = useState(null);
  const set = (id, k, v) => onChange(items.map((it) => it.id === id ? { ...it, [k]: v } : it));
  const del = (id) => onChange(items.filter((it) => it.id !== id));
  const add = () => onChange([...items, newItem()]);
  const saveRow = (it) => { if (window.saveRowToBook && window.saveRowToBook(it)) { setSavedId(it.id); setTimeout(() => setSavedId(null), 1400); } };
  return (
    <div>
      <div className="table-wrap">
        <table className="items-tbl">
          <thead><tr>
            {showCategory && <th style={{ width: "16%" }}>{t("common.category")}</th>}
            <th>{t("common.description")}</th>
            <th style={{ width: 80 }} className="num">{t("doc.item.volume")}</th>
            <th style={{ width: 80 }}>{t("doc.item.unit")}</th>
            <th style={{ width: 150 }} className="num">{t("doc.item.unitPrice")}</th>
            <th style={{ width: 150 }} className="num">{t("doc.item.amount")}</th>
            <th style={{ width: 60 }}></th>
          </tr></thead>
          <tbody>
            {items.map((it) => (
              <tr key={it.id}>
                {showCategory && <td>
                  <input className="input" list="cat-list" value={it.category} placeholder="—" onChange={(e) => set(it.id, "category", e.target.value)} />
                </td>}
                <td><input className="input" value={it.description} onChange={(e) => set(it.id, "description", e.target.value)} placeholder={t("common.description")} /></td>
                <td><input className="input num" inputMode="decimal" value={it.volume} onChange={(e) => set(it.id, "volume", parseFloat(e.target.value.replace(",", ".")) || 0)} /></td>
                <td><input className="input" list="unit-list" value={it.unit} onChange={(e) => set(it.id, "unit", e.target.value)} /></td>
                <td><input className="input num" inputMode="numeric" value={it.unitPrice ? S.formatNumber(it.unitPrice) : ""} onChange={(e) => set(it.id, "unitPrice", parseInt(e.target.value.replace(/[^0-9]/g, ""), 10) || 0)} /></td>
                <td><input className="input num cell-amt" readOnly value={S.formatNumber((Number(it.volume) || 0) * (Number(it.unitPrice) || 0))} /></td>
                <td><div className="row" style={{ gap: 0, justifyContent: "flex-end" }}>
                  <Button variant="ghost" size="sm" icon={savedId === it.id ? "check" : "copy"} title={savedId === it.id ? t("pb.saved") : t("pb.saveItem")} onClick={() => saveRow(it)} />
                  <Button variant="ghost" size="sm" icon="trash" onClick={() => del(it.id)} />
                </div></td>
              </tr>
            ))}
            {items.length === 0 && <tr><td colSpan={showCategory ? 7 : 6} className="muted tiny" style={{ padding: 14 }}>{t("common.empty")}</td></tr>}
          </tbody>
        </table>
      </div>
      <datalist id="cat-list">{RAB_CATEGORIES.map((c) => <option key={c} value={c} />)}</datalist>
      <datalist id="unit-list">{UNITS.map((u) => <option key={u} value={u} />)}</datalist>
      <div className="row" style={{ gap: 10, marginTop: 12, flexWrap: "wrap" }}>
        <Button size="sm" icon="plus" onClick={add}>{t("doc.addItem")}</Button>
        <Button size="sm" icon="rab" onClick={() => setPicker(true)}>{t("pb.pick")}</Button>
      </div>
      {picker && window.PricePickerModal && <PricePickerModal onClose={() => setPicker(false)} onPick={(rows) => onChange([...items.filter((x) => x.description || x.unitPrice), ...rows])} />}
    </div>
  );
}

/* ---------------- totals box ---------------- */
function TotalsBox({ doc, onChange, editable }) {
  const tt = S.docTotals(doc);
  return (
    <div className="card pad" style={{ maxWidth: 380, marginLeft: "auto" }}>
      <div className="stat-line"><span>{t("common.subtotal")}</span><span className="v">{S.formatRupiah(tt.subtotal)}</span></div>
      <div className="stat-line"><span>{t("common.discount")}</span>
        {editable ? <div style={{ width: 150 }}><MoneyInput value={doc.discount || 0} onChange={(v) => onChange({ ...doc, discount: v })} /></div>
          : <span className="v">{S.formatRupiah(doc.discount || 0)}</span>}
      </div>
      <div className="stat-line"><span>{t("common.ppn")}
        {editable ? <input className="input num" style={{ width: 56, display: "inline-block", marginLeft: 8, padding: "3px 6px" }} value={doc.ppnPercent || 0} onChange={(e) => onChange({ ...doc, ppnPercent: parseFloat(e.target.value) || 0 })} />
          : <span> {tt.ppnPercent}%</span>}{editable && " %"}</span>
        <span className="v">{S.formatRupiah(tt.ppnAmount)}</span>
      </div>
      <div className="divider" style={{ margin: "12px 0" }}></div>
      <div className="stat-line" style={{ fontWeight: 600 }}><span className="serif" style={{ fontSize: 17 }}>{t("common.total")}</span><span className="v serif" style={{ fontSize: 19 }}>{S.formatRupiah(tt.total)}</span></div>
    </div>
  );
}

/* ---------------- editor chrome: header bar with actions ---------------- */
function EditorHead({ backPath, backLabel, code, title, statusNode, actions }) {
  return (
    <div>
      <div className="row" style={{ gap: 10, marginBottom: 14 }}><Button variant="ghost" size="sm" icon="back" onClick={() => go(backPath)}>{backLabel}</Button></div>
      <div className="page-head">
        <div>
          <div className="row" style={{ gap: 12, marginBottom: 6 }}>{code && <span className="mono subtle">{code}</span>}{statusNode}</div>
          <h1 className="page-title" style={{ fontSize: 30 }}>{title}</h1>
        </div>
        <div className="row" style={{ gap: 10 }}>{actions}</div>
      </div>
    </div>
  );
}

function ProjectSelect({ value, onChange }) {
  const projects = S.all("projects");
  return (
    <Select value={value || ""} onChange={(e) => onChange(e.target.value)}>
      <option value="">— {t("common.project")} —</option>
      {projects.map((p) => <option key={p.id} value={p.id}>{p.code} · {p.name}</option>)}
    </Select>
  );
}
function StatusSelect({ value, onChange, options }) {
  return <Select value={value} onChange={(e) => onChange(e.target.value)}>{options.map((s) => <option key={s} value={s}>{tStatus(s)}</option>)}</Select>;
}

/* ===================================================================
   RAB
   =================================================================== */
function RabList() {
  useStore();
  const [lang] = useLang();
  const [q, setQ] = useState(""); const [filter, setFilter] = useState("all");
  const [confirm, confirmNode] = useConfirm();
  let rows = S.all("rab").slice().sort((a, b) => (b.date || "").localeCompare(a.date || ""));
  if (filter !== "all") rows = rows.filter((r) => r.status === filter);
  if (q) rows = rows.filter((r) => (r.number + r.title + S.projectName(r.projectId)).toLowerCase().includes(q.toLowerCase()));
  return (
    <div>
      <PageHead title={t("doc.rab")} sub={lang === "en" ? "Internal cost breakdowns (Bill of Quantities)." : "Rincian anggaran biaya internal."}>
        <Button variant="primary" icon="plus" onClick={() => go("#/dokumen/rab/baru")}>{t("common.new")} {t("doc.rab")}</Button>
      </PageHead>
      <div className="toolbar">
        <div className="search"><Icon name="search" className="ico" /><Input value={q} onChange={(e) => setQ(e.target.value)} placeholder={t("common.search")} /></div>
        <div className="filters"><span className={"chip" + (filter === "all" ? " on" : "")} onClick={() => setFilter("all")}>{t("common.all")}</span>
          {RAB_STATUSES.map((s) => <span key={s} className={"chip" + (filter === s ? " on" : "")} onClick={() => setFilter(s)}>{tStatus(s)}</span>)}</div>
      </div>
      <div className="card"><div className="table-wrap"><table className="tbl">
        <thead><tr><th>{t("common.number")}</th><th>{t("common.project")}</th><th>{t("common.title")}</th><th>{t("common.status")}</th><th className="num">{t("common.total")}</th><th>{t("common.date")}</th><th></th></tr></thead>
        <tbody>
          {rows.length === 0 && <tr><td colSpan="7"><Empty icon="rab" title={t("common.empty")} /></td></tr>}
          {rows.map((r) => (
            <tr key={r.id} className="clickable" onClick={() => go("#/dokumen/rab/" + r.id)}>
              <td className="mono" style={{ fontWeight: 600, fontSize: 12 }}>{r.number}</td>
              <td>{S.projectName(r.projectId)}</td><td>{r.title}</td>
              <td><StatusBadge status={r.status} /></td>
              <td className="num" style={{ fontWeight: 600 }}>{S.formatRupiah(S.docTotals(r).total)}</td>
              <td>{S.shortDate(r.date)}</td>
              <td className="num" onClick={(e) => e.stopPropagation()}><Button variant="ghost" size="sm" icon="trash" onClick={() => confirm(t("common.confirmDelete"), () => S.remove("rab", r.id))} /></td>
            </tr>
          ))}
        </tbody>
      </table></div></div>
      {confirmNode}
    </div>
  );
}

function RabEditor({ id, createNew }) {
  useStore();
  const [lang] = useLang();
  const qp = routeQuery(window.location.hash);
  const existing = id ? S.find("rab", id) : null;
  const [doc, setDoc] = useState(existing || {
    number: "", date: S.todayISO(), version: "Rev. 1", projectId: qp.project || "", title: "", status: "draft",
    items: [newItem()], discount: 0, ppnPercent: S.getDB().company.defaultPpn || 11, note: ""
  });
  const [confirm, confirmNode] = useConfirm();
  if (id && !existing) return <Empty icon="rab" title={t("common.empty")} action={<Button onClick={() => go("#/dokumen/rab")}>{t("common.back")}</Button>} />;
  const set = (patch) => setDoc((o) => ({ ...o, ...patch }));
  const recap = S.rabCategoryRecap(doc);

  const save = () => { const s = saveDoc("rab", "rab", doc); setDoc(s); if (createNew) go("#/dokumen/rab/" + s.id); };
  const makeQuotation = () => {
    const saved = saveDoc("rab", "rab", doc); setDoc(saved);
    const quo = saveDoc("quotations", "quotation", {
      date: S.todayISO(), validUntil: S.addDays(S.todayISO(), 30), projectId: saved.projectId, rabId: saved.id,
      status: "draft", language: lang, items: (saved.items || []).map((it) => ({ ...it, id: S.uid("qi") })),
      discount: saved.discount, ppnPercent: saved.ppnPercent, paymentTerms: "", note: ""
    });
    go("#/dokumen/penawaran/" + quo.id);
  };

  return (
    <div>
      <EditorHead backPath="#/dokumen/rab" backLabel={t("doc.rab")} code={doc.number || t("common.new")} title={doc.title || t("doc.rab")}
        statusNode={<StatusBadge status={doc.status} />}
        actions={<>
          {!createNew && doc.number && <Button icon="quotation" onClick={makeQuotation}>{t("doc.makeQuotation")}</Button>}
          {!createNew && doc.number && <Button icon="copy" onClick={() => { const c = S.duplicateDoc("rab", "rab", doc.id); if (c) go("#/dokumen/rab/" + c.id); }}>{t("common.duplicate")}</Button>}
          {!createNew && doc.number && <Button icon="print" onClick={() => { save(); go("#/cetak/rab/" + doc.id); }}>{t("common.print")}</Button>}
          <Button variant="primary" icon="check" onClick={save}>{t("common.save")}</Button>
        </>} />

      <div className="card pad" style={{ marginBottom: 20 }}>
        <div className="form-grid">
          <Field label={t("common.project")}><ProjectSelect value={doc.projectId} onChange={(v) => set({ projectId: v })} /></Field>
          <Field label={t("common.title")}><Input value={doc.title} onChange={(e) => set({ title: e.target.value })} placeholder={lang === "en" ? "e.g. BoQ Villa Uluwatu" : "mis. RAB Villa Uluwatu"} /></Field>
          <Field label={t("common.date")}><Input type="date" value={doc.date} onChange={(e) => set({ date: e.target.value })} /></Field>
          <Field label={t("doc.version")}><Input value={doc.version} onChange={(e) => set({ version: e.target.value })} /></Field>
          <Field label={t("common.status")}><StatusSelect value={doc.status} onChange={(v) => set({ status: v })} options={RAB_STATUSES} /></Field>
          <Field label={t("common.note")} optional><Input value={doc.note} onChange={(e) => set({ note: e.target.value })} /></Field>
        </div>
      </div>

      <div className="card pad" style={{ marginBottom: 20 }}>
        <h2 className="section">{t("common.description")}</h2>
        <ItemsEditor items={doc.items} onChange={(items) => set({ items })} showCategory />
      </div>

      <div className="grid-2" style={{ alignItems: "start" }}>
        <div className="card pad">
          <h2 className="section">{t("doc.recap")}</h2>
          <div className="cat-recap">
            {recap.length === 0 && <div className="muted tiny">{t("common.empty")}</div>}
            {recap.map((r) => <div key={r.category} className="stat-line"><span>{r.category || "—"}</span><span className="v">{S.formatRupiah(r.amount)}</span></div>)}
          </div>
        </div>
        <TotalsBox doc={doc} onChange={setDoc} editable />
      </div>
      {confirmNode}
    </div>
  );
}

/* ===================================================================
   PENAWARAN (Quotation)
   =================================================================== */
function QuotationList() {
  useStore();
  const [lang] = useLang();
  const [q, setQ] = useState(""); const [filter, setFilter] = useState("all");
  const [confirm, confirmNode] = useConfirm();
  let rows = S.all("quotations").slice().sort((a, b) => (b.date || "").localeCompare(a.date || ""));
  if (filter !== "all") rows = rows.filter((r) => r.status === filter);
  if (q) rows = rows.filter((r) => (r.number + S.projectName(r.projectId)).toLowerCase().includes(q.toLowerCase()));
  return (
    <div>
      <PageHead title={t("doc.quotation")} sub={lang === "en" ? "Client-facing quotations." : "Penawaran untuk klien."}>
        <Button variant="primary" icon="plus" onClick={() => go("#/dokumen/penawaran/baru")}>{t("common.new")} {t("doc.quotation")}</Button>
      </PageHead>
      <div className="toolbar">
        <div className="search"><Icon name="search" className="ico" /><Input value={q} onChange={(e) => setQ(e.target.value)} placeholder={t("common.search")} /></div>
        <div className="filters"><span className={"chip" + (filter === "all" ? " on" : "")} onClick={() => setFilter("all")}>{t("common.all")}</span>
          {QUO_STATUSES.map((s) => <span key={s} className={"chip" + (filter === s ? " on" : "")} onClick={() => setFilter(s)}>{tStatus(s)}</span>)}</div>
      </div>
      <div className="card"><div className="table-wrap"><table className="tbl">
        <thead><tr><th>{t("common.number")}</th><th>{t("common.project")}</th><th>{t("common.status")}</th><th>{t("doc.validUntil")}</th><th className="num">{t("common.total")}</th><th>Lang</th><th></th></tr></thead>
        <tbody>
          {rows.length === 0 && <tr><td colSpan="7"><Empty icon="quotation" title={t("common.empty")} /></td></tr>}
          {rows.map((r) => (
            <tr key={r.id} className="clickable" onClick={() => go("#/dokumen/penawaran/" + r.id)}>
              <td className="mono" style={{ fontWeight: 600, fontSize: 12 }}>{r.number}</td>
              <td>{S.projectName(r.projectId)}</td><td><StatusBadge status={r.status} /></td>
              <td>{S.shortDate(r.validUntil)}</td>
              <td className="num" style={{ fontWeight: 600 }}>{S.formatRupiah(S.docTotals(r).total)}</td>
              <td><Badge tone="neutral">{(r.language || "id").toUpperCase()}</Badge></td>
              <td className="num" onClick={(e) => e.stopPropagation()}><Button variant="ghost" size="sm" icon="trash" onClick={() => confirm(t("common.confirmDelete"), () => S.remove("quotations", r.id))} /></td>
            </tr>
          ))}
        </tbody>
      </table></div></div>
      {confirmNode}
    </div>
  );
}

function QuotationEditor({ id, createNew }) {
  useStore();
  const [lang] = useLang();
  const qp = routeQuery(window.location.hash);
  const existing = id ? S.find("quotations", id) : null;
  const [doc, setDoc] = useState(existing || {
    number: "", date: S.todayISO(), validUntil: S.addDays(S.todayISO(), 30), projectId: qp.project || "", rabId: qp.from || "",
    status: "draft", language: lang, items: [newItem()], discount: 0, ppnPercent: S.getDB().company.defaultPpn || 11,
    paymentTerms: lang === "en" ? (S.getDB().company.paymentTermsEn || "") : (S.getDB().company.paymentTermsId || ""), note: ""
  });
  if (id && !existing) return <Empty icon="quotation" title={t("common.empty")} action={<Button onClick={() => go("#/dokumen/penawaran")}>{t("common.back")}</Button>} />;
  const set = (patch) => setDoc((o) => ({ ...o, ...patch }));
  const save = () => { const s = saveDoc("quotations", "quotation", doc); setDoc(s); if (createNew) go("#/dokumen/penawaran/" + s.id); };
  const approveToProject = () => {
    const s = saveDoc("quotations", "quotation", { ...doc, status: "disetujui" }); setDoc(s);
    if (s.projectId) { const p = S.find("projects", s.projectId); if (p && p.status !== "berjalan" && p.status !== "selesai") S.upsert("projects", { ...p, status: "berjalan", contractValue: p.contractValue || S.docTotals(s).total }); }
  };

  return (
    <div>
      <EditorHead backPath="#/dokumen/penawaran" backLabel={t("doc.quotation")} code={doc.number || t("common.new")} title={t("doc.quotation")}
        statusNode={<StatusBadge status={doc.status} />}
        actions={<>
          {doc.status !== "disetujui" && doc.projectId && <Button icon="check" onClick={approveToProject}>{lang === "en" ? "Approve → Active" : "Setujui → Berjalan"}</Button>}
          {!createNew && doc.number && <Button icon="copy" onClick={() => { const c = S.duplicateDoc("quotations", "quotation", doc.id); if (c) go("#/dokumen/penawaran/" + c.id); }}>{t("common.duplicate")}</Button>}
          {!createNew && doc.number && <Button icon="print" onClick={() => { save(); go("#/cetak/penawaran/" + doc.id); }}>{t("common.print")}</Button>}
          <Button variant="primary" icon="check" onClick={save}>{t("common.save")}</Button>
        </>} />

      <div className="card pad" style={{ marginBottom: 20 }}>
        <div className="form-grid">
          <Field label={t("common.project")}><ProjectSelect value={doc.projectId} onChange={(v) => set({ projectId: v })} /></Field>
          <Field label={t("common.documentLang")}><DocLangToggle value={doc.language} onChange={(v) => set({ language: v })} /></Field>
          <Field label={t("common.date")}><Input type="date" value={doc.date} onChange={(e) => set({ date: e.target.value })} /></Field>
          <Field label={t("doc.validUntil")}><Input type="date" value={doc.validUntil} onChange={(e) => set({ validUntil: e.target.value })} /></Field>
          <Field label={t("common.status")}><StatusSelect value={doc.status} onChange={(v) => set({ status: v })} options={QUO_STATUSES} /></Field>
          {doc.rabId && <Field label={t("doc.fromRab")}><Input readOnly value={(S.find("rab", doc.rabId) || {}).number || "—"} /></Field>}
          <Field label={t("doc.paymentTerms")} optional full><Textarea value={doc.paymentTerms} onChange={(e) => set({ paymentTerms: e.target.value })} /></Field>
        </div>
      </div>

      <div className="card pad" style={{ marginBottom: 20 }}>
        <h2 className="section">{t("common.description")}</h2>
        <ItemsEditor items={doc.items} onChange={(items) => set({ items })} showCategory />
      </div>

      <div className="grid-2" style={{ alignItems: "start" }}>
        <div className="card pad"><Field label={t("common.note")} optional><Textarea value={doc.note} onChange={(e) => set({ note: e.target.value })} style={{ minHeight: 120 }} /></Field></div>
        <TotalsBox doc={doc} onChange={setDoc} editable />
      </div>
    </div>
  );
}

/* ===================================================================
   SPK (Work Order)
   =================================================================== */
function SpkList() {
  useStore();
  const [lang] = useLang();
  const [q, setQ] = useState(""); const [confirm, confirmNode] = useConfirm();
  let rows = S.all("workOrders").slice().sort((a, b) => (b.date || "").localeCompare(a.date || ""));
  if (q) rows = rows.filter((r) => (r.number + r.title + S.projectName(r.projectId)).toLowerCase().includes(q.toLowerCase()));
  return (
    <div>
      <PageHead title={t("doc.spk")} sub={lang === "en" ? "Work orders issued after a quotation is approved." : "Surat Perintah Kerja setelah penawaran disetujui."}>
        <Button variant="primary" icon="plus" onClick={() => go("#/dokumen/spk/baru")}>{t("common.new")} {t("nav.spk")}</Button>
      </PageHead>
      <div className="toolbar"><div className="search"><Icon name="search" className="ico" /><Input value={q} onChange={(e) => setQ(e.target.value)} placeholder={t("common.search")} /></div></div>
      <div className="card"><div className="table-wrap"><table className="tbl">
        <thead><tr><th>{t("common.number")}</th><th>{t("common.project")}</th><th>{t("common.title")}</th><th>{t("common.status")}</th><th className="num">{t("common.value")}</th><th>{t("common.date")}</th><th></th></tr></thead>
        <tbody>
          {rows.length === 0 && <tr><td colSpan="7"><Empty icon="spk" title={t("common.empty")} /></td></tr>}
          {rows.map((r) => (
            <tr key={r.id} className="clickable" onClick={() => go("#/dokumen/spk/" + r.id)}>
              <td className="mono" style={{ fontWeight: 600, fontSize: 12 }}>{r.number}</td>
              <td>{S.projectName(r.projectId)}</td><td>{r.title}</td>
              <td><StatusBadge status={r.status} /></td>
              <td className="num" style={{ fontWeight: 600 }}>{S.formatRupiah(r.value)}</td>
              <td>{S.shortDate(r.date)}</td>
              <td className="num" onClick={(e) => e.stopPropagation()}><Button variant="ghost" size="sm" icon="trash" onClick={() => confirm(t("common.confirmDelete"), () => S.remove("workOrders", r.id))} /></td>
            </tr>
          ))}
        </tbody>
      </table></div></div>
      {confirmNode}
    </div>
  );
}

function SpkEditor({ id, createNew }) {
  useStore();
  const [lang] = useLang();
  const qp = routeQuery(window.location.hash);
  const existing = id ? S.find("workOrders", id) : null;
  const quotations = S.all("quotations");
  const [doc, setDoc] = useState(existing || {
    number: "", date: S.todayISO(), projectId: qp.project || "", quotationId: "", title: "", scope: "",
    value: 0, startDate: "", endDate: "", status: "draft", language: lang, note: ""
  });
  if (id && !existing) return <Empty icon="spk" title={t("common.empty")} action={<Button onClick={() => go("#/dokumen/spk")}>{t("common.back")}</Button>} />;
  const set = (patch) => setDoc((o) => ({ ...o, ...patch }));
  const onPickQuotation = (qid) => {
    const quo = S.find("quotations", qid);
    if (!quo) return set({ quotationId: "" });
    const proj = S.find("projects", quo.projectId);
    const scope = (quo.items || []).filter((it) => it.description).map((it) => "• " + it.description + (it.volume ? " (" + S.formatNumber(it.volume) + " " + it.unit + ")" : "")).join("\n");
    set({
      quotationId: qid,
      projectId: quo.projectId || doc.projectId,
      value: S.docTotals(quo).total,
      title: doc.title || (proj ? (lang === "en" ? "Execution of " : "Pelaksanaan ") + proj.name : doc.title),
      scope: doc.scope || scope
    });
  };
  const save = () => { const s = saveDoc("workOrders", "workOrder", doc); setDoc(s); if (createNew) go("#/dokumen/spk/" + s.id); };
  return (
    <div>
      <EditorHead backPath="#/dokumen/spk" backLabel={t("doc.spk")} code={doc.number || t("common.new")} title={doc.title || t("doc.spk")}
        statusNode={<StatusBadge status={doc.status} />}
        actions={<>
          {!createNew && doc.number && <Button icon="copy" onClick={() => { const c = S.duplicateDoc("workOrders", "workOrder", doc.id); if (c) go("#/dokumen/spk/" + c.id); }}>{t("common.duplicate")}</Button>}
          {!createNew && doc.number && <Button icon="print" onClick={() => { save(); go("#/cetak/spk/" + doc.id); }}>{t("common.print")}</Button>}
          <Button variant="primary" icon="check" onClick={save}>{t("common.save")}</Button>
        </>} />
      <div className="card pad">
        <div className="form-grid">
          <Field label={t("common.project")}><ProjectSelect value={doc.projectId} onChange={(v) => set({ projectId: v })} /></Field>
          <Field label={t("common.documentLang")}><DocLangToggle value={doc.language} onChange={(v) => set({ language: v })} /></Field>
          <Field label={t("common.title")} full><Input value={doc.title} onChange={(e) => set({ title: e.target.value })} /></Field>
          <Field label={t("doc.relatedQuotation")} optional>
            <Select value={doc.quotationId || ""} onChange={(e) => onPickQuotation(e.target.value)}>
              <option value="">— {t("common.none")} —</option>
              {quotations.map((q) => <option key={q.id} value={q.id}>{q.number}{q.projectId ? " · " + S.projectName(q.projectId) : ""}</option>)}
            </Select>
          </Field>
          <Field label={t("common.status")}><StatusSelect value={doc.status} onChange={(v) => set({ status: v })} options={SPK_STATUSES} /></Field>
          <Field label={t("common.value")}><MoneyInput value={doc.value} onChange={(v) => set({ value: v })} /></Field>
          <Field label={t("common.date")}><Input type="date" value={doc.date} onChange={(e) => set({ date: e.target.value })} /></Field>
          <Field label={t("proj.startDate")} optional><Input type="date" value={doc.startDate} onChange={(e) => set({ startDate: e.target.value })} /></Field>
          <Field label={t("proj.targetDate")} optional><Input type="date" value={doc.endDate} onChange={(e) => set({ endDate: e.target.value })} /></Field>
          <Field label={t("doc.scope")} full><Textarea value={doc.scope} onChange={(e) => set({ scope: e.target.value })} style={{ minHeight: 100 }} /></Field>
          <Field label={t("common.note")} optional full><Textarea value={doc.note} onChange={(e) => set({ note: e.target.value })} /></Field>
        </div>
      </div>
    </div>
  );
}

Object.assign(window, {
  RAB_CATEGORIES, UNITS, RAB_STATUSES, QUO_STATUSES, SPK_STATUSES, INV_STATUSES,
  saveDoc, newItem, ItemsEditor, TotalsBox, EditorHead, ProjectSelect, StatusSelect,
  RabList, RabEditor, QuotationList, QuotationEditor, SpkList, SpkEditor
});
