import React, { useState } from "react";
import { MRT_TableInstance, MRT_Column } from "material-react-table";
import {
  IconButton,
  Popover,
  TextField,
  Box,
  Divider,
  Switch,
  Typography,
  Button,
} from "@mui/material";
import ShowHideColumns from "../../assets/TableIcons/ShowHideColumns";

interface Props<TData> {
  table: MRT_TableInstance<TData>;
}

export function ShowHideColumnsMenu<TData>({ table }: Props<TData>) {
  const [anchorEl, setAnchorEl] = useState<null | HTMLElement>(null);
  const [search, setSearch] = useState("");

  const handleOpen = (event: React.MouseEvent<HTMLElement>) =>
    setAnchorEl(event.currentTarget);

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

  const columnVisibility = table.getState().columnVisibility;

  const columnMatchesSearch = (col: MRT_Column<TData>, term: string): boolean => {
    if (!term) return true;
    const searchTerm = term.toLowerCase();
    const headerText = col.columnDef.header?.toString().toLowerCase() ?? "";
    if (headerText.includes(searchTerm)) return true;
    return (col.columns ?? []).some((child) =>
      columnMatchesSearch(child as MRT_Column<TData>, term)
    );
  };

  const toggleColumn = (colId: string, value: boolean) =>
    table.setColumnVisibility({ ...columnVisibility, [colId]: value });

  const toggleGroup = (group: MRT_Column<TData>, value: boolean) => {
    const updates: Record<string, boolean> = {};
    group.getLeafColumns().forEach((leaf) => (updates[leaf.id] = value));
    updates[group.id] = value;
    table.setColumnVisibility({ ...columnVisibility, ...updates });
  };

  const renderColumnGroup = (col: MRT_Column<TData>, level = 0) => {
    if (!columnMatchesSearch(col, search)) return null;

    const subCols = col.columns ?? [];
    const hasChildren = subCols.length > 0;

    if (hasChildren) {
      const groupVisible = col
        .getLeafColumns()
        .some((leaf) => columnVisibility[leaf.id] ?? true);

      return (
        <Box key={col.id} sx={{ mb: 1 }}>
          <Box
            sx={{
              display: "flex",
              alignItems: "center",
              justifyContent: "space-between",
              pl: level * 2,
            }}
          >
            <Typography variant="body2" sx={{ fontWeight: 600 }}>
              {col.columnDef.header?.toString() || "Group"}
            </Typography>
            <Switch
              size="small"
              checked={groupVisible}
              onChange={(e) => toggleGroup(col, e.target.checked)}
            />
          </Box>

          {subCols
            .filter((child) => {
              const childCol = child as MRT_Column<TData>;
              return (childCol.columns?.length ?? 0) > 0 || !!childCol.columnDef.header;
            })
            .map((child) => renderColumnGroup(child as MRT_Column<TData>, level + 1))}
        </Box>
      );
    }
    if (!col.columnDef.header) return null;

    return (
      <Box
        key={col.id}
        sx={{
          display: "flex",
          alignItems: "center",
          justifyContent: "space-between",
          pl: level * 2,
          py: 0.5,
        }}
      >
        <Typography variant="body2" sx={{ fontWeight: 500 }}>
          {col.columnDef.header?.toString()}
        </Typography>
        <Switch
          size="small"
          checked={columnVisibility[col.id] ?? true}
          onChange={(e) => toggleColumn(col.id, e.target.checked)}
        />
      </Box>
    );
  };
  const hideableLeafCols = table.getAllLeafColumns().filter((c) => c.getCanHide());
  const allLeafHidden = hideableLeafCols.every(
    (c) => (columnVisibility[c.id] ?? true) === false
  );
  const allLeafVisible = hideableLeafCols.every(
    (c) => (columnVisibility[c.id] ?? true) === true
  );

  return (
    <>
      <IconButton onClick={handleOpen} size="small">
        <ShowHideColumns />
      </IconButton>
      <Popover
        open={Boolean(anchorEl)}
        anchorEl={anchorEl}
        onClose={handleClose}
        anchorOrigin={{ vertical: "bottom", horizontal: "left" }}
      >
        <Box sx={{ p: 1.5, width: 260, maxHeight: 400, overflowY: "auto" }}>
          <TextField
            size="small"
            placeholder="Search columns..."
            fullWidth
            value={search}
            onChange={(e) => setSearch(e.target.value)}
            sx={{
              mb: 1,
              "& .MuiOutlinedInput-root": { borderRadius: "8px" },
            }}
          />
          <Box sx={{ display: "flex", justifyContent: "space-between", mb: 1 }}>
            <Button
              size="small"
              disabled={allLeafHidden}
              onClick={() =>
                table.setColumnVisibility(
                  Object.fromEntries(hideableLeafCols.map((col) => [col.id, false]))
                )
              }
            >
              HIDE ALL
            </Button>
            <Button
              size="small"
              disabled={allLeafVisible}
              onClick={() =>
                table.setColumnVisibility(
                  Object.fromEntries(hideableLeafCols.map((col) => [col.id, true]))
                )
              }
            >
              SHOW ALL
            </Button>
          </Box>
          <Divider sx={{ mb: 1 }} />
          {table
            .getAllColumns()
            .filter((col) => col.getCanHide())
            .map((col) => renderColumnGroup(col))}
        </Box>
      </Popover>
    </>
  );
}
