"use client";

import { useState, useMemo } from "react";

import {
  ColumnDef,
  ColumnFiltersState,
  SortingState,
  VisibilityState,
  flexRender,
  getCoreRowModel,
  getFilteredRowModel,
  getPaginationRowModel,
  getSortedRowModel,
  useReactTable,
} from "@tanstack/react-table";
import {
  Search,
  Filter,
  Download,
  Plus,
  RefreshCw,
  ChevronLeft,
  ChevronRight,
  ArrowUpDown,
  Settings,
} from "lucide-react";

import { Button } from "@/components/ui/button";
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card";
import {
  DropdownMenu,
  DropdownMenuCheckboxItem,
  DropdownMenuContent,
  DropdownMenuTrigger,
} from "@/components/ui/dropdown-menu";
import { Input } from "@/components/ui/input";
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select";
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@/components/ui/table";
import { cn } from "@/lib/utils";
import { BankingTransaction } from "@/types/banking";

import { StatusBadge } from "./status-badge";
import { DateCell, TypeCell, DescriptionCell, AccountCell, AmountCell, ActionsCell } from "./transaction-cells";

interface TransactionsTableProps {
  transactions: BankingTransaction[];
  loading?: boolean;
  onCreateTransaction?: () => void;
  onViewTransaction?: (transactionId: string) => void;
  onEditTransaction?: (transactionId: string) => void;
  onRefresh?: () => void;
  onExport?: () => void;
  className?: string;
}

interface TransactionFilters {
  search: string;
  transaction_type: string;
  status: string;
  account_id: string;
  date_range: string;
}

const transactionTypeOptions = [
  { value: "all", label: "Tous les types" },
  { value: "deposit", label: "Dépôt" },
  { value: "withdrawal", label: "Retrait" },
  { value: "transfer", label: "Transfert" },
  { value: "interest", label: "Intérêts" },
  { value: "fee", label: "Frais" },
  { value: "loan_payment", label: "Remboursement" },
  { value: "adjustment", label: "Ajustement" },
];

const statusOptions = [
  { value: "all", label: "Tous les statuts" },
  { value: "pending", label: "En attente" },
  { value: "completed", label: "Terminé" },
  { value: "failed", label: "Échoué" },
  { value: "cancelled", label: "Annulé" },
];

const dateRangeOptions = [
  { value: "all", label: "Toutes les dates" },
  { value: "today", label: "Aujourd'hui" },
  { value: "week", label: "Cette semaine" },
  { value: "month", label: "Ce mois" },
  { value: "quarter", label: "Ce trimestre" },
  { value: "year", label: "Cette année" },
];

export function TransactionsTable({
  transactions,
  loading = false,
  onCreateTransaction,
  onViewTransaction,
  onEditTransaction,
  onRefresh,
  onExport,
  className,
}: TransactionsTableProps) {
  const [sorting, setSorting] = useState<SortingState>([{ id: "transaction_date", desc: true }]);
  const [columnFilters, setColumnFilters] = useState<ColumnFiltersState>([]);
  const [columnVisibility, setColumnVisibility] = useState<VisibilityState>({});
  const [rowSelection, setRowSelection] = useState({});

  const [filters, setFilters] = useState<TransactionFilters>({
    search: "",
    transaction_type: "all",
    status: "all",
    account_id: "all",
    date_range: "all",
  });

  const columns: ColumnDef<BankingTransaction>[] = [
    {
      accessorKey: "transaction_date",
      header: "Date",
      cell: ({ row }) => <DateCell date={row.getValue("transaction_date")} />,
    },
    {
      accessorKey: "transaction_type",
      header: "Type",
      cell: ({ row }) => <TypeCell transactionType={row.getValue("transaction_type")} />,
      filterFn: (row, id, value) => {
        return value === "all" || row.getValue(id) === value;
      },
    },
    {
      accessorKey: "description",
      header: "Description",
      cell: ({ row }) => (
        <DescriptionCell description={row.getValue("description")} reference={row.original.reference} />
      ),
    },
    {
      accessorKey: "account_id",
      header: "Compte",
      cell: ({ row }) => <AccountCell accountId={row.getValue("account_id")} />,
    },
    {
      accessorKey: "amount",
      header: "Montant",
      cell: ({ row }) => <AmountCell amount={row.getValue("amount")} transactionType={row.original.transaction_type} />,
    },
    {
      accessorKey: "status",
      header: "Statut",
      cell: ({ row }) => <StatusBadge status={row.getValue("status")} variant="transaction" />,
      filterFn: (row, id, value) => {
        return value === "all" || row.getValue(id) === value;
      },
    },
    {
      id: "actions",
      enableHiding: false,
      cell: ({ row }) => (
        <ActionsCell
          transaction={row.original}
          onViewTransaction={onViewTransaction}
          onEditTransaction={onEditTransaction}
        />
      ),
    },
  ];

  // Filtrage des données
  const filteredTransactions = useMemo(() => {
    return transactions.filter((transaction) => {
      // Filtre par recherche
      const searchMatch =
        !filters.search ||
        transaction.description.toLowerCase().includes(filters.search.toLowerCase()) ||
        (transaction.reference?.toLowerCase().includes(filters.search.toLowerCase()) ?? false) ||
        transaction.account_id.toLowerCase().includes(filters.search.toLowerCase());

      // Filtre par type
      const typeMatch = filters.transaction_type === "all" || transaction.transaction_type === filters.transaction_type;

      // Filtre par statut
      const statusMatch = filters.status === "all" || transaction.status === filters.status;

      // Filtre par compte
      const accountMatch = filters.account_id === "all" || transaction.account_id === filters.account_id;

      // Filtre par date
      let dateMatch = true;
      if (filters.date_range !== "all") {
        const transactionDate = new Date(transaction.transaction_date);
        const now = new Date();

        switch (filters.date_range) {
          case "today": {
            const today = new Date(now.getFullYear(), now.getMonth(), now.getDate());
            dateMatch = transactionDate >= today;
            break;
          }
          case "week": {
            const weekAgo = new Date(now.getTime() - 7 * 24 * 60 * 60 * 1000);
            dateMatch = transactionDate >= weekAgo;
            break;
          }
          case "month": {
            const monthStart = new Date(now.getFullYear(), now.getMonth(), 1);
            dateMatch = transactionDate >= monthStart;
            break;
          }
          case "quarter": {
            const quarterStart = new Date(now.getFullYear(), Math.floor(now.getMonth() / 3) * 3, 1);
            dateMatch = transactionDate >= quarterStart;
            break;
          }
          case "year": {
            const yearStart = new Date(now.getFullYear(), 0, 1);
            dateMatch = transactionDate >= yearStart;
            break;
          }
        }
      }

      return searchMatch && typeMatch && statusMatch && accountMatch && dateMatch;
    });
  }, [transactions, filters]);

  const table = useReactTable({
    data: filteredTransactions,
    columns,
    onSortingChange: setSorting,
    onColumnFiltersChange: setColumnFilters,
    getCoreRowModel: getCoreRowModel(),
    getPaginationRowModel: getPaginationRowModel(),
    getSortedRowModel: getSortedRowModel(),
    getFilteredRowModel: getFilteredRowModel(),
    onColumnVisibilityChange: setColumnVisibility,
    onRowSelectionChange: setRowSelection,
    state: {
      sorting,
      columnFilters,
      columnVisibility,
      rowSelection,
    },
    initialState: {
      pagination: {
        pageSize: 10,
      },
    },
  });

  // Comptes uniques pour le filtre
  const uniqueAccounts = useMemo(() => {
    const accounts = new Set(transactions.map((t) => t.account_id));
    return Array.from(accounts).map((accountId) => ({
      value: accountId,
      label: `Compte ${accountId}`,
    }));
  }, [transactions]);

  return (
    <Card className={cn("w-full", className)}>
      <CardHeader>
        <div className="flex items-center justify-between">
          <div>
            <CardTitle>Transactions</CardTitle>
            <CardDescription>Gérez et consultez toutes les transactions bancaires</CardDescription>
          </div>
          <div className="flex items-center gap-2">
            <Button variant="outline" size="sm" onClick={onRefresh} disabled={loading}>
              <RefreshCw className={cn("h-4 w-4", loading && "animate-spin")} />
            </Button>
            <Button variant="outline" size="sm" onClick={onExport}>
              <Download className="h-4 w-4" />
            </Button>
            <DropdownMenu>
              <DropdownMenuTrigger asChild>
                <Button variant="outline" size="sm">
                  <Settings className="h-4 w-4" />
                </Button>
              </DropdownMenuTrigger>
              <DropdownMenuContent align="end">
                {table
                  .getAllColumns()
                  .filter((column) => column.getCanHide())
                  .map((column) => {
                    return (
                      <DropdownMenuCheckboxItem
                        key={column.id}
                        className="capitalize"
                        checked={column.getIsVisible()}
                        onCheckedChange={(value) => column.toggleVisibility(!!value)}
                      >
                        {column.id}
                      </DropdownMenuCheckboxItem>
                    );
                  })}
              </DropdownMenuContent>
            </DropdownMenu>
            <Button size="sm" onClick={onCreateTransaction}>
              <Plus className="h-4 w-4" />
              Nouvelle transaction
            </Button>
          </div>
        </div>

        {/* Filtres */}
        <div className="flex flex-wrap items-center gap-4">
          <div className="flex items-center space-x-2">
            <Search className="text-muted-foreground h-4 w-4" />
            <Input
              placeholder="Rechercher..."
              value={filters.search}
              onChange={(e) => setFilters({ ...filters, search: e.target.value })}
              className="w-64"
            />
          </div>

          <Select
            value={filters.transaction_type}
            onValueChange={(value) => setFilters({ ...filters, transaction_type: value })}
          >
            <SelectTrigger className="w-48">
              <SelectValue placeholder="Type de transaction" />
            </SelectTrigger>
            <SelectContent>
              {transactionTypeOptions.map((option) => (
                <SelectItem key={option.value} value={option.value}>
                  {option.label}
                </SelectItem>
              ))}
            </SelectContent>
          </Select>

          <Select value={filters.status} onValueChange={(value) => setFilters({ ...filters, status: value })}>
            <SelectTrigger className="w-40">
              <SelectValue placeholder="Statut" />
            </SelectTrigger>
            <SelectContent>
              {statusOptions.map((option) => (
                <SelectItem key={option.value} value={option.value}>
                  {option.label}
                </SelectItem>
              ))}
            </SelectContent>
          </Select>

          <Select value={filters.account_id} onValueChange={(value) => setFilters({ ...filters, account_id: value })}>
            <SelectTrigger className="w-48">
              <SelectValue placeholder="Compte" />
            </SelectTrigger>
            <SelectContent>
              <SelectItem value="all">Tous les comptes</SelectItem>
              {uniqueAccounts.map((account) => (
                <SelectItem key={account.value} value={account.value}>
                  {account.label}
                </SelectItem>
              ))}
            </SelectContent>
          </Select>

          <Select value={filters.date_range} onValueChange={(value) => setFilters({ ...filters, date_range: value })}>
            <SelectTrigger className="w-48">
              <SelectValue placeholder="Période" />
            </SelectTrigger>
            <SelectContent>
              {dateRangeOptions.map((option) => (
                <SelectItem key={option.value} value={option.value}>
                  {option.label}
                </SelectItem>
              ))}
            </SelectContent>
          </Select>

          {(filters.search ||
            filters.transaction_type !== "all" ||
            filters.status !== "all" ||
            filters.account_id !== "all" ||
            filters.date_range !== "all") && (
            <Button
              variant="ghost"
              size="sm"
              onClick={() =>
                setFilters({
                  search: "",
                  transaction_type: "all",
                  status: "all",
                  account_id: "all",
                  date_range: "all",
                })
              }
            >
              <Filter className="h-4 w-4" />
              Effacer les filtres
            </Button>
          )}
        </div>
      </CardHeader>

      <CardContent>
        <div className="rounded-md border">
          <Table>
            <TableHeader>
              {table.getHeaderGroups().map((headerGroup) => (
                <TableRow key={headerGroup.id}>
                  {headerGroup.headers.map((header) => {
                    return (
                      <TableHead key={header.id}>
                        {header.isPlaceholder ? null : (
                          <div
                            className={cn(
                              "flex items-center space-x-2",
                              header.column.getCanSort() && "cursor-pointer select-none",
                            )}
                            onClick={header.column.getToggleSortingHandler()}
                          >
                            {flexRender(header.column.columnDef.header, header.getContext())}
                            {header.column.getCanSort() && <ArrowUpDown className="ml-2 h-4 w-4" />}
                          </div>
                        )}
                      </TableHead>
                    );
                  })}
                </TableRow>
              ))}
            </TableHeader>
            <TableBody>
              {loading ? (
                <TableRow>
                  <TableCell colSpan={columns.length} className="h-24 text-center">
                    <div className="flex items-center justify-center">
                      <RefreshCw className="mr-2 h-4 w-4 animate-spin" />
                      Chargement...
                    </div>
                  </TableCell>
                </TableRow>
              ) : table.getRowModel().rows.length ? (
                table.getRowModel().rows.map((row) => (
                  <TableRow key={row.id} data-state={row.getIsSelected() && "selected"}>
                    {row.getVisibleCells().map((cell) => (
                      <TableCell key={cell.id}>{flexRender(cell.column.columnDef.cell, cell.getContext())}</TableCell>
                    ))}
                  </TableRow>
                ))
              ) : (
                <TableRow>
                  <TableCell colSpan={columns.length} className="h-24 text-center">
                    Aucune transaction trouvée.
                  </TableCell>
                </TableRow>
              )}
            </TableBody>
          </Table>
        </div>

        {/* Pagination */}
        <div className="flex items-center justify-between space-x-2 py-4">
          <div className="text-muted-foreground text-sm">
            {table.getFilteredSelectedRowModel().rows.length} sur {table.getFilteredRowModel().rows.length}{" "}
            transaction(s) sélectionnée(s).
          </div>
          <div className="flex items-center space-x-2">
            <Button
              variant="outline"
              size="sm"
              onClick={() => table.previousPage()}
              disabled={!table.getCanPreviousPage()}
            >
              <ChevronLeft className="h-4 w-4" />
              Précédent
            </Button>
            <div className="text-sm font-medium">
              Page {table.getState().pagination.pageIndex + 1} sur {table.getPageCount()}
            </div>
            <Button variant="outline" size="sm" onClick={() => table.nextPage()} disabled={!table.getCanNextPage()}>
              Suivant
              <ChevronRight className="h-4 w-4" />
            </Button>
          </div>
        </div>
      </CardContent>
    </Card>
  );
}
