// Tenant subscription + billing — self-service surface.
//
// Wired to /api/v1/billing/* on arcadia-core. The payment provider is resolved
// server-side (mock in dev), so "Subscribe" creates a hosted checkout session
// and redirects the browser to the returned URL; on return the overview
// reflects the new plan.

import { useCallback, useEffect, useState } from "react"
import {
  AlertCircle,
  Check,
  CreditCard,
  ExternalLink,
  Loader2,
} from "lucide-react"

import { ArcadiaError, useArcadiaClient } from "@crema/arcadia-client"
import { AppShell } from "~/components/layout/app-shell"
import { Alert, AlertDescription, AlertTitle } from "~/components/ui/alert"
import { Badge } from "~/components/ui/badge"
import { Button } from "~/components/ui/button"
import {
  Card,
  CardContent,
  CardDescription,
  CardFooter,
  CardHeader,
  CardTitle,
} from "~/components/ui/card"
import { Separator } from "~/components/ui/separator"
import { Skeleton } from "~/components/ui/skeleton"
import {
  Table,
  TableBody,
  TableCell,
  TableHead,
  TableHeader,
  TableRow,
} from "~/components/ui/table"
import {
  type BillingOverview,
  type CatalogPlan,
  type Invoice,
  type PlanPricing,
  cancelSubscription,
  createCheckoutSession,
  createPortalSession,
  getBillingOverview,
  listBillingPlans,
  listInvoices,
} from "~/lib/arcadia/billing"

// ---------------------------------------------------------------------------
// Formatting helpers
// ---------------------------------------------------------------------------

function monthlyPricing(plan: CatalogPlan): PlanPricing | null {
  if (!plan.pricing.length) return null
  return plan.pricing.find((p) => p.period === "monthly") ?? plan.pricing[0]
}

function formatMoney(cents: number | null, currency: string | null): string {
  if (cents == null) return "—"
  const cur = currency || "AUD"
  try {
    return new Intl.NumberFormat(undefined, {
      style: "currency",
      currency: cur,
    }).format(cents / 100)
  } catch {
    return `${(cents / 100).toFixed(2)} ${cur}`
  }
}

function formatDate(iso: string | null): string {
  if (!iso) return "—"
  const d = new Date(iso)
  return Number.isNaN(d.getTime())
    ? "—"
    : d.toLocaleDateString(undefined, {
        year: "numeric",
        month: "short",
        day: "numeric",
      })
}

function statusVariant(
  status: string,
): "default" | "secondary" | "destructive" | "outline" {
  switch (status) {
    case "active":
      return "default"
    case "trialing":
      return "secondary"
    case "past_due":
    case "unpaid":
    case "canceled":
    case "cancelled":
      return "destructive"
    default:
      return "outline"
  }
}

// ---------------------------------------------------------------------------
// Route
// ---------------------------------------------------------------------------

export default function PlanRoute() {
  const arcadia = useArcadiaClient()

  const [overview, setOverview] = useState<BillingOverview | null>(null)
  const [plans, setPlans] = useState<CatalogPlan[]>([])
  const [invoices, setInvoices] = useState<Invoice[]>([])
  const [loading, setLoading] = useState(true)
  const [error, setError] = useState<string | null>(null)
  // slug currently being acted on (checkout), or "__portal"/"__cancel"
  const [busy, setBusy] = useState<string | null>(null)

  const load = useCallback(async () => {
    setError(null)
    try {
      const [ov, pls, invs] = await Promise.all([
        getBillingOverview(arcadia),
        listBillingPlans(arcadia).catch(() => [] as CatalogPlan[]),
        listInvoices(arcadia, { limit: 12 }).catch(() => [] as Invoice[]),
      ])
      setOverview(ov)
      setPlans(pls)
      setInvoices(invs)
    } catch (e) {
      setError(
        e instanceof ArcadiaError || e instanceof Error
          ? e.message
          : "Failed to load billing details.",
      )
    } finally {
      setLoading(false)
    }
  }, [arcadia])

  useEffect(() => {
    void load()
  }, [load])

  const returnUrl =
    typeof window !== "undefined" ? window.location.href : undefined

  async function handleSubscribe(plan: CatalogPlan) {
    setBusy(plan.slug)
    setError(null)
    try {
      const { url } = await createCheckoutSession(arcadia, {
        plan: plan.slug,
        successUrl: returnUrl,
        cancelUrl: returnUrl,
      })
      window.location.href = url
    } catch (e) {
      setError(e instanceof Error ? e.message : "Could not start checkout.")
      setBusy(null)
    }
  }

  async function handlePortal() {
    setBusy("__portal")
    setError(null)
    try {
      const { url } = await createPortalSession(arcadia, { returnUrl })
      window.location.href = url
    } catch (e) {
      setError(
        e instanceof Error ? e.message : "Could not open the billing portal.",
      )
      setBusy(null)
    }
  }

  async function handleCancel() {
    if (
      typeof window !== "undefined" &&
      !window.confirm(
        "Cancel your subscription at the end of the current period?",
      )
    ) {
      return
    }
    setBusy("__cancel")
    setError(null)
    try {
      await cancelSubscription(arcadia)
      await load()
    } catch (e) {
      setError(
        e instanceof Error ? e.message : "Could not cancel the subscription.",
      )
    } finally {
      setBusy(null)
    }
  }

  const currentSlug = overview?.plan
  const hasActiveSub =
    overview != null &&
    overview.plan !== "free" &&
    ["active", "trialing", "past_due"].includes(overview.subscription_status)

  return (
    <AppShell>
      <div className="flex items-center gap-3">
        <div className="flex size-10 items-center justify-center rounded-lg bg-primary/10 text-primary">
          <CreditCard className="size-5" />
        </div>
        <div>
          <h1 className="text-2xl font-semibold">Plan</h1>
          <p className="text-sm text-muted-foreground">
            Your tenant's subscription, billing details, and invoice history.
          </p>
        </div>
      </div>

      {error && (
        <Alert variant="destructive">
          <AlertCircle className="size-4" />
          <AlertTitle>Something went wrong</AlertTitle>
          <AlertDescription>{error}</AlertDescription>
        </Alert>
      )}

      {loading ? (
        <div className="space-y-4">
          <Skeleton className="h-32 w-full" />
          <div className="grid gap-4 sm:grid-cols-2 lg:grid-cols-3">
            <Skeleton className="h-48 w-full" />
            <Skeleton className="h-48 w-full" />
            <Skeleton className="h-48 w-full" />
          </div>
        </div>
      ) : (
        <>
          {/* Current plan */}
          {overview && (
            <Card>
              <CardHeader>
                <div className="flex flex-wrap items-center justify-between gap-3">
                  <div className="flex items-center gap-3">
                    <CardTitle className="capitalize">
                      {overview.plan} plan
                    </CardTitle>
                    <Badge variant={statusVariant(overview.subscription_status)}>
                      {overview.subscription_status}
                    </Badge>
                  </div>
                  <div className="flex gap-2">
                    {hasActiveSub && (
                      <Button
                        variant="outline"
                        size="sm"
                        onClick={handlePortal}
                        disabled={busy != null}
                      >
                        {busy === "__portal" ? (
                          <Loader2 className="size-4 animate-spin" />
                        ) : (
                          <ExternalLink className="size-4" />
                        )}
                        Manage billing
                      </Button>
                    )}
                    {hasActiveSub && (
                      <Button
                        variant="ghost"
                        size="sm"
                        onClick={handleCancel}
                        disabled={busy != null}
                      >
                        {busy === "__cancel" ? (
                          <Loader2 className="size-4 animate-spin" />
                        ) : null}
                        Cancel
                      </Button>
                    )}
                  </div>
                </div>
                <CardDescription>
                  {overview.current_period_end
                    ? `Renews ${formatDate(overview.current_period_end)}`
                    : "No active billing period."}
                  {overview.trial_ends_at
                    ? ` · Trial ends ${formatDate(overview.trial_ends_at)}`
                    : ""}
                </CardDescription>
              </CardHeader>
              {overview.billing_email && (
                <CardContent className="text-sm text-muted-foreground">
                  Billing email: {overview.billing_email}
                </CardContent>
              )}
            </Card>
          )}

          {/* Plan picker */}
          {plans.length > 0 && (
            <div className="space-y-3">
              <h2 className="text-lg font-medium">Available plans</h2>
              <div className="grid gap-4 sm:grid-cols-2 lg:grid-cols-3">
                {plans.map((plan) => {
                  const price = monthlyPricing(plan)
                  const isCurrent = plan.slug === currentSlug
                  const isAud = (price?.currency || "AUD") === "AUD"
                  return (
                    <Card
                      key={plan.slug}
                      className={isCurrent ? "border-primary" : undefined}
                    >
                      <CardHeader>
                        <div className="flex items-center justify-between gap-2">
                          <CardTitle>{plan.name}</CardTitle>
                          {isCurrent && (
                            <Badge variant="secondary">
                              <Check className="size-3" />
                              Current
                            </Badge>
                          )}
                        </div>
                        <CardDescription>{plan.description}</CardDescription>
                      </CardHeader>
                      <CardContent className="space-y-2">
                        <div className="flex items-baseline gap-1">
                          <span className="text-2xl font-semibold">
                            {price
                              ? formatMoney(price.price_cents, price.currency)
                              : "—"}
                          </span>
                          {price && (
                            <span className="text-sm text-muted-foreground">
                              /{price.period}
                              {isAud ? " incl. GST" : ""}
                            </span>
                          )}
                        </div>
                        {price?.discount_label && (
                          <Badge variant="outline">{price.discount_label}</Badge>
                        )}
                        {plan.trial_days > 0 && (
                          <p className="text-sm text-muted-foreground">
                            {plan.trial_days}-day free trial
                          </p>
                        )}
                        {plan.meters.length > 0 && (
                          <>
                            <Separator />
                            <ul className="space-y-1 text-sm text-muted-foreground">
                              {plan.meters.slice(0, 5).map((m) => (
                                <li
                                  key={m.meter_key}
                                  className="flex items-center gap-2"
                                >
                                  <Check className="size-3 text-primary" />
                                  {m.included_units != null
                                    ? `${m.included_units.toLocaleString()} `
                                    : ""}
                                  {m.meter_key.replace(/_/g, " ")}
                                </li>
                              ))}
                            </ul>
                          </>
                        )}
                      </CardContent>
                      <CardFooter>
                        <Button
                          className="w-full"
                          variant={isCurrent ? "outline" : "default"}
                          disabled={isCurrent || busy != null}
                          onClick={() => handleSubscribe(plan)}
                        >
                          {busy === plan.slug ? (
                            <Loader2 className="size-4 animate-spin" />
                          ) : null}
                          {isCurrent
                            ? "Current plan"
                            : hasActiveSub
                              ? `Switch to ${plan.name}`
                              : `Subscribe to ${plan.name}`}
                        </Button>
                      </CardFooter>
                    </Card>
                  )
                })}
              </div>
            </div>
          )}

          {/* Invoices */}
          <Card>
            <CardHeader>
              <CardTitle>Invoices</CardTitle>
              <CardDescription>
                Recent billing history for this tenant.
              </CardDescription>
            </CardHeader>
            <CardContent>
              {invoices.length === 0 ? (
                <p className="text-sm text-muted-foreground">No invoices yet.</p>
              ) : (
                <Table>
                  <TableHeader>
                    <TableRow>
                      <TableHead>Date</TableHead>
                      <TableHead>Status</TableHead>
                      <TableHead className="text-right">Amount</TableHead>
                      <TableHead className="text-right">Invoice</TableHead>
                    </TableRow>
                  </TableHeader>
                  <TableBody>
                    {invoices.map((inv, i) => (
                      <TableRow key={inv.id ?? i}>
                        <TableCell>
                          {formatDate(inv.paid_at ?? inv.due_date)}
                        </TableCell>
                        <TableCell>
                          <Badge variant={statusVariant(inv.status ?? "")}>
                            {inv.status ?? "—"}
                          </Badge>
                        </TableCell>
                        <TableCell className="text-right">
                          {formatMoney(inv.amount, inv.currency)}
                        </TableCell>
                        <TableCell className="text-right">
                          {inv.invoice_url || inv.pdf_url ? (
                            <a
                              href={(inv.invoice_url ?? inv.pdf_url) as string}
                              target="_blank"
                              rel="noreferrer"
                              className="inline-flex items-center gap-1 text-primary hover:underline"
                            >
                              View <ExternalLink className="size-3" />
                            </a>
                          ) : (
                            "—"
                          )}
                        </TableCell>
                      </TableRow>
                    ))}
                  </TableBody>
                </Table>
              )}
            </CardContent>
          </Card>
        </>
      )}
    </AppShell>
  )
}
