"use client";

import {
  type ColumnDef,
  flexRender,
  getCoreRowModel,
  useReactTable,
} from "@tanstack/react-table";
import { subMonths, startOfMonth } from "date-fns";
import {
  ChevronsLeftIcon,
  ChevronsRightIcon,
  SkipBackIcon,
  SkipForwardIcon,
} from "lucide-react";
import { useMemo, useState } from "react";
import { useSearch } from "@tanstack/react-router";
import { Button } from "@/components/ui/button";
import { DatePicker } from "@/components/ui/date-picker";
import {
  Pagination,
  PaginationContent,
  PaginationItem,
  PaginationLink,
  PaginationNext,
  PaginationPrevious,
} from "@/components/ui/pagination";
import {
  Select,
  SelectContent,
  SelectItem,
  SelectTrigger,
  SelectValue,
} from "@/components/ui/select";
import type { Wallet, WalletMovement, WalletMovementsFilter } from "@/lib/api";
import { useWalletMovementsFiltered, useWallets } from "@/lib/queries";

const amountFormatter = new Intl.NumberFormat("es-AR", {
  minimumFractionDigits: 2,
  maximumFractionDigits: 4,
});

const dateFormatter = new Intl.DateTimeFormat("es-AR", {
  day: "2-digit",
  month: "2-digit",
  year: "numeric",
  hour: "2-digit",
  minute: "2-digit",
});

const typeLabels: Record<string, string> = {
  DEPOSIT: "Depósito",
  WITHDRAWAL: "Extracción",
  TRANSFER_IN: "Transferencia recibida",
  TRANSFER_OUT: "Transferencia enviada",
  ADJUSTMENT: "Ajuste",
};

function TypeBadge({ type }: { type: string }) {
  const styles: Record<string, string> = {
    DEPOSIT:
      "bg-emerald-100 text-emerald-700 dark:bg-emerald-900/30 dark:text-emerald-400",
    WITHDRAWAL:
      "bg-red-100 text-red-700 dark:bg-red-900/30 dark:text-red-400",
    TRANSFER_IN:
      "bg-blue-100 text-blue-700 dark:bg-blue-900/30 dark:text-blue-400",
    TRANSFER_OUT:
      "bg-orange-100 text-orange-700 dark:bg-orange-900/30 dark:text-orange-400",
    ADJUSTMENT:
      "bg-purple-100 text-purple-700 dark:bg-purple-900/30 dark:text-purple-400",
  };

  return (
    <span
      className={
        `inline-flex h-5 shrink-0 items-center rounded-md px-1.5 text-xs font-medium ` +
        (styles[type] ?? "")
      }
    >
      {typeLabels[type] ?? type}
    </span>
  );
}

export function WalletMovementsPage() {
  const { walletId: initialWalletId } = useSearch({
    from: "/_authenticated/wallets/movements",
  });
  const { data: wallets } = useWallets();

  const [walletId, setWalletId] = useState<number | undefined>(initialWalletId);

  const today = new Date();
  const [startDate, setStartDate] = useState<Date | undefined>(
    startOfMonth(subMonths(today, 1)),
  );
  const [endDate, setEndDate] = useState<Date | undefined>(today);

  const [page, setPage] = useState(1);
  const pageSize = 20;

  const filter: WalletMovementsFilter = useMemo(
    () => ({
      walletId,
      startDate: startDate?.toISOString(),
      endDate: endDate?.toISOString(),
      page,
      pageSize,
    }),
    [walletId, startDate, endDate, page, pageSize],
  );

  const { data: result, isLoading } = useWalletMovementsFiltered(filter);

  const movements = result?.data ?? [];
  const total = result?.total ?? 0;

  const columns = useMemo<ColumnDef<WalletMovement>[]>(
    () => [
      {
        header: "Tipo",
        accessorKey: "type",
        cell: ({ row }) => <TypeBadge type={row.getValue("type") as string} />,
      },
      {
        header: "Descripción",
        accessorKey: "description",
        cell: ({ row }) => {
          const desc = row.getValue("description") as string | null;
          return (
            <span className="text-muted-foreground">
              {desc ?? (
                <span className="italic text-muted-foreground/50">
                  Sin descripción
                </span>
              )}
            </span>
          );
        },
      },
      {
        header: "Billetera",
        id: "walletName",
        cell: ({ row }) => {
          const w = wallets?.find(
            (w) => w.id === row.original.walletId,
          );
          return w ? (
            <span className="text-xs text-muted-foreground">{w.name}</span>
          ) : null;
        },
      },
      {
        header: "Monto",
        accessorKey: "amount",
        cell: ({ row }) => {
          const amount = row.getValue("amount") as number;
          return (
            <span
              className={`tabular-nums font-medium ${
                amount >= 0
                  ? "text-emerald-600 dark:text-emerald-400"
                  : "text-red-600 dark:text-red-400"
              }`}
            >
              {amount >= 0 ? "+" : ""}
              {amountFormatter.format(amount)}
            </span>
          );
        },
      },
      {
        header: "Fecha",
        accessorKey: "createdAt",
        cell: ({ row }) => {
          return (
            <span className="text-xs text-muted-foreground tabular-nums">
              {dateFormatter.format(
                new Date(row.getValue("createdAt") as string),
              )}
            </span>
          );
        },
      },
    ],
    [wallets],
  );

  const table = useReactTable({
    data: movements,
    columns,
    getCoreRowModel: getCoreRowModel(),
  });

  const totalPages = Math.max(1, Math.ceil(total / pageSize));
  const GROUP_SIZE = 3;
  const currentGroup = Math.floor((page - 1) / GROUP_SIZE);
  const startPage = currentGroup * GROUP_SIZE + 1;
  const endPage = Math.min(startPage + GROUP_SIZE - 1, totalPages);
  const firstItem = total === 0 ? 0 : (page - 1) * pageSize + 1;
  const lastItem = Math.min(page * pageSize, total);

  const mobilePagination =
    total > 0 ? (
      <div className="rounded-lg border bg-card p-2 sm:hidden">
        <div className="mb-2 text-center text-xs text-muted-foreground tabular-nums">
          {firstItem}-{lastItem} de {total} · Página {page} de {totalPages}
        </div>
        <div className="grid grid-cols-2 gap-2">
          <Button
            variant="outline"
            size="sm"
            disabled={page <= 1}
            onClick={() => setPage(page - 1)}
          >
            Anterior
          </Button>
          <Button
            variant="outline"
            size="sm"
            disabled={page >= totalPages}
            onClick={() => setPage(page + 1)}
          >
            Siguiente
          </Button>
        </div>
      </div>
    ) : null;

  return (
    <div className="space-y-4">
      <h1 className="text-2xl font-semibold">Movimientos</h1>

      <div className="flex flex-wrap items-end gap-3">
        <div className="flex flex-col gap-1.5">
          <label className="text-xs font-medium text-muted-foreground">
            Billetera
          </label>
          <Select
            value={walletId !== undefined ? String(walletId) : "all"}
            onValueChange={(v) => {
              setWalletId(v === "all" ? undefined : Number(v));
              setPage(1);
            }}
          >
            <SelectTrigger className="h-8 w-44">
              <SelectValue placeholder="Todas las billeteras" />
            </SelectTrigger>
            <SelectContent>
              <SelectItem value="all">
                Todas las billeteras
              </SelectItem>
              {wallets?.map((w: Wallet) => (
                <SelectItem key={w.id} value={String(w.id)}>
                  {w.name} ({w.currency})
                </SelectItem>
              ))}
            </SelectContent>
          </Select>
        </div>

        <div className="flex flex-col gap-1.5">
          <label className="text-xs font-medium text-muted-foreground">
            Desde
          </label>
          <DatePicker
            value={startDate}
            onChange={(d) => {
              setStartDate(d);
              setPage(1);
            }}
            placeholder="Fecha inicial"
          />
        </div>

        <div className="flex flex-col gap-1.5">
          <label className="text-xs font-medium text-muted-foreground">
            Hasta
          </label>
          <DatePicker
            value={endDate}
            onChange={(d) => {
              setEndDate(d);
              setPage(1);
            }}
            placeholder="Fecha final"
          />
        </div>

        {(walletId || startDate || endDate) && (
          <Button
            variant="ghost"
            size="sm"
            onClick={() => {
              setWalletId(undefined);
              setStartDate(undefined);
              setEndDate(undefined);
              setPage(1);
            }}
          >
            Limpiar filtros
          </Button>
        )}
      </div>

      {isLoading ? (
        <p className="text-sm text-muted-foreground">Cargando...</p>
      ) : (
        <>
          {mobilePagination}

          <div className="space-y-2 sm:hidden">
            {movements.map((m) => {
              const wallet = wallets?.find((w) => w.id === m.walletId);
              return (
                <div
                  key={m.id}
                  className="rounded-lg border bg-card p-3 text-sm"
                >
                  <div className="flex items-start justify-between gap-3">
                    <TypeBadge type={m.type} />
                    <span
                      className={`tabular-nums font-medium ${
                        m.amount >= 0
                          ? "text-emerald-600 dark:text-emerald-400"
                          : "text-red-600 dark:text-red-400"
                      }`}
                    >
                      {m.amount >= 0 ? "+" : ""}
                      {amountFormatter.format(m.amount)}
                    </span>
                  </div>

                  <div className="mt-2 space-y-1">
                    {m.description && (
                      <p className="text-muted-foreground">{m.description}</p>
                    )}
                    <div className="flex items-center gap-2 text-xs text-muted-foreground">
                      {wallet && <span>{wallet.name}</span>}
                      <span>&middot;</span>
                      <span>{dateFormatter.format(new Date(m.createdAt))}</span>
                    </div>
                  </div>
                </div>
              );
            })}
            {movements.length === 0 && (
              <div className="rounded-lg border px-3 py-8 text-center text-sm text-muted-foreground">
                No hay movimientos para mostrar.
              </div>
            )}
          </div>

          <div className="hidden overflow-x-auto rounded-lg border sm:block">
            <table className="w-full text-sm">
              <thead>
                {table.getHeaderGroups().map((headerGroup) => (
                  <tr key={headerGroup.id} className="border-b bg-muted/50">
                    {headerGroup.headers.map((header) => (
                      <th
                        key={header.id}
                        className="px-3 py-2 text-left text-xs font-medium text-muted-foreground"
                      >
                        {flexRender(
                          header.column.columnDef.header,
                          header.getContext(),
                        )}
                      </th>
                    ))}
                  </tr>
                ))}
              </thead>
              <tbody>
                {table.getRowModel().rows.map((row) => (
                  <tr
                    key={row.id}
                    className="border-b last:border-0 hover:bg-muted/30"
                  >
                    {row.getVisibleCells().map((cell) => (
                      <td key={cell.id} className="px-3 py-2.5">
                        {flexRender(
                          cell.column.columnDef.cell,
                          cell.getContext(),
                        )}
                      </td>
                    ))}
                  </tr>
                ))}
                {table.getRowModel().rows.length === 0 && (
                  <tr>
                    <td
                      colSpan={columns.length}
                      className="px-3 py-8 text-center text-sm text-muted-foreground"
                    >
                      No hay movimientos para mostrar.
                    </td>
                  </tr>
                )}
              </tbody>
            </table>
          </div>

          {mobilePagination}

          {totalPages > 1 && (
            <Pagination className="hidden sm:flex">
              <PaginationContent>
                <PaginationItem>
                  <PaginationLink
                    onClick={(e) => {
                      e.preventDefault();
                      setPage(1);
                    }}
                    href="#"
                    aria-label="Ir a la primera página"
                    className={
                      page <= 1 ? "pointer-events-none opacity-50" : ""
                    }
                  >
                    <SkipBackIcon className="size-4" />
                  </PaginationLink>
                </PaginationItem>
                <PaginationItem>
                  <PaginationPrevious
                    onClick={(e) => {
                      e.preventDefault();
                      if (page > 1) setPage(page - 1);
                    }}
                    href="#"
                    className={
                      page <= 1 ? "pointer-events-none opacity-50" : ""
                    }
                    text="Anterior"
                  />
                </PaginationItem>
                {currentGroup > 0 && (
                  <PaginationItem>
                    <PaginationLink
                      onClick={(e) => {
                        e.preventDefault();
                        setPage(startPage - 1);
                      }}
                      href="#"
                      aria-label="Ir al grupo anterior"
                    >
                      <ChevronsLeftIcon className="size-4" />
                    </PaginationLink>
                  </PaginationItem>
                )}
                {Array.from(
                  { length: endPage - startPage + 1 },
                  (_, i) => startPage + i,
                ).map((p) => (
                  <PaginationItem key={p}>
                    <PaginationLink
                      isActive={p === page}
                      onClick={(e) => {
                        e.preventDefault();
                        setPage(p);
                      }}
                      href="#"
                    >
                      {p}
                    </PaginationLink>
                  </PaginationItem>
                ))}
                {(currentGroup + 1) * GROUP_SIZE < totalPages && (
                  <PaginationItem>
                    <PaginationLink
                      onClick={(e) => {
                        e.preventDefault();
                        setPage(endPage + 1);
                      }}
                      href="#"
                      aria-label="Ir al siguiente grupo"
                    >
                      <ChevronsRightIcon className="size-4" />
                    </PaginationLink>
                  </PaginationItem>
                )}
                <PaginationItem>
                  <PaginationNext
                    onClick={(e) => {
                      e.preventDefault();
                      if (page < totalPages) setPage(page + 1);
                    }}
                    href="#"
                    className={
                      page >= totalPages ? "pointer-events-none opacity-50" : ""
                    }
                    text="Siguiente"
                  />
                </PaginationItem>
                <PaginationItem>
                  <PaginationLink
                    onClick={(e) => {
                      e.preventDefault();
                      setPage(totalPages);
                    }}
                    href="#"
                    aria-label="Ir a la última página"
                    className={
                      page >= totalPages ? "pointer-events-none opacity-50" : ""
                    }
                  >
                    <SkipForwardIcon className="size-4" />
                  </PaginationLink>
                </PaginationItem>
              </PaginationContent>
            </Pagination>
          )}
        </>
      )}
    </div>
  );
}
