/* Views: Overview, Machines list, MachineDetail, Profile */
const { useState: useStateViews, useMemo: useMemoViews, useEffect: useEffectViews } = React;

// Per-category safe temperature window. Outside this range raises an alert in
// the admin overview. Coffee machines don't have an internal cabinet temp
// constraint exposed via telemetry, so we leave them unmonitored (null).
const TEMP_RANGES = {
  combo:  { min: 2,   max: 8,  label: "2–8°C"   },
  frozen: { min: -25, max: -5, label: "-25 ke -5°C" },
  coffee: null,
};

// Skema yang TIDAK punya tagihan bulanan — supaya "Per Bulan / Breakdown Biaya"
// disembunyikan. Beli Putus = client beli mesin outright; Kerjasama Lokasi =
// revenue-sharing tanpa sewa flat.
const NON_MONTHLY_SCHEMES = new Set(["Beli Putus", "Kerjasama Lokasi"]);
const isMonthlyScheme = (m) =>
  !NON_MONTHLY_SCHEMES.has(m?.scheme) && Number(m?.monthlyRevenue || 0) > 0;

function invoiceStatusTone(s) {
  if (s === "Lunas") return "success";
  if (s === "Outstanding") return "danger";
  return "warning";
}

/* ===== Stat card ===== */
function StatCard({ label, value, sub, tone, icon, accent }) {
  return (
    <Card className="p-5">
      <div className="flex items-start gap-3">
        <div className={`w-11 h-11 rounded-xl flex items-center justify-center flex-none ${accent || "bg-pink-50 text-[#FF2D55]"}`}>
          <Icon name={icon} size={20} />
        </div>
        <div className="flex-1 min-w-0">
          <div className="text-[11px] font-bold uppercase tracking-widest text-stone-500">{label}</div>
          <div className="font-display text-3xl uppercase mt-1 text-[#1A1A1A] leading-none truncate">{value}</div>
          {sub && <div className="text-xs text-stone-500 mt-1.5">{sub}</div>}
        </div>
        {tone && <Badge tone={tone.tone}>{tone.label}</Badge>}
      </div>
    </Card>
  );
}

/* ===== ADMIN ANALYTICS BLOCK ===== */
function AdminAnalyticsBlock({ machines, invoices }) {
  const [latestTele, setLatestTele] = useStateViews({});
  const [sales7d, setSales7d]       = useStateViews([]);
  const [loading, setLoading]       = useStateViews(true);

  useEffectViews(() => {
    let cancelled = false;
    (async () => {
      try {
        const latest = await db.latestTelemetry();
        if (cancelled) return;
        setLatestTele(latest);

        // 7-day sales aggregate from telemetry (max sales_today per machine per day)
        const since = new Date(TODAY); since.setDate(since.getDate() - 6); since.setHours(0,0,0,0);
        const { data, error } = await sb.from("yappari_telemetry")
          .select("machine_id, sales_today, recorded_at")
          .gte("recorded_at", since.toISOString())
          .order("recorded_at", { ascending: true });
        if (error) throw error;

        const bucket = {}; // { 'YYYY-MM-DD': { machineId: maxSales } }
        (data || []).forEach(r => {
          const day = r.recorded_at.slice(0, 10);
          bucket[day] = bucket[day] || {};
          bucket[day][r.machine_id] = Math.max(bucket[day][r.machine_id] || 0, Number(r.sales_today) || 0);
        });
        const days = [];
        for (let i = 6; i >= 0; i--) {
          const d = new Date(TODAY); d.setDate(d.getDate() - i);
          const key = d.toISOString().slice(0,10);
          const total = Object.values(bucket[key] || {}).reduce((s, v) => s + v, 0);
          days.push({ date: key, label: d.toLocaleDateString("id-ID", { weekday: "short" }), total });
        }
        if (!cancelled) setSales7d(days);
      } catch (e) {
        console.warn("AdminAnalyticsBlock fetch failed:", e);
      } finally {
        if (!cancelled) setLoading(false);
      }
    })();
    return () => { cancelled = true; };
  }, []);

  // ── Revenue this month vs last month (from invoices) ──
  const { thisMonth, lastMonth, deltaPct } = useMemoViews(() => {
    const t = TODAY;
    const tYear = t.getFullYear(), tMonth = t.getMonth();
    let thisMonth = 0, lastMonth = 0;
    invoices.forEach(inv => {
      if (inv.status !== "Lunas") return;
      const d = new Date(inv.date);
      if (d.getFullYear() === tYear && d.getMonth() === tMonth) thisMonth += inv.amount;
      else if ((tMonth === 0 && d.getFullYear() === tYear - 1 && d.getMonth() === 11) ||
               (d.getFullYear() === tYear && d.getMonth() === tMonth - 1)) lastMonth += inv.amount;
    });
    const deltaPct = lastMonth > 0 ? ((thisMonth - lastMonth) / lastMonth) * 100 : null;
    return { thisMonth, lastMonth, deltaPct };
  }, [invoices]);

  // ── Alerts: offline machines + abnormal temp ──
  const alerts = useMemoViews(() => {
    const out = [];
    machines.forEach(m => {
      const tele = latestTele[m.id];
      if (!tele) return; // no data yet
      if (tele.is_online === false) {
        out.push({ machine: m, kind: "offline", detail: `Tidak online sejak ${new Date(tele.recorded_at).toLocaleString("id-ID")}` });
      }
      const range = TEMP_RANGES[m.category];
      if (range && tele.temperature != null) {
        const t = Number(tele.temperature);
        if (t < range.min || t > range.max) {
          out.push({ machine: m, kind: "temp", detail: `Suhu ${t}°C (aman: ${range.label})` });
        }
      }
    });
    return out;
  }, [machines, latestTele]);

  const hasTelemetry = Object.keys(latestTele).length > 0;
  const max7d        = Math.max(1, ...sales7d.map(d => d.total));
  const chartW = 700, chartH = 180, padL = 36, padB = 28, padT = 12, padR = 12;
  const innerW = chartW - padL - padR, innerH = chartH - padT - padB;
  const barW = sales7d.length ? innerW / sales7d.length * 0.65 : 0;
  const stepX = sales7d.length ? innerW / sales7d.length : 0;

  return (
    <div className="mt-9 space-y-5">
      <div>
        <div className="text-[11px] font-bold uppercase tracking-[0.18em] text-stone-500">Analytics</div>
        <h2 className="font-display text-2xl uppercase text-[#1A1A1A] mt-1">Insight Admin</h2>
      </div>

      <div className="grid grid-cols-1 lg:grid-cols-3 gap-5">
        {/* Revenue month-over-month */}
        <Card className="p-6 lg:col-span-1">
          <div className="text-[11px] font-bold uppercase tracking-widest text-stone-500">Revenue Bulan Ini</div>
          <div className="font-display text-3xl text-[#1A1A1A] mt-1">{formatRp(thisMonth)}</div>
          <div className="mt-3 flex items-center gap-2">
            {deltaPct === null ? (
              <Badge tone="neutral">Belum ada perbandingan</Badge>
            ) : deltaPct >= 0 ? (
              <Badge tone="success"><Icon name="trending" size={12}/> +{deltaPct.toFixed(1)}%</Badge>
            ) : (
              <Badge tone="danger">{deltaPct.toFixed(1)}%</Badge>
            )}
            <span className="text-xs text-stone-500">vs bulan lalu ({formatRp(lastMonth)})</span>
          </div>
        </Card>

        {/* 7-day sales chart */}
        <Card className="p-6 lg:col-span-2">
          <div className="flex items-end justify-between mb-3">
            <div>
              <div className="text-[11px] font-bold uppercase tracking-widest text-stone-500">Sales 7 Hari</div>
              <div className="font-display text-xl uppercase text-[#1A1A1A] mt-0.5">
                Total: {formatRp(sales7d.reduce((s, d) => s + d.total, 0))}
              </div>
            </div>
            <div className="text-[10px] text-stone-400">sumber: telemetry</div>
          </div>
          {loading ? (
            <div className="h-44 flex items-center justify-center text-sm text-stone-400">Memuat…</div>
          ) : !hasTelemetry || sales7d.every(d => d.total === 0) ? (
            <div className="h-44 flex flex-col items-center justify-center text-center text-stone-400">
              <Icon name="trending" size={28} className="mb-2"/>
              <div className="text-sm">Belum ada data telemetry.</div>
              <div className="text-xs mt-1">Aktifkan sync Telemetron untuk melihat tren penjualan.</div>
            </div>
          ) : (
            <svg viewBox={`0 0 ${chartW} ${chartH}`} className="w-full h-44">
              {/* y gridlines */}
              {[0.25, 0.5, 0.75, 1].map((p, i) => (
                <line key={i}
                  x1={padL} x2={chartW - padR}
                  y1={padT + innerH * (1 - p)} y2={padT + innerH * (1 - p)}
                  stroke="#E7E5E4" strokeDasharray="3 3"/>
              ))}
              {/* y labels */}
              {[0, 0.5, 1].map((p, i) => (
                <text key={i} x={padL - 6} y={padT + innerH * (1 - p) + 4}
                  textAnchor="end" fontSize="10" fill="#a8a29e" fontFamily="monospace">
                  {Math.round(max7d * p / 1000)}k
                </text>
              ))}
              {/* bars */}
              {sales7d.map((d, i) => {
                const x  = padL + stepX * i + (stepX - barW) / 2;
                const h  = (d.total / max7d) * innerH;
                const y  = padT + innerH - h;
                return (
                  <g key={d.date}>
                    <rect x={x} y={y} width={barW} height={h} rx={4} fill="#FF2D55"/>
                    <text x={x + barW / 2} y={chartH - padB + 16} textAnchor="middle" fontSize="11" fill="#57534E">
                      {d.label}
                    </text>
                    {d.total > 0 && (
                      <text x={x + barW / 2} y={y - 4} textAnchor="middle" fontSize="9" fill="#1A1A1A" fontWeight="600">
                        {Math.round(d.total / 1000)}k
                      </text>
                    )}
                  </g>
                );
              })}
            </svg>
          )}
        </Card>
      </div>

      {/* Alerts */}
      {alerts.length > 0 && (
        <Card className="p-5 border-rose-200 bg-rose-50/50">
          <div className="flex items-center gap-2 mb-3">
            <Icon name="alertCircle" size={18} className="text-rose-600"/>
            <div className="font-display text-lg uppercase text-rose-700">
              {alerts.length} Peringatan Mesin
            </div>
          </div>
          <div className="space-y-2">
            {alerts.slice(0, 8).map((a, i) => (
              <div key={i} className="flex items-center gap-3 px-3 py-2 rounded-lg bg-white border border-rose-100">
                <div className="w-8 h-8 rounded-lg flex items-center justify-center flex-none" style={{ background: a.machine.color }}>
                  <Icon name={a.kind === "offline" ? "x" : "thermometer"} size={14} className="text-rose-700"/>
                </div>
                <div className="flex-1 min-w-0">
                  <div className="text-sm font-semibold text-[#1A1A1A]">{a.machine.id}</div>
                  <div className="text-xs text-stone-500 truncate">{a.detail}</div>
                </div>
                <Badge tone={a.kind === "offline" ? "danger" : "warning"}>
                  {a.kind === "offline" ? "Offline" : "Suhu"}
                </Badge>
              </div>
            ))}
          </div>
        </Card>
      )}

      {/* Online/offline machine table */}
      <Card className="overflow-hidden">
        <div className="px-5 py-4 border-b border-stone-100 flex items-center justify-between">
          <div>
            <div className="text-[11px] font-bold uppercase tracking-widest text-stone-500">Status Realtime</div>
            <div className="font-display text-lg uppercase text-[#1A1A1A] mt-0.5">Telemetry Mesin</div>
          </div>
          {!hasTelemetry && <Badge tone="neutral">Belum ada data</Badge>}
        </div>
        <div className="overflow-x-auto">
          <table className="w-full text-sm">
            <thead>
              <tr className="bg-stone-50 border-b border-stone-200 text-[11px] font-bold uppercase tracking-widest text-stone-500">
                <th className="px-5 py-3 text-left">Mesin</th>
                <th className="px-5 py-3 text-center">Status</th>
                <th className="px-5 py-3 text-right hidden md:table-cell">Sales Hari Ini</th>
                <th className="px-5 py-3 text-right hidden md:table-cell">Trx</th>
                <th className="px-5 py-3 text-right hidden lg:table-cell">Suhu</th>
                <th className="px-5 py-3 text-right hidden lg:table-cell">Stok</th>
                <th className="px-5 py-3 text-right text-stone-400">Update</th>
              </tr>
            </thead>
            <tbody>
              {machines.map(m => {
                const tele = latestTele[m.id];
                const online = tele?.is_online === true;
                const offline = tele && tele.is_online === false;
                const range = TEMP_RANGES[m.category];
                const tempBad = range && tele?.temperature != null &&
                  (Number(tele.temperature) < range.min || Number(tele.temperature) > range.max);
                return (
                  <tr key={m.id} className="border-b border-stone-100 last:border-0">
                    <td className="px-5 py-3">
                      <div className="flex items-center gap-2.5">
                        <div className="w-8 h-8 rounded-lg flex items-center justify-center flex-none" style={{ background: m.color }}>
                          <Icon name={m.category === "coffee" ? "coffee" : m.category === "frozen" ? "thermometer" : "grid"} size={14} className="text-[#1A1A1A]"/>
                        </div>
                        <div>
                          <div className="font-semibold text-[#1A1A1A] text-sm">{m.id}</div>
                          <div className="text-[11px] text-stone-500">{m.location}</div>
                        </div>
                      </div>
                    </td>
                    <td className="px-5 py-3 text-center">
                      {online   && <Badge tone="success">● Online</Badge>}
                      {offline  && <Badge tone="danger">● Offline</Badge>}
                      {!tele    && <Badge tone="neutral">—</Badge>}
                    </td>
                    <td className="px-5 py-3 text-right hidden md:table-cell font-semibold text-[#1A1A1A]">
                      {tele ? formatRp(tele.sales_today || 0) : "—"}
                    </td>
                    <td className="px-5 py-3 text-right hidden md:table-cell text-stone-600">
                      {tele?.transactions_today ?? "—"}
                    </td>
                    <td className={`px-5 py-3 text-right hidden lg:table-cell font-mono text-xs ${tempBad ? "text-rose-600 font-bold" : "text-stone-600"}`}>
                      {tele?.temperature != null ? `${tele.temperature}°C` : "—"}
                    </td>
                    <td className="px-5 py-3 text-right hidden lg:table-cell text-stone-600">
                      {tele?.stock_level != null ? `${tele.stock_level}%` : "—"}
                    </td>
                    <td className="px-5 py-3 text-right text-[11px] text-stone-400">
                      {tele ? new Date(tele.recorded_at).toLocaleTimeString("id-ID", { hour: "2-digit", minute: "2-digit" }) : "—"}
                    </td>
                  </tr>
                );
              })}
            </tbody>
          </table>
        </div>
      </Card>
    </div>
  );
}

/* ===== OVERVIEW ===== */
function OverviewView() {
  const { user, isAdmin, machines, allMachines, navigate, users, invoices } = useApp();

  /* admin sees all machines, client sees their own */
  const myMachines = isAdmin ? allMachines : machines;
  const active        = myMachines.filter(m => statusForMachine(m).tone !== "danger").length;
  const expiringSoon  = myMachines.filter(m => statusForMachine(m).tone === "warning");
  const totalMonthly  = myMachines.reduce((s, m) => s + m.monthlyRevenue, 0);
  const totalSales    = myMachines.reduce((s, m) => s + m.salesThisMonth, 0);
  const totalTx       = myMachines.reduce((s, m) => s + m.transactionsThisMonth, 0);
  const clients       = users.filter(u => u.role === "client");

  // Client invoices — used both for the Tagihan StatCard and the "Invoice Saya" table.
  const myInvoices = useMemoViews(
    () => isAdmin ? [] : invoices.filter(i => i.clientId === user?.id),
    [invoices, isAdmin, user?.id]
  );
  const outstandingInvoices = myInvoices.filter(i => i.status !== "Lunas");
  const totalOutstanding    = outstandingInvoices.reduce((s, i) => s + Number(i.amount || 0), 0);

  const nextBilling = myMachines.length > 0
    ? myMachines
        .map(m => ({ machine: m, date: m.contractEnd, amount: m.monthlyRevenue }))
        .sort((a, b) => new Date(a.date) - new Date(b.date))[0]
    : null;

  return (
    <div className="px-5 md:px-8 py-7 md:py-9 max-w-6xl mx-auto">
      <PageHeader
        eyebrow={`Halo, ${user?.name?.split(" ")[0] || ""}!`}
        jp={isAdmin ? "管理者ダッシュボード" : "お帰りなさい！"}
        title={isAdmin ? "Admin Dashboard" : "Welcome back."}
        sub={isAdmin
          ? `${clients.length} client aktif · ${allMachines.length} mesin terpasang`
          : "Ringkasan mesin, tagihan, dan aktivitas terbaru Anda di Yappari!"}
        actions={isAdmin
          ? <><Button onClick={() => navigate({ name: "admin-clients" })} variant="dark">Daftar Client <Icon name="arrowR" size={16}/></Button>
              <Button onClick={() => navigate({ name: "admin-machines" })} variant="primary">Status Mesin <Icon name="arrowR" size={16}/></Button></>
          : <Button onClick={() => navigate({ name: "machines" })} variant="primary">Kelola Mesin <Icon name="arrowR" size={16}/></Button>
        }
      />

      {/* Expiring alert */}
      {expiringSoon.length > 0 && (
        <div className="mb-6 bg-amber-50 border border-amber-200 rounded-2xl px-5 py-4 flex flex-wrap items-center gap-3">
          <div className="w-10 h-10 rounded-full bg-amber-100 text-amber-700 flex items-center justify-center flex-none">
            <Icon name="bell" size={20} />
          </div>
          <div className="flex-1 min-w-[200px]">
            <div className="font-semibold text-amber-900 text-sm">{expiringSoon.length} mesin mendekati expired</div>
            <div className="text-xs text-amber-800/80 mt-0.5">
              Mesin <strong>{expiringSoon[0].id}</strong> berakhir dalam {statusForMachine(expiringSoon[0]).days} hari.
            </div>
          </div>
          <Button size="sm" variant="dark"
            onClick={() => navigate(isAdmin
              ? { name: "admin-machines" }
              : { name: "machine-renew", id: expiringSoon[0].id }
            )}>
            {isAdmin ? "Lihat Semua" : "Perpanjang"} <Icon name="arrowR" size={14} />
          </Button>
        </div>
      )}

      {/* Summary grid */}
      <div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-4">
        {isAdmin && (
          <StatCard label="Total Client" value={`${clients.length}`} sub="client aktif" icon="users" accent="bg-sky-50 text-sky-700"/>
        )}
        <StatCard label="Mesin Aktif" value={`${active}`} sub={`${myMachines.length} total mesin`} icon="grid" accent="bg-pink-50 text-[#FF2D55]"/>
        {isAdmin
          ? (nextBilling && (
              <StatCard
                label="Pendapatan Bulanan"
                value={"Rp" + (totalMonthly/1000000).toFixed(1) + "Jt"}
                sub="total semua mesin"
                icon="wallet"
                accent="bg-amber-50 text-amber-700"
              />
            ))
          : (
              <StatCard
                label="Tagihan"
                value={outstandingInvoices.length ? formatRp(totalOutstanding) : "Lunas"}
                sub={outstandingInvoices.length
                  ? `${outstandingInvoices.length} invoice belum dibayar`
                  : "Tidak ada tagihan terbuka"}
                icon="wallet"
                accent={outstandingInvoices.length ? "bg-amber-50 text-amber-700" : "bg-emerald-50 text-emerald-700"}
              />
            )
        }
        <StatCard label="Sales Bulan Ini" value={"Rp" + (totalSales/1000000).toFixed(1) + "Jt"} sub={`${totalTx.toLocaleString("id-ID")} transaksi`} icon="trending" accent="bg-emerald-50 text-emerald-700"/>
        <StatCard label="Status" value={expiringSoon.length > 0 ? "Perhatian" : "Normal"} sub={expiringSoon.length > 0 ? `${expiringSoon.length} mesin expiring` : "Semua mesin oke"} icon="shield" accent={expiringSoon.length > 0 ? "bg-amber-50 text-amber-700" : "bg-emerald-50 text-emerald-700"}/>
      </div>

      {/* Admin-only analytics */}
      {isAdmin && (
        <AdminAnalyticsBlock machines={allMachines} invoices={invoices} />
      )}

      {/* Machines mini-list */}
      <div className="mt-9">
        <div className="flex items-end justify-between mb-4">
          <div>
            <div className="text-[11px] font-bold uppercase tracking-[0.18em] text-stone-500">Mesin</div>
            <h2 className="font-display text-2xl uppercase text-[#1A1A1A] mt-1">Status Mesin</h2>
          </div>
          <button
            onClick={() => navigate({ name: isAdmin ? "admin-machines" : "machines" })}
            className="text-sm font-semibold text-[#FF2D55] hover:underline">
            Lihat semua →
          </button>
        </div>
        <div className="grid gap-3">
          {myMachines.slice(0, 5).map(m => {
            const s = statusForMachine(m);
            const client = isAdmin ? USERS.find(u => u.id === m.clientId) : null;
            return (
              <Card key={m.id} className="p-5 hover:border-[#FF2D55] transition-colors cursor-pointer group"
                onClick={() => navigate(isAdmin ? { name: "admin-machines" } : { name: "machine-detail", id: m.id })}>
                <div className="flex flex-wrap items-center gap-4">
                  <div className="w-14 h-14 rounded-xl flex-none flex items-center justify-center" style={{ background: m.color }}>
                    <Icon name={m.category === "coffee" ? "coffee" : m.category === "frozen" ? "thermometer" : "grid"} size={26} className="text-[#1A1A1A]" />
                  </div>
                  <div className="flex-1 min-w-[160px]">
                    <div className="text-[11px] font-bold uppercase tracking-widest text-stone-500">{m.model}</div>
                    <div className="font-semibold text-[#1A1A1A] mt-0.5">{m.id}</div>
                    {isAdmin && client && <div className="text-xs text-stone-500 mt-0.5 flex items-center gap-1"><Icon name="user" size={11}/> {client.name}</div>}
                    <div className="text-xs text-stone-500 mt-0.5 flex items-center gap-1"><Icon name="mapPin" size={11}/> {m.location}</div>
                  </div>
                  <div className="hidden md:block text-right">
                    {isMonthlyScheme(m) ? (
                      <>
                        <div className="text-[11px] font-bold uppercase tracking-widest text-stone-500">Per bulan</div>
                        <div className="font-display text-xl text-[#1A1A1A] mt-0.5">{formatRp(m.monthlyRevenue)}</div>
                      </>
                    ) : (
                      <>
                        <div className="text-[11px] font-bold uppercase tracking-widest text-stone-500">Skema</div>
                        <div className="font-display text-xl text-[#1A1A1A] mt-0.5">{m.scheme || "Beli Putus"}</div>
                      </>
                    )}
                  </div>
                  <div className="flex flex-col items-end gap-1">
                    <Badge tone={s.tone}>{s.tone === "success" ? "Aktif" : s.tone === "warning" ? "Akan Berakhir" : "Expired"}</Badge>
                    <div className="text-[11px] text-stone-500">{s.label}</div>
                  </div>
                  <Icon name="chevronR" size={18} className="text-stone-300 group-hover:text-[#FF2D55] transition-colors" />
                </div>
              </Card>
            );
          })}
        </div>
      </div>

      {/* Client invoices — only for clients (admins use the Invoices view) */}
      {!isAdmin && (
        <div className="mt-9">
          <div className="flex items-end justify-between mb-4">
            <div>
              <div className="text-[11px] font-bold uppercase tracking-[0.18em] text-stone-500">Tagihan</div>
              <h2 className="font-display text-2xl uppercase text-[#1A1A1A] mt-1">Invoice Saya</h2>
            </div>
            {outstandingInvoices.length > 0 && (
              <Badge tone="danger">{outstandingInvoices.length} belum dibayar</Badge>
            )}
          </div>
          <Card className="overflow-hidden">
            {myInvoices.length === 0 ? (
              <div className="px-5 py-10 text-center text-stone-400 text-sm">Belum ada invoice.</div>
            ) : (
              <div className="overflow-x-auto">
                <table className="w-full text-sm">
                  <thead>
                    <tr className="bg-stone-50 border-b border-stone-200 text-[11px] font-bold uppercase tracking-widest text-stone-500">
                      <th className="px-5 py-3 text-left">No Invoice</th>
                      <th className="px-5 py-3 text-left">Periode</th>
                      <th className="px-5 py-3 text-right">Nominal</th>
                      <th className="px-5 py-3 text-center">Status</th>
                      <th className="px-5 py-3 text-right">PDF</th>
                    </tr>
                  </thead>
                  <tbody>
                    {myInvoices.map(inv => (
                      <tr key={inv.id} className="border-b border-stone-100 last:border-0 hover:bg-stone-50/50">
                        <td className="px-5 py-3.5">
                          <div className="font-mono text-xs font-semibold text-[#1A1A1A]">{inv.id}</div>
                          <div className="text-[11px] text-stone-400 mt-0.5">{formatDateID(inv.date)}</div>
                        </td>
                        <td className="px-5 py-3.5 text-stone-700">{inv.period || "—"}</td>
                        <td className="px-5 py-3.5 text-right font-semibold text-[#1A1A1A]">{formatRp(inv.amount)}</td>
                        <td className="px-5 py-3.5 text-center">
                          <Badge tone={invoiceStatusTone(inv.status)}>{inv.status}</Badge>
                        </td>
                        <td className="px-5 py-3.5 text-right">
                          <button
                            title="Download PDF"
                            onClick={() => {
                              try { window.exportInvoiceDoc(inv, user?.name || "—"); }
                              catch (e) { console.warn("PDF gagal:", e); }
                            }}
                            className="p-2 rounded-lg text-stone-400 hover:bg-stone-100 hover:text-[#FF2D55]">
                            <Icon name="download" size={15}/>
                          </button>
                        </td>
                      </tr>
                    ))}
                  </tbody>
                </table>
              </div>
            )}
          </Card>
        </div>
      )}

      {/* Recent payments */}
      <div className="mt-9">
        <div className="mb-4">
          <div className="text-[11px] font-bold uppercase tracking-[0.18em] text-stone-500">Aktivitas</div>
          <h2 className="font-display text-2xl uppercase text-[#1A1A1A] mt-1">Pembayaran Terbaru</h2>
        </div>
        <Card className="overflow-hidden">
          <div className="grid grid-cols-12 px-5 py-3 text-[11px] font-bold uppercase tracking-widest text-stone-500 bg-stone-50 border-b border-stone-200">
            <div className="col-span-3">Tanggal</div>
            <div className="col-span-4">Mesin</div>
            <div className="col-span-2">Metode</div>
            <div className="col-span-2 text-right">Nominal</div>
            <div className="col-span-1 text-right">Status</div>
          </div>
          {myMachines.flatMap(m => m.payments.slice(0, 2).map(p => ({ ...p, machine: m }))).slice(0, 6).map((p, i) => (
            <div key={i} className="grid grid-cols-12 px-5 py-3.5 items-center text-sm border-b border-stone-100 last:border-0 hover:bg-stone-50/50">
              <div className="col-span-3 text-stone-700">{formatDateID(p.date)}</div>
              <div className="col-span-4 font-medium text-[#1A1A1A]">{p.machine.id}<div className="text-xs text-stone-500 font-normal">{p.machine.model}</div></div>
              <div className="col-span-2 text-stone-600">{p.method}</div>
              <div className="col-span-2 text-right font-semibold text-[#1A1A1A]">{formatRp(p.amount)}</div>
              <div className="col-span-1 flex justify-end"><Badge tone="success">Lunas</Badge></div>
            </div>
          ))}
        </Card>
      </div>
    </div>
  );
}

/* ===== CLIENT: MACHINES LIST ===== */
function MachinesView() {
  const { machines, navigate } = useApp();
  const [filter, setFilter] = useStateViews("all");

  const filtered = filter === "all" ? machines : machines.filter(m => {
    const s = statusForMachine(m).tone;
    return (filter === "active" && s === "success") ||
           (filter === "expiring" && s === "warning") ||
           (filter === "expired" && s === "danger");
  });

  return (
    <div className="px-5 md:px-8 py-7 md:py-9 max-w-6xl mx-auto">
      <PageHeader eyebrow="Mesin Saya" jp="自販機リスト" title="Daftar Mesin"
        sub={`Total ${machines.length} mesin. Pantau status, lihat detail, atau perpanjang kontrak.`}
      />
      <div className="flex flex-wrap items-center gap-2 mb-5">
        {[
          { id: "all",      label: "Semua" },
          { id: "active",   label: "Aktif" },
          { id: "expiring", label: "Akan Berakhir" },
          { id: "expired",  label: "Expired" },
        ].map(f => (
          <button key={f.id} onClick={() => setFilter(f.id)}
            className={`px-4 py-2 rounded-full text-sm font-semibold transition ${filter === f.id ? "bg-[#1A1A1A] text-white" : "bg-white border border-stone-200 text-stone-700 hover:border-[#FF2D55] hover:text-[#FF2D55]"}`}>
            {f.label}
          </button>
        ))}
      </div>
      <div className="grid grid-cols-1 lg:grid-cols-2 gap-4">
        {filtered.map(m => {
          const s = statusForMachine(m);
          return (
            <Card key={m.id} className="overflow-hidden hover:shadow-lg hover:-translate-y-0.5 transition-all cursor-pointer"
              onClick={() => navigate({ name: "machine-detail", id: m.id })}>
              <div className="p-5 flex gap-4">
                <div className="w-16 h-20 rounded-xl flex items-center justify-center flex-none" style={{ background: m.color }}>
                  <Icon name={m.category === "coffee" ? "coffee" : m.category === "frozen" ? "thermometer" : "grid"} size={32} className="text-[#1A1A1A]" />
                </div>
                <div className="flex-1 min-w-0">
                  <div className="flex items-start justify-between gap-2">
                    <div>
                      <div className="text-[11px] font-bold uppercase tracking-widest text-stone-500">{m.model}</div>
                      <div className="font-display text-xl text-[#1A1A1A] uppercase leading-none mt-1">{m.id}</div>
                      <div className="text-sm text-stone-600 mt-1.5">{m.type}</div>
                    </div>
                    <Badge tone={s.tone}>{s.tone === "success" ? "Aktif" : s.tone === "warning" ? "Akan Berakhir" : "Expired"}</Badge>
                  </div>
                </div>
              </div>
              <div className="px-5 pb-5 grid grid-cols-2 gap-3 text-sm">
                <div><div className="text-[10px] font-bold uppercase tracking-widest text-stone-500">Lokasi</div>
                  <div className="text-stone-700 mt-0.5 flex items-start gap-1"><Icon name="mapPin" size={13} className="mt-0.5 flex-none text-[#FF2D55]"/>{m.location}</div></div>
                <div><div className="text-[10px] font-bold uppercase tracking-widest text-stone-500">Skema</div>
                  <div className="text-stone-700 mt-0.5">{m.scheme}</div></div>
                <div><div className="text-[10px] font-bold uppercase tracking-widest text-stone-500">Mulai</div>
                  <div className="text-stone-700 mt-0.5">{formatDateID(m.contractStart)}</div></div>
                <div><div className="text-[10px] font-bold uppercase tracking-widest text-stone-500">Berakhir</div>
                  <div className="text-stone-700 mt-0.5">{formatDateID(m.contractEnd)}</div></div>
              </div>
              <div className="px-5 py-4 border-t border-stone-100 bg-stone-50/60 flex items-center justify-between">
                <div>
                  {isMonthlyScheme(m) ? (
                    <>
                      <div className="text-[10px] font-bold uppercase tracking-widest text-stone-500">Per bulan</div>
                      <div className="font-display text-lg text-[#FF2D55]">{formatRp(m.monthlyRevenue)}</div>
                    </>
                  ) : (
                    <>
                      <div className="text-[10px] font-bold uppercase tracking-widest text-stone-500">Skema</div>
                      <div className="font-display text-lg text-[#1A1A1A]">{m.scheme || "Beli Putus"}</div>
                    </>
                  )}
                </div>
                <div className="flex gap-2">
                  <Button size="sm" variant="subtle" onClick={e => { e.stopPropagation(); navigate({ name: "machine-detail", id: m.id }); }}>Detail</Button>
                  {(s.tone === "warning" || s.tone === "danger") && (
                    <Button size="sm" variant="primary" onClick={e => { e.stopPropagation(); navigate({ name: "machine-renew", id: m.id }); }}>
                      Perpanjang <Icon name="arrowR" size={14}/>
                    </Button>
                  )}
                </div>
              </div>
            </Card>
          );
        })}
      </div>
    </div>
  );
}

/* ===== CLIENT: MACHINE DETAIL ===== */
function MachineDetailView() {
  const { route, machines, navigate } = useApp();
  const m = machines.find(x => x.id === route.id) || machines[0];
  const s = statusForMachine(m);
  const monthly = isMonthlyScheme(m);

  // ── Telemetron connection + latest telemetry for this machine ──────────────
  const [teleStatus, setTeleStatus] = useStateViews({ loading: true, mapped: false, latest: null });
  useEffectViews(() => {
    let cancelled = false;
    (async () => {
      try {
        const [creds, latest] = await Promise.all([
          db.getSetting("telemetron").catch(() => null),
          db.latestTelemetry().catch(() => ({})),
        ]);
        if (cancelled) return;
        const map    = creds?.machine_map || {};
        const mapped = Object.values(map).some(v => String(v) === String(m.id));
        setTeleStatus({ loading: false, mapped, latest: latest?.[m.id] || null });
      } catch (e) {
        if (!cancelled) setTeleStatus({ loading: false, mapped: false, latest: null });
      }
    })();
    return () => { cancelled = true; };
  }, [m.id]);

  const teleConnected = teleStatus.mapped && !!teleStatus.latest;
  const teleBadge     = teleStatus.loading
    ? { tone: "neutral", label: "Telemetron: Memuat…" }
    : teleConnected
      ? { tone: "success", label: "Telemetron: Terhubung" }
      : { tone: "neutral", label: "Telemetron: Belum Sinkron" };

  const breakdown = [
    { label: "Sewa Pokok", val: m.rates.sewa, active: true },
    { label: "Cloud Server / Dashboard", val: m.rates.cloud, active: m.addons.cloud },
    { label: "Jasa Refill", val: m.rates.refill, active: m.addons.refill },
    { label: "Cloud API", val: 100000, active: m.addons.cloudApi },
  ];
  const total = breakdown.filter(b => b.active).reduce((a, b) => a + b.val, 0);

  return (
    <div className="px-5 md:px-8 py-7 md:py-9 max-w-6xl mx-auto">
      <button onClick={() => navigate({ name: "machines" })} className="flex items-center gap-1.5 text-sm font-semibold text-stone-500 hover:text-[#FF2D55] mb-5">
        <Icon name="chevronL" size={16}/> Kembali ke Mesin
      </button>
      <div className="flex flex-wrap gap-5 items-start justify-between mb-7">
        <div className="flex gap-5">
          <div className="w-20 h-24 rounded-2xl flex items-center justify-center flex-none" style={{ background: m.color }}>
            <Icon name={m.category === "coffee" ? "coffee" : m.category === "frozen" ? "thermometer" : "grid"} size={36} className="text-[#1A1A1A]"/>
          </div>
          <div>
            <div className="text-[11px] font-bold uppercase tracking-[0.18em] text-[#FF2D55]">{m.model}</div>
            <h1 className="font-display text-3xl md:text-4xl uppercase text-[#1A1A1A] mt-1 leading-none">{m.id}</h1>
            <div className="text-stone-600 mt-2">{m.type}</div>
            <div className="flex flex-wrap items-center gap-2 mt-3">
              <Badge tone={s.tone}>{s.label}</Badge>
              <Badge tone="brand">{m.scheme}</Badge>
              <Badge tone="info"><Icon name="shield" size={12}/> Garansi 1 Tahun</Badge>
              <Badge tone={teleBadge.tone}>{teleBadge.label}</Badge>
            </div>
          </div>
        </div>
        {(s.tone === "warning" || s.tone === "danger") && (
          <Button variant="primary" onClick={() => navigate({ name: "machine-renew", id: m.id })}>
            Perpanjang Kontrak <Icon name="arrowR" size={16}/>
          </Button>
        )}
      </div>

      <div className="grid grid-cols-1 lg:grid-cols-3 gap-5">
        <div className="lg:col-span-2 space-y-5">
          <Card className="p-6">
            <div className="text-[11px] font-bold uppercase tracking-widest text-stone-500 mb-3">Kontrak</div>
            <div className="grid grid-cols-2 md:grid-cols-4 gap-5">
              {[
                { label: "Skema", val: m.scheme },
                { label: "Mulai", val: formatDateID(m.contractStart) },
                { label: "Berakhir", val: formatDateID(m.contractEnd) },
                { label: "Lokasi", val: m.location },
              ].map(item => (
                <div key={item.label}>
                  <div className="text-xs text-stone-500">{item.label}</div>
                  <div className="font-semibold text-[#1A1A1A] mt-0.5 leading-snug">{item.val}</div>
                </div>
              ))}
            </div>
            <div className="mt-5"><ProgressBar machine={m}/></div>
          </Card>

          {monthly ? (
            <Card className="overflow-hidden">
              <div className="px-6 py-4 border-b border-stone-100 flex items-center justify-between">
                <div>
                  <div className="text-[11px] font-bold uppercase tracking-widest text-stone-500">Breakdown Biaya</div>
                  <div className="font-display text-xl uppercase text-[#1A1A1A] mt-0.5">Tagihan Bulanan</div>
                </div>
                <div className="text-right">
                  <div className="text-[11px] text-stone-500">Total / bulan</div>
                  <div className="font-display text-2xl text-[#FF2D55] leading-none mt-0.5">{formatRp(total)}</div>
                </div>
              </div>
              {breakdown.map((b, i) => (
                <div key={i} className={`px-6 py-4 flex items-center justify-between border-b border-stone-100 last:border-0 ${!b.active ? "opacity-40" : ""}`}>
                  <div className="flex items-center gap-3">
                    <div className={`w-2 h-2 rounded-full ${b.active ? "bg-[#FF2D55]" : "bg-stone-300"}`}></div>
                    <div>
                      <div className="font-medium text-[#1A1A1A]">{b.label}</div>
                      {!b.active && <div className="text-xs text-stone-500 mt-0.5">Tidak aktif</div>}
                    </div>
                  </div>
                  <div className="font-display text-lg text-[#1A1A1A]">{formatRp(b.val)}<span className="text-xs text-stone-400 font-sans font-normal ml-1">/bln</span></div>
                </div>
              ))}
            </Card>
          ) : (
            <Card className="p-6">
              <div className="text-[11px] font-bold uppercase tracking-widest text-stone-500">Skema Pembayaran</div>
              <div className="font-display text-xl uppercase text-[#1A1A1A] mt-0.5">{m.scheme || "Beli Putus"}</div>
              <p className="text-sm text-stone-600 mt-3">
                Mesin ini menggunakan skema <strong>{m.scheme || "Beli Putus"}</strong> — tidak ada tagihan sewa bulanan.
              </p>
            </Card>
          )}

          <Card className="overflow-hidden">
            <div className="px-6 py-4 border-b border-stone-100">
              <div className="text-[11px] font-bold uppercase tracking-widest text-stone-500">Riwayat</div>
              <div className="font-display text-xl uppercase text-[#1A1A1A] mt-0.5">Pembayaran</div>
            </div>
            {m.payments.map((p, i) => (
              <div key={i} className="px-6 py-4 flex items-center gap-4 border-b border-stone-100 last:border-0">
                <div className="w-10 h-10 rounded-full bg-emerald-50 text-emerald-700 flex items-center justify-center"><Icon name="check" size={18}/></div>
                <div className="flex-1">
                  <div className="font-medium text-[#1A1A1A]">{formatDateID(p.date)}</div>
                  <div className="text-xs text-stone-500 mt-0.5">via {p.method}</div>
                </div>
                <div className="text-right">
                  <div className="font-semibold text-[#1A1A1A]">{formatRp(p.amount)}</div>
                  <Badge tone="success" className="mt-1">{p.status}</Badge>
                </div>
                <button className="text-stone-400 hover:text-[#FF2D55]"><Icon name="download" size={18}/></button>
              </div>
            ))}
          </Card>
        </div>

        <div className="space-y-5">
          <Card className="p-6">
            <div className="flex items-start justify-between gap-3 mb-3">
              <div className="text-[11px] font-bold uppercase tracking-widest text-stone-500">Performa Bulan Ini</div>
              <Badge tone={teleBadge.tone}>{teleConnected ? "Terhubung" : "Belum Sinkron"}</Badge>
            </div>
            {teleConnected ? (
              <>
                <div className="font-display text-3xl text-[#1A1A1A]">{formatRp(m.salesThisMonth)}</div>
                <div className="text-sm text-stone-500 mt-1">
                  {Number(m.transactionsThisMonth || 0).toLocaleString("id-ID")} transaksi
                </div>
              </>
            ) : (
              <div className="text-sm text-stone-500 leading-relaxed">
                Data penjualan akan muncul setelah Telemetron tersinkronisasi.
                {!teleStatus.mapped && (
                  <span className="block mt-1 text-xs text-stone-400">
                    Mesin belum di-mapping. Hubungkan di menu Admin → Telemetron Settings.
                  </span>
                )}
              </div>
            )}
            <div className="mt-4 pt-4 border-t border-stone-100">
              <div className="flex gap-1.5 flex-wrap">
                {["QRIS","OVO","GoPay","DANA"].map(t => (
                  <span key={t} className="text-[10px] font-bold uppercase tracking-wider px-2 py-1 bg-stone-100 text-stone-600 rounded">{t}</span>
                ))}
              </div>
            </div>
          </Card>

          <Card className="p-6 bg-gradient-to-br from-[#1A1A1A] to-[#2A2A2A] text-white relative overflow-hidden">
            <div className="absolute -right-4 -bottom-6 font-jp font-black text-[120px] leading-[0.8] text-white/5 select-none">保証</div>
            <div className="relative">
              <Icon name="shield" size={28} className="text-[#FF2D55]"/>
              <div className="font-display text-xl uppercase mt-3">Garansi Mesin</div>
              <ul className="mt-3 space-y-2 text-sm text-stone-300">
                <li className="flex gap-2"><Icon name="check" size={16} className="text-[#FF2D55] flex-none mt-0.5"/>Sparepart 1 tahun</li>
                <li className="flex gap-2"><Icon name="check" size={16} className="text-[#FF2D55] flex-none mt-0.5"/>Service remote gratis</li>
                <li className="flex gap-2"><Icon name="check" size={16} className="text-[#FF2D55] flex-none mt-0.5"/>Response time &lt; 24 jam</li>
              </ul>
            </div>
          </Card>

          <Card className="p-6">
            <div className="text-[11px] font-bold uppercase tracking-widest text-stone-500 mb-2">Butuh bantuan?</div>
            <div className="font-display text-lg uppercase text-[#1A1A1A]">Hubungi Ines</div>
            <a href="https://wa.me/628976046500" target="_blank" rel="noopener"
               className="mt-3 inline-flex items-center gap-2 text-[#FF2D55] font-semibold hover:underline">
              0897 604 6500 <Icon name="arrowR" size={14}/>
            </a>
          </Card>
        </div>
      </div>
    </div>
  );
}

/* Progress bar */
function ProgressBar({ machine }) {
  const start = new Date(machine.contractStart).getTime();
  const end   = new Date(machine.contractEnd).getTime();
  const now   = TODAY.getTime();
  const pct   = end > start ? Math.min(Math.max((now - start) / (end - start) * 100, 0), 100) : 0;
  const days  = Math.max(0, Math.round((end - now) / 86400000));
  const tone  = pct > 90 ? "danger" : pct > 80 ? "warning" : "success";
  const bar   = tone === "danger" ? "bg-rose-500" : tone === "warning" ? "bg-amber-500" : "bg-emerald-500";
  return (
    <div>
      <div className="flex justify-between text-xs mb-2">
        <span className="text-stone-500">Progress kontrak</span>
        <span className="font-semibold text-[#1A1A1A]">{Math.round(pct)}% · {days} hari tersisa</span>
      </div>
      <div className="w-full h-2 bg-stone-100 rounded-full overflow-hidden">
        <div className={`h-full ${bar} transition-all`} style={{ width: pct + "%" }}></div>
      </div>
      <div className="flex justify-between mt-2 text-[11px] text-stone-400">
        <span>{formatDateID(machine.contractStart)}</span>
        <span>{formatDateID(machine.contractEnd)}</span>
      </div>
    </div>
  );
}

/* ===== PROFILE ===== */
function ProfileView() {
  const { user, setUsers, toast, isAdmin } = useApp();
  const [profile, setProfile] = useStateViews({ ...user });
  const [pw, setPw]           = useStateViews({ old: "", n1: "", n2: "" });
  const [showOld, setShowOld] = useStateViews(false);
  const [showN1, setShowN1]   = useStateViews(false);
  const [showN2, setShowN2]   = useStateViews(false);

  function saveProfile(e) {
    e.preventDefault();
    const updated = { ...user, ...profile };
    setUsers && setUsers(prev => prev.map(u => u.id === updated.id ? updated : u));
    toast("Profil berhasil diupdate.", "success");
    db.upsertUser(updated).catch(err => toast("Gagal simpan ke Supabase: " + err.message, "danger"));
  }

  function changePassword(e) {
    e.preventDefault();
    if (!pw.old)         { toast("Masukkan password lama.", "danger"); return; }
    if (pw.old !== user.password) { toast("Password lama tidak cocok.", "danger"); return; }
    if (pw.n1.length < 6) { toast("Password baru minimal 6 karakter.", "danger"); return; }
    if (pw.n1 !== pw.n2) { toast("Konfirmasi password tidak cocok.", "danger"); return; }
    const updated = { ...user, password: pw.n1 };
    setUsers && setUsers(prev => prev.map(u => u.id === updated.id ? updated : u));
    setPw({ old: "", n1: "", n2: "" });
    toast("Password berhasil diubah.", "success");
    db.upsertUser(updated).catch(err => toast("Gagal simpan ke Supabase: " + err.message, "danger"));
  }

  const PwField = ({ label, val, onChange, show, setShow }) => (
    <div>
      <label className="text-[11px] font-bold uppercase tracking-widest text-stone-500">{label}</label>
      <div className="mt-1.5 relative">
        <input
          type={show ? "text" : "password"} value={val} onChange={e => onChange(e.target.value)}
          className="w-full px-4 py-2.5 pr-14 rounded-xl border border-stone-300 bg-white text-[#1A1A1A] focus:border-[#FF2D55] focus:ring-2 focus:ring-pink-100 outline-none transition"
          placeholder="••••••••"
        />
        <button type="button" onClick={() => setShow(s => !s)}
          className="absolute right-3 top-1/2 -translate-y-1/2 text-stone-400 hover:text-stone-700 text-xs font-semibold">
          {show ? "HIDE" : "SHOW"}
        </button>
      </div>
    </div>
  );

  return (
    <div className="px-5 md:px-8 py-7 md:py-9 max-w-4xl mx-auto">
      <PageHeader eyebrow="Akun" jp="プロフィール" title="Profil & Akun"
        sub="Kelola informasi akun dan ubah password."
      />
      <div className="grid grid-cols-1 md:grid-cols-3 gap-5">
        {/* Avatar card */}
        <Card className="p-6 md:col-span-1 text-center">
          <div className={`w-24 h-24 rounded-full flex items-center justify-center font-jp text-4xl font-bold mx-auto text-white ${isAdmin ? "bg-[#1A1A1A]" : "bg-[#FF2D55]"}`}>
            {user?.name?.charAt(0)}
          </div>
          <div className="font-display text-xl uppercase text-[#1A1A1A] mt-4">{user?.name}</div>
          <div className="text-sm text-stone-500 mt-1">{user?.email}</div>
          <Badge tone={isAdmin ? "danger" : "brand"} className="mt-3">
            {isAdmin ? "Administrator" : `Client sejak ${user?.joined?.split(" ").slice(-2).join(" ")}`}
          </Badge>
          {user?.address && (
            <div className="mt-5 pt-5 border-t border-stone-100 text-left">
              <div className="text-[10px] font-bold uppercase tracking-widest text-stone-500 mb-1">Alamat</div>
              <div className="text-sm text-stone-700 flex gap-1.5 items-start">
                <Icon name="mapPin" size={14} className="text-[#FF2D55] mt-0.5 flex-none"/>{user.address}
              </div>
            </div>
          )}
        </Card>

        <div className="md:col-span-2 space-y-5">
          {/* Edit profile */}
          <Card className="p-6">
            <div className="text-[11px] font-bold uppercase tracking-widest text-stone-500 mb-1">Informasi</div>
            <h2 className="font-display text-2xl uppercase text-[#1A1A1A]">Detail Akun</h2>
            <form onSubmit={saveProfile} className="mt-5 grid grid-cols-1 md:grid-cols-2 gap-4">
              <Field label="Nama" value={profile.name || ""} onChange={v => setProfile({ ...profile, name: v })}/>
              <Field label="Email" type="email" value={profile.email || ""} onChange={v => setProfile({ ...profile, email: v })}/>
              <Field label="Nomor HP" value={profile.phone || ""} onChange={v => setProfile({ ...profile, phone: v })}/>
              {profile.address !== undefined && (
                <Field label="Alamat" value={profile.address || ""} onChange={v => setProfile({ ...profile, address: v })} full/>
              )}
              <div className="md:col-span-2 flex gap-2">
                <Button type="submit" variant="primary">Simpan Perubahan</Button>
                <Button type="button" variant="subtle" onClick={() => setProfile({ ...user })}>Batal</Button>
              </div>
            </form>
          </Card>

          {/* Change password */}
          <Card className="p-6">
            <div className="text-[11px] font-bold uppercase tracking-widest text-stone-500 mb-1">Keamanan</div>
            <h2 className="font-display text-2xl uppercase text-[#1A1A1A]">Ubah Password</h2>
            <form onSubmit={changePassword} className="mt-5 space-y-4">
              <PwField label="Password Lama" val={pw.old} onChange={v => setPw({ ...pw, old: v })} show={showOld} setShow={setShowOld}/>
              <div className="grid grid-cols-1 md:grid-cols-2 gap-4">
                <PwField label="Password Baru" val={pw.n1} onChange={v => setPw({ ...pw, n1: v })} show={showN1} setShow={setShowN1}/>
                <PwField label="Konfirmasi Password Baru" val={pw.n2} onChange={v => setPw({ ...pw, n2: v })} show={showN2} setShow={setShowN2}/>
              </div>
              <div className="p-3 rounded-xl bg-stone-50 border border-stone-200 text-xs text-stone-500 flex items-start gap-2">
                <Icon name="alertCircle" size={14} className="flex-none mt-0.5"/>
                Password minimal 6 karakter.
              </div>
              <Button type="submit" variant="dark">
                <Icon name="lock" size={16}/> Ubah Password
              </Button>
            </form>
          </Card>
        </div>
      </div>
    </div>
  );
}

Object.assign(window, { OverviewView, MachinesView, MachineDetailView, ProfileView, ProgressBar, StatCard, AdminAnalyticsBlock });
