import {
  type ColumnDef,
  flexRender,
  getCoreRowModel,
  useReactTable,
} from "@tanstack/react-table";
import {
  ChevronsLeftIcon,
  ChevronsRightIcon,
  CircleDollarSign,
  Pencil,
  SkipBackIcon,
  SkipForwardIcon,
} from "lucide-react";
import { useMemo } from "react";
import { Button } from "@/components/ui/button";
import {
  Pagination,
  PaginationContent,
  PaginationItem,
  PaginationLink,
  PaginationNext,
  PaginationPrevious,
} from "@/components/ui/pagination";
import type { Expense } from "@/lib/api";

interface ExpensesTableProps {
  data: Expense[];
  onPay: (expense: Expense) => void;
  onEdit: (expense: Expense) => void;
  page: number;
  total: number;
  pageSize: number;
  onPageChange: (page: number) => void;
}

function formatExpenseDate(value: string) {
  return new Date(value).toLocaleDateString("es-AR", {
    timeZone: "UTC",
    day: "2-digit",
    month: "2-digit",
    year: "numeric",
  });
}

function formatExpenseAmount(expense: Expense) {
  const isPayed = expense.status === "PAYED";
  const value =
    isPayed && expense.amountPayed
      ? Number(expense.amountPayed)
      : Number(expense.amount);

  return `$${value.toLocaleString("es-AR", { minimumFractionDigits: 2 })}`;
}

function ExpenseStatusBadge({ status }: { status: Expense["status"] }) {
  const isPayed = status === "PAYED";

  return (
    <span
      className={
        isPayed
          ? "inline-flex h-5 shrink-0 items-center rounded-md bg-green-100 px-1.5 text-xs font-medium text-green-700 dark:bg-green-900/30 dark:text-green-400"
          : "inline-flex h-5 shrink-0 items-center rounded-md bg-yellow-100 px-1.5 text-xs font-medium text-yellow-700 dark:bg-yellow-900/30 dark:text-yellow-400"
      }
    >
      {isPayed ? "Pagado" : "Pendiente"}
    </span>
  );
}

export function ExpensesTable({
  data,
  onPay,
  onEdit,
  page,
  total,
  pageSize,
  onPageChange,
}: ExpensesTableProps) {
  const columns = useMemo<ColumnDef<Expense>[]>(
    () => [
      {
        header: "Descripción",
        accessorKey: "description",
        cell: ({ row }) => (
          <span className="font-medium">{row.getValue("description")}</span>
        ),
      },
      {
        header: "Monto",
        accessorKey: "amount",
        cell: ({ row }) => {
          const expense = row.original;
          return (
            <span className="tabular-nums">{formatExpenseAmount(expense)}</span>
          );
        },
      },
      {
        header: "USDC",
        accessorKey: "usdcEquivalent",
        cell: ({ row }) => {
          const value = row.getValue("usdcEquivalent");
          if (!value) {
            return <span className="text-muted-foreground">--</span>;
          }
          return (
            <span className="tabular-nums">
              {Number(value).toLocaleString("es-AR", {
                minimumFractionDigits: 2,
                maximumFractionDigits: 2,
              })}{" "}
              USDC
            </span>
          );
        },
      },
      {
        header: "Vencimiento",
        accessorKey: "dueDate",
        cell: ({ row }) => {
          return (
            <span className="text-muted-foreground">
              {formatExpenseDate(row.getValue("dueDate") as string)}
            </span>
          );
        },
      },
      {
        header: "Estado",
        accessorKey: "status",
        cell: ({ row }) => {
          return (
            <ExpenseStatusBadge
              status={row.getValue("status") as Expense["status"]}
            />
          );
        },
      },
      {
        header: "Fecha de pago",
        accessorKey: "paymentDate",
        cell: ({ row }) => {
          const paymentDate = row.getValue("paymentDate");
          if (!paymentDate) {
            return <span className="text-muted-foreground">--</span>;
          }
          return (
            <span className="text-muted-foreground">
              {formatExpenseDate(paymentDate as string)}
            </span>
          );
        },
      },
      {
        id: "actions",
        cell: ({ row }) => {
          const expense = row.original;
          return (
            <div className="flex justify-end gap-1">
              <Button variant="ghost" size="xs" onClick={() => onEdit(expense)}>
                <Pencil className="size-3.5" />
                Editar
              </Button>
              {expense.status !== "PAYED" && (
                <Button
                  variant="outline"
                  size="xs"
                  onClick={() => onPay(expense)}
                >
                  <CircleDollarSign className="size-3.5" />
                  Pagar
                </Button>
              )}
            </div>
          );
        },
      },
    ],
    [onPay, onEdit],
  );

  const table = useReactTable({
    data,
    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={() => onPageChange(page - 1)}
          >
            Anterior
          </Button>
          <Button
            variant="outline"
            size="sm"
            disabled={page >= totalPages}
            onClick={() => onPageChange(page + 1)}
          >
            Siguiente
          </Button>
        </div>
      </div>
    ) : null;

  return (
    <div className="space-y-4">
      {mobilePagination}

      <div className="space-y-2 sm:hidden">
        {data.map((expense) => (
          <div
            key={expense.id}
            className="rounded-lg border bg-card p-3 text-sm"
          >
            <div className="flex items-start justify-between gap-3">
              <div className="min-w-0">
                <p className="truncate font-medium">{expense.description}</p>
                <p className="mt-1 text-xs text-muted-foreground">
                  Vence {formatExpenseDate(expense.dueDate)}
                </p>
              </div>
              <ExpenseStatusBadge status={expense.status} />
            </div>

            <div className="mt-3 flex items-end justify-between gap-3">
              <div className="min-w-0">
                <p className="text-lg font-semibold tabular-nums">
                  {formatExpenseAmount(expense)}
                </p>
                <p className="text-xs text-muted-foreground">
                  {expense.paymentDate
                    ? `Pagado ${formatExpenseDate(expense.paymentDate)}`
                    : "Sin fecha de pago"}
                </p>
                {expense.usdcEquivalent && (
                  <p className="text-xs text-muted-foreground tabular-nums">
                    {Number(expense.usdcEquivalent).toLocaleString("es-AR", {
                      minimumFractionDigits: 2,
                      maximumFractionDigits: 2,
                    })}{" "}
                    USDC
                  </p>
                )}
              </div>

              <div className="flex gap-1">
                <Button
                  variant="ghost"
                  size="sm"
                  className="shrink-0"
                  onClick={() => onEdit(expense)}
                >
                  <Pencil className="size-3.5" />
                </Button>
                {expense.status !== "PAYED" && (
                  <Button
                    variant="outline"
                    size="sm"
                    className="shrink-0"
                    onClick={() => onPay(expense)}
                  >
                    <CircleDollarSign className="size-3.5" />
                    Pagar
                  </Button>
                )}
              </div>
            </div>
          </div>
        ))}
        {data.length === 0 && (
          <div className="rounded-lg border px-3 py-8 text-center text-sm text-muted-foreground">
            No hay gastos 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 gastos para mostrar.
                </td>
              </tr>
            )}
          </tbody>
        </table>
      </div>

      {mobilePagination}

      {totalPages > 1 && (
        <Pagination className="hidden sm:flex">
          <PaginationContent>
            <PaginationItem>
              <PaginationLink
                onClick={(e) => {
                  e.preventDefault();
                  onPageChange(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) onPageChange(page - 1);
                }}
                href="#"
                className={page <= 1 ? "pointer-events-none opacity-50" : ""}
              />
            </PaginationItem>
            {currentGroup > 0 && (
              <PaginationItem>
                <PaginationLink
                  onClick={(e) => {
                    e.preventDefault();
                    onPageChange(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();
                    onPageChange(p);
                  }}
                  href="#"
                >
                  {p}
                </PaginationLink>
              </PaginationItem>
            ))}
            {(currentGroup + 1) * GROUP_SIZE < totalPages && (
              <PaginationItem>
                <PaginationLink
                  onClick={(e) => {
                    e.preventDefault();
                    onPageChange(endPage + 1);
                  }}
                  href="#"
                  aria-label="Ir al siguiente grupo"
                >
                  <ChevronsRightIcon className="size-4" />
                </PaginationLink>
              </PaginationItem>
            )}
            <PaginationItem>
              <PaginationNext
                onClick={(e) => {
                  e.preventDefault();
                  if (page < totalPages) onPageChange(page + 1);
                }}
                href="#"
                className={
                  page >= totalPages ? "pointer-events-none opacity-50" : ""
                }
              />
            </PaginationItem>
            <PaginationItem>
              <PaginationLink
                onClick={(e) => {
                  e.preventDefault();
                  onPageChange(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>
  );
}
