"use client";

import clsx from "clsx";
import { useState, type FormEvent } from "react";
import { AlertTriangle, Check, Download, Plus, Wallet } from "lucide-react";
import { Badge, Button, Dialog, EmptyState, Field, Input, PageHeader, Panel, Skeleton } from "@/components/ui/kit";
import { useToast } from "@/components/ui/toast";
import { useSession } from "@/components/session";
import { CheckoutRunner } from "@/components/billing/checkout";
import { limitText, PAYMENT_STATUS, SubscriptionBadge } from "@/components/billing/plan-badge";
import { UsageChart } from "@/components/billing/usage-chart";
import { api, ApiError, qs } from "@/lib/api";
import { formatDate, formatDateTime, formatPaise, paiseToInput, rupeesToPaise } from "@/lib/format";
import { useApi } from "@/lib/use-api";
import type { BillingSummary, Checkout, LedgerEntry, Payment, Plan } from "@/lib/types";

const PRESETS = [50000, 100000, 250000, 500000];
const LEDGER_LABEL: Record<string, string> = { recharge: "Recharge", usage: "Message usage", subscription: "Plan", refund: "Refund", refund_reversal: "Refund reversed", adjustment: "Adjustment" };
const TABS = [
  ["usage", "Usage"],
  ["transactions", "Transactions"],
  ["payments", "Payments & invoices"],
  ["prices", "Message prices"],
  ["details", "Billing details"],
] as const;

function RechargeDialog({ onClose, onCheckout }: { onClose: () => void; onCheckout: (c: Checkout) => void }) {
  const toast = useToast();
  const [amount, setAmount] = useState("1000");
  const [error, setError] = useState<string | null>(null);
  const [busy, setBusy] = useState(false);
  const paise = rupeesToPaise(amount);
  async function submit(e?: FormEvent) {
    e?.preventDefault();
    setBusy(true);
    setError(null);
    try {
      const r = await api.post<{ data: Checkout }>("/billing/recharge", { amount });
      onCheckout(r.data);
    } catch (err) {
      if (err instanceof ApiError && err.fields.amount) setError(err.fields.amount);
      else toast("error", (err as Error).message);
    } finally {
      setBusy(false);
    }
  }
  return (
    <Dialog
      open
      onClose={onClose}
      title="Recharge wallet"
      description="Your wallet pays for template messages WhatsApp charges for, and can pay your plan."
      footer={
        <>
          <Button onClick={onClose}>Cancel</Button>
          <Button variant="primary" loading={busy} disabled={!paise} onClick={() => submit()}>
            Continue to payment
          </Button>
        </>
      }
    >
      <form onSubmit={submit} className="space-y-4">
        <div className="flex flex-wrap gap-2">
          {PRESETS.map((p) => (
            <button
              key={p}
              type="button"
              onClick={() => setAmount(paiseToInput(p))}
              className={clsx("tabular rounded-full border px-3 py-1.5 text-sm", paise === p ? "border-teal bg-teal-soft text-teal" : "border-line hover:border-teal/40")}
            >
              {formatPaise(p, { compact: true })}
            </button>
          ))}
        </div>
        <Field label="Amount (₹)" htmlFor="rc-amount" error={error ?? undefined} hint="GST is added at checkout; the full amount you enter goes into your wallet.">
          <Input id="rc-amount" inputMode="decimal" value={amount} onChange={(e) => setAmount(e.target.value)} invalid={!!error} />
        </Field>
      </form>
    </Dialog>
  );
}

function PlansDialog({ current, balance, onClose, onCheckout, onPaid }: { current: Plan | null; balance: number; onClose: () => void; onCheckout: (c: Checkout) => void; onPaid: () => void }) {
  const toast = useToast();
  const { data } = useApi<{ data: Plan[] }>("/billing/plans");
  const [busy, setBusy] = useState<string | null>(null);
  // One idempotency key per dialog: a double click can't pay twice from the wallet.
  const [key] = useState(() => (typeof crypto !== "undefined" && "randomUUID" in crypto ? crypto.randomUUID() : `k-${Date.now()}-${Math.random().toString(16).slice(2)}`));
  async function choose(p: Plan, method: "online" | "wallet") {
    setBusy(`${p.id}-${method}`);
    try {
      const r = await api.post<{ data: Checkout | { paid: true } }>("/billing/subscription", { plan_id: p.id, method, idempotency_key: `${key}-${p.id}` });
      if ("paid" in r.data) {
        toast("success", `You're on ${p.name}`);
        onPaid();
      } else onCheckout(r.data);
    } catch (e) {
      toast("error", (e as Error).message);
    } finally {
      setBusy(null);
    }
  }
  return (
    <Dialog open onClose={onClose} size="lg" title="Choose a plan" description="Prices are per month before GST. Paying from the wallet uses balance you've already recharged.">
      {!data ? (
        <Skeleton className="h-48 w-full" />
      ) : (
        <div className="grid gap-4 md:grid-cols-3">
          {data.data.map((p) => {
            const isCurrent = current?.id === p.id;
            return (
              <div key={p.id} className={clsx("flex flex-col rounded-xl border p-4", isCurrent ? "border-teal ring-2 ring-teal/20" : "border-line")}>
                <div className="flex items-center justify-between gap-2">
                  <h3 className="font-semibold">{p.name}</h3>
                  {isCurrent && <Badge tone="teal">Current</Badge>}
                </div>
                <p className="tabular mt-2 text-2xl font-semibold tracking-tight text-ink">
                  {formatPaise(p.price_paise, { compact: true })}
                  <span className="text-sm font-normal text-muted">/{p.interval === "year" ? "year" : "month"}</span>
                </p>
                <ul className="mt-3 flex-1 space-y-1.5 text-sm">
                  <li>{limitText(p.limits.whatsapp_numbers)} WhatsApp numbers</li>
                  <li>{limitText(p.limits.team_members)} team members</li>
                  <li>{limitText(p.limits.contacts)} contacts</li>
                  {(["campaigns", "bot_flows", "api_access"] as const).map((f) => (
                    <li key={f} className={clsx("flex items-center gap-1.5", !p.features[f] && "text-muted line-through decoration-line")}>
                      <Check className={clsx("size-3.5", p.features[f] ? "text-teal" : "text-transparent")} />
                      {f === "campaigns" ? "Campaigns" : f === "bot_flows" ? "Bot flows" : "API access"}
                    </li>
                  ))}
                </ul>
                <div className="mt-4 space-y-2">
                  <Button variant="primary" className="w-full" loading={busy === `${p.id}-online`} disabled={busy !== null} onClick={() => choose(p, "online")}>
                    Pay online
                  </Button>
                  <Button className="w-full" loading={busy === `${p.id}-wallet`} disabled={busy !== null || balance < p.price_paise} onClick={() => choose(p, "wallet")} title={balance < p.price_paise ? "Not enough wallet balance" : undefined}>
                    Pay from wallet
                  </Button>
                </div>
              </div>
            );
          })}
        </div>
      )}
    </Dialog>
  );
}

function Pager({ page, last, onPage }: { page: number; last: number; onPage: (p: number) => void }) {
  if (last <= 1) return null;
  return (
    <div className="flex items-center justify-end gap-2 border-t border-line px-5 py-3 text-sm text-muted">
      <span className="tabular mr-auto">
        Page {page} of {last}
      </span>
      <Button size="sm" disabled={page <= 1} onClick={() => onPage(page - 1)}>
        Previous
      </Button>
      <Button size="sm" disabled={page >= last} onClick={() => onPage(page + 1)}>
        Next
      </Button>
    </div>
  );
}

function Transactions() {
  const [page, setPage] = useState(1);
  const { data } = useApi<{ data: LedgerEntry[]; meta: { last_page: number } }>(`/billing/ledger${qs({ page })}`);
  if (!data) return <Skeleton className="m-5 h-40" />;
  if (!data.data.length) return <p className="px-5 py-10 text-center text-sm text-muted">No wallet transactions yet.</p>;
  return (
    <>
      <div className="relative overflow-x-auto">
        <table className="w-full min-w-[640px] text-sm">
          <thead className="text-left text-[13px] text-muted">
            <tr>
              <th className="px-5 py-2.5 font-medium">Date</th>
              <th className="px-3 py-2.5 font-medium">Description</th>
              <th className="px-3 py-2.5 text-right font-medium">Amount</th>
              <th className="px-5 py-2.5 text-right font-medium">Balance</th>
            </tr>
          </thead>
          <tbody className="divide-y divide-line border-t border-line">
            {data.data.map((e) => (
              <tr key={e.id}>
                <td className="tabular whitespace-nowrap px-5 py-2.5 text-muted">{formatDateTime(e.created_at)}</td>
                <td className="px-3 py-2.5">
                  <span className="block font-medium">{LEDGER_LABEL[e.type] ?? e.type}</span>
                  <span className="text-[13px] text-muted">{e.description}</span>
                </td>
                <td className={clsx("tabular px-3 py-2.5 text-right font-medium", e.amount_paise > 0 ? "text-teal" : "text-text")}>
                  {e.amount_paise > 0 ? "+" : ""}
                  {formatPaise(e.amount_paise)}
                </td>
                <td className="tabular px-5 py-2.5 text-right text-muted">{formatPaise(e.balance_after_paise)}</td>
              </tr>
            ))}
          </tbody>
        </table>
      </div>
      <Pager page={page} last={data.meta.last_page} onPage={setPage} />
    </>
  );
}

function Payments() {
  const [page, setPage] = useState(1);
  const { data } = useApi<{ data: Payment[]; meta: { last_page: number } }>(`/billing/payments${qs({ page })}`);
  if (!data) return <Skeleton className="m-5 h-40" />;
  if (!data.data.length) return <p className="px-5 py-10 text-center text-sm text-muted">No payments yet.</p>;
  return (
    <>
      <div className="relative overflow-x-auto">
        <table className="w-full min-w-[680px] text-sm">
          <thead className="text-left text-[13px] text-muted">
            <tr>
              <th className="px-5 py-2.5 font-medium">Date</th>
              <th className="px-3 py-2.5 font-medium">For</th>
              <th className="px-3 py-2.5 text-right font-medium">Total</th>
              <th className="px-3 py-2.5 font-medium">Status</th>
              <th className="px-5 py-2.5 text-right font-medium">Invoice</th>
            </tr>
          </thead>
          <tbody className="divide-y divide-line border-t border-line">
            {data.data.map((p) => (
              <tr key={p.id}>
                <td className="tabular whitespace-nowrap px-5 py-2.5 text-muted">{formatDateTime(p.paid_at ?? p.created_at)}</td>
                <td className="px-3 py-2.5">
                  <span className="block font-medium">{p.purpose === "recharge" ? "Wallet recharge" : "Plan"}</span>
                  <span className="text-[13px] text-muted">
                    {p.provider === "wallet" ? "From wallet" : p.receipt}
                    {p.failure_reason && p.status === "failed" ? `: ${p.failure_reason}` : ""}
                  </span>
                </td>
                <td className="tabular px-3 py-2.5 text-right">
                  {formatPaise(p.total_paise)}
                  {p.refunded_paise > 0 && <span className="block text-xs text-muted">{formatPaise(p.refunded_paise)} refunded</span>}
                </td>
                <td className="px-3 py-2.5">
                  <Badge tone={PAYMENT_STATUS[p.status]?.tone ?? "neutral"}>{PAYMENT_STATUS[p.status]?.label ?? p.status}</Badge>
                </td>
                <td className="px-5 py-2.5 text-right">
                  {p.invoice_id ? (
                    <a href={`/api/billing/invoices/${p.invoice_id}/html`} target="_blank" rel="noreferrer" className="inline-flex items-center gap-1 font-medium text-teal hover:underline">
                      <Download className="size-3.5" /> View
                    </a>
                  ) : (
                    <span className="text-muted">—</span>
                  )}
                </td>
              </tr>
            ))}
          </tbody>
        </table>
      </div>
      <Pager page={page} last={data.meta.last_page} onPage={setPage} />
    </>
  );
}

function Prices() {
  const { data } = useApi<{ data: { category: string; country_prefix: string; price_paise: number }[] }>("/billing/pricing");
  if (!data) return <Skeleton className="m-5 h-32" />;
  if (!data.data.length) return <p className="px-5 py-10 text-center text-sm text-muted">Message charges are not set up on this platform.</p>;
  return (
    <div className="p-5">
      <p className="mb-4 max-w-2xl text-sm text-muted">
        WhatsApp charges per template message delivered, by category and the recipient&apos;s country. Replies inside the 24-hour window are free, and so are utility templates sent inside it. Messages that fail or are never delivered
        are not charged.
      </p>
      <table className="w-full max-w-lg text-sm">
        <thead className="text-left text-[13px] text-muted">
          <tr>
            <th className="py-2 font-medium">Category</th>
            <th className="py-2 font-medium">Recipients</th>
            <th className="py-2 text-right font-medium">Per message</th>
          </tr>
        </thead>
        <tbody className="divide-y divide-line border-t border-line">
          {data.data.map((r) => (
            <tr key={`${r.category}-${r.country_prefix}`}>
              <td className="py-2 capitalize">{r.category}</td>
              <td className="py-2 text-muted">{r.country_prefix === "*" ? "Other countries" : `+${r.country_prefix}`}</td>
              <td className="tabular py-2 text-right">{formatPaise(r.price_paise)}</td>
            </tr>
          ))}
        </tbody>
      </table>
    </div>
  );
}

function Details({ summary, onSaved }: { summary: BillingSummary; onSaved: () => void }) {
  const toast = useToast();
  const p = summary.profile;
  const [f, setF] = useState({ legal_name: p?.legal_name ?? "", gstin: p?.gstin ?? "", address: p?.address ?? "", state_code: p?.state_code ?? "", email: p?.email ?? "" });
  const [low, setLow] = useState(paiseToInput(summary.wallet.low_balance_paise));
  const [errors, setErrors] = useState<Record<string, string>>({});
  const [busy, setBusy] = useState(false);
  async function save(e: FormEvent) {
    e.preventDefault();
    setBusy(true);
    setErrors({});
    try {
      await api.put("/billing/profile", f);
      await api.patch("/billing/settings", { low_balance: low });
      toast("success", "Billing details saved");
      onSaved();
    } catch (err) {
      if (err instanceof ApiError && Object.keys(err.fields).length) setErrors(err.fields);
      else toast("error", (err as Error).message);
    } finally {
      setBusy(false);
    }
  }
  const set = (k: keyof typeof f) => (e: React.ChangeEvent<HTMLInputElement>) => setF({ ...f, [k]: e.target.value });
  return (
    <form onSubmit={save} className="grid max-w-2xl gap-4 p-5 sm:grid-cols-2">
      <Field label="Legal name on invoices" htmlFor="bp-name" error={errors.legal_name}>
        <Input id="bp-name" value={f.legal_name} onChange={set("legal_name")} />
      </Field>
      <Field label="GSTIN" htmlFor="bp-gstin" error={errors.gstin} optional>
        <Input id="bp-gstin" value={f.gstin} onChange={set("gstin")} maxLength={15} invalid={!!errors.gstin} />
      </Field>
      <Field label="Billing address" htmlFor="bp-address" error={errors.address}>
        <Input id="bp-address" value={f.address} onChange={set("address")} />
      </Field>
      <Field label="GST state code" htmlFor="bp-state" error={errors.state_code} hint="e.g. 27 for Maharashtra; decides CGST+SGST or IGST">
        <Input id="bp-state" value={f.state_code} onChange={set("state_code")} maxLength={2} invalid={!!errors.state_code} />
      </Field>
      <Field label="Invoice email" htmlFor="bp-email" error={errors.email}>
        <Input id="bp-email" type="email" value={f.email} onChange={set("email")} invalid={!!errors.email} />
      </Field>
      <Field label="Low-balance alert below (₹)" htmlFor="bp-low" error={errors.low_balance}>
        <Input id="bp-low" inputMode="decimal" value={low} onChange={(e) => setLow(e.target.value)} invalid={!!errors.low_balance} />
      </Field>
      <div className="sm:col-span-2">
        <Button type="submit" variant="primary" loading={busy}>
          Save details
        </Button>
      </div>
    </form>
  );
}

function UsageTab() {
  const { data } = useApi<{ data: { days: { date: string; messages: number; charged_paise: number; estimated_paise: number; free: number }[]; by_category: Record<string, { messages: number; charged_paise: number }>; totals: { messages: number; charged_paise: number; pending_paise: number; free: number } } }>("/billing/usage?days=30");
  if (!data) return <Skeleton className="m-5 h-52" />;
  const t = data.data.totals;
  return (
    <div className="space-y-6 p-5">
      <dl className="grid grid-cols-2 gap-4 md:grid-cols-4">
        {[
          ["Template messages", t.messages.toLocaleString("en-IN")],
          ["Charged", formatPaise(t.charged_paise)],
          ["Awaiting confirmation", formatPaise(t.pending_paise)],
          ["Free", t.free.toLocaleString("en-IN")],
        ].map(([l, v]) => (
          <div key={l}>
            <dt className="text-[13px] text-muted">{l}</dt>
            <dd className="tabular text-xl font-semibold text-ink">{v}</dd>
          </div>
        ))}
      </dl>
      <div className="pl-8">
        <UsageChart days={data.data.days} />
      </div>
      {Object.keys(data.data.by_category).length > 0 && (
        <table className="w-full max-w-md text-sm">
          <caption className="mb-2 text-left text-[13px] font-medium text-muted">By category, last 30 days</caption>
          <tbody className="divide-y divide-line border-y border-line">
            {Object.entries(data.data.by_category).map(([c, v]) => (
              <tr key={c}>
                <td className="py-2 capitalize">{c}</td>
                <td className="tabular py-2 text-right text-muted">{v.messages} messages</td>
                <td className="tabular py-2 text-right">{formatPaise(v.charged_paise)}</td>
              </tr>
            ))}
          </tbody>
        </table>
      )}
      <p className="text-[13px] text-muted">Charges are estimated when a template is sent, then confirmed (or cleared as free) from WhatsApp&apos;s delivery report. Your wallet is charged only for confirmed messages.</p>
    </div>
  );
}

export default function BillingPage() {
  const toast = useToast();
  const { can } = useSession();
  const manage = can("billing.manage");
  const { data, reload } = useApi<{ data: BillingSummary }>("/billing/summary");
  const [dialog, setDialog] = useState<"recharge" | "plans" | null>(null);
  const [checkout, setCheckout] = useState<Checkout | null>(null);
  const [tab, setTab] = useState<(typeof TABS)[number][0]>("usage");
  const [v, setV] = useState(0);
  const s = data?.data;
  const sub = s?.subscription;

  async function toggleRenew(on: boolean) {
    try {
      await api.patch("/billing/settings", { auto_renew: on });
      reload();
    } catch (e) {
      toast("error", (e as Error).message);
    }
  }

  const banner =
    sub && sub.status === "suspended"
      ? { tone: "brick", text: "Your account is suspended because the plan wasn't renewed. Sending is paused until you pay; your data is safe." }
      : sub && sub.status === "past_due"
        ? { tone: "amber", text: `${sub.last_error ?? "Payment is due"}. Pay before ${formatDate(sub.grace_until)} to avoid suspension.` }
        : s?.wallet.low && s.pricing_active
          ? { tone: "amber", text: `Your wallet is below ${formatPaise(s.wallet.low_balance_paise)}. Recharge so template messages and campaigns keep sending.` }
          : null;

  return (
    <>
      <PageHeader title="Wallet & plan" description="Recharge your messaging wallet, manage your plan, and download invoices." />
      {!s ? (
        <div className="grid gap-4 md:grid-cols-2">
          <Skeleton className="h-44" />
          <Skeleton className="h-44" />
        </div>
      ) : (
        <>
          {banner && (
            <div className={clsx("mb-4 flex items-start gap-3 rounded-lg px-4 py-3 text-sm", banner.tone === "brick" ? "bg-brick-soft text-brick" : "bg-amber-soft text-amber")} role="status">
              <AlertTriangle className="mt-0.5 size-4 shrink-0" />
              {banner.text}
            </div>
          )}
          <div className="grid grid-cols-1 gap-4 lg:grid-cols-2">
            <Panel className="flex flex-col p-5">
              <div className="flex items-start justify-between gap-3">
                <div>
                  <p className="text-[13px] font-medium text-muted">Wallet balance</p>
                  <p className="tabular mt-1 text-[34px] font-semibold leading-none tracking-tight text-ink">{formatPaise(s.wallet.balance_paise)}</p>
                  {s.wallet.held_paise > 0 && (
                    <p className="tabular mt-2 text-[13px] text-muted">
                      {formatPaise(s.wallet.available_paise)} available; {formatPaise(s.wallet.held_paise)} held for messages awaiting WhatsApp&apos;s confirmation
                    </p>
                  )}
                </div>
                <span className="grid size-10 place-items-center rounded-full bg-teal-soft text-teal">
                  <Wallet className="size-5" />
                </span>
              </div>
              <div className="mt-auto flex flex-wrap items-center gap-3 pt-5">
                {manage && (
                  <Button variant="primary" icon={<Plus className="size-4" />} onClick={() => setDialog("recharge")} disabled={!s.payments_configured}>
                    Recharge
                  </Button>
                )}
                {!s.payments_configured ? (
                  <span className="text-[13px] text-muted">Online payments aren&apos;t set up yet on this platform.</span>
                ) : (
                  s.payments_simulated && <Badge tone="amber">Test mode</Badge>
                )}
              </div>
            </Panel>

            <Panel className="flex flex-col p-5">
              {sub ? (
                <>
                  <div className="flex items-start justify-between gap-3">
                    <div>
                      <p className="text-[13px] font-medium text-muted">Plan</p>
                      <p className="mt-1 flex items-center gap-2 text-xl font-semibold text-ink">
                        {sub.plan.name} <SubscriptionBadge status={sub.status} />
                      </p>
                      <p className="tabular mt-1 text-sm text-muted">
                        {formatPaise(sub.price_paise, { compact: true })} per {sub.plan.interval}
                        {sub.status === "trialing" ? `, trial ends ${formatDate(sub.trial_ends_at)}` : sub.status === "active" ? `, ${sub.cancel_at_period_end ? "ends" : "renews"} ${formatDate(sub.current_period_end)}` : ""}
                      </p>
                    </div>
                  </div>
                  <dl className="mt-4 grid grid-cols-3 gap-3 text-sm">
                    {(
                      [
                        ["Numbers", s.usage.whatsapp_numbers, sub.plan.limits.whatsapp_numbers],
                        ["Team", s.usage.team_members, sub.plan.limits.team_members],
                        ["Contacts", s.usage.contacts, sub.plan.limits.contacts],
                      ] as const
                    ).map(([l, used, lim]) => (
                      <div key={l}>
                        <dt className="text-[13px] text-muted">{l}</dt>
                        <dd className="tabular font-medium">
                          {used.toLocaleString("en-IN")}
                          <span className="font-normal text-muted"> / {limitText(lim)}</span>
                        </dd>
                        {lim !== null && (
                          <div className="mt-1 h-1 overflow-hidden rounded-full bg-paper">
                            <div className={clsx("h-full", used >= lim ? "bg-brick" : "bg-teal")} style={{ width: `${Math.min(100, (used / Math.max(1, lim)) * 100)}%` }} />
                          </div>
                        )}
                      </div>
                    ))}
                  </dl>
                  {manage && (
                    <div className="mt-auto flex flex-wrap items-center gap-3 pt-5">
                      <Button onClick={() => setDialog("plans")}>{sub.status === "active" ? "Change plan" : "Pay for a plan"}</Button>
                      <label className="flex items-center gap-2 text-[13px]">
                        <input type="checkbox" className="size-4 accent-teal" checked={sub.auto_renew} onChange={(e) => toggleRenew(e.target.checked)} />
                        Renew automatically from the wallet
                      </label>
                    </div>
                  )}
                </>
              ) : (
                <EmptyState icon={<Check />} title="No plan needed" body="This workspace isn't on a billed plan. Message charges, if any, come from the wallet." />
              )}
            </Panel>
          </div>

          <Panel className="mt-6">
            <div className="flex gap-1 overflow-x-auto border-b border-line px-4 py-2" role="tablist" aria-label="Billing sections">
              {TABS.map(([k, l]) => (
                <button key={k} role="tab" aria-selected={tab === k} onClick={() => setTab(k)} className={clsx("shrink-0 rounded-full px-3 py-1.5 text-sm", tab === k ? "bg-ink text-white" : "text-muted hover:bg-paper")}>
                  {l}
                </button>
              ))}
            </div>
            <div key={`${tab}-${v}`}>
              {tab === "usage" && <UsageTab />}
              {tab === "transactions" && <Transactions />}
              {tab === "payments" && <Payments />}
              {tab === "prices" && <Prices />}
              {tab === "details" && <Details summary={s} onSaved={reload} />}
            </div>
          </Panel>
        </>
      )}
      {dialog === "recharge" && (
        <RechargeDialog
          onClose={() => setDialog(null)}
          onCheckout={(c) => {
            setDialog(null);
            setCheckout(c);
          }}
        />
      )}
      {dialog === "plans" && s && (
        <PlansDialog
          current={sub?.plan ?? null}
          balance={s.wallet.available_paise}
          onClose={() => setDialog(null)}
          onCheckout={(c) => {
            setDialog(null);
            setCheckout(c);
          }}
          onPaid={() => {
            setDialog(null);
            reload();
            setV((x) => x + 1);
          }}
        />
      )}
      {checkout && (
        <CheckoutRunner
          checkout={checkout}
          onDone={(p, err) => {
            setCheckout(null);
            if (err) toast("error", err);
            else if (p?.status === "paid") toast("success", p.purpose === "recharge" ? `${formatPaise(p.amount_paise)} added to your wallet` : "Plan payment received");
            else if (p?.status === "failed") toast("error", `Payment failed: ${p.failure_reason ?? "it didn't go through"}`);
            reload();
            setV((x) => x + 1);
          }}
        />
      )}
    </>
  );
}
