import { Box, CircularProgress, Collapse, darken, IconButton, InputAdornment, Paper, SxProps, Table, TableBody, TableCell, TableContainer, TableHead, TablePagination, TableRow, TextField, Theme, Typography } from "@mui/material";
import { makeStyles } from "@mui/styles";
import { ChevronRight, Search } from "@mui/icons-material"
import { useEffect, useState } from "react";
import React from "react";

const useStyles = makeStyles((theme: Theme) => {
  // const isMobile = useMobile()
  return ({
    gutter: {
      backgroundColor: darken(theme.palette.background.paper, 0.03),
      border: "none"
    },
    tableContainer: {
      margin: theme.spacing(1),
      [theme.breakpoints.up("sm")]: {
        margin: theme.spacing(2)
      },
      width: "auto"
    },
    title: {
      padding: theme.spacing(1)
    },
    titleContainer: {
      border: "none",
    },
    searchContainer: {
      border: "none",
      textAlign: "right",
    },
  })},
);

export interface Column<T> {
  title: string | JSX.Element;
  cellStyle?: SxProps<Theme> | undefined
  render?: (row: T) => JSX.Element;
}

interface Props<T> {
  rows: T[],
  columns?: Column<T>[],
  title?: string;
  total: number,
  pageSize: number,
  page: number,
  setPage: (value: React.SetStateAction<number>) => void,
  handleRowsPerPageChange: (event: any) => void,
  renderGutter?: (row: T) => JSX.Element,
  setSearchText?: React.Dispatch<React.SetStateAction<string>>,
  isLoading?: boolean;
  multiGutter?: boolean;
}

export default function ResponsiveTable<T extends Object>(props: Props<T>) {
  const { 
    rows, 
    total, 
    page, 
    pageSize, 
    setPage, 
    handleRowsPerPageChange, 
    title, 
    renderGutter,
    setSearchText, 
    isLoading,
    multiGutter,
    columns
  } = props
  const classes = useStyles();

  const [inputSearchText, setInputSearchText] = useState("");
  const [openGutters, setOpenGutters] = useState<number[]>([])

  useEffect(() => {
    if (!setSearchText) return;
    if (inputSearchText === undefined) return;
    const handler = setTimeout(() => {
      setSearchText(inputSearchText);
    }, 750); // Delay of 750ms

    return () => clearTimeout(handler); // Cleanup on change
  }, [inputSearchText]);

  const handleCollapse = (index: number) => {
    if (multiGutter) {
      if (openGutters.includes(index)) {
        setOpenGutters(openGutters => openGutters.filter(num => num !== index));
      } else {
        setOpenGutters(openGutters => [...openGutters, index]);
      }
    } else {
      if (openGutters.includes(index)) {
        setOpenGutters([])
      } else {
        setOpenGutters([index])
      }
    }
  }

  const handlePageChange = (page: number) => {
    setOpenGutters([])
    setPage(page)
  }

  return (
    <TableContainer className={classes.tableContainer} component={Paper}>
      <Table>
        <TableHead>
          <TableRow>
            {title && <TableCell colSpan={2} className={classes.titleContainer}>
              {typeof(title) === "string" ? 
                <Typography variant="h5" className={classes.title}>
                  {title}
                </Typography>
              :
                <Box className={classes.title}>
                  title
                </Box>
              }
            </TableCell>}
            { setSearchText &&
              <TableCell colSpan={title ? 2 : 4} className={classes.searchContainer}>
                <TextField 
                  variant="standard"
                  className={classes.title}
                  value={inputSearchText}
                  onChange={e => setInputSearchText(e.currentTarget.value)}
                  InputProps={{
                    startAdornment: (
                      <InputAdornment position="start">
                        <Search />
                      </InputAdornment>
                    ),
                  }}
                />
              </TableCell>
            } 
          </TableRow>
          <TableRow>
            { renderGutter && <TableCell></TableCell>}
            { columns ?
              columns.map((column, index) => {
                return (
                  <TableCell key={"header-cell-"+index}>
                    {column.title}
                  </TableCell>
                )
              })
            : rows.length > 0 &&
              Object.keys(rows[0]).map((value, index) => {
                return(
                  <TableCell key={"header-cell-"+index}>
                    {value.toString()}
                  </TableCell>
                )
              })
            }
          </TableRow>
        </TableHead>
        <TableBody>
          { isLoading ? 
            <TableRow>
              { isLoading &&
                <TableCell colSpan={6} sx={{ textAlign: "center"}}>
                  <CircularProgress />
                </TableCell>
              }
            </TableRow>
          :
            rows.map((row, index) => {
              return (
                <React.Fragment key={"row-"+index}>
                  <TableRow>
                    {renderGutter && 
                      <TableCell width={1}>
                        <IconButton sx={{
                          transform: openGutters.includes(index) ? 
                                      'rotate(90deg)' : 'rotate(0deg)',
                          transition: 'transform 0.3s ease',
                        }}
                        onClick={() => handleCollapse(index)}>
                          <ChevronRight/>
                        </IconButton>
                      </TableCell>
                    }
                    {columns ? 
                      columns.map((column, j) => {
                        if (column.render) return (
                          <TableCell key={"row-"+index+"cell-"+j}>
                            {column.render(row)}
                          </TableCell>
                        )
                        return (
                          <TableCell key={"row-"+index+"cell-"+j}>
                            {Object.values(row)[j].toString()}
                          </TableCell>
                        )
                      })
                    :
                      Object.values(row).map((value, j) => {
                        return (
                          <TableCell key={"row-"+index+"cell-"+j}>
                            {value.toString()}
                          </TableCell>
                        )
                      })
                    }
                  </TableRow>
                  {renderGutter && 
                    <TableRow className={classes.gutter}>
                      <TableCell colSpan={6} sx={{padding:0, margin: 0, border: "none"}}>
                        <Collapse in={openGutters.includes(index)} timeout="auto" unmountOnExit>
                          {renderGutter(row)}
                        </Collapse>
                      </TableCell>
                    </TableRow>
                  }
                </React.Fragment>
              )
            })
          }
        </TableBody>
      </Table>
      <TablePagination
        rowsPerPageOptions={[5, 10, 20]}
        component="div"
        count={total}
        rowsPerPage={pageSize}
        page={page}
        onPageChange={(_event, page) => handlePageChange(page)}
        onRowsPerPageChange={handleRowsPerPageChange}
      />
    </TableContainer>
  )
}