import React, { useState, useEffect } from "react";
import PropTypes from "prop-types";
import {
  Typography,
  Table,
  TableBody,
  TableCell,
  TableContainer,
  TableHead,
  TableRow,
  Paper,
  Grid,
  Checkbox,
  FormControlLabel,
  IconButton,
  Popover,
  Divider,
  Button,
  Pagination,
  FormControl,
  InputLabel,
  Select,
  MenuItem,
  TextField,
  Tooltip,
} from "@mui/material";
import TableViewIcon from "@mui/icons-material/TableView";
import FilterAltIcon from "@mui/icons-material/FilterAlt";
import styled from "styled-components";
import Lottie from "lottie-react";
import EmptyAnimation from "../../assets/lottie/Empty.json";
import FilterAltOffIcon from "@mui/icons-material/FilterAltOff";
import GridViewIcon from "@mui/icons-material/GridView";
import AdsClickIcon from "@mui/icons-material/AdsClick";
import BoxShowTable from "./BoxShowTable";
import Zoom from "@mui/material/Zoom";
import { motion } from "framer-motion";

const ResponsiveTable = ({
  columns: initialColumns,
  data,
  title,
  paginated = false,
  handlePageChange,
  handlePerRowsChange,
  totalRows,
  page,
  perPage,
  customColors,
  noPagination,
  changed,
  isDashboard,
  noSearch,
  operation,
  allColors,
  activeRows,
  customWidth,
  ignoreTextsLength,
  CustomColumnsColor,
  hasSum,
  hasSumColumn,
}) => {
  const pathname = window.location.pathname;
  const storageKey = `${pathname}_${
    initialColumns.length
  }_columnsVisibility${title}${initialColumns.join(" ")}`;

  const getInitialColumns = () => {
    const savedColumns = localStorage.getItem(storageKey);

    if (
      savedColumns &&
      JSON.parse(savedColumns)?.length === initialColumns?.length &&
      !changed
    ) {
      return JSON.parse(savedColumns);
    }
    return initialColumns.map((col) => ({ name: col, visible: true }));
  };

  useEffect(() => {
    setColumns(getInitialColumns());
  }, [initialColumns]);

  function isPositiveNumber(str) {
    const data = String(str);
    const sanitizedStr = data?.replace(/,/g, "");
    const num = Number(sanitizedStr);

    if (!isNaN(num)) {
      return num >= 0;
    } else {
      return true;
    }
  }

  const [itemsPerPage, setItemsPerPage] = useState(10);
  const [currentPage, setCurrentPage] = useState(1);
  const [searchQuery, setSearchQuery] = useState("");
  const [searchPageIndex, setSearchPageIndex] = useState(null);
  const [columns, setColumns] = useState(getInitialColumns());
  const [sortConfig, setSortConfig] = useState({ key: null, direction: "asc" });

  useEffect(() => {
    localStorage.setItem(storageKey, JSON.stringify(columns));
  }, [columns]);

  const handleSort = (columnIndex) => {
    const newDirection =
      sortConfig.key === columnIndex && sortConfig.direction === "asc"
        ? "desc"
        : "asc";
    setSortConfig({ key: columnIndex, direction: newDirection });
  };

  const sortedData = [...(data || [])].sort((a, b) => {
    if (sortConfig.key === null) return 0;

    const itemA = String(a[sortConfig.key]);
    const itemB = String(b[sortConfig.key]);

    const isNumericA = !isNaN(itemA.replace(/,/g, ""));
    const isNumericB = !isNaN(itemB.replace(/,/g, ""));

    if (isNumericA && isNumericB) {
      const valueA = parseFloat(itemA.replace(/,/g, ""));
      const valueB = parseFloat(itemB.replace(/,/g, ""));
      return sortConfig.direction === "asc" ? valueA - valueB : valueB - valueA;
    }

    if (typeof itemA === "string" && typeof itemB === "string") {
      return sortConfig.direction === "asc"
        ? itemA.localeCompare(itemB, "fa", { sensitivity: "base" })
        : itemB.localeCompare(itemA, "fa", { sensitivity: "base" });
    }

    if (isNumericA) return sortConfig.direction === "asc" ? -1 : 1;
    if (isNumericB) return sortConfig.direction === "asc" ? 1 : -1;

    return 0;
  });

  const filteredData = sortedData.filter((row) =>
    row.some((cell) =>
      cell?.toString()?.toLowerCase()?.includes(searchQuery.toLowerCase())
    )
  );

  useEffect(() => {
    setCurrentPage(1);
  }, [searchQuery]);

  const totalPages = Math.ceil(filteredData?.length / itemsPerPage);

  const startIndex = (currentPage - 1) * itemsPerPage;
  const endIndex = startIndex + itemsPerPage;

  const slicedData = paginated
    ? filteredData.slice(startIndex, endIndex)
    : filteredData;

  const toggleColumnVisibility = (index) => {
    const updatedColumns = [...columns];
    updatedColumns[index].visible = !updatedColumns[index].visible;
    setColumns(updatedColumns);
  };

  const [anchorEl, setAnchorEl] = useState(null);

  const handleClick = (event) => {
    setAnchorEl(event.currentTarget);
  };

  const handleClose = () => {
    setAnchorEl(null);
  };

  const open = Boolean(anchorEl);
  const id = open ? "simple-popover" : undefined;

  const [openS, setOpenS] = useState(false);

  const handleChange = (event) => {
    setItemsPerPage(event.target.value, setCurrentPage(1));
  };

  const handleCloseS = () => {
    setOpenS(false);
  };

  const handleOpenS = () => {
    setOpenS(true);
  };
  const dotVariants = {
    hidden: { opacity: 0 },
    visible: { opacity: 1 },
  };

  const AnimatedEllipsis = () => {
    return (
      <motion.span
        style={{ display: "inline-flex" }}
        initial="hidden"
        animate="visible"
        transition={{ staggerChildren: 1.5, repeat: Infinity }}
      >
        {[".", ".", "."].map((dot, index) => (
          <motion.span
            key={index}
            variants={dotVariants}
            transition={{ duration: 1.5 }}
          >
            {dot}
          </motion.span>
        ))}
      </motion.span>
    );
  };

  const tableTitle = (
    <Grid
      container
      alignItems="center"
      justifyContent="space-between"
      xs={12}
      style={{
        width: "100%",
      }}
    >
      <Grid gap={2} alignItems="center">
        <Grid container gap={2} alignItems="center">
          {isDashboard ? (
            <GridViewIcon sx={{ color: "#c23616" }} />
          ) : (
            <TableViewIcon sx={{ color: "#547687" }} />
          )}
          <Typography
            style={{
              fontSize: "16px",
              color: isDashboard ? "#c23616" : "black",
            }}
            variant="body2"
          >
            {title}
          </Typography>
        </Grid>
      </Grid>

      <Grid gap={2} alignItems="center" justifyContent="center">
        <Grid container gap={1} alignItems="center">
          <Grid item>{operation}</Grid>
          {paginated && !noSearch && (
            <Grid item>
              <TextField
                size="small"
                type="search"
                variant="standard"
                placeholder="جستجو..."
                value={searchQuery}
                onChange={(e) => setSearchQuery(e.target.value)}
              />
            </Grid>
          )}
          <Grid item>
            {!isDashboard && (
              <IconButton
                onClick={handleClick}
                aria-describedby={id}
                color={
                  columns.filter((item) => item?.visible === false).length
                    ? "error"
                    : "primary"
                }
              >
                {columns.filter((item) => item?.visible === false).length ? (
                  <FilterAltIcon />
                ) : (
                  <FilterAltOffIcon />
                )}
              </IconButton>
            )}
          </Grid>
          <Grid container xs={4}>
            <Popover
              id={id}
              open={open}
              anchorEl={anchorEl}
              onClose={handleClose}
              anchorOrigin={{
                vertical: "bottom",
                horizontal: "left",
              }}
            >
              <Grid container width="300px" p={3}>
                <Grid
                  container
                  xs={12}
                  justifyContent="space-between"
                  alignItems="center"
                >
                  <Typography variant="body1" color="primary">
                    فیلتر ستون ها
                  </Typography>
                  <Button
                    color="error"
                    onClick={() => {
                      handleClose();
                    }}
                  >
                    بازگشت
                  </Button>
                </Grid>
                <Divider style={{ width: "100%" }} />
                {columns.map((column, index) => (
                  <Grid container alignItems="center" gap={1} key={index}>
                    <FormControlLabel
                      style={{ color: column.visible ? "black" : "red" }}
                      key={index}
                      control={
                        <Checkbox
                          size="small"
                          checked={column.visible}
                          onChange={() => toggleColumnVisibility(index)}
                        />
                      }
                      label={column.name}
                    />
                  </Grid>
                ))}
              </Grid>
            </Popover>
          </Grid>
        </Grid>
      </Grid>
    </Grid>
  );

  const CustomTableCell = styled(TableCell)`
    font-weight: bold;
    background: ${({ bgColor }) => `${bgColor} !important`};
    color: ${({ bgColor, textColor }) =>
      `${
        textColor
          ? textColor
          : isDashboard
          ? "white"
          : allColors
          ? allColors?.text
          : bgColor === "black" ||
            bgColor === "blue" ||
            bgColor === "red" ||
            bgColor === "brown" ||
            bgColor === "green"
          ? "white"
          : "black"
      } !important`};
  `;

  const getColumnColor = (column) => {
    if (CustomColumnsColor) {
      const c = CustomColumnsColor?.find((item) =>
        column?.name.includes(item.key)
      );
      if (c) {
        return c.color;
      }
    }
    const c = customColors?.find((item) => item.name === column?.name)
      ? customColors?.find((item) => item.name === column?.name)
      : customColors?.find((item) => item.rest === true);
    if (c) {
      return c.color;
    } else if (allColors) {
      return allColors.color;
    } else {
      if (isDashboard) {
        return "#c23616";
      } else if (customColors?.length) {
        return "#f6e58d";
      } else {
        return null;
      }
    }
  };

  const parseNumber = (value) => {
    const dateRegex = /^\d{4}\/\d{2}\/\d{2}$/;
    const isLargeNumber =
      typeof value === "string" && value.replace(/,/g, "").length > 14;

    if (typeof value === "string" && (dateRegex.test(value) || isLargeNumber)) {
      return 0;
    }

    if (typeof value === "string") {
      const parsed = parseFloat(value.replace(/,/g, ""));
      return isNaN(parsed) ? 0 : parsed;
    }

    return typeof value === "number" ? value : 0;
  };
  const calculateColumnSum = (colIndex) => {
    let hasNumericData = false;
    const sum = slicedData.reduce((total, row) => {
      const value = parseNumber(row[colIndex]);
      if (value !== null) {
        hasNumericData = true;
        return total + value;
      }
      return total;
    }, 0);
    return hasNumericData ? sum : null;
  };

  const AnimatedTableRow = motion(TableRow);

  const rowAnimation = {
    active: {
      backgroundColor: hasSum
        ? [
            "rgba(176, 84, 237, 0.8)",
            "rgba(176, 84, 237, 0.6)",
            "rgba(176, 84, 237, 0.8)",
          ]
        : [
            "rgb(234, 137, 130, 0.6)",
            "rgb(234, 137, 130, 0.4)",
            "rgb(234, 137, 130, 0.6)",
          ],
      transition: {
        duration: 3,
        repeat: Infinity,
        ease: "easeInOut",
      },
    },
  };

  return (
    <>
      {tableTitle}
      <Grid
        id="startoftable"
        display={{ xs: "none", sm: "grid" }}
        style={{
          width: customWidth ? customWidth : "100%",
        }}
      >
        <TableContainer
          component={Paper}
          sx={{ maxHeight: "70vh", overflow: "auto" }}
        >
          <Table aria-label="simple table" stickyHeader>
            <TableHead>
              <TableRow>
                {columns
                  .filter((d) => d.visible)
                  .map((column, index) => {
                    const columnSum = calculateColumnSum(index);
                    return (
                      <Tooltip
                        key={index}
                        title={`مجموع: ${parseInt(
                          calculateColumnSum(index)
                        ).toLocaleString()}`}
                        arrow
                        placement="top"
                        disableHoverListener={
                          columnSum === 0 ||
                          isDashboard ||
                          column?.name === "ردیف" ||
                          column?.name?.includes("موبایل") ||
                          column?.name?.includes("حساب") ||
                          column?.name?.includes("شماره") ||
                          slicedData?.length === 1
                        }
                        slots={{
                          transition: Zoom,
                        }}
                      >
                        <CustomTableCell
                          key={index}
                          bgColor={getColumnColor(column)}
                          textColor={
                            CustomColumnsColor?.find((item) =>
                              column?.name.includes(item.key)
                            )?.text || null
                          }
                          onClick={() => handleSort(index)}
                          style={{ cursor: "pointer" }}
                        >
                          {column?.name}
                          {sortConfig.key === index &&
                            !isDashboard &&
                            (sortConfig.direction === "asc" ? " 🔻" : " 🔺")}
                        </CustomTableCell>
                      </Tooltip>
                    );
                  })}
              </TableRow>
            </TableHead>
            <TableBody>
              {slicedData?.map((row, rowIndex) => (
                <AnimatedTableRow
                  style={{
                    background:
                      activeRows && activeRows[rowIndex]
                        ? "rgb(249 218 218)"
                        : rowIndex % 2 === 0
                        ? isDashboard
                          ? "white"
                          : "#daeef0"
                        : "white",
                    borderStyle:
                      activeRows && activeRows[rowIndex] ? "solid" : "none",
                    borderWidth:
                      activeRows && activeRows[rowIndex] ? "1px" : "none",
                  }}
                  key={rowIndex}
                  variants={rowAnimation}
                  initial="initial"
                  animate={
                    activeRows && activeRows[rowIndex] ? "active" : "inactive"
                  }
                >
                  {row?.map(
                    (cell, cellIndex) =>
                      columns[cellIndex]?.visible && (
                        <TableCell key={cellIndex}>
                          <Grid
                            container
                            justifyContent="center"
                            alignItems="center"
                            xs={12}
                            style={{
                              color: !isPositiveNumber(cell) ? "red" : "black",
                            }}
                          >
                            <Grid style={{ textAlign: "center" }}>
                              {!isPositiveNumber(cell) ? (
                                String(cell).replace("-", "") + "-‌ ‌"
                              ) : typeof cell === "string" &&
                                !ignoreTextsLength &&
                                cell.length > 30 ? (
                                <Tooltip title={cell} placement="top">
                                  <span>{cell.slice(0, 30) + " ... "}</span>
                                  <AdsClickIcon
                                    color="primary"
                                    fontSize="5px"
                                  />
                                </Tooltip>
                              ) : (cell?.toString() === "NaN" || !cell) &&
                                cell !== 0 ? (
                                "-"
                              ) : (
                                cell
                              )}
                            </Grid>
                          </Grid>
                        </TableCell>
                      )
                  )}
                </AnimatedTableRow>
              ))}
              {hasSum && (
                <AnimatedTableRow
                  style={{
                    background: "#2c3e50",
                    borderStyle: "none",
                    borderWidth: "none",
                  }}
                  variants={rowAnimation}
                  initial="initial"
                  animate="active"
                >
                  {columns
                    .filter((d) => d.visible)
                    .map((column, index) => {
                      const columnSum = calculateColumnSum(index);
                      return (
                        <TableCell key={index}>
                          <Grid
                            container
                            justifyContent="center"
                            alignItems="center"
                            xs={12}
                            style={{
                              color: "white",
                            }}
                          >
                            <Grid style={{ textAlign: "center" }}>
                              {column?.name === "ردیف"
                                ? slicedData?.length + 1
                                : column?.name === hasSumColumn
                                ? "مجموع"
                                : !isPositiveNumber(columnSum)
                                ? String(columnSum).replace("-", "") + "-‌ ‌"
                                : columnSum?.toLocaleString()}
                            </Grid>
                          </Grid>
                        </TableCell>
                      );
                    })}
                </AnimatedTableRow>
              )}
            </TableBody>
          </Table>
        </TableContainer>
      </Grid>
      {!slicedData?.length && (
        <Grid container xs={12} mt={2} mb={2} justifyContent="center">
          {!isDashboard && !noPagination && (
            <Grid width="120px" alignSelf="center">
              <Lottie animationData={EmptyAnimation} loop={true} />
            </Grid>
          )}
          <Grid xs={12} justifyContent="center" container>
            <Typography>
              {isDashboard ? (
                <>
                  در حال دریافت اطلاعات {"‌‌"}
                  <AnimatedEllipsis />
                </>
              ) : (
                "داده ای دریافت نشد!"
              )}
            </Typography>
          </Grid>
        </Grid>
      )}
      <Grid display={{ xs: "grid", sm: "none" }} style={{ width: "100%" }}>
        <BoxShowTable
          columns={columns}
          data={slicedData}
          paginated={paginated}
          isDashboard={isDashboard}
          allColors={allColors}
          customColors={customColors}
        />
      </Grid>

      {!noPagination && (
        <Grid container mt={2}>
          {paginated ? (
            <Grid
              container
              mb={2}
              justifyContent="center"
              xs={12}
              alignItems="center"
              gap={2}
            >
              <FormControl sx={{ width: 80 }}>
                <InputLabel id="demo-controlled-open-select-label">
                  تعداد
                </InputLabel>
                <Select
                  size="small"
                  labelId="demo-controlled-open-select-label"
                  id="demo-controlled-open-select"
                  open={openS}
                  onClose={handleCloseS}
                  onOpen={handleOpenS}
                  value={itemsPerPage}
                  label="Age"
                  onChange={handleChange}
                >
                  <MenuItem value={10}>10</MenuItem>
                  <MenuItem value={20}>20</MenuItem>
                  <MenuItem value={40}>40</MenuItem>
                  <MenuItem value={100}>100</MenuItem>
                  <MenuItem value={1000}>همه</MenuItem>
                </Select>
              </FormControl>
              {itemsPerPage !== 1000 && (
                <Pagination
                  count={totalPages}
                  page={currentPage}
                  variant="outlined"
                  onChange={(event, page) => setCurrentPage(page)}
                />
              )}
            </Grid>
          ) : (
            <Grid
              container
              mb={2}
              justifyContent="center"
              xs={12}
              alignItems="center"
              gap={2}
            >
              <FormControl sx={{ width: 80 }}>
                <InputLabel id="demo-controlled-open-select-label">
                  تعداد
                </InputLabel>
                <Select
                  size="small"
                  labelId="demo-controlled-open-select-label"
                  id="demo-controlled-open-select"
                  open={openS}
                  onClose={handleCloseS}
                  onOpen={handleOpenS}
                  value={perPage}
                  label="Age"
                  onChange={(e) => {
                    handlePerRowsChange(e.target.value);
                  }}
                >
                  <MenuItem value={10}>10</MenuItem>
                  <MenuItem value={20}>20</MenuItem>
                  <MenuItem value={40}>40</MenuItem>
                  <MenuItem value={100}>100</MenuItem>
                </Select>
              </FormControl>
              <Pagination
                count={Math.ceil(totalRows / perPage)}
                page={page}
                variant="outlined"
                onChange={(event, page) => handlePageChange(page)}
              />
              <Grid
                container
                justifyContent="center"
                alignItems="center"
                gap={1}
                sx={{ maxWidth: "65px" }}
              >
                <TextField
                  size="small"
                  type="search"
                  variant="standard"
                  placeholder="برو به..."
                  value={searchPageIndex}
                  onChange={(e) => setSearchPageIndex(e.target.value)}
                  onKeyDown={(e) => {
                    if (
                      e.key === "Enter" &&
                      parseInt(searchPageIndex) <=
                        Math.ceil(totalRows / perPage) &&
                      parseInt(searchPageIndex) > 0
                    ) {
                      handlePageChange(parseInt(searchPageIndex));
                    }
                  }}
                />
              </Grid>
            </Grid>
          )}
        </Grid>
      )}
    </>
  );
};

ResponsiveTable.propTypes = {
  columns: PropTypes.arrayOf(PropTypes.string).isRequired,
  data: PropTypes.arrayOf(PropTypes.arrayOf(PropTypes.any)).isRequired,
  title: PropTypes.string.isRequired,
  paginated: PropTypes.bool,
};

export default ResponsiveTable;
