import { useState } from "react";
import { createFileRoute, useNavigate } from "@tanstack/react-router";
import { Plus } from "lucide-react";
import { toast } from "sonner";

import { ListPage } from "@/components/app/ListPage";
import { ProgressBar, formatDate, formatINR } from "@/components/app/Primitives";
import { RecordPaymentDrawer } from "@/components/app/RecordPaymentDrawer";
import { StatusPill } from "@/components/app/StatusPill";
import type { TableColumn } from "@/components/table/DataTable";
import type { GridColumn } from "@/components/grid/types";
import { validators } from "@/components/grid/types";
import { Button } from "@/components/ui/button";
import { payments } from "@/data/mock";
import type { Payment } from "@/data/types";
import { billedTotal, collectedTotal, daysUntil, outstandingTotal, overduePayments } from "@/lib/ops";

export const Route = createFileRoute("/payments")({
  head: () => ({
    meta: [
      { title: "Payments | KareVoyage Operations" },
      { name: "description", content: "Collections, outstanding balances, discounts and reward redemptions per booking." },
      { property: "og:title", content: "Payments | KareVoyage Operations" },
      { property: "og:description", content: "Track money in and money owed across every journey." },
    ],
  }),
  component: PaymentsPage,
});

const gridColumns: GridColumn<Payment>[] = [
  { key: "id", header: "Payment ID", width: 130, editable: false, frozen: true },
  { key: "guest", header: "Guest", width: 170, validate: validators.required("Guest") },
  { key: "tripId", header: "Trip", width: 140 },
  { key: "bookingId", header: "Booking", width: 130 },
  { key: "totalCost", header: "Total", width: 120, type: "money", align: "right" },
  { key: "discount", header: "Discount", width: 110, type: "money", align: "right" },
  { key: "rewardsUsed", header: "Rewards", width: 110, type: "money", align: "right" },
  { key: "netPayable", header: "Net payable", width: 130, type: "money", align: "right" },
  { key: "paid", header: "Paid", width: 120, type: "money", align: "right" },
  { key: "due", header: "Due", width: 120, type: "money", align: "right" },
  { key: "dueDate", header: "Due date", width: 120, type: "date", validate: validators.date },
  { key: "mode", header: "Mode", width: 130 },
  { key: "reference", header: "Reference", width: 140 },
  { key: "status", header: "Status", width: 120, type: "status" },
];

const isOverdue = (p: Payment) => p.due > 0 && daysUntil(p.dueDate) < 0;

function PaymentsPage() {
  const navigate = useNavigate();
  const [drawerOpen, setDrawerOpen] = useState(false);
  const [preset, setPreset] = useState<Payment | undefined>(undefined);

  const openFor = (p?: Payment) => {
    setPreset(p);
    setDrawerOpen(true);
  };

  const columns: TableColumn<Payment>[] = [
    {
      key: "guest",
      header: "Guest",
      sortValue: (p) => p.guest,
      cell: (p) => (
        <div className="min-w-0">
          <p className="truncate font-medium">{p.guest}</p>
          <p className="truncate text-xs text-muted-foreground">{p.bookingId}</p>
        </div>
      ),
    },
    {
      key: "trip",
      header: "Trip",
      responsive: "hidden lg:table-cell",
      sortValue: (p) => p.tour,
      cell: (p) => (
        <div className="min-w-0">
          <p className="truncate text-sm">{p.tour}</p>
          <p className="truncate text-xs text-muted-foreground">{p.tripId}</p>
        </div>
      ),
    },
    {
      key: "collected",
      header: "Paid / total",
      sortValue: (p) => p.paid / Math.max(1, p.netPayable),
      cell: (p) => (
        <div className="w-36">
          <p className="mb-1 text-xs tabular-nums">
            {formatINR(p.paid)} <span className="text-muted-foreground">/ {formatINR(p.netPayable)}</span>
          </p>
          <ProgressBar value={(p.paid / Math.max(1, p.netPayable)) * 100} tone={p.due === 0 ? "success" : "brand"} />
        </div>
      ),
    },
    {
      key: "due",
      header: "Due",
      align: "right",
      sortValue: (p) => p.due,
      cell: (p) => (
        <div className="text-right">
          <p className={p.due > 0 ? "text-destructive" : "text-muted-foreground"}>{formatINR(p.due)}</p>
          <p className="text-xs text-muted-foreground">{p.due > 0 ? formatDate(p.dueDate) : "settled"}</p>
        </div>
      ),
    },
    {
      key: "last",
      header: "Payment date",
      responsive: "hidden xl:table-cell",
      sortValue: (p) => p.lastPaymentDate,
      cell: (p) => (p.lastPaymentDate ? formatDate(p.lastPaymentDate) : "—"),
    },
    {
      key: "mode",
      header: "Mode",
      responsive: "hidden xl:table-cell",
      sortValue: (p) => p.mode,
      cell: (p) => (
        <div>
          <p className="text-sm">{p.mode || "—"}</p>
          <p className="text-xs text-muted-foreground">{p.reference || ""}</p>
        </div>
      ),
    },
    {
      key: "receipt",
      header: "Receipt",
      responsive: "hidden xl:table-cell",
      sortValue: (p) => p.receipt,
      cell: (p) => (
        <span className={p.receipt === "Uploaded" ? "text-xs text-success" : "text-xs text-muted-foreground"}>{p.receipt}</span>
      ),
    },
    {
      key: "status",
      header: "Status",
      sortValue: (p) => p.status,
      cell: (p) => <StatusPill value={isOverdue(p) ? "Overdue" : p.status} />,
    },
  ];

  return (
    <>
      <ListPage
        title="Payments"
        description="Money collected, money owed and where to chase next."
        countLabel={(n) => `${n} booking ledgers`}
        searchPlaceholder="Search guest, booking, trip…"
        actions={
          <Button className="gap-1.5" onClick={() => openFor(undefined)}>
            <Plus className="h-4 w-4" /> Record payment
          </Button>
        }
        above={
          <div className="grid gap-4 sm:grid-cols-2 lg:grid-cols-4">
            {[
              { label: "Billed", value: formatINR(billedTotal), tone: "" },
              { label: "Collected", value: formatINR(collectedTotal), tone: "text-success" },
              { label: "Outstanding", value: formatINR(outstandingTotal), tone: "text-warning-foreground" },
              { label: "Overdue records", value: String(overduePayments.length), tone: "text-destructive" },
            ].map((s) => (
              <div key={s.label} className="rounded-xl border border-border bg-surface px-5 py-4">
                <p className="kv-eyebrow">{s.label}</p>
                <p className={`mt-2 font-display text-[26px] leading-none ${s.tone}`}>{s.value}</p>
              </div>
            ))}
          </div>
        }
        rows={payments}
        columns={columns}
        getId={(p) => p.id}
        searchText={(p) => `${p.id} ${p.guest} ${p.tripId} ${p.tour} ${p.bookingId} ${p.reference}`}
        quickFilters={[
          { key: "all", label: "All", test: () => true },
          { key: "overdue", label: "Overdue", test: isOverdue },
          { key: "pending", label: "Pending", test: (p) => p.status === "Pending" },
          { key: "partial", label: "Partial", test: (p) => p.status === "Partial" },
          { key: "paid", label: "Paid", test: (p) => p.status === "Paid" },
        ]}
        filters={[
          { key: "status", label: "Status", get: (p) => p.status },
          { key: "mode", label: "Mode", get: (p) => p.mode },
          { key: "destination", label: "Destination", get: (p) => p.destination },
        ]}
        rowActions={[
          { label: "Record payment", onSelect: (p) => openFor(p) },
          { label: "Send reminder", onSelect: (p) => toast.success(`Reminder sent to ${p.guest}.`) },
          { label: "Open trip", onSelect: (p) => navigate({ to: "/trips/$id", params: { id: p.tripId } }) },
        ]}
        bulkBar={(ids, clear) => (
          <>
            <Button size="sm" variant="outline" onClick={() => toast.success(`${ids.length} reminders sent.`)}>
              Send reminders
            </Button>
            <Button size="sm" variant="ghost" onClick={clear}>
              Clear
            </Button>
          </>
        )}
        gridColumns={gridColumns}
        gridModule="Payments"
        emptyTitle="No payments"
        emptyMessage="Payment records appear here once bookings are invoiced."
      />
      <RecordPaymentDrawer open={drawerOpen} onOpenChange={setDrawerOpen} presetPayment={preset} />
    </>
  );
}
