"use client";

import {
  Box,
  Card,
  Pagination,
  Stack,
  Table,
  TableBody,
  TableCell,
  TableContainer,
  TableHead,
  TableRow,
  Typography,
  useMediaQuery,
  useTheme,
} from "@mui/material";
import { ReactNode } from "react";
import { usePathname, useRouter, useSearchParams } from "next/navigation";

export type Column<T> = {
  id: string;
  label: string;
  align?: "left" | "right" | "center";
  width?: string | number;
  render?: (row: T) => ReactNode;
};

type DataTableProps<T> = {
  columns: Column<T>[];
  data: T[];
  keyField: keyof T;
  emptyMessage?: string;
  loading?: boolean;
  onRowClick?: (row: T) => void;
  pagination?: {
    total: number;
    page: number;
    perPage: number;
  };
  /** If provided, renders this instead of the table on xs/sm screens */
  mobileCard?: (row: T) => ReactNode;
};

function PaginationBar({ page, perPage, total }: { page: number; perPage: number; total: number }) {
  const router = useRouter();
  const pathname = usePathname();
  const searchParams = useSearchParams();
  const pageCount = Math.ceil(total / perPage);

  if (pageCount <= 1) return null;

  function handlePageChange(_: React.ChangeEvent<unknown>, newPage: number) {
    const params = new URLSearchParams(searchParams.toString());
    params.set("page", String(newPage));
    router.push(`${pathname}?${params.toString()}`);
  }

  return (
    <Box sx={{ display: "flex", justifyContent: "center", mt: 2 }}>
      <Pagination
        count={pageCount}
        page={page}
        onChange={handlePageChange}
        color="primary"
        shape="rounded"
      />
    </Box>
  );
}

export function DataTable<T>({
  columns,
  data,
  keyField,
  emptyMessage = "No data available",
  loading = false,
  onRowClick,
  pagination,
  mobileCard,
}: DataTableProps<T>) {
  const theme = useTheme();
  const isMobile = useMediaQuery(theme.breakpoints.down("md"));

  const isEmpty = data.length === 0 && !loading;

  if (isMobile && mobileCard) {
    return (
      <Box>
        {isEmpty ? (
          <Card variant="outlined" sx={{ py: 6, textAlign: "center" }}>
            <Typography color="text.secondary">{emptyMessage}</Typography>
          </Card>
        ) : (
          <Stack spacing={1.5}>
            {data.map((row) => (
              <Box key={String(row[keyField])}>
                {mobileCard(row)}
              </Box>
            ))}
          </Stack>
        )}
        {pagination && <PaginationBar {...pagination} />}
      </Box>
    );
  }

  return (
    <Box>
      <TableContainer component={Card} variant="outlined" sx={{ overflowX: "auto" }}>
        <Table sx={{ minWidth: 600 }}>
          <TableHead>
            <TableRow>
              {columns.map((col) => (
                <TableCell
                  key={col.id}
                  align={col.align || "left"}
                  width={col.width}
                >
                  {col.label}
                </TableCell>
              ))}
            </TableRow>
          </TableHead>
          <TableBody>
            {isEmpty ? (
              <TableRow>
                <TableCell colSpan={columns.length} align="center" sx={{ py: 8 }}>
                  <Typography color="text.secondary">{emptyMessage}</Typography>
                </TableCell>
              </TableRow>
            ) : (
              data.map((row) => (
                <TableRow
                  key={String(row[keyField])}
                  onClick={onRowClick ? () => onRowClick(row) : undefined}
                  sx={onRowClick ? { cursor: "pointer", "&:hover": { bgcolor: "action.hover" } } : undefined}
                >
                  {columns.map((col) => (
                    <TableCell key={col.id} align={col.align || "left"}>
                      {col.render ? col.render(row) : (row as Record<string, unknown>)[col.id] as ReactNode}
                    </TableCell>
                  ))}
                </TableRow>
              ))
            )}
          </TableBody>
        </Table>
      </TableContainer>

      {pagination && <PaginationBar {...pagination} />}
    </Box>
  );
}
