import { useNavigate } from "@tanstack/react-router";
import { CalendarClock, ExternalLink } from "lucide-react";
import { useMemo } from "react";
import type { PendingUpcomingExpense } from "@/lib/api";
import { usePendingUpcomingExpenses } from "@/lib/queries";

type GroupedExpense = {
  periodicExpenseId: number;
  description: string;
  totalAmount: number;
  earliestDueDate: string;
  dueType: "overdue" | "upcoming";
  count: number;
};

function groupExpenses(expenses: PendingUpcomingExpense[]): GroupedExpense[] {
  const map = new Map<number, GroupedExpense>();

  for (const e of expenses) {
    if (e.periodicExpenseId === null) continue;

    const key = e.periodicExpenseId;
    const existing = map.get(key);

    if (existing) {
      existing.totalAmount += Number(e.amount);
      existing.count += 1;
      if (e.dueDate < existing.earliestDueDate) {
        existing.earliestDueDate = e.dueDate;
      }
      if (e.dueType === "overdue") {
        existing.dueType = "overdue";
      }
    } else {
      map.set(key, {
        periodicExpenseId: key,
        description: e.periodicExpense?.description ?? e.description,
        totalAmount: Number(e.amount),
        earliestDueDate: e.dueDate,
        dueType: e.dueType,
        count: 1,
      });
    }
  }

  return Array.from(map.values()).sort((a, b) => {
    if (a.dueType !== b.dueType) return a.dueType === "overdue" ? -1 : 1;
    return a.earliestDueDate.localeCompare(b.earliestDueDate);
  });
}

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

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

function DueTypeBadge({ dueType }: { dueType: "overdue" | "upcoming" }) {
  return (
    <span
      className={
        dueType === "overdue"
          ? "inline-flex h-5 shrink-0 items-center rounded-md bg-red-100 px-1.5 text-xs font-medium text-red-700 dark:bg-red-900/30 dark:text-red-400"
          : "inline-flex h-5 shrink-0 items-center rounded-md bg-amber-100 px-1.5 text-xs font-medium text-amber-700 dark:bg-amber-900/30 dark:text-amber-400"
      }
    >
      {dueType === "overdue" ? "Vencido" : "Próximo"}
    </span>
  );
}

export function DashboardExpensesTable() {
  const { data: expenses, isLoading } = usePendingUpcomingExpenses();
  const navigate = useNavigate();

  const groups = useMemo(() => {
    if (!expenses) return [];
    return groupExpenses(expenses);
  }, [expenses]);

  function goToExpenses(periodicExpenseId: number) {
    navigate({ to: "/expenses", search: { periodicExpenseId } });
  }

  const overdueCount = groups.filter((g) => g.dueType === "overdue").length;
  const upcomingCount = groups.filter((g) => g.dueType === "upcoming").length;
  const grandTotal = groups.reduce((sum, g) => sum + g.totalAmount, 0);
  const hasData = groups.length > 0;

  return (
    <div className="rounded-lg border">
      <div className="flex items-center gap-2 border-b px-4 py-3">
        <CalendarClock className="size-4 text-muted-foreground" />
        <h2 className="text-sm font-medium">Gastos por vencer</h2>
        {isLoading && (
          <span className="ml-auto text-xs text-muted-foreground">
            Cargando...
          </span>
        )}
        {!isLoading && hasData && (
          <span className="ml-auto text-xs text-muted-foreground tabular-nums">
            {overdueCount} vencido{overdueCount !== 1 ? "s" : ""}
            {upcomingCount > 0 &&
              ` · ${upcomingCount} próximo${upcomingCount !== 1 ? "s" : ""}`}
          </span>
        )}
      </div>

      {!isLoading && !hasData && (
        <div className="px-4 py-8 text-center text-sm text-muted-foreground">
          No hay gastos pendientes.
        </div>
      )}

      {isLoading && (
        <div className="px-4 py-8 text-center text-sm text-muted-foreground">
          Cargando...
        </div>
      )}

      <div className="space-y-1 p-1 sm:hidden">
        {groups.map((group) => (
          <div
            key={group.periodicExpenseId}
            className="rounded-lg border p-3 text-sm"
          >
            <div className="flex items-start justify-between gap-3">
              <div className="min-w-0">
                <button
                  type="button"
                  onClick={() => goToExpenses(group.periodicExpenseId)}
                  className="truncate font-medium text-left hover:underline cursor-pointer inline-flex items-center gap-1"
                >
                  {group.description}
                  <ExternalLink className="size-3 shrink-0 text-muted-foreground" />
                </button>
                <p className="mt-1 text-xs text-muted-foreground">
                  Vence {formatDate(group.earliestDueDate)}
                  {group.count > 1 && ` (${group.count} gastos)`}
                </p>
              </div>
              <DueTypeBadge dueType={group.dueType} />
            </div>

            <p className="mt-3 text-lg font-semibold tabular-nums">
              {formatAmount(group.totalAmount)}
            </p>
          </div>
        ))}
        {hasData && (
          <div className="flex items-center justify-between rounded-lg border bg-muted/50 px-3 py-2.5 text-sm font-medium">
            <span>Total</span>
            <span className="tabular-nums">{formatAmount(grandTotal)}</span>
          </div>
        )}
      </div>

      <div className="hidden overflow-x-auto sm:block">
        <table className="w-full text-sm">
          <thead>
            <tr className="border-b bg-muted/50">
              <th className="px-3 py-2 text-left text-xs font-medium text-muted-foreground">
                Descripción
              </th>
              <th className="px-3 py-2 text-left text-xs font-medium text-muted-foreground">
                Monto
              </th>
              <th className="px-3 py-2 text-left text-xs font-medium text-muted-foreground">
                Vencimiento
              </th>
              <th className="px-3 py-2 text-left text-xs font-medium text-muted-foreground">
                Cantidad
              </th>
              <th className="px-3 py-2 text-left text-xs font-medium text-muted-foreground">
                Estado
              </th>
            </tr>
          </thead>
          <tbody>
            {groups.map((group) => (
              <tr
                key={group.periodicExpenseId}
                className="border-b last:border-0 hover:bg-muted/30"
              >
                <td className="px-3 py-2.5">
                  <button
                    type="button"
                    onClick={() => goToExpenses(group.periodicExpenseId)}
                    className="font-medium text-left hover:underline cursor-pointer inline-flex items-center gap-1"
                  >
                    {group.description}
                    <ExternalLink className="size-3 shrink-0 text-muted-foreground" />
                  </button>
                </td>
                <td className="px-3 py-2.5 tabular-nums">
                  {formatAmount(group.totalAmount)}
                </td>
                <td className="px-3 py-2.5 text-muted-foreground">
                  {formatDate(group.earliestDueDate)}
                </td>
                <td className="px-3 py-2.5 text-muted-foreground tabular-nums">
                  {group.count > 1 ? `${group.count} gastos` : "1 gasto"}
                </td>
                <td className="px-3 py-2.5">
                  <DueTypeBadge dueType={group.dueType} />
                </td>
              </tr>
            ))}
            {hasData && (
              <tr className="border-t bg-muted/50 font-medium">
                <td className="px-3 py-2.5">Total</td>
                <td className="px-3 py-2.5 tabular-nums">
                  {formatAmount(grandTotal)}
                </td>
                <td colSpan={3} />
              </tr>
            )}
          </tbody>
        </table>
      </div>
    </div>
  );
}
