// ============================================================
// BusManager — Master Data (Bus, Sopir, Penyewa, Kategori) — wired
// ============================================================

// ---------- MASTER BUS ----------
function MasterBus() {
  const { actions, version } = useApp();
  void version;
  const [showForm, setShowForm] = useState(false);
  const [editing, setEditing] = useState(null);
  const [confirmDel, setConfirmDel] = useState(null);
  const toast = useToast();

  const handleSave = (data) => {
    try {
      actions.saveBus(data);
      toast.push(editing ? "Unit bus diperbarui" : "Unit bus tersimpan");
      setShowForm(false); setEditing(null);
    } catch (e) { toast.push(e.message, "error"); }
  };

  const handleDel = (id) => {
    try {
      actions.deleteBus(id);
      toast.push("Unit bus dihapus");
    } catch (e) { toast.push(e.message, "error"); }
  };

  return (
    <div>
      <div className="page-head">
        <div className="ttl">
          <h2>Unit Bus</h2>
          <div className="sub">{window.BUSES.length} unit armada terdaftar · {window.BUSES.filter(b => b.status === "aktif").length} aktif</div>
        </div>
        <div className="actions">
          <button className="btn btn-primary" onClick={() => { setEditing(null); setShowForm(true); }}>
            <I.Plus size={15} /> Tambah Bus
          </button>
        </div>
      </div>

      <div className="grid grid-4 mb-4">
        {window.BUSES.map(b => (
          <div key={b.id} className="card" style={{padding: 0, overflow: "hidden"}}>
            <div style={{
              height: 100,
              background: b.status === "aktif"
                ? `linear-gradient(135deg, oklch(0.7 0.10 ${235 + b.id * 8}), oklch(0.45 0.13 ${235 + b.id * 8}))`
                : "linear-gradient(135deg, oklch(0.85 0.005 80), oklch(0.65 0.008 80))",
              color: "white",
              display: "grid", placeItems: "center",
              position: "relative",
            }}>
              <div style={{position: "absolute", top: 10, right: 10, display: "flex", gap: 4}}>
                {b.status === "aktif"
                  ? <span className="badge no-dot" style={{background: "oklch(1 0 0 / .25)", color: "white", border: "1px solid oklch(1 0 0 / .3)", backdropFilter: "blur(4px)"}}>Aktif</span>
                  : <span className="badge no-dot" style={{background: "oklch(1 0 0 / .25)", color: "white", border: "1px solid oklch(1 0 0 / .3)"}}>Nonaktif</span>}
              </div>
              <I.Bus size={36} style={{opacity: .35, position: "absolute", left: 14, bottom: 14}} />
              <div style={{fontSize: 32, fontWeight: 700, letterSpacing: "-0.02em"}}>{b.kode}</div>
            </div>
            <div style={{padding: "14px 16px"}}>
              <div style={{display: "flex", alignItems: "center", justifyContent: "space-between", gap: 8}}>
                <div style={{minWidth: 0, flex: 1}}>
                  <div style={{fontSize: 15, fontWeight: 700, whiteSpace: "nowrap", overflow: "hidden", textOverflow: "ellipsis"}}>{b.nama}</div>
                  <div className="mono" style={{fontSize: 12, color: "var(--ink-mute)"}}>{b.plate}</div>
                </div>
                <div style={{display: "flex", gap: 2, flex: "none"}}>
                  <button className="btn btn-sm btn-icon btn-ghost" onClick={() => { setEditing(b); setShowForm(true); }} title="Edit">
                    <I.Edit size={14} />
                  </button>
                  <button className="btn btn-sm btn-icon btn-ghost" onClick={() => setConfirmDel(b)} title="Hapus">
                    <I.Trash size={14} />
                  </button>
                </div>
              </div>
              <div className="divider" style={{margin: "10px 0"}} />
              <div style={{display: "flex", justifyContent: "space-between", fontSize: 12, color: "var(--ink-2)"}}>
                <div><span style={{color: "var(--ink-mute)"}}>Kapasitas:</span> <strong>{b.kapasitas} seat</strong></div>
                <div><span style={{color: "var(--ink-mute)"}}>Tahun:</span> <strong>{b.tahun}</strong></div>
              </div>
              {b.catatan && (
                <div style={{marginTop: 10, fontSize: 12, color: "var(--ink-mute)", lineHeight: 1.4, padding: 8, background: "var(--surface-sunken)", borderRadius: 6}}>
                  {b.catatan}
                </div>
              )}
            </div>
          </div>
        ))}

        {/* Add card placeholder */}
        <button onClick={() => { setEditing(null); setShowForm(true); }}
          className="card" style={{
            padding: 0, overflow: "hidden", cursor: "pointer",
            border: "1.5px dashed var(--border-strong)",
            background: "transparent",
            minHeight: 230,
            display: "grid", placeItems: "center",
            color: "var(--ink-mute)",
          }}>
          <div style={{textAlign: "center"}}>
            <div style={{width: 48, height: 48, borderRadius: 12, background: "var(--surface)", display: "grid", placeItems: "center", margin: "0 auto 8px"}}>
              <I.Plus size={20} />
            </div>
            <div style={{fontWeight: 700, fontSize: 13, color: "var(--ink-2)"}}>Tambah Unit Bus</div>
          </div>
        </button>
      </div>

      <Modal open={showForm} onClose={() => { setShowForm(false); setEditing(null); }}
        title={editing ? `Edit ${editing.kode}` : "Tambah Unit Bus"}
        icon={<I.Bus size={20} style={{color: "var(--brand)"}} />}>
        <BusForm editing={editing} onCancel={() => { setShowForm(false); setEditing(null); }} onSave={handleSave} />
      </Modal>

      <ConfirmDialog open={!!confirmDel} onClose={() => setConfirmDel(null)}
        onConfirm={() => handleDel(confirmDel.id)}
        title={`Hapus ${confirmDel?.kode}?`}
        confirmLabel="Ya, Hapus" danger
        body="Unit bus akan dihapus permanen. Jika unit ini punya sewa aktif, sistem akan menolak."
      />
    </div>
  );
}

function BusForm({ editing, onCancel, onSave }) {
  const [f, setF] = useState(editing ? { ...editing } : {
    kode: "", plate: "", nama: "", kapasitas: "", tahun: 2024, catatan: "", status: "aktif",
  });
  const [errors, setErrors] = useState({});
  const set = (k, v) => { setF(x => ({...x, [k]: v})); setErrors(e => ({...e, [k]: null})); };

  const submit = () => {
    const e = {};
    if (!f.kode?.trim()) e.kode = "Kode wajib";
    if (!f.plate?.trim()) e.plate = "Nomor polisi wajib";
    // unique plate check
    const dup = window.BUSES.find(b => b.plate?.toLowerCase() === f.plate?.toLowerCase().trim() && b.id !== editing?.id);
    if (dup) e.plate = `Nomor polisi sudah dipakai unit ${dup.kode}`;
    setErrors(e);
    if (Object.keys(e).length) return;
    onSave({
      ...(editing ? { id: editing.id } : {}),
      kode: f.kode.trim().toUpperCase(),
      plate: f.plate.trim().toUpperCase(),
      nama: f.nama?.trim() || f.kode,
      kapasitas: parseInt(f.kapasitas) || 0,
      tahun: parseInt(f.tahun) || new Date().getFullYear(),
      catatan: f.catatan || "",
      status: f.status,
    });
  };

  return (
    <div>
      <div className="field-row" style={{gridTemplateColumns: "1fr 1fr"}}>
        <div className="field">
          <label className="lbl">Kode Unit <span className="req">*</span></label>
          <input className={`input mono ${errors.kode ? "err" : ""}`} placeholder="BJL-09" value={f.kode} onChange={e => set("kode", e.target.value)} />
        </div>
        <div className="field">
          <label className="lbl">Nomor Polisi <span className="req">*</span></label>
          <input className={`input mono ${errors.plate ? "err" : ""}`} placeholder="L 1234 UB" value={f.plate} onChange={e => set("plate", e.target.value)} />
          {errors.plate && <div className="hint" style={{color: "var(--danger)"}}>{errors.plate}</div>}
          {!errors.plate && <div className="hint">Harus unik. Sistem cek otomatis.</div>}
        </div>
      </div>
      <div className="field-row mt-3" style={{gridTemplateColumns: "2fr 1fr 1fr"}}>
        <div className="field"><label className="lbl">Nama Unit</label><input className="input" placeholder="cth: Bintang 09" value={f.nama} onChange={e => set("nama", e.target.value)} /></div>
        <div className="field"><label className="lbl">Kapasitas (seat)</label><input type="number" className="input" placeholder="0" value={f.kapasitas} onChange={e => set("kapasitas", e.target.value)} /></div>
        <div className="field"><label className="lbl">Tahun</label><input type="number" className="input" placeholder="2024" value={f.tahun} onChange={e => set("tahun", e.target.value)} /></div>
      </div>
      <div className="field mt-3">
        <label className="lbl">Foto</label>
        <div style={{border: "1.5px dashed var(--border-strong)", borderRadius: 10, padding: 20, textAlign: "center", color: "var(--ink-mute)", background: "var(--surface-2)"}}>
          <I.Camera size={20} style={{display: "block", margin: "0 auto 6px"}} />
          <div style={{fontSize: 13, color: "var(--ink-2)"}}>Tarik foto bus ke sini atau klik untuk upload</div>
        </div>
      </div>
      <div className="field mt-3"><label className="lbl">Catatan</label><textarea className="textarea" value={f.catatan} onChange={e => set("catatan", e.target.value)} placeholder="Catatan tambahan, riwayat, dll..." /></div>
      <div className="field mt-3">
        <label className="lbl">Status</label>
        <div style={{display: "flex", gap: 8, alignItems: "center", padding: "8px 0"}}>
          <span className={`switch ${f.status === "aktif" ? "on" : ""}`} onClick={() => set("status", f.status === "aktif" ? "nonaktif" : "aktif")} />
          <span style={{fontSize: 13}}>Unit aktif (siap operasional)</span>
        </div>
      </div>
      <div style={{display: "flex", gap: 10, justifyContent: "flex-end", marginTop: 18, paddingTop: 16, borderTop: "1px solid var(--divider)"}}>
        <button className="btn" onClick={onCancel}>Batal</button>
        <button className="btn btn-primary" onClick={submit}><I.Save size={14} /> Simpan</button>
      </div>
    </div>
  );
}

// ---------- MASTER SOPIR ----------
function MasterSopir() {
  const { actions, version } = useApp();
  void version;
  const [showForm, setShowForm] = useState(false);
  const [editing, setEditing] = useState(null);
  const [confirmDel, setConfirmDel] = useState(null);
  const [search, setSearch] = useState("");
  const toast = useToast();

  const handleSave = (data) => {
    try {
      actions.saveDriver(data);
      toast.push(editing ? "Data sopir diperbarui" : "Sopir baru tersimpan");
      setShowForm(false); setEditing(null);
    } catch (e) { toast.push(e.message, "error"); }
  };
  const handleDel = (id) => {
    try {
      actions.deleteDriver(id);
      toast.push("Sopir dihapus");
    } catch (e) { toast.push(e.message, "error"); }
  };

  const drivers = window.DRIVERS.filter(d =>
    !search || d.nama.toLowerCase().includes(search.toLowerCase()) || d.phone?.includes(search)
  );

  return (
    <div>
      <div className="page-head">
        <div className="ttl">
          <h2>Sopir</h2>
          <div className="sub">{window.DRIVERS.length} sopir terdaftar · {window.DRIVERS.filter(d => d.status === "aktif").length} aktif</div>
        </div>
        <div className="actions">
          <button className="btn btn-primary" onClick={() => { setEditing(null); setShowForm(true); }}>
            <I.Plus size={15} /> Tambah Sopir
          </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 nama atau nomor HP..." value={search} onChange={e => setSearch(e.target.value)} />
            </div>
            <div className="sp" />
            <span style={{fontSize: 12, color: "var(--ink-mute)"}}>{drivers.length} hasil</span>
          </div>
        </div>
        <div className="tbl-wrap">
          <table className="tbl">
            <thead>
              <tr><th>Nama</th><th>No KTP</th><th>HP</th><th>Alamat</th><th>Status</th><th className="right">Trip</th><th></th></tr>
            </thead>
            <tbody>
              {drivers.map(d => {
                const tripCount = window.RENTALS.filter(r => r.driverIds?.includes(d.id) && r.status !== "batal").length;
                return (
                  <tr key={d.id}>
                    <td><PersonChip name={d.nama} /></td>
                    <td className="mono" style={{fontSize: 12}}>{d.ktp}</td>
                    <td className="mono" style={{fontSize: 13}}>{d.phone}</td>
                    <td style={{fontSize: 12, color: "var(--ink-2)"}}>{d.alamat}</td>
                    <td><span className={`badge ${d.status}`}>{d.status === "aktif" ? "Aktif" : "Nonaktif"}</span></td>
                    <td className="num right">{tripCount}x</td>
                    <td>
                      <div className="row-actions">
                        <button className="btn btn-sm btn-ghost btn-icon" onClick={() => { setEditing(d); setShowForm(true); }}><I.Edit size={14} /></button>
                        <button className="btn btn-sm btn-ghost btn-icon" onClick={() => setConfirmDel(d)}><I.Trash size={14} /></button>
                      </div>
                    </td>
                  </tr>
                );
              })}
              {drivers.length === 0 && <tr><td colSpan={7}><EmptyState ic={I.User} title="Sopir tidak ditemukan" /></td></tr>}
            </tbody>
          </table>
        </div>
      </div>

      <Modal open={showForm} onClose={() => { setShowForm(false); setEditing(null); }}
        title={editing ? `Edit ${editing.nama}` : "Tambah Sopir"}
        icon={<I.User size={20} style={{color: "var(--brand)"}} />}>
        <SopirForm editing={editing} onCancel={() => { setShowForm(false); setEditing(null); }} onSave={handleSave} />
      </Modal>

      <ConfirmDialog open={!!confirmDel} onClose={() => setConfirmDel(null)}
        onConfirm={() => handleDel(confirmDel.id)}
        title={`Hapus ${confirmDel?.nama}?`} confirmLabel="Ya, Hapus" danger
        body="Data sopir akan dihapus dari master data." />
    </div>
  );
}

function SopirForm({ editing, onCancel, onSave }) {
  const [f, setF] = useState(editing ? { ...editing } : {
    nama: "", ktp: "", phone: "", alamat: "", catatan: "", status: "aktif",
  });
  const [errors, setErrors] = useState({});
  const set = (k, v) => { setF(x => ({...x, [k]: v})); setErrors(e => ({...e, [k]: null})); };
  const submit = () => {
    const e = {};
    if (!f.nama?.trim()) e.nama = "Nama wajib";
    if (!f.ktp?.trim()) e.ktp = "KTP wajib";
    if (!f.phone?.trim()) e.phone = "HP wajib";
    setErrors(e);
    if (Object.keys(e).length) return;
    onSave({ ...(editing ? { id: editing.id } : {}), ...f, nama: f.nama.trim() });
  };
  return (
    <div>
      <div className="field-row" style={{gridTemplateColumns: "1fr 1fr"}}>
        <div className="field"><label className="lbl">Nama <span className="req">*</span></label><input className={`input ${errors.nama ? "err" : ""}`} value={f.nama} onChange={e => set("nama", e.target.value)} autoFocus /></div>
        <div className="field"><label className="lbl">No KTP <span className="req">*</span></label><input className={`input mono ${errors.ktp ? "err" : ""}`} value={f.ktp} onChange={e => set("ktp", e.target.value)} /></div>
      </div>
      <div className="field-row mt-3" style={{gridTemplateColumns: "1fr 1fr"}}>
        <div className="field"><label className="lbl">No HP <span className="req">*</span></label><input className={`input mono ${errors.phone ? "err" : ""}`} value={f.phone} onChange={e => set("phone", e.target.value)} /></div>
        <div className="field">
          <label className="lbl">Status</label>
          <div style={{display: "flex", gap: 8, alignItems: "center", padding: "8px 0"}}>
            <span className={`switch ${f.status === "aktif" ? "on" : ""}`} onClick={() => set("status", f.status === "aktif" ? "nonaktif" : "aktif")} />
            <span style={{fontSize: 13}}>Sopir aktif</span>
          </div>
        </div>
      </div>
      <div className="field mt-3"><label className="lbl">Alamat</label><textarea className="textarea" value={f.alamat} onChange={e => set("alamat", e.target.value)} /></div>
      <div className="field mt-3"><label className="lbl">Catatan</label><textarea className="textarea" value={f.catatan} onChange={e => set("catatan", e.target.value)} /></div>
      <div style={{display: "flex", gap: 10, 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={submit}><I.Save size={14} /> Simpan</button>
      </div>
    </div>
  );
}

// ---------- MASTER PENYEWA ----------
function MasterPenyewa() {
  const { actions, version } = useApp();
  void version;
  const [showForm, setShowForm] = useState(false);
  const [editing, setEditing] = useState(null);
  const [confirmDel, setConfirmDel] = useState(null);
  const [search, setSearch] = useState("");
  const [filterJenis, setFilterJenis] = useState("all");
  const toast = useToast();

  const handleSave = (data) => {
    try {
      actions.saveCustomer(data);
      toast.push(editing ? "Penyewa diperbarui" : "Penyewa baru tersimpan");
      setShowForm(false); setEditing(null);
    } catch (e) { toast.push(e.message, "error"); }
  };
  const handleDel = (id) => {
    try {
      actions.deleteCustomer(id);
      toast.push("Penyewa dihapus");
    } catch (e) { toast.push(e.message, "error"); }
  };

  const list = window.CUSTOMERS.filter(c => {
    const m = !search || c.nama.toLowerCase().includes(search.toLowerCase()) || c.phone?.includes(search);
    const mj = filterJenis === "all" || c.jenis === filterJenis;
    return m && mj;
  });

  return (
    <div>
      <div className="page-head">
        <div className="ttl">
          <h2>Penyewa</h2>
          <div className="sub">{window.CUSTOMERS.length} penyewa terdaftar</div>
        </div>
        <div className="actions">
          <button className="btn btn-primary" onClick={() => { setEditing(null); setShowForm(true); }}>
            <I.Plus size={15} /> Tambah Penyewa
          </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 nama atau telepon..." value={search} onChange={e => setSearch(e.target.value)} />
            </div>
            <div className="chip-filter">
              <I.Users size={14} style={{color: "var(--ink-mute)"}} />
              <select value={filterJenis} onChange={e => setFilterJenis(e.target.value)}>
                <option value="all">Semua Jenis</option>
                <option value="perorangan">Perorangan</option>
                <option value="instansi">Instansi</option>
              </select>
            </div>
            <div className="sp" />
            <span style={{fontSize: 12, color: "var(--ink-mute)"}}>{list.length} hasil</span>
          </div>
        </div>
        <div className="tbl-wrap">
          <table className="tbl">
            <thead>
              <tr><th>Nama</th><th>Jenis</th><th>Telepon</th><th>Alamat</th><th className="right">Total Trip</th><th className="right">Total Nilai</th><th></th></tr>
            </thead>
            <tbody>
              {list.map(c => {
                const trips = window.RENTALS.filter(r => r.customerId === c.id && r.status !== "batal");
                const total = trips.reduce((s,r) => s + r.harga, 0);
                return (
                  <tr key={c.id}>
                    <td>
                      <div style={{fontWeight: 600}}>{c.nama}</div>
                      {c.catatan && <div className="cell-secondary">{c.catatan}</div>}
                    </td>
                    <td><span className="badge no-dot" style={{background: c.jenis === "instansi" ? "var(--brand-tint)" : "var(--surface-sunken)", color: c.jenis === "instansi" ? "var(--brand-ink)" : "var(--ink-2)"}}>{c.jenis === "instansi" ? "Instansi" : "Perorangan"}</span></td>
                    <td className="mono" style={{fontSize: 13}}>{c.phone}</td>
                    <td style={{fontSize: 12, color: "var(--ink-2)"}}>{c.alamat}</td>
                    <td className="num right">{trips.length}x</td>
                    <td className="num right">{window.RP(total)}</td>
                    <td>
                      <div className="row-actions">
                        <button className="btn btn-sm btn-ghost btn-icon" onClick={() => { setEditing(c); setShowForm(true); }}><I.Edit size={14} /></button>
                        <button className="btn btn-sm btn-ghost btn-icon" onClick={() => setConfirmDel(c)}><I.Trash size={14} /></button>
                      </div>
                    </td>
                  </tr>
                );
              })}
              {list.length === 0 && <tr><td colSpan={7}><EmptyState ic={I.Users} title="Penyewa tidak ditemukan" /></td></tr>}
            </tbody>
          </table>
        </div>
      </div>

      <Modal open={showForm} onClose={() => { setShowForm(false); setEditing(null); }}
        title={editing ? `Edit ${editing.nama}` : "Tambah Penyewa"}
        icon={<I.Users size={20} style={{color: "var(--brand)"}} />}>
        <PenyewaForm editing={editing} onCancel={() => { setShowForm(false); setEditing(null); }} onSave={handleSave} />
      </Modal>

      <ConfirmDialog open={!!confirmDel} onClose={() => setConfirmDel(null)}
        onConfirm={() => handleDel(confirmDel.id)}
        title={`Hapus ${confirmDel?.nama}?`} confirmLabel="Ya, Hapus" danger
        body="Penyewa dengan riwayat sewa tidak dapat dihapus." />
    </div>
  );
}

function PenyewaForm({ editing, onCancel, onSave }) {
  const [f, setF] = useState(editing ? { ...editing } : { nama: "", phone: "", alamat: "", jenis: "perorangan", catatan: "" });
  const [errors, setErrors] = useState({});
  const set = (k, v) => { setF(x => ({...x, [k]: v})); setErrors(e => ({...e, [k]: null})); };
  const submit = () => {
    const e = {};
    if (!f.nama?.trim()) e.nama = "wajib";
    setErrors(e);
    if (Object.keys(e).length) return;
    onSave({ ...(editing ? { id: editing.id } : {}), ...f, nama: f.nama.trim() });
  };
  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 ${errors.nama ? "err" : ""}`} 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><textarea className="textarea" value={f.alamat} onChange={e => set("alamat", e.target.value)} /></div>
      <div className="field mt-3"><label className="lbl">Catatan</label><textarea className="textarea" value={f.catatan} onChange={e => set("catatan", e.target.value)} /></div>
      <div style={{display: "flex", gap: 10, 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={submit}><I.Save size={14} /> Simpan</button>
      </div>
    </div>
  );
}

// ---------- MASTER KATEGORI ----------
function MasterKategori() {
  const { actions, version } = useApp();
  void version;
  const [showForm, setShowForm] = useState(false);
  const [editing, setEditing] = useState(null);
  const [confirmDel, setConfirmDel] = useState(null);
  const toast = useToast();

  const handleSave = (data) => {
    try {
      actions.saveCat(data);
      toast.push(editing ? "Kategori diperbarui" : "Kategori baru tersimpan");
      setShowForm(false); setEditing(null);
    } catch (e) { toast.push(e.message, "error"); }
  };
  const handleDel = (id) => {
    try {
      actions.deleteCat(id);
      toast.push("Kategori dihapus");
    } catch (e) { toast.push(e.message, "error"); }
  };
  const toggleAktif = (cat) => {
    try {
      actions.saveCat({ ...cat, aktif: !cat.aktif });
      toast.push(`Kategori "${cat.nama}" ${cat.aktif ? "dinonaktifkan" : "diaktifkan"}`);
    } catch (e) { toast.push(e.message, "error"); }
  };

  return (
    <div>
      <div className="page-head">
        <div className="ttl">
          <h2>Kategori Kas</h2>
          <div className="sub">{window.CASH_CATS.length} kategori · digunakan untuk klasifikasi kas masuk/keluar</div>
        </div>
        <div className="actions">
          <button className="btn btn-primary" onClick={() => { setEditing(null); setShowForm(true); }}>
            <I.Plus size={15} /> Tambah Kategori
          </button>
        </div>
      </div>

      <div className="grid grid-2">
        {["masuk", "keluar"].map(tipe => (
          <div key={tipe} className="card">
            <div className="card-head">
              <div className="ic-bg" style={{
                width: 28, height: 28, borderRadius: 8,
                background: tipe === "masuk" ? "var(--st-lunas-tint)" : "var(--st-batal-tint)",
                color: tipe === "masuk" ? "var(--st-lunas)" : "var(--st-batal)",
                display: "grid", placeItems: "center",
              }}>
                {tipe === "masuk" ? <I.ArrowDown size={15} /> : <I.ArrowUp size={15} />}
              </div>
              <h3>Kategori {tipe === "masuk" ? "Kas Masuk" : "Kas Keluar"}</h3>
              <span className="sub">{window.CASH_CATS.filter(c => c.tipe === tipe).length} kategori</span>
            </div>
            <div>
              {window.CASH_CATS.filter(c => c.tipe === tipe).map(c => (
                <div key={c.id} style={{padding: "10px 18px", display: "flex", alignItems: "center", borderBottom: "1px solid var(--divider)"}}>
                  <div style={{flex: 1}}>
                    <div style={{fontWeight: 600, fontSize: 13, display: "flex", alignItems: "center", gap: 8}}>
                      {c.nama}
                      {c.seeded && <span className="badge no-dot" style={{background: "var(--brand-tint)", color: "var(--brand-ink)", fontSize: 10, padding: "1px 6px"}}>BAWAAN</span>}
                    </div>
                  </div>
                  <button onClick={() => toggleAktif(c)} title={c.aktif ? "Nonaktifkan" : "Aktifkan"} style={{border: 0, background: "transparent", cursor: "pointer", padding: 6}}>
                    <span className={`badge ${c.aktif ? "aktif" : "nonaktif"}`}>{c.aktif ? "Aktif" : "Nonaktif"}</span>
                  </button>
                  <div className="row-actions" style={{marginLeft: 8}}>
                    <button className="btn btn-sm btn-ghost btn-icon" onClick={() => { setEditing(c); setShowForm(true); }}><I.Edit size={14} /></button>
                    <button className="btn btn-sm btn-ghost btn-icon"
                      disabled={c.seeded}
                      title={c.seeded ? "Bawaan tidak dapat dihapus" : "Hapus"}
                      onClick={() => setConfirmDel(c)}>
                      <I.Trash size={14} />
                    </button>
                  </div>
                </div>
              ))}
            </div>
          </div>
        ))}
      </div>

      <Modal open={showForm} onClose={() => { setShowForm(false); setEditing(null); }}
        title={editing ? `Edit ${editing.nama}` : "Tambah Kategori Kas"}
        icon={<I.Tag size={20} style={{color: "var(--brand)"}} />}>
        <KategoriForm editing={editing} onCancel={() => { setShowForm(false); setEditing(null); }} onSave={handleSave} />
      </Modal>

      <ConfirmDialog open={!!confirmDel} onClose={() => setConfirmDel(null)}
        onConfirm={() => handleDel(confirmDel.id)}
        title={`Hapus kategori "${confirmDel?.nama}"?`} confirmLabel="Ya, Hapus" danger
        body="Kategori yang sudah dipakai di transaksi kas tidak dapat dihapus." />
    </div>
  );
}

function KategoriForm({ editing, onCancel, onSave }) {
  const [f, setF] = useState(editing ? { ...editing } : { nama: "", tipe: "masuk", aktif: true });
  const [errors, setErrors] = useState({});
  const set = (k, v) => { setF(x => ({...x, [k]: v})); setErrors(e => ({...e, [k]: null})); };
  const submit = () => {
    if (!f.nama?.trim()) { setErrors({ nama: "wajib" }); return; }
    onSave({ ...(editing ? { id: editing.id, seeded: editing.seeded } : {}), ...f, nama: f.nama.trim() });
  };
  return (
    <div>
      <div className="field"><label className="lbl">Nama Kategori <span className="req">*</span></label><input className={`input ${errors.nama ? "err" : ""}`} placeholder="cth: Cuci Bus" value={f.nama} onChange={e => set("nama", e.target.value)} autoFocus /></div>
      <div className="field mt-3">
        <label className="lbl">Tipe <span className="req">*</span></label>
        <div style={{display: "grid", gridTemplateColumns: "1fr 1fr", gap: 8}}>
          <label className="btn" style={{
            cursor: "pointer", height: 44,
            background: f.tipe === "masuk" ? "var(--st-lunas-tint)" : "var(--surface)",
            borderColor: f.tipe === "masuk" ? "var(--st-lunas)" : "var(--border-strong)",
            color: f.tipe === "masuk" ? "oklch(0.32 0.10 155)" : "var(--ink)",
            fontWeight: 600,
          }}>
            <input type="radio" name="kt" checked={f.tipe === "masuk"} onChange={() => set("tipe", "masuk")} style={{marginRight: 6}} /> Kas Masuk
          </label>
          <label className="btn" style={{
            cursor: "pointer", height: 44,
            background: f.tipe === "keluar" ? "var(--st-batal-tint)" : "var(--surface)",
            borderColor: f.tipe === "keluar" ? "var(--st-batal)" : "var(--border-strong)",
            color: f.tipe === "keluar" ? "oklch(0.42 0.17 25)" : "var(--ink)",
            fontWeight: 600,
          }}>
            <input type="radio" name="kt" checked={f.tipe === "keluar"} onChange={() => set("tipe", "keluar")} style={{marginRight: 6}} /> Kas Keluar
          </label>
        </div>
      </div>
      <div className="field mt-3">
        <label className="lbl">Status</label>
        <div style={{display: "flex", gap: 8, alignItems: "center", padding: "8px 0"}}>
          <span className={`switch ${f.aktif ? "on" : ""}`} onClick={() => set("aktif", !f.aktif)} />
          <span style={{fontSize: 13}}>Aktif (muncul di pilihan saat input kas)</span>
        </div>
      </div>
      <div style={{display: "flex", gap: 10, 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={submit}><I.Save size={14} /> Simpan</button>
      </div>
    </div>
  );
}

Object.assign(window, { MasterBus, BusForm, MasterSopir, SopirForm, MasterPenyewa, PenyewaForm, MasterKategori, KategoriForm });
