import React, { useState, useMemo, useCallback } from 'react';
import {
  Box,
  Paper,
  Table,
  TableBody,
  TableCell,
  TableContainer,
  TableHead,
  TablePagination,
  TableRow,
  TextField,
  Typography,
  Skeleton,
  InputAdornment,
} from '@mui/material';
import SearchIcon from '@mui/icons-material/Search';
import ArrowUpwardIcon from '@mui/icons-material/ArrowUpward';
import ArrowDownwardIcon from '@mui/icons-material/ArrowDownward';
import InboxIcon from '@mui/icons-material/Inbox';

export interface Column<T> {
  key: string;
  label: string;
  align?: 'left' | 'center' | 'right';
  width?: number | string;
  render?: (row: T) => React.ReactNode;
  sortable?: boolean;
  searchable?: boolean;
}

export interface DataTableProps<T> {
  columns: Column<T>[];
  data: T[];
  isLoading?: boolean;
  skeletonRows?: number;
  emptyMessage?: string;
  emptyIcon?: React.ReactNode;
  onRowClick?: (row: T) => void;
  rowKey: (row: T) => string | number;
  searchPlaceholder?: string;
  searchEnabled?: boolean;
  paginationEnabled?: boolean;
  defaultRowsPerPage?: number;
  rowsPerPageOptions?: number[];
  filters?: React.ReactNode;
  actions?: React.ReactNode;
  title?: string;
  stickyHeader?: boolean;
  maxHeight?: number | string;
  size?: 'small' | 'medium';
  dense?: boolean;
}

/** Universal data table with search, sorting, and pagination. */
export function DataTable<T>({
  columns,
  data,
  isLoading = false,
  skeletonRows = 5,
  emptyMessage = 'Keine Einträge',
  emptyIcon,
  onRowClick,
  rowKey,
  searchPlaceholder = 'Suchen...',
  searchEnabled = true,
  paginationEnabled = true,
  defaultRowsPerPage = 10,
  rowsPerPageOptions = [5, 10, 25],
  filters,
  actions,
  title,
  stickyHeader = false,
  maxHeight,
  size = 'small',
  dense = false,
}: DataTableProps<T>) {
  const [search, setSearch] = useState('');
  const [sortKey, setSortKey] = useState<string | null>(null);
  const [sortDir, setSortDir] = useState<'asc' | 'desc'>('asc');
  const [page, setPage] = useState(0);
  const [rowsPerPage, setRowsPerPage] = useState(defaultRowsPerPage);

  const handleSort = useCallback((key: string) => {
    if (sortKey === key) {
      if (sortDir === 'asc') {
        setSortDir('desc');
      } else {
        setSortKey(null);
        setSortDir('asc');
      }
    } else {
      setSortKey(key);
      setSortDir('asc');
    }
  }, [sortKey, sortDir]);

  const filteredData = useMemo(() => {
    if (!search.trim()) return data;
    const term = search.toLowerCase();
    const searchableCols = columns.filter((c) => c.searchable !== false);
    return data.filter((row) =>
      searchableCols.some((col) => {
        const val = (row as Record<string, unknown>)[col.key];
        return val != null && String(val).toLowerCase().includes(term);
      })
    );
  }, [data, search, columns]);

  const sortedData = useMemo(() => {
    if (!sortKey) return filteredData;
    return [...filteredData].sort((a, b) => {
      const aVal = (a as Record<string, unknown>)[sortKey];
      const bVal = (b as Record<string, unknown>)[sortKey];
      if (aVal == null && bVal == null) return 0;
      if (aVal == null) return 1;
      if (bVal == null) return -1;
      const cmp = String(aVal).localeCompare(String(bVal), undefined, { numeric: true });
      return sortDir === 'asc' ? cmp : -cmp;
    });
  }, [filteredData, sortKey, sortDir]);

  const paginatedData = paginationEnabled
    ? sortedData.slice(page * rowsPerPage, page * rowsPerPage + rowsPerPage)
    : sortedData;

  const showToolbar = title || actions || searchEnabled;

  return (
    <Paper>
      {showToolbar && (
        <Box sx={{ px: 2.5, py: 2, display: 'flex', alignItems: 'center', justifyContent: 'space-between', gap: 2 }}>
          {title && <Typography variant="h6" fontWeight={700}>{title}</Typography>}
          <Box sx={{ flex: 1 }} />
          {searchEnabled && (
            <TextField
              size="small"
              placeholder={searchPlaceholder}
              value={search}
              onChange={(e) => { setSearch(e.target.value); setPage(0); }}
              sx={{ maxWidth: 280, '& .MuiOutlinedInput-root': { bgcolor: 'rgba(0,0,0,0.02)' } }}
              InputProps={{
                startAdornment: (
                  <InputAdornment position="start">
                    <SearchIcon fontSize="small" sx={{ color: 'text.disabled' }} />
                  </InputAdornment>
                ),
              }}
            />
          )}
          {actions}
        </Box>
      )}
      {filters && <Box sx={{ px: 2, pb: 1 }}>{filters}</Box>}
      <TableContainer sx={{ maxHeight }}>
        <Table size={dense ? 'small' : size} stickyHeader={stickyHeader}>
          <TableHead>
            <TableRow>
              {columns.map((col) => (
                <TableCell
                  key={col.key}
                  align={col.align}
                  width={col.width}
                  sx={{
                    cursor: col.sortable !== false ? 'pointer' : 'default',
                    bgcolor: 'background.default',
                    userSelect: 'none',
                  }}
                  onClick={() => col.sortable !== false && handleSort(col.key)}
                >
                  <Box display="inline-flex" alignItems="center" gap={0.5}>
                    {col.label}
                    {sortKey === col.key && (
                      sortDir === 'asc'
                        ? <ArrowUpwardIcon sx={{ fontSize: 14 }} />
                        : <ArrowDownwardIcon sx={{ fontSize: 14 }} />
                    )}
                  </Box>
                </TableCell>
              ))}
            </TableRow>
          </TableHead>
          <TableBody>
            {isLoading ? (
              Array.from({ length: skeletonRows }, (_, i) => (
                <TableRow key={i}>
                  {columns.map((col) => (
                    <TableCell key={col.key}>
                      <Skeleton animation="wave" />
                    </TableCell>
                  ))}
                </TableRow>
              ))
            ) : paginatedData.length === 0 ? (
              <TableRow>
                <TableCell colSpan={columns.length} align="center" sx={{ py: 6 }}>
                  <Box display="flex" flexDirection="column" alignItems="center" color="text.secondary">
                    {emptyIcon ?? <InboxIcon sx={{ fontSize: 40, mb: 1, opacity: 0.5 }} />}
                    <Typography variant="body2" color="text.secondary">
                      {emptyMessage}
                    </Typography>
                  </Box>
                </TableCell>
              </TableRow>
            ) : (
              paginatedData.map((row) => (
                <TableRow
                  key={rowKey(row)}
                  hover
                  onClick={() => onRowClick?.(row)}
                  sx={{ cursor: onRowClick ? 'pointer' : 'default' }}
                >
                  {columns.map((col) => (
                    <TableCell key={col.key} align={col.align}>
                      {col.render ? col.render(row) : (row as Record<string, unknown>)[col.key] as React.ReactNode}
                    </TableCell>
                  ))}
                </TableRow>
              ))
            )}
          </TableBody>
        </Table>
      </TableContainer>
      {paginationEnabled && !isLoading && (
        <TablePagination
          component="div"
          count={filteredData.length}
          page={page}
          onPageChange={(_, p) => setPage(p)}
          rowsPerPage={rowsPerPage}
          onRowsPerPageChange={(e) => { setRowsPerPage(parseInt(e.target.value, 10)); setPage(0); }}
          rowsPerPageOptions={rowsPerPageOptions}
          labelRowsPerPage="Zeilen pro Seite:"
        />
      )}
    </Paper>
  );
}
