import React, { useEffect, useState } from "react";
import { TextField, Button, Paper, TablePagination, IconButton, Modal, Box } from "@mui/material";
import { FirstPage, LastPage, Close } from "@mui/icons-material";
import PropTypes from "prop-types";
import { Link } from "react-router-dom";
import pkg from 'react-lazy-load-image-component';
import { DataGrid, useGridApiRef } from "@mui/x-data-grid";
import { nanoid } from 'nanoid';
import secondToTimeConverter from "../utils/secondToTime.js";
import formatDateToUTC from "../utils/dateFormat.js";
import ActionBtn from "./ActionBtn.js";
import PopupForAuditLogs from "./PopupForAuditLogs.js";
import ActionForPermission from "../pages/ActionForPermission.js";
import { useUser } from "../context/UserContext.js"
import "./LineChart.css";
import { permissionTypes } from "../constants/userConstants.js";

const { LazyLoadImage } = pkg;

function CommonTable(props) {
  const {
    data,
    columns,
    defaultSortColumn,
    onChange,
    filters,
    getUsersTable,
    disableSorting,
    title,
    isAutoHeight,
    containerHeight,
    handleModifyPermissions,
  } = props;
  const apiRef = useGridApiRef();
  const [sortedData, setSortedData] = useState([]);
  const [order, setOrder] = useState("ASC");
  const [orderBy, setOrderBy] = useState(defaultSortColumn || "");
  const [page, setPage] = useState(1);
  const [rowsPerPage, setRowsPerPage] = useState(50);
  const [totalRecords, setTotalRecords] = useState(0);
  const [filter, setFilter] = useState({ ...filters });
  const [jumpPage, setJumpPage] = useState("");
  const [isDisable, setIsDisable] = useState(true);
  const [selectedImage, setSelectedImage] = useState(null);
  const [openImage, setOpenImage] = useState(false);
  const { permissions } = useUser();
  const isProfileAccess = permissions?.some((permission) => permission.Path === "/user-profile" && permission.Permission_Id !== `${permissionTypes[2].key}`);
  const [popupVisible, setPopupVisible] = useState(false);
  const [selectedRow, setSelectedRow] = useState(null);

  useEffect(() => {
    if (title === "Dashboard") {
      setSortedData(data);
      setPage(0);
      setTotalRecords(0);
    } else {
      setSortedData(data?.Records);
      setPage(data?.CurrentPage);
      setTotalRecords(data?.TotalRecords);
      setFilter({ ...filters });
    }
  }, [
    data?.CurrentPage,
    data?.PageSize,
    data?.Records,
    data?.TotalRecords,
    filters,
    data,
    title,
  ]);

  useEffect(() => {
    setJumpPage("");
  }, [page]);

  const handleRequestSort = async (property) => {
    if (!property) {
      setOrder(null);
      setOrderBy(null);
      const updatedFilter = {
        ...filter,
        SortOrder: null,
        SortColumn: null,
      };
      setFilter(updatedFilter)
      onChange(updatedFilter);
      return
    }
    const newOrderBy = property === "EmpCode" || property === "emp_code" ? "EmployeeName" : property
    const newOrder = orderBy === property && order === "ASC" ? "DESC" : "ASC";
    setOrder(newOrder);
    setOrderBy(property);
    let updatedFilter = {
      ...filter,
      SortOrder: newOrder,
      SortColumn: newOrderBy,
    };
    if (props.component === "ManageUser") {
      updatedFilter = {
        ...filter,
        Filter: {
          SortColumn: newOrderBy,
          SortDirection: newOrder,
          FilterColumn: null,
          FilterValue: null,
        },
      };
      setFilter(updatedFilter);
      onChange(updatedFilter);
      return;
    }
    setFilter(updatedFilter);
    onChange(updatedFilter);
  };


  useEffect(() => {
    apiRef.current?.scrollToIndexes({ rowIndex: 0 })
  }, [page])

  const getStatusClassName = (value) => {
    switch (value) {
      case "Idle":
        return "idle";
      case "Active":
        return "active";
      case "Sleep":
        return "sleep";
      case "Logged In":
        return "Login";
      case "Logged Out":
        return "Logout";
      default:
        return "default";
    }
  };

  const handleChangePage = (_event, newPage) => {
    const pageValue = Number.parseInt(newPage) + 1;
    setPage(Number.parseInt(newPage) + 1);
    const updatedFilter = { ...filter, PageNumber: pageValue, PageSize: filter.PageSize };
    setFilter(updatedFilter);
    onChange(updatedFilter);
    if (jumpPage * rowsPerPage < totalRecords) {
      setIsDisable(true);
    } else {
      setIsDisable(false);
    }
  };

  const handleChangeRowsPerPage = (event) => {
    const rowsPerPage = Number.parseInt(event.target.value, 10);
    setRowsPerPage(rowsPerPage);
    setPage(1);
    const updatedFilter = { ...filter, PageNumber: 1, PageSize: rowsPerPage };
    setFilter(updatedFilter);
    onChange(updatedFilter);
  };

  const handleFirstPageButtonClick = () => {
    handleChangePage(null, 0);
  };

  const handleLastPageButtonClick = () => {
    handleChangePage(null, Math.ceil(totalRecords / rowsPerPage) - 1);
  };

  const handleJumpToPage = () => {
    const newPage = Number(jumpPage) - 1;

    if (
      newPage >= 0 &&
      newPage < Math.ceil(totalRecords / rowsPerPage) &&
      newPage + 1 !== page
    ) {
      handleChangePage(null, newPage);
    }
  };
  const handleInputChange = (e) => {
    const {value} = e.target;
    if (/^\d*$/.test(value)) {
      // Only allow numbers
      setJumpPage(value);
      if (
        Number(value) > totalPages ||
        Number(value) < 1 ||
        Number(value) === page
      ) {
        setIsDisable(true);
      } else {
        setIsDisable(false);
      }
    } else {
      setJumpPage("");
      setIsDisable(true);
    }
  };

  const handleOpenImage = (imageUrl) => {
    setSelectedImage(imageUrl);
    setOpenImage(true);
  };

  const handleCloseImage = () => {
    setOpenImage(false);
    setSelectedImage(null);
  };

  const getScreenShot = (row, field) => (
    <LazyLoadImage
      src={row[field]}
      alt="Image"
      effect="blur"
      height="50"
      width="75"
      style={{ cursor: "pointer", borderRadius: "4px", padding: "2px" }}
      onClick={() => handleOpenImage(row[field])}
    />
  );

  // Helper functions
  const renderStatusBox = (value) => (
    <span className={`box ${getStatusClassName(value)}`}>{value}</span>
  );

  const renderPopupData = (row, from) => (
    <button
      className="app-name-popup"
      style={{ cursor: "pointer" }}
      tabIndex={0}
      onClick={() => props.togglePopup(row.emp_code, row.application_name)}
      onKeyDown={(e) => {
        if (e.key === "Enter" || e.key === " ") {
          props.togglePopup(row.emp_code, row.application_name);
        }
      }}
    >
      {from === "name" ? row.application_name : row.application_count}
    </button>
  );

  const renderLink = (row, field, empCode) => (
    <Link
      className="link"
      style={{ color: "rgba(0, 0, 0, 0.87)" }}
      title={row[field]}
      to={`/user-profile/${empCode}`}
    >
      {row.EmployeeName || row[field]}
    </Link>
  );

  const getEmpCode = (row) => row.emp_code || row.EmpCode

  const getApplicationName = (row) => row.application_count > 1 ? (
      renderPopupData(row, 'name')
    ) : (
      <span style={{ cursor: "pointer" }}>{row.application_name}</span>
    )

  const getApplicationCount = (row) => row.application_count > 1 ? (
      renderPopupData(row, 'count')
    ) : (
      <span style={{ cursor: "pointer" }}>{row.application_count}</span>
    )

  const getLoginDate = (row, field) => typeof row[field] === "string"
      ? row[field].split("T")[0]
      : row[field]

 // =======================
// Main Function
// =======================

const getCellValue = (column, row) => {
  const { field, type, headerName } = column;
  const empCode = getEmpCode(row);

  if (isImageColumn(headerName)) {
    return getScreenShot(row, field);
  }

  if (isActivityStatusColumn(field)) {
    return renderStatusBox(row[field]);
  }

  if (isManageUserEmail(field)) {
    return renderEmailCell(row, field);
  }

  const typedValue = handleColumnType(type, row, field);
  if (typedValue !== undefined) {
    return typedValue;
  }

  return handleFieldSpecificCases(field, headerName, row, empCode);
};



// =======================
// Condition Helpers
// =======================

const isImageColumn = (headerName) => headerName === "Image";

const isActivityStatusColumn = (field) =>
  props.component === "Activity" && field === "SystemStatus";

const isManageUserEmail = (field) =>
  props.component === "ManageUser" && field === "user_email";



// =======================
// Type Handler
// =======================

const handleColumnType = (type, row, field) => {
  if (type === Date) return formatDateToUTC(row[field]);
  if (type === Number) return secondToTimeConverter(row[field]);
  if (type === Boolean) return String(row[field]);
  return undefined;
};



// =======================
// Field Switch Handler
// =======================

const handleFieldSpecificCases = (field, headerName, row, empCode) => {
  switch (field) {
    case "EmpCode":
    case "emp_code":
    case "EmployeeName":
      return renderEmployeeCell(headerName, row, empCode);

    case "operation_type":
      return renderOperationType(row);

    case "Action":
      return renderAction(row);

    case "Permission":
      return renderPermission(row);

    case "application_name":
      return getApplicationName(row);

    case "application_count":
      return getApplicationCount(row);

    case "loginDate":
      return getLoginDate(row, field);

    default:
      return row[field];
  }
};



// =======================
// Employee Cell Renderer
// =======================

const renderEmployeeCell = (headerName, row, empCode) => {
  const employeeName = row["EmployeeName"] || row["emp_name"] || "Unknown";
  const employeeId = empCode || "N/A";
  const displayText = `${employeeName} (${employeeId})`;

  if (
    headerName === "Employee Name & ID" ||
    headerName === "Employee & ID"
  ) {
    return renderEmployeeLink(displayText, empCode);
  }

  if (headerName === "Employee ID") {
    return renderEmployeeLink(employeeId, empCode);
  }

  if (!isProfileAccess) {
    return <span>{employeeName}</span>;
  }

  return renderLink(row, "EmployeeName", empCode);
};



const renderEmployeeLink = (text, empCode) => {
  if (!isProfileAccess) {
    return <span title={text}>{text}</span>;
  }

  return (
    <Link
      className="link"
      style={{ color: "rgba(0, 0, 0, 0.87)" }}
      title={text}
      to={`/user-profile/${empCode}`}
    >
      {text}
    </Link>
  );
};



// =======================
// Email Cell
// =======================

const renderEmailCell = (row, field) => (
  <span
    title={row[field]}
    style={{
      maxWidth: "100px",
      whiteSpace: "nowrap",
      overflow: "hidden",
      textOverflow: "ellipsis",
      cursor: "pointer",
    }}
  >
    {row[field]}
  </span>
);



// =======================
// Operation Type
// =======================

const renderOperationType = (row) => {
  const value = row?.operation_type;

  if (!row?.new_data && !row?.old_data) {
    return <span>{value}</span>;
  }

  return (
    <button
      style={{
        cursor: "pointer",
        color: "blue",
        textDecoration: "underline",
        background: "none",
        border: "none",
      }}
      onClick={() => {
        setSelectedRow(row);
        setPopupVisible(true);
      }}
    >
      {value}
    </button>
  );
};



// =======================
// Action Renderer
// =======================

const renderAction = (row) => (
  <ActionBtn
    getUsersTable={getUsersTable}
    userData={row}
    getUserData={onChange}
  />
);



// =======================
// Permission Renderer
// =======================

const renderPermission = (row) => (
  <ActionForPermission
    getUsersTable={getUsersTable}
    userData={row}
    getUserData={onChange}
    handleModifyPermissions={handleModifyPermissions}
  />
);

  const totalPages = Math.ceil(totalRecords / rowsPerPage);

  const rowsWithUniqueIds = sortedData?.map((row, index) => ({
    ...row,
    id: nanoid(),
  }));

  const updatedColumns = [
    {
      field: "sno",
      headerName: "S.No",
      flex: 1,
      sortable: false,
      filterable: false,
      renderCell: (params) => {
        const index = params.api.getSortedRowIds().indexOf(params?.id);
        if (title === "Dashboard") {
          return index + 1
        }
        return index > -1 ? (page - 1) * rowsPerPage + index + 1 : "-";
      },
    },
    ...columns.map((column) => ({
      ...column,
      renderCell: (params) => getCellValue(column, params.row),
    })),
  ];

  return (


    <Paper
      className="table-container-outer"
      sx={{ height: containerHeight || (isAutoHeight ? "auto" : "calc(100vh - 200px)") }}
    >
      <DataGrid
        apiRef={apiRef}
        data-testid="common-table"
        className="common-data-table"
        columns={(updatedColumns || []).filter(col => !col.disableColumnSelector)}
        rows={rowsWithUniqueIds || []}
        getRowId={(row) => row.id}
        disableColumnSorting={disableSorting}
        localeText={{ noRowsLabel: "No data available" }}
        sortingMode="server"
        sortModel={orderBy ? [{ field: orderBy, sort: order?.toLowerCase() }] : []}
        onSortModelChange={(model) => {
          if (model?.length > 0) {
            handleRequestSort(model[0].field);
          } else {
            handleRequestSort(null);
          }
        }}
        disableColumnMenu // Removes the extra filter/sort menu if not needed
        hideFooter
        sx={{
          "& .MuiDataGrid-columnHeaders": {
            position: "sticky",
            top: 0,
            backgroundColor: "#fff",
            fontWeight: "bold",
            zIndex: 1000,
          },
          "& .MuiDataGrid-columnHeaderTitle": {
            fontWeight: "bold",
          },
          "& .MuiDataGrid-virtualScroller": {
            overflow: "auto",
          },
          // Remove outline from cells
          '.MuiDataGrid-cell:focus, .MuiDataGrid-cell:focus-within': {
            outline: 'none',
          },
          // Remove outline from column headers
          '.MuiDataGrid-columnHeader:focus, .MuiDataGrid-columnHeader:focus-within': {
            outline: 'none',
          },
        }}
      />
      {/* Custom Pagination Controls */}
      {sortedData && sortedData?.length > 0 && (
        <div
          className="pagination-controls pagination"
          style={{
            display: title === "Dashboard" ? "none" : "flex",
            justifyContent: "flex-end",
            marginTop: 10,
          }}
        >
          <IconButton
            onClick={handleFirstPageButtonClick}
            disabled={page === 1}
          >
            <FirstPage />
          </IconButton>
          <TablePagination
            className="tablePagination"
            component="div"
            count={totalRecords}
            page={page - 1} // Adjust to zero-based index
            onPageChange={handleChangePage}
            rowsPerPage={rowsPerPage}
            onRowsPerPageChange={handleChangeRowsPerPage}
            labelDisplayedRows={({ from, to, count }) =>
              `Showing ${from}-${to} of ${count} entries`
            }
          />
          <IconButton
            onClick={handleLastPageButtonClick}
            disabled={page === totalPages}
          >
            <LastPage />
          </IconButton>

          <div
            style={{ display: "flex", alignItems: "center", marginLeft: 16 }}
          >
            <TextField
              className="inputForPagination"
              value={jumpPage}
              onChange={handleInputChange}
              onKeyDown={(e) => e.key === "Enter" && handleJumpToPage()}
              variant="outlined"
              size="small"
              placeholder="Page No"
              style={{ width: 80, marginRight: 8 }}
              inputProps={{ style: { textAlign: "center", padding: "4px 1px", background: "#fff" } }}
            />
            <Button
              variant="contained"
              size="small"
              color="primary"
              onClick={handleJumpToPage}
              style={{ height: "30px", minWidth: "30px", paddingTop: "3px" }}
              disabled={isDisable}
            >
              Go
            </Button>
            <div style={{ marginLeft: 16, fontWeight: "400", fontSize: "14px" }}>
              Page {page} of {totalPages}
            </div>
          </div>
        </div>
      )}

      {/* Image Modal */}
      <Modal open={openImage} onClose={handleCloseImage}>
        <Box
          className="screenshot-modal"
          sx={{
            position: "absolute",
            top: "50%",
            left: "50%",
            transform: "translate(-50%, -50%)",
            width: "80%",
            bgcolor: "background.paper",
            boxShadow: 24,
          }}
        >
          <IconButton
            onClick={handleCloseImage}
            sx={{
              position: "absolute",
              top: 8,
              right: 8,
              color: "#000",
            }}
          >
            <Close className="close-screenshot-button" />
          </IconButton>
          {selectedImage && (
            <img
              src={selectedImage}
              alt="Selected"
              style={{ width: "100%", maxHeight: "80vh", objectFit: "fill" }}
            />
          )}
        </Box>
      </Modal>
      {popupVisible && selectedRow && (
        <PopupForAuditLogs
          togglePopup={() => setPopupVisible(false)}
          summaryFilter={selectedRow}
          searchText={filters.SearchText}
          selectedRange={props.selectedRange}
          data={selectedRow}
        />
      )}
    </Paper>


  );
}

CommonTable.propTypes = {
  data: PropTypes.oneOfType([PropTypes.array, PropTypes.object]),
  columns: PropTypes.array.isRequired,
  component: PropTypes.string,
  defaultSortColumn: PropTypes.string,
  onChange: PropTypes.func,
  filters: PropTypes.object.isRequired,
  getUsersTable: PropTypes.func,
  disableSorting: PropTypes.bool,
  title: PropTypes.string,
  isAutoHeight: PropTypes.bool,
  containerHeight: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
  handleModifyPermissions: PropTypes.func,
  togglePopup: PropTypes.func,
  selectedRange: PropTypes.array,
};

export default CommonTable;
