import * as React from "react";
import Box from "@mui/material/Box";
import Table from "@mui/material/Table";
import TableBody from "@mui/material/TableBody";
import TableCell from "@mui/material/TableCell";
import TableContainer from "@mui/material/TableContainer";
import TableHead from "@mui/material/TableHead";
import TablePagination from "@mui/material/TablePagination";
import TableRow from "@mui/material/TableRow";
import Paper from "@mui/material/Paper";
import IconButton from "@mui/material/IconButton";
import Tooltip from "@mui/material/Tooltip";
import { visuallyHidden } from "@mui/utils";
import TableSortLabel from "@mui/material/TableSortLabel";
import MenuItem from "@mui/material/MenuItem";
import Select from "@mui/material/Select";
import Swal from "sweetalert2"; // Import SweetAlert

import FirstPageIcon from "@mui/icons-material/FirstPage";
import KeyboardArrowLeft from "@mui/icons-material/KeyboardArrowLeft";
import KeyboardArrowRight from "@mui/icons-material/KeyboardArrowRight";
import LastPageIcon from "@mui/icons-material/LastPage";
import FormControl from "@mui/material/FormControl";
import InputLabel from "@mui/material/InputLabel/InputLabel";
import {
  EnhancedTableProps,
  Row,
  TablePaginationActionsProps,
} from "@/types/form";
import { Oval } from "react-loader-spinner";
import Loader from "../common/Loader";

function TablePaginationActions(props: TablePaginationActionsProps) {
  const { count, page, rowsPerPage, onPageChange } = props;

  const handleFirstPageButtonClick = (
    event: React.MouseEvent<HTMLButtonElement>
  ) => {
    onPageChange(event, 0);
  };

  const handleBackButtonClick = (
    event: React.MouseEvent<HTMLButtonElement>
  ) => {
    onPageChange(event, page - 1);
  };

  const handleNextButtonClick = (
    event: React.MouseEvent<HTMLButtonElement>
  ) => {
    onPageChange(event, page + 1);
  };

  const handleLastPageButtonClick = (
    event: React.MouseEvent<HTMLButtonElement>
  ) => {
    onPageChange(event, Math.max(0, Math.ceil(count / rowsPerPage) - 1));
  };

  return (
    <Box sx={{ flexShrink: 0, ml: 2.5 }}>
      <IconButton
        onClick={handleFirstPageButtonClick}
        disabled={page === 0}
        aria-label="first page"
      >
        <FirstPageIcon />
      </IconButton>
      <IconButton
        onClick={handleBackButtonClick}
        disabled={page === 0}
        aria-label="previous page"
      >
        <KeyboardArrowLeft />
      </IconButton>
      <IconButton
        onClick={handleNextButtonClick}
        disabled={page >= Math.ceil(count / rowsPerPage) - 1}
        aria-label="next page"
      >
        <KeyboardArrowRight />
      </IconButton>
      <IconButton
        onClick={handleLastPageButtonClick}
        disabled={page >= Math.ceil(count / rowsPerPage) - 1}
        aria-label="last page"
      >
        <LastPageIcon />
      </IconButton>
    </Box>
  );
}

export default function EnhancedTable({
  fetchData,
  modelName,
  deleteRow,
  customActions = [],
  additionalOptions = [],
  listable,
}: EnhancedTableProps) {
  const [page, setPage] = React.useState(0);
  const [rowsPerPage, setRowsPerPage] = React.useState(50);
  const [rows, setRows] = React.useState<Row[]>([]);
  const [totalCount, setTotalCount] = React.useState(0);
  const [order, setOrder] = React.useState<"asc" | "desc">("asc");
  const [orderBy, setOrderBy] = React.useState<keyof Row>("name");
  const [isLoading, setLoading] = React.useState<boolean>(false);

  const handleRequestSort = (
    event: React.MouseEvent<unknown>,
    property: keyof Row
  ) => {
    const element = listable.find((el) => el.key === property);
    if (!element || !element.sortable) return; // Check if column is sortable

    const isAsc = orderBy === property && order === "asc";
    setOrder(isAsc ? "desc" : "asc");
    setOrderBy(property);
    fetchData(page, rowsPerPage).then(({ data }) => {
      const sortedRows = data.slice().sort((a, b) => {
        if (isAsc) {
          return a[property] > b[property] ? 1 : -1;
        } else {
          return a[property] < b[property] ? 1 : -1;
        }
      });
      setRows(sortedRows);
    });
  };

  React.useEffect(() => {
    const fetchInitialData = async () => {
      setLoading(true);
      const { data, total } = await fetchData(page, rowsPerPage);
      setRows(data);
      console.log(rows);

      setTotalCount(total);
      setLoading(false);
    };
    fetchInitialData();
  }, [fetchData, page, rowsPerPage]);

  const handleDeleteRow = async (id: string) => {
    // Show confirmation dialog
    const result = await Swal.fire({
      title: "Are you sure?",
      text: "You won't be able to revert this!",
      icon: "warning",
      showCancelButton: true,
      confirmButtonColor: "#3085d6",
      cancelButtonColor: "#d33",
      confirmButtonText: "Yes, delete it!",
    });

    // If user confirms deletion, call deleteRow function
    if (result.isConfirmed) {
      try {
        await deleteRow(id); // Call deleteRow API
        // Reload data after deletion
        const { data, total } = await fetchData(page, rowsPerPage);
        setRows(data);
        setTotalCount(total);
        // Show success message
        Swal.fire("Deleted!", "Your row has been deleted.", "success");
      } catch (error) {
        // Show error message if deletion fails
        Swal.fire("Error!", "Failed to delete the row.", "error");
      }
    }
  };

  return (
    <Paper>
      {isLoading && <Loader />}
      <TableContainer>
        <Table>
          <TableHead>
            <TableRow>
              {listable.map((element) => (
                <TableCell key={element.key}>
                  {element.sortable ? (
                    <Tooltip
                      title="Sort"
                      placement="bottom-start"
                      enterDelay={300}
                    >
                      <TableSortLabel
                        active={orderBy === element.key}
                        direction={orderBy === element.key ? order : "asc"}
                        onClick={(event) =>
                          handleRequestSort(event, element.key)
                        }
                      >
                        {element.label} {/* Use label instead of key */}
                        {orderBy === element.key ? (
                          <span style={visuallyHidden}>
                            {order === "desc"
                              ? "sorted descending"
                              : "sorted ascending"}
                          </span>
                        ) : null}
                      </TableSortLabel>
                    </Tooltip>
                  ) : (
                    element.label // Render the column name if not sortable
                  )}
                </TableCell>
              ))}
              {modelName !== "countries" &&
                modelName !== "states" &&
                modelName !== "cities" && <TableCell>Actions</TableCell>}
            </TableRow>
          </TableHead>

          <TableBody>
            {rows.map((row) => (
              <TableRow key={row.id}>
                {listable.map((column) => (
                  <TableCell key={column.key}>
                    {column.key.includes(".")
                      ? // If the key contains dot, split and access nested property
                        row[column.key.split(".")[0]][column.key.split(".")[1]]
                      : // Otherwise, access the property directly
                        row[column.key]}
                  </TableCell>
                ))}
                {modelName !== "countries" && (
                  <TableCell>
                    <Box sx={{ minWidth: 120 }}>
                      <FormControl fullWidth>
                        <InputLabel id="demo-simple-select-label">
                          Actions
                        </InputLabel>
                        <Select
                          value=""
                          onChange={(event) => {
                            const action = event.target.value;
                            // Redirect based on the selected action
                            if (action === "edit") {
                              window.location.href = `/actions/${modelName}/edit/${row.id}`;
                            } else if (action === "view") {
                              window.location.href = `/actions/${modelName}/view/${row.id}`;
                            } else if (action === "delete") {
                              // Call handleDeleteRow function
                              handleDeleteRow(row.id);
                            } else {
                              // Handle additional custom options
                              const selectedOption = customActions.find(
                                (option) => option.name === action
                              );
                              if (selectedOption) {
                                window.location.href =
                                  selectedOption.url + row.id;
                              } else {
                                const additionalOption: any =
                                  additionalOptions.find(
                                    (option) => option.name === action
                                  );
                                if (additionalOption) {
                                  window.location.href =
                                    additionalOption.url + row.id;
                                }
                              }
                            }
                          }}
                        >
                          <MenuItem value="edit">Edit</MenuItem>
                          <MenuItem value="view">View</MenuItem>
                          <MenuItem value="delete">Delete</MenuItem>
                          {customActions.map((action) => (
                            <MenuItem key={action.name} value={action.name}>
                              {action.name}
                            </MenuItem>
                          ))}
                          {additionalOptions &&
                            additionalOptions.map((option) => (
                              <MenuItem key={option.name} value={option.name}>
                                {option.name}
                              </MenuItem>
                            ))}
                        </Select>
                      </FormControl>
                    </Box>
                  </TableCell>
                )}
              </TableRow>
            ))}
          </TableBody>
        </Table>
      </TableContainer>
      <TablePagination
        rowsPerPageOptions={[50, 100, 200]}
        colSpan={Object.keys(rows[0] || {}).length}
        count={totalCount}
        rowsPerPage={rowsPerPage}
        page={page}
        onPageChange={(event, newPage) => setPage(newPage)}
        onRowsPerPageChange={(event) => {
          setRowsPerPage(parseInt(event.target.value, 10));
          setPage(0);
        }}
        ActionsComponent={TablePaginationActions}
      />
    </Paper>
  );
}
