// ============================================================
// BusManager — Modul Sewa (List + Form + Detail) — wired
// ============================================================

// ---- PrintMenu dropdown (portaled to body) ----
function PrintMenu({ rental, children, align = "right", upward = false }) {
  const [open, setOpen] = useState(false);
  const [coords, setCoords] = useState(null);
  const trigRef = useRef(null);
  const menuRef = useRef(null);

  const toggle = (e) => {
    e?.stopPropagation();
    if (open) { setOpen(false); return; }
    const el = trigRef.current;
    if (!el) return;
    const r = el.getBoundingClientRect();
    const next = {};
    if (align === "left") next.left = r.left;
    else next.right = window.innerWidth - r.right;
    if (upward) next.bottom = window.innerHeight - r.top + 6;
    else next.top = r.bottom + 6;
    setCoords(next);
    setOpen(true);
  };

  useEffect(() => {
    if (!open) return;
    const close = (e) => {
      if (menuRef.current?.contains(e.target)) return;
      if (trigRef.current?.contains(e.target)) return;
      setOpen(false);
    };
    const onEsc = (e) => { if (e.key === "Escape") setOpen(false); };
    const onScroll = () => setOpen(false);
    setTimeout(() => document.addEventListener("click", close), 0);
    document.addEventListener("keydown", onEsc);
    window.addEventListener("scroll", onScroll, true);
    return () => {
      document.removeEventListener("click", close);
      document.removeEventListener("keydown", onEsc);
      window.removeEventListener("scroll", onScroll, true);
    };
  }, [open]);

  const hasDP = (rental.dp || 0) > 0;
  const isLunas = rental.status === "lunas" || rental.status === "selesai";
  const isBatal = rental.status === "batal";

  const Item = ({ onClick, icon, label, hint, disabled }) => (
    <button className="pm-item" disabled={disabled} onClick={(e) => { e.stopPropagation(); if (disabled) return; onClick(); setOpen(false); }}>
      <div className="pm-ic">{icon}</div>
      <div style={{textAlign: "left", flex: 1, minWidth: 0}}>
        <div style={{fontWeight: 600, fontSize: 13}}>{label}</div>
        {hint && <div style={{fontSize: 11, color: "var(--ink-mute)", marginTop: 2}}>{hint}</div>}
      </div>
    </button>
  );

  // attach toggle to trigger child via ref
  const trigger = React.cloneElement(children, {
    ref: trigRef,
    onClick: (e) => { children.props.onClick?.(e); toggle(e); },
    "aria-expanded": open,
  });

  const menu = open && coords ? ReactDOM.createPortal(
    <div ref={menuRef} className="print-menu" style={{position: "fixed", ...coords}} onClick={e => e.stopPropagation()}>
      <div className="pm-section">CETAK DOKUMEN</div>
      <Item
        icon={<I.Receipt size={16} />}
        label={isLunas ? "Invoice (Lunas)" : "Invoice / Tagihan"}
        hint={isLunas ? "Invoice dengan status LUNAS" : "Dokumen tagihan untuk customer"}
        onClick={() => window.printInvoice(rental)}
        disabled={isBatal}
      />
      <Item
        icon={<I.PiggyBank size={16} />}
        label="Kwitansi DP"
        hint={hasDP ? `Tanda terima ${window.RP(rental.dp)}` : "Belum ada DP diterima"}
        disabled={!hasDP || isBatal}
        onClick={() => window.printKwitansi(rental, { mode: "dp" })}
      />
      <Item
        icon={<I.Star size={16} />}
        label="Kwitansi Pelunasan"
        hint={isLunas ? `Pembayaran lunas ${window.RP(rental.harga)}` : "Hanya untuk sewa Lunas / Selesai"}
        disabled={!isLunas}
        onClick={() => window.printKwitansi(rental, { mode: "lunas" })}
      />
    </div>,
    document.body
  ) : null;

  return <>{trigger}{menu}</>;
}
window.PrintMenu = PrintMenu;

function PelunasanModal({ open, rental, onClose, onConfirm }) {
  const sisa = rental ? Math.max(0, (rental.harga || 0) - (rental.dp || 0)) : 0;
  const cust = rental ? window.getCustomer(rental.customerId) : null;
  const bus = rental ? window.getBus(rental.busId) : null;
  const [metode, setMetode] = useState("transfer");
  const [catatan, setCatatan] = useState("");

  if (!open || !rental) return null;

  return (
    <Modal open={open} onClose={onClose} title="Pelunasan Sewa"
      icon={<I.Check size={20} style={{color: "var(--success)"}} />}>
      <div>
        <div style={{padding: 16, background: "var(--surface-sunken)", borderRadius: 10, marginBottom: 18}}>
          <div style={{display: "flex", justifyContent: "space-between", alignItems: "center", marginBottom: 8}}>
            <span className="mono" style={{fontSize: 12, color: "var(--ink-mute)", fontWeight: 600}}>{rental.kode}</span>
            <StatusBadge s={rental.status} />
          </div>
          <div style={{fontWeight: 700, fontSize: 15}}>{cust?.nama || "—"}</div>
          <div style={{fontSize: 12, color: "var(--ink-mute)", marginTop: 2}}>{rental.tujuan} · {bus?.kode} · {window.FDATE_SHORT(rental.start)}</div>
        </div>

        <div className="grid grid-3" style={{marginBottom: 18}}>
          <div className="mini-stat">
            <div className="lbl">Total Ongkos</div>
            <div className="val mono">{window.RP(rental.harga)}</div>
          </div>
          <div className="mini-stat">
            <div className="lbl">DP Diterima</div>
            <div className="val mono">{window.RP(rental.dp)}</div>
          </div>
          <div className="mini-stat">
            <div className="lbl">Sisa Bayar</div>
            <div className="val mono" style={{color: "var(--danger)", fontSize: 18}}>{window.RP(sisa)}</div>
          </div>
        </div>

        <div className="field mb-3">
          <label className="lbl">Metode Pembayaran</label>
          <select className="select" value={metode} onChange={e => setMetode(e.target.value)}>
            <option value="transfer">Transfer Bank</option>
            <option value="tunai">Tunai</option>
            <option value="qris">QRIS</option>
          </select>
        </div>

        <div className="field mb-3">
          <label className="lbl">Catatan Pelunasan <span style={{fontSize: 11, color: "var(--ink-mute)", fontWeight: 400}}>(opsional)</span></label>
          <input className="input" placeholder="cth: Transfer BCA 20 Mei 2026" value={catatan} onChange={e => setCatatan(e.target.value)} />
        </div>

        <div style={{padding: 14, background: "oklch(0.95 0.04 155)", borderRadius: 10, border: "1px solid oklch(0.8 0.08 155)", marginBottom: 18}}>
          <div style={{display: "flex", alignItems: "center", gap: 8}}>
            <I.Check size={16} style={{color: "var(--success)"}} />
            <div style={{fontSize: 13, fontWeight: 600, color: "oklch(0.32 0.10 155)"}}>
              Setelah dilunasi:
            </div>
          </div>
          <ul style={{margin: "8px 0 0 24px", padding: 0, fontSize: 12, color: "oklch(0.35 0.08 155)", lineHeight: 1.8}}>
            <li>Status sewa berubah menjadi <strong>Lunas</strong></li>
            <li>Kas masuk <strong>{window.RP(sisa)}</strong> tercatat otomatis (kategori: Pendapatan Sewa)</li>
            <li>Kwitansi pelunasan & invoice lunas siap dicetak</li>
          </ul>
        </div>

        <div style={{display: "flex", gap: 10, justifyContent: "flex-end", paddingTop: 14, borderTop: "1px solid var(--divider)"}}>
          <button className="btn" onClick={onClose}>Batal</button>
          <button className="btn btn-primary" onClick={() => onConfirm({ metode, catatan })} style={{background: "var(--success)", borderColor: "var(--success)"}}>
            <I.Check size={14} /> Lunasi {window.RP(sisa)}
          </button>
        </div>
      </div>
    </Modal>
  );
}

function ManajemenSewa({ initialAction, initialDetail, onClearInitial }) {
  const { actions, version } = useApp();
  void version;
  const [showForm, setShowForm] = useState(false);
  const [editId, setEditId] = useState(null);
  const [detailId, setDetailId] = useState(null);
  const [confirmCancel, setConfirmCancel] = useState(null);
  const [confirmDelete, setConfirmDelete] = useState(null);
  const [pelunasanRental, setPelunasanRental] = useState(null);
  const [search, setSearch] = useState("");
  const [filterStatus, setFilterStatus] = useState("all");
  const [filterBus, setFilterBus] = useState("all");
  const toast = useToast();

  useEffect(() => {
    if (initialAction === "new") { setShowForm(true); setEditId(null); onClearInitial?.(); }
    if (initialDetail) { setDetailId(initialDetail); onClearInitial?.(); }
  }, [initialAction, initialDetail]);

  const rentals = useMemo(() => {
    return window.RENTALS.filter(r => {
      const cust = window.getCustomer(r.customerId);
      const bus = window.getBus(r.busId);
      const q = search.toLowerCase();
      const m = !q ||
        r.kode?.toLowerCase().includes(q) ||
        cust?.nama.toLowerCase().includes(q) ||
        bus?.plate.toLowerCase().includes(q) ||
        r.tujuan?.toLowerCase().includes(q);
      const ms = filterStatus === "all" || r.status === filterStatus;
      const mb = filterBus === "all" || r.busId === parseInt(filterBus);
      return m && ms && mb;
    }).sort((a,b) => (b.start || "").localeCompare(a.start || ""));
  }, [search, filterStatus, filterBus, version]);

  const detail = detailId ? window.RENTALS.find(r => r.id === detailId) : null;

  const counts = {
    booking: window.RENTALS.filter(r => r.status === "booking").length,
    dp: window.RENTALS.filter(r => r.status === "dp").length,
    lunas: window.RENTALS.filter(r => r.status === "lunas").length,
    selesai: window.RENTALS.filter(r => r.status === "selesai").length,
    batal: window.RENTALS.filter(r => r.status === "batal").length,
  };

  const handleSave = (formData, andNew = false) => {
    try {
      const saved = actions.saveRental(formData);
      toast.push(editId ? `Sewa ${saved.kode} diperbarui` : `Sewa baru ${saved.kode} tersimpan`);
      if (andNew) {
        setEditId(null);
      } else {
        setShowForm(false);
        setEditId(null);
      }
    } catch (e) {
      toast.push(e.message, "error");
    }
  };

  const handleCancel = (id) => {
    try {
      actions.cancelRental(id);
      toast.push("Sewa dibatalkan");
      setDetailId(null);
    } catch (e) { toast.push(e.message, "error"); }
  };

  const handleDelete = (id) => {
    try {
      actions.deleteRental(id);
      toast.push("Sewa dihapus permanen");
      setDetailId(null);
    } catch (e) { toast.push(e.message, "error"); }
  };

  const handlePelunasan = (rental, opts) => {
    try {
      const updated = { ...rental, status: "lunas", dp: rental.harga, catatanPelunasan: opts.catatan, metodePelunasan: opts.metode, tanggalLunas: window.todayISO() };
      actions.saveRental(updated);
      toast.push(`Sewa ${rental.kode} telah dilunasi — ${window.RP(rental.harga)}`);
      setPelunasanRental(null);
    } catch (e) { toast.push(e.message, "error"); }
  };

  return (
    <div>
      <div className="page-head">
        <div className="ttl">
          <h2>Manajemen Sewa</h2>
          <div className="sub">{window.RENTALS.length} transaksi tercatat · {counts.booking + counts.dp} aktif menunggu pelunasan</div>
        </div>
        <div className="actions">
          <button className="btn" onClick={() => exportRentalsExcel(rentals)}><I.Download size={15} /> Export Excel</button>
          <button className="btn btn-primary" onClick={() => { setEditId(null); setShowForm(true); }}>
            <I.Plus size={15} /> Sewa Baru
          </button>
        </div>
      </div>

      {/* Status pills strip */}
      <div className="card mb-4" style={{padding: "12px 18px"}}>
        <div style={{display: "flex", gap: 16, alignItems: "center", flexWrap: "wrap"}}>
          {[
            { k: "all", l: "Semua", c: window.RENTALS.length, color: "var(--ink-2)" },
            { k: "booking", l: "Booking", c: counts.booking, color: "var(--st-booking)" },
            { k: "dp", l: "DP", c: counts.dp, color: "oklch(0.55 0.13 70)" },
            { k: "lunas", l: "Lunas", c: counts.lunas, color: "var(--st-lunas)" },
            { k: "selesai", l: "Selesai", c: counts.selesai, color: "var(--ink-mute)" },
            { k: "batal", l: "Batal", c: counts.batal, color: "var(--st-batal)" },
          ].map(s => (
            <button key={s.k}
              className={`btn ${filterStatus === s.k ? "btn-primary" : "btn-ghost"}`}
              style={filterStatus !== s.k ? {color: s.color, border: 0} : {}}
              onClick={() => setFilterStatus(s.k)}>
              {s.l}
              <span style={{
                fontSize: 11.5, fontWeight: 700, marginLeft: 4,
                padding: "1px 7px", borderRadius: 999,
                background: filterStatus === s.k ? "rgba(255,255,255,.2)" : "var(--surface-sunken)",
                color: filterStatus === s.k ? "white" : "var(--ink-2)"
              }}>{s.c}</span>
            </button>
          ))}
        </div>
      </div>

      <div className="card">
        <div className="card-head">
          <div className="toolbar" style={{margin: 0, flex: 1}}>
            <div className="search">
              <I.Search size={16} className="ic" />
              <input placeholder="Cari kode, penyewa, plat, tujuan..." value={search} onChange={e => setSearch(e.target.value)} />
            </div>
            <div className="chip-filter">
              <I.Bus size={14} style={{color: "var(--ink-mute)"}} />
              <select value={filterBus} onChange={e => setFilterBus(e.target.value)}>
                <option value="all">Semua Unit</option>
                {window.BUSES.map(b => <option key={b.id} value={b.id}>{b.kode}</option>)}
              </select>
            </div>
            <div className="sp" />
            <span style={{fontSize: 12, color: "var(--ink-mute)"}}>{rentals.length} hasil</span>
          </div>
        </div>

        <div className="tbl-wrap">
          <table className="tbl">
            <thead>
              <tr>
                <th>Kode</th>
                <th>Tanggal</th>
                <th>Penyewa</th>
                <th>Unit & Tujuan</th>
                <th className="right">Ongkos</th>
                <th className="right">DP</th>
                <th>Status</th>
                <th></th>
              </tr>
            </thead>
            <tbody>
              {rentals.map(r => {
                const cust = window.getCustomer(r.customerId);
                const bus = window.getBus(r.busId);
                return (
                  <tr key={r.id}>
                    <td className="mono" style={{fontSize: 12, color: "var(--ink-mute)", fontWeight: 600}}>{r.kode}</td>
                    <td>
                      <div style={{fontWeight: 600, fontSize: 13}}>{window.FDATE_SHORT(r.start)}</div>
                      {r.start !== r.end && <div className="cell-secondary">→ {window.FDATE_SHORT(r.end)}</div>}
                    </td>
                    <td>
                      <div style={{fontWeight: 600}}>{cust?.nama}</div>
                      <div className="cell-secondary">{cust?.jenis === "instansi" ? "Instansi" : "Perorangan"} · {cust?.phone}</div>
                    </td>
                    <td>
                      <div style={{fontWeight: 500, fontSize: 13}}>{r.tujuan}</div>
                      <div className="cell-secondary">{bus?.kode} · {bus?.plate}</div>
                    </td>
                    <td className="num right">{window.RP(r.harga)}</td>
                    <td className="num right">
                      {window.RP(r.dp)}
                      {r.harga > 0 && r.dp < r.harga && r.status !== "batal" && r.status !== "selesai" && (
                        <div style={{marginTop: 4, width: 70, marginLeft: "auto"}}>
                          <div className="prog"><div className="fill" style={{width: `${(r.dp/r.harga)*100}%`}} /></div>
                        </div>
                      )}
                    </td>
                    <td><StatusBadge s={r.status} /></td>
                    <td>
                      <div className="row-actions">
                        <button className="btn btn-sm btn-ghost btn-icon" onClick={() => setDetailId(r.id)} title="Detail"><I.Eye size={15} /></button>
                        <button className="btn btn-sm btn-ghost btn-icon" onClick={() => { setEditId(r.id); setShowForm(true); }} title="Edit"><I.Edit size={15} /></button>
                        {(r.status === "booking" || r.status === "dp") && (
                          <button className="btn btn-sm" style={{background: "var(--success)", color: "white", border: 0, fontWeight: 600, fontSize: 11.5}} onClick={() => setPelunasanRental(r)} title="Lunasi pembayaran">
                            <I.Check size={13} /> Lunasi
                          </button>
                        )}
                        <PrintMenu rental={r}>
                          <button className="btn btn-sm btn-ghost btn-icon" title="Cetak dokumen"><I.Print size={15} /></button>
                        </PrintMenu>
                      </div>
                    </td>
                  </tr>
                );
              })}
              {rentals.length === 0 && (
                <tr><td colSpan={8}><EmptyState ic={I.Bus} title="Belum ada transaksi sewa yang cocok" hint="Coba ubah filter atau buat sewa baru" /></td></tr>
              )}
            </tbody>
          </table>
        </div>

        <div style={{padding: "12px 18px", borderTop: "1px solid var(--divider)", display: "flex", alignItems: "center", gap: 10}}>
          <span style={{fontSize: 12, color: "var(--ink-mute)"}}>Menampilkan {rentals.length} dari {window.RENTALS.length} transaksi</span>
        </div>
      </div>

      {/* Form modal */}
      <Modal open={showForm} onClose={() => setShowForm(false)} wide
        title={editId ? "Edit Transaksi Sewa" : "Transaksi Sewa Baru"}
        icon={<I.Bus size={20} style={{color: "var(--brand)"}} />}>
        <SewaForm
          editingId={editId}
          onCancel={() => setShowForm(false)}
          onSave={(data, andNew) => handleSave(data, andNew)}
        />
      </Modal>

      {/* Detail drawer */}
      <Drawer open={!!detail} onClose={() => setDetailId(null)}
        title={detail?.kode}
        icon={<I.Receipt size={20} style={{color: "var(--brand)"}} />}
        footer={detail && <>
          {detail.status !== "batal" && detail.status !== "lunas" && detail.status !== "selesai" && (
            <button className="btn btn-danger" onClick={() => setConfirmCancel(detail.id)}>
              <I.X size={14} /> Batalkan
            </button>
          )}
          <div style={{flex: 1}} />
          {(detail.status === "booking" || detail.status === "dp") && (
            <button className="btn" style={{background: "var(--success)", color: "white", border: 0, fontWeight: 600}} onClick={() => { setPelunasanRental(detail); setDetailId(null); }}>
              <I.Check size={14} /> Lunasi
            </button>
          )}
          <PrintMenu rental={detail} align="left" upward>
            <button className="btn"><I.Print size={14} /> Cetak <I.ChevronDown size={12} /></button>
          </PrintMenu>
          <button className="btn btn-primary" onClick={() => { setEditId(detailId); setShowForm(true); setDetailId(null); }}>
            <I.Edit size={14} /> Edit
          </button>
        </>}>
        {detail && <RentalDetailContent rental={detail} onDelete={() => setConfirmDelete(detail.id)} onPelunasan={() => { setPelunasanRental(detail); setDetailId(null); }} />}
      </Drawer>

      <ConfirmDialog open={!!confirmCancel} onClose={() => setConfirmCancel(null)}
        onConfirm={() => handleCancel(confirmCancel)}
        title="Batalkan transaksi sewa?"
        confirmLabel="Ya, Batalkan"
        danger
        body={<>Sewa akan diubah ke status <strong>Batal</strong>. Catatan kas yang sudah tercatat tidak akan terhapus otomatis — pastikan refund DP dicatat manual jika perlu.</>}
      />

      <ConfirmDialog open={!!confirmDelete} onClose={() => setConfirmDelete(null)}
        onConfirm={() => handleDelete(confirmDelete)}
        title="Hapus permanen?"
        confirmLabel="Ya, Hapus"
        danger
        body={<>Transaksi sewa beserta seluruh entry kas auto-generate akan dihapus permanen. Aksi ini tidak dapat di-undo.</>}
      />

      <PelunasanModal
        open={!!pelunasanRental}
        rental={pelunasanRental}
        onClose={() => setPelunasanRental(null)}
        onConfirm={(opts) => handlePelunasan(pelunasanRental, opts)}
      />
    </div>
  );
}

function RentalDetailContent({ rental, onDelete, onPelunasan }) {
  const cust = window.getCustomer(rental.customerId);
  const sisa = Math.max(0, (rental.harga || 0) - (rental.dp || 0));
  const canLunasi = (rental.status === "booking" || rental.status === "dp") && sisa > 0;
  return (
    <div>
      <div style={{display: "flex", gap: 10, marginBottom: 18, alignItems: "center"}}>
        <StatusBadge s={rental.status} />
        <span className="mono" style={{fontSize: 12, color: "var(--ink-mute)"}}>{rental.kode}</span>
        {onDelete && (
          <button className="btn btn-sm btn-ghost btn-icon" style={{marginLeft: "auto"}} title="Hapus permanen" onClick={onDelete}>
            <I.Trash size={14} style={{color: "var(--danger)"}} />
          </button>
        )}
      </div>

      {canLunasi && (
        <div style={{padding: 14, background: "oklch(0.96 0.03 70)", border: "1px solid oklch(0.82 0.08 70)", borderRadius: 10, marginBottom: 18, display: "flex", alignItems: "center", gap: 12}}>
          <div style={{flex: 1}}>
            <div style={{fontWeight: 700, fontSize: 13, color: "oklch(0.35 0.10 70)"}}>Menunggu Pelunasan</div>
            <div style={{fontSize: 12, color: "oklch(0.45 0.08 70)", marginTop: 2}}>Sisa pembayaran: <strong className="mono">{window.RP(sisa)}</strong></div>
          </div>
          <button className="btn" style={{background: "var(--success)", color: "white", border: 0, fontWeight: 600}} onClick={onPelunasan}>
            <I.Check size={14} /> Lunasi Sekarang
          </button>
        </div>
      )}

      {(rental.status === "lunas" || rental.status === "selesai") && (
        <div style={{padding: 14, background: "oklch(0.95 0.04 155)", border: "1px solid oklch(0.8 0.08 155)", borderRadius: 10, marginBottom: 18, display: "flex", alignItems: "center", gap: 12}}>
          <I.Check size={18} style={{color: "var(--success)"}} />
          <div style={{flex: 1}}>
            <div style={{fontWeight: 700, fontSize: 13, color: "oklch(0.32 0.10 155)"}}>Pembayaran Lunas</div>
            <div style={{fontSize: 12, color: "oklch(0.4 0.08 155)", marginTop: 2}}>
              Total {window.RP(rental.harga)} telah diterima
              {rental.tanggalLunas && <span> · {window.FDATE(rental.tanggalLunas)}</span>}
              {rental.metodePelunasan && <span> · {rental.metodePelunasan}</span>}
            </div>
          </div>
          <button className="btn btn-sm" style={{fontWeight: 600}} onClick={() => window.printKwitansi(rental, { mode: "lunas" })}>
            <I.Print size={13} /> Cetak Kwitansi
          </button>
        </div>
      )}

      <div className="kv mb-4">
        <span className="k">Tanggal</span>
        <span className="v">{window.FDATE(rental.start)}{rental.start !== rental.end ? ` – ${window.FDATE(rental.end)}` : ""}</span>
        <span className="k">Penyewa</span>
        <span className="v">{cust?.nama}<div style={{fontSize: 12, color: "var(--ink-mute)", fontWeight: 400}}>{cust?.phone}</div></span>
        <span className="k">Unit Bus</span>
        <span className="v"><BusChip id={rental.busId} /></span>
        <span className="k">Tujuan</span>
        <span className="v">{rental.tujuan}</span>
        <span className="k">Penjemputan</span>
        <span className="v">{rental.lokasi}<div style={{fontSize: 12, color: "var(--ink-mute)", fontWeight: 400}}>jam {rental.jam}</div></span>
        <span className="k">Sopir</span>
        <span className="v">
          {rental.driverIds?.length > 0 ? rental.driverIds.map(id => window.getDriver(id)?.nama).join(", ") : <em style={{color: "var(--ink-mute)"}}>belum diassign</em>}
        </span>
        <span className="k">Catatan</span>
        <span className="v">{rental.catatan || <em style={{color: "var(--ink-mute)"}}>—</em>}</span>
      </div>

      <div style={{borderTop: "1px solid var(--divider)", paddingTop: 16}}>
        <div className="fs-title">Pembayaran</div>
        <div className="grid grid-3">
          <div className="mini-stat">
            <div className="lbl">Ongkos Sewa</div>
            <div className="val mono">{window.RP(rental.harga)}</div>
          </div>
          <div className="mini-stat">
            <div className="lbl">DP Diterima</div>
            <div className="val mono">{window.RP(rental.dp)}</div>
          </div>
          <div className="mini-stat">
            <div className="lbl">Sisa</div>
            <div className="val mono" style={{color: rental.harga - rental.dp > 0 ? "var(--danger)" : "var(--success)"}}>
              {window.RP(Math.max(0, rental.harga - rental.dp))}
            </div>
          </div>
        </div>
      </div>

      {/* Linked cash entries */}
      <div style={{marginTop: 18}}>
        <div className="fs-title">Riwayat Kas Terkait</div>
        {window.CASH_TX.filter(t => t.rentalId === rental.id).length === 0
          ? <div style={{fontSize: 12, color: "var(--ink-mute)", padding: "8px 0"}}>Belum ada entry kas terkait.</div>
          : window.CASH_TX.filter(t => t.rentalId === rental.id).map(t => (
            <div key={t.id} style={{display: "flex", padding: "8px 0", borderBottom: "1px solid var(--divider)", fontSize: 13, alignItems: "center"}}>
              <div style={{flex: 1}}>
                <div>{t.deskripsi}</div>
                <div style={{fontSize: 11, color: "var(--ink-mute)"}}>{window.FDATE(t.tanggal)} · {window.getCat(t.catId)?.nama}</div>
              </div>
              <div className="mono" style={{fontWeight: 600, color: t.tipe === "masuk" ? "var(--success)" : "var(--danger)"}}>
                {t.tipe === "masuk" ? "+" : "−"}{window.RP(t.jumlah)}
              </div>
            </div>
          ))
        }
      </div>
    </div>
  );
}

// ============================================================
// SEWA FORM — wired
// ============================================================
function SewaForm({ editingId, onCancel, onSave }) {
  const { actions } = useApp();
  const existing = editingId ? window.RENTALS.find(r => r.id === editingId) : null;
  const [showNewCust, setShowNewCust] = useState(false);
  const [errors, setErrors] = useState({});
  const toast = useToast();

  const [f, setF] = useState(existing ? {
    ...existing,
    busId: String(existing.busId),
    customerId: String(existing.customerId),
    harga: String(existing.harga),
    dp: String(existing.dp),
  } : {
    start: window.todayISO ? window.todayISO() : "2026-05-25",
    end: window.todayISO ? window.todayISO() : "2026-05-25",
    busId: "", customerId: "",
    tujuan: "", lokasi: "", jam: "07:00",
    driverIds: [],
    harga: "", dp: "",
    status: "booking",
    catatan: "",
  });
  const set = (k, v) => { setF(x => ({...x, [k]: v})); setErrors(e => ({ ...e, [k]: null })); };

  // Auto-set status when dp changes
  useEffect(() => {
    const harga = parseInt(f.harga) || 0;
    const dp = parseInt(f.dp) || 0;
    if (harga > 0 && dp >= harga && f.status !== "lunas" && f.status !== "selesai" && f.status !== "batal") {
      setF(x => ({ ...x, status: "lunas" }));
    } else if (dp > 0 && dp < harga && f.status === "booking") {
      setF(x => ({ ...x, status: "dp" }));
    }
  }, [f.harga, f.dp]);

  // Conflict detection
  const busConflict = useMemo(() => {
    if (!f.busId || !f.start) return null;
    return window.RENTALS.find(r => {
      if (r.id === editingId) return false;
      if (r.busId !== parseInt(f.busId)) return false;
      if (r.status === "batal") return false;
      const s = new Date(r.start), e = new Date(r.end);
      const fs = new Date(f.start), fe = new Date(f.end || f.start);
      return !(fe < s || fs > e);
    });
  }, [f.busId, f.start, f.end, editingId]);

  const driverConflicts = useMemo(() => {
    if (!f.driverIds?.length || !f.start) return [];
    return f.driverIds.flatMap(did => {
      const c = window.RENTALS.find(r => {
        if (r.id === editingId) return false;
        if (!r.driverIds?.includes(did)) return false;
        if (r.status === "batal") return false;
        const s = new Date(r.start), e = new Date(r.end);
        const fs = new Date(f.start), fe = new Date(f.end || f.start);
        return !(fe < s || fs > e);
      });
      return c ? [{ driverId: did, conflict: c }] : [];
    });
  }, [f.driverIds, f.start, f.end, editingId]);

  const sisa = (parseInt(f.harga) || 0) - (parseInt(f.dp) || 0);

  const validate = () => {
    const e = {};
    if (!f.start) e.start = "wajib";
    if (!f.end) e.end = "wajib";
    if (new Date(f.end) < new Date(f.start)) e.end = "Tanggal selesai tidak boleh sebelum tanggal mulai";
    if (!f.busId) e.busId = "Pilih unit bus";
    if (!f.customerId) e.customerId = "Pilih penyewa";
    if (!f.tujuan?.trim()) e.tujuan = "Tujuan wajib diisi";
    if (!f.harga || parseInt(f.harga) <= 0) e.harga = "Ongkos sewa wajib > 0";
    if (parseInt(f.dp) > parseInt(f.harga)) e.dp = "DP tidak boleh > ongkos sewa";
    setErrors(e);
    return Object.keys(e).length === 0;
  };

  const submit = (andNew) => {
    if (!validate()) {
      toast.push("Periksa kembali isian form", "error");
      return;
    }
    const payload = {
      ...(editingId ? { id: editingId, kode: existing.kode } : {}),
      start: f.start,
      end: f.end || f.start,
      busId: parseInt(f.busId),
      customerId: parseInt(f.customerId),
      tujuan: f.tujuan.trim(),
      lokasi: f.lokasi?.trim() || "",
      jam: f.jam || "—",
      driverIds: f.driverIds || [],
      harga: parseInt(f.harga) || 0,
      dp: parseInt(f.dp) || 0,
      status: f.status,
      catatan: f.catatan || "",
    };
    onSave(payload, andNew);
    if (andNew) {
      // reset form for new entry
      setF({
        start: f.start, end: f.start,
        busId: "", customerId: "", tujuan: "", lokasi: "", jam: "07:00",
        driverIds: [], harga: "", dp: "", status: "booking", catatan: "",
      });
      setErrors({});
    }
  };

  return (
    <div>
      {/* Section 1: Periode */}
      <div className="fs-card" style={{padding: 0, marginBottom: 18}}>
        <div className="fs-title"><span className="num">1</span>PERIODE SEWA</div>
        <div className="field-row" style={{gridTemplateColumns: "1fr 1fr 1fr"}}>
          <div className="field">
            <label className="lbl">Tanggal Mulai <span className="req">*</span></label>
            <input type="date" className={`input ${errors.start ? "err" : ""}`} value={f.start} onChange={e => set("start", e.target.value)} />
          </div>
          <div className="field">
            <label className="lbl">Tanggal Selesai <span className="req">*</span></label>
            <input type="date" className={`input ${errors.end ? "err" : ""}`} value={f.end} onChange={e => set("end", e.target.value)} />
            {errors.end && <div className="hint" style={{color: "var(--danger)"}}>{errors.end}</div>}
          </div>
          <div className="field">
            <label className="lbl">Jam Penjemputan</label>
            <input type="time" className="input" value={f.jam} onChange={e => set("jam", e.target.value)} />
          </div>
        </div>
      </div>

      {/* Section 2: Armada & Sopir */}
      <div className="fs-card" style={{padding: 0, marginBottom: 18, borderTop: "1px solid var(--divider)", paddingTop: 18}}>
        <div className="fs-title"><span className="num">2</span>ARMADA & SOPIR</div>
        <div className="field-row" style={{gridTemplateColumns: "1fr 1fr"}}>
          <div className="field">
            <label className="lbl">Unit Bus <span className="req">*</span></label>
            <select className={`select ${(busConflict || errors.busId) ? "err" : ""}`} value={f.busId} onChange={e => set("busId", e.target.value)}>
              <option value="">— Pilih unit bus —</option>
              {window.BUSES.filter(b => b.status === "aktif").map(b => (
                <option key={b.id} value={b.id}>{b.kode} · {b.plate} · {b.kapasitas} seat</option>
              ))}
            </select>
            {errors.busId && <div className="hint" style={{color: "var(--danger)"}}>{errors.busId}</div>}
            {busConflict && (
              <div className="field-warn">
                <I.Alert className="ic" />
                <div>
                  <strong>Bentrok jadwal!</strong> Unit ini sudah dibooking <strong>{window.getCustomer(busConflict.customerId)?.nama}</strong>
                  {" "}({window.FDATE_SHORT(busConflict.start)} – {window.FDATE_SHORT(busConflict.end)}, <code>{busConflict.kode}</code>).
                </div>
              </div>
            )}
          </div>
          <div className="field">
            <label className="lbl">Sopir <span style={{fontSize: 11, color: "var(--ink-mute)", fontWeight: 400}}>(pilih 1-2)</span></label>
            <div style={{display: "flex", flexWrap: "wrap", gap: 6, padding: 8, border: "1px solid var(--border-strong)", borderRadius: 8, minHeight: 38, background: "var(--surface)"}}>
              {window.DRIVERS.filter(d => d.status === "aktif").map(d => {
                const on = f.driverIds?.includes(d.id);
                return (
                  <button key={d.id} type="button"
                    onClick={() => set("driverIds", on ? f.driverIds.filter(x => x !== d.id) : (f.driverIds || []).concat(d.id))}
                    className="btn btn-sm"
                    style={{
                      background: on ? "var(--brand-tint)" : "var(--surface)",
                      border: `1px solid ${on ? "var(--brand)" : "var(--border-strong)"}`,
                      color: on ? "var(--brand-ink)" : "var(--ink-2)",
                    }}>
                    {on && <I.Check size={12} />}
                    {d.nama.replace("Pak ", "")}
                  </button>
                );
              })}
            </div>
            {driverConflicts.length > 0 && (
              <div className="field-warn">
                <I.Alert className="ic" />
                <div>
                  <strong>{window.getDriver(driverConflicts[0].driverId)?.nama}</strong> sudah ditugaskan di sewa <code>{driverConflicts[0].conflict.kode}</code> pada tanggal yang sama.
                </div>
              </div>
            )}
          </div>
        </div>
      </div>

      {/* Section 3: Penyewa */}
      <div className="fs-card" style={{padding: 0, marginBottom: 18, borderTop: "1px solid var(--divider)", paddingTop: 18}}>
        <div className="fs-title"><span className="num">3</span>PENYEWA</div>
        <div className="field-row" style={{gridTemplateColumns: "2fr 1fr"}}>
          <div className="field">
            <label className="lbl">Penyewa <span className="req">*</span></label>
            <div style={{display: "flex", gap: 6}}>
              <select className={`select ${errors.customerId ? "err" : ""}`} value={f.customerId} onChange={e => set("customerId", e.target.value)} style={{flex: 1}}>
                <option value="">— Pilih penyewa —</option>
                {window.CUSTOMERS.map(c => (
                  <option key={c.id} value={c.id}>{c.nama} · {c.phone}</option>
                ))}
              </select>
              <button type="button" className="btn" onClick={() => setShowNewCust(true)}><I.Plus size={14} /> Baru</button>
            </div>
            {errors.customerId && <div className="hint" style={{color: "var(--danger)"}}>{errors.customerId}</div>}
          </div>
          <div className="field">
            <label className="lbl">Tipe Penyewa</label>
            <div style={{padding: "8px 11px", background: "var(--surface-sunken)", borderRadius: 8, fontSize: 13, color: "var(--ink-2)"}}>
              {f.customerId ? (window.getCustomer(parseInt(f.customerId))?.jenis === "instansi" ? "Instansi" : "Perorangan") : <em style={{color: "var(--ink-mute)"}}>—</em>}
            </div>
          </div>
        </div>
      </div>

      {/* Section 4: Detail Trip */}
      <div className="fs-card" style={{padding: 0, marginBottom: 18, borderTop: "1px solid var(--divider)", paddingTop: 18}}>
        <div className="fs-title"><span className="num">4</span>DETAIL TRIP</div>
        <div className="field-row" style={{gridTemplateColumns: "1fr 1fr"}}>
          <div className="field">
            <label className="lbl">Tujuan <span className="req">*</span></label>
            <input className={`input ${errors.tujuan ? "err" : ""}`} placeholder="cth: Malang - Batu" value={f.tujuan} onChange={e => set("tujuan", e.target.value)} />
          </div>
          <div className="field">
            <label className="lbl">Lokasi Penjemputan</label>
            <input className="input" placeholder="cth: SMAN 5 Surabaya" value={f.lokasi} onChange={e => set("lokasi", e.target.value)} />
          </div>
        </div>
        <div className="field mt-3">
          <label className="lbl">Catatan Tambahan</label>
          <textarea className="textarea" placeholder="cth: Berangkat lebih awal, ada permintaan konsumsi crew" value={f.catatan} onChange={e => set("catatan", e.target.value)} />
        </div>
      </div>

      {/* Section 5: Pembayaran */}
      <div className="fs-card" style={{padding: 0, borderTop: "1px solid var(--divider)", paddingTop: 18}}>
        <div className="fs-title"><span className="num">5</span>PEMBAYARAN & STATUS</div>
        <div className="field-row" style={{gridTemplateColumns: "1fr 1fr 1fr"}}>
          <div className="field">
            <label className="lbl">Ongkos Sewa (Rp) <span className="req">*</span></label>
            <div className="input-prefix-wrap">
              <span className="input-prefix">Rp</span>
              <input type="number" className={`input mono ${errors.harga ? "err" : ""}`} value={f.harga} onChange={e => set("harga", e.target.value)} placeholder="0" />
            </div>
            {errors.harga && <div className="hint" style={{color: "var(--danger)"}}>{errors.harga}</div>}
          </div>
          <div className="field">
            <label className="lbl">DP Diterima (Rp)</label>
            <div className="input-prefix-wrap">
              <span className="input-prefix">Rp</span>
              <input type="number" className={`input mono ${errors.dp ? "err" : ""}`} value={f.dp} onChange={e => set("dp", e.target.value)} placeholder="0" />
            </div>
            <div className="hint">Otomatis dicatat sebagai Kas Masuk · kategori "Pendapatan Sewa".</div>
          </div>
          <div className="field">
            <label className="lbl">Status</label>
            <select className="select" value={f.status} onChange={e => set("status", e.target.value)}>
              <option value="booking">Booking (belum bayar)</option>
              <option value="dp">DP</option>
              <option value="lunas">Lunas</option>
              <option value="selesai">Selesai (trip sudah jalan)</option>
              {editingId && <option value="batal">Batal</option>}
            </select>
          </div>
        </div>

        <div className="mt-3" style={{padding: 14, background: "var(--surface-sunken)", borderRadius: 10, display: "flex", gap: 20, alignItems: "center"}}>
          <div>
            <div style={{fontSize: 11, textTransform: "uppercase", letterSpacing: ".04em", color: "var(--ink-mute)", fontWeight: 700}}>Sisa Pembayaran</div>
            <div className="mono" style={{fontSize: 22, fontWeight: 700, marginTop: 4, color: sisa > 0 ? "var(--danger)" : "var(--success)"}}>{window.RP(Math.max(0, sisa))}</div>
          </div>
          {(f.status === "lunas" || f.status === "selesai") && (
            <div className="field-warn" style={{margin: 0, background: "var(--st-lunas-tint)", color: "oklch(0.32 0.10 155)", borderColor: "oklch(0.7 0.10 155)"}}>
              <I.Check className="ic" style={{color: "var(--st-lunas)"}} />
              <div>
                Status <strong>{window.STATUS_LABEL[f.status]}</strong> akan membuat catatan Kas Masuk sejumlah selisih (otomatis).
              </div>
            </div>
          )}
        </div>
      </div>

      {/* Foot */}
      <div style={{display: "flex", gap: 10, justifyContent: "flex-end", paddingTop: 18, marginTop: 18, borderTop: "1px solid var(--divider)"}}>
        <div style={{flex: 1, fontSize: 11.5, color: "var(--ink-mute)", display: "flex", alignItems: "center", gap: 6}}>
          <I.Save size={13} /> Tersimpan ke database lokal (localStorage)
        </div>
        <button className="btn" onClick={onCancel}>Batal</button>
        {!editingId && (
          <button className="btn" onClick={() => submit(true)}>Simpan & Tambah Lagi</button>
        )}
        <button className="btn btn-primary" onClick={() => submit(false)}>
          <I.Check size={14} /> {editingId ? "Simpan Perubahan" : "Simpan Sewa"}
        </button>
      </div>

      {/* New customer quick modal */}
      <Modal open={showNewCust} onClose={() => setShowNewCust(false)} title="Tambah Penyewa Cepat"
        icon={<I.Users size={20} style={{color: "var(--brand)"}} />}>
        <QuickCustomerForm
          onCancel={() => setShowNewCust(false)}
          onSaved={(c) => { set("customerId", String(c.id)); setShowNewCust(false); toast.push(`Penyewa "${c.nama}" ditambahkan`); }}
        />
      </Modal>
    </div>
  );
}

function QuickCustomerForm({ onCancel, onSaved }) {
  const { actions } = useApp();
  const [f, setF] = useState({ nama: "", phone: "", alamat: "", jenis: "perorangan", catatan: "" });
  const set = (k, v) => setF(x => ({...x, [k]: v}));
  const save = () => {
    if (!f.nama.trim()) return;
    const c = actions.saveCustomer({ ...f, nama: f.nama.trim() });
    onSaved(c);
  };
  return (
    <div>
      <div className="field-row" style={{gridTemplateColumns: "2fr 1fr"}}>
        <div className="field"><label className="lbl">Nama <span className="req">*</span></label><input className="input" value={f.nama} onChange={e => set("nama", e.target.value)} autoFocus /></div>
        <div className="field">
          <label className="lbl">Jenis</label>
          <select className="select" value={f.jenis} onChange={e => set("jenis", e.target.value)}>
            <option value="perorangan">Perorangan</option>
            <option value="instansi">Instansi</option>
          </select>
        </div>
      </div>
      <div className="field mt-3"><label className="lbl">No HP</label><input className="input mono" value={f.phone} onChange={e => set("phone", e.target.value)} /></div>
      <div className="field mt-3"><label className="lbl">Alamat</label><input className="input" value={f.alamat} onChange={e => set("alamat", e.target.value)} /></div>
      <div style={{display: "flex", gap: 8, justifyContent: "flex-end", marginTop: 16, paddingTop: 14, borderTop: "1px solid var(--divider)"}}>
        <button className="btn" onClick={onCancel}>Batal</button>
        <button className="btn btn-primary" onClick={save}><I.Save size={14} /> Simpan</button>
      </div>
    </div>
  );
}

// ============================================================
// Empty state
// ============================================================
function EmptyState({ ic: Ic, title, hint, action }) {
  return (
    <div style={{textAlign: "center", padding: "48px 24px"}}>
      <div style={{width: 56, height: 56, margin: "0 auto 14px", borderRadius: 14, background: "var(--surface-sunken)", color: "var(--ink-soft)", display: "grid", placeItems: "center"}}>
        {Ic && <Ic size={26} />}
      </div>
      <div style={{fontWeight: 700, fontSize: 14, color: "var(--ink)"}}>{title}</div>
      {hint && <div style={{fontSize: 13, color: "var(--ink-mute)", marginTop: 4}}>{hint}</div>}
      {action && <div style={{marginTop: 14}}>{action}</div>}
    </div>
  );
}

// Helper: today ISO
window.todayISO = () => new Date().toISOString().slice(0,10);

// Export helpers
function exportRentalsExcel(rentals) {
  const lines = ["Kode\tTanggal Mulai\tTanggal Selesai\tPenyewa\tUnit\tTujuan\tHarga\tDP\tStatus"];
  rentals.forEach(r => {
    const cust = window.getCustomer(r.customerId);
    const bus = window.getBus(r.busId);
    lines.push([
      r.kode, r.start, r.end,
      cust?.nama || "",
      bus?.kode || "",
      r.tujuan, r.harga, r.dp, r.status,
    ].join("\t"));
  });
  const blob = new Blob([lines.join("\n")], { type: "text/tab-separated-values" });
  const a = document.createElement("a");
  a.href = URL.createObjectURL(blob);
  a.download = `sewa-export-${window.todayISO()}.tsv`;
  a.click();
}
window.exportRentalsExcel = exportRentalsExcel;

Object.assign(window, { ManajemenSewa, SewaForm, RentalDetailContent, EmptyState, QuickCustomerForm, PelunasanModal });
