import {
  Avatar,
  Box,
  Button,
  Chip,
  darken,
  DialogActions,
  DialogContent,
  DialogTitle,
  Divider,
  Grid2,
  IconButton,
  List,
  ListItem,
  ListItemAvatar,
  ListItemButton,
  ListItemIcon,
  ListItemText,
  ListSubheader,
  PaletteColor,
  Theme,
} from "@mui/material";
import ResponsiveDialog from "common/ResponsiveDialog";
import SearchSelect, { Option } from "common/SearchSelect";
import { useMobile, useSnackbar, useUserAPI } from "hooks";
import { User } from "models";
import PageContainer from "pages/PageContainer";
// import { ListUsersResponse } from "providers/pond/userAPI";
import { useEffect, useState } from "react";
import { makeStyles } from "@mui/styles";
import { getSecondaryColour, getSignatureAccentColour } from "services/whiteLabel";
import { Add, Face, Remove } from "@mui/icons-material";
import ResponsiveTable, { Column } from "common/ResponsiveTable";

const useStyles = makeStyles((theme: Theme) => {
  // const isMobile = useMobile()
  return ({
  gutter: {
    backgroundColor: darken(theme.palette.background.paper, 0.03),
    border: "none"
  },
  dataTable: {
    backgroundColor: theme.palette.background.paper
  },
  tableContainer: {
    margin: theme.spacing(1),
    [theme.breakpoints.up("sm")]: {
      margin: theme.spacing(2)
    },
    width: "auto"
  },
  title: {
    padding: theme.spacing(1)
  },
  titleContainer: {
    border: "none"
  },
  chipContainer: {
    maxWidth: "100%",
    maxHeight: "100%",
    justifyContent: "flex-start",
    alignItems: "flex-start"
  },
  deleteIcon: {
    color: "var(--status-alert)"
  },
  userAvatar: {
    color: "#fff",
    backgroundColor: getSecondaryColour()["700" as keyof PaletteColor],
    [theme.breakpoints.down("xs")]: {
      width: "32px",
      height: "32px"
    }
  },
  listItemButton: {
    '&:hover': {
      color: getSignatureAccentColour()
    }
  },
  avatarContainer: {
    textAlign: "center",
    justifyContent: "center",
  },
  addIcon: {
    color: "var(--status-ok)"
  }})},
);

export default function Users() {
  const classes = useStyles();
  const isMobile = useMobile();
  const userAPI = useUserAPI();
  // let tableRef: any = React.createRef();
  const { error, success } = useSnackbar();
  const [pageSize, setPageSize] = useState(5);
  const [isLoading, setIsLoading] = useState(false);
  const [page, setPage] = useState(0);
  const [total, setTotal] = useState(0);
  const [showAllowAction, setShowAllowAction] = useState(false);
  const [selectedAction, setSelectedAction] = useState<Option | undefined>();
  const [showEnableFeature, setShowEnableFeature] = useState(false);
  const [selectedFeature, setSelectedFeature] = useState<Option | undefined>();
  const [selectedUser, setSelectedUser] = useState(User.create());
  const [searchText, setSearchText] = useState("");
  const actions = [
    "provision",
    "upload-firmware",
    "remove-devices",
    "copy-token",
    "recluse",
    "pause-data"
  ].sort();
  const features = [
    "admin",
    "beta",
    "billing",
    "security",
    "dev-channel",
    "docs",
    "sleep",
    "support",
    "tasks",
    "teams",
    "maps",
    "json",
    "john-deere",
    "grain-composition",
    "developer",
    "marketplace",
    "installer",
    "cnhi",
    "libracart"
  ].sort();

  const [rows, setRows] = useState<User[]>([])

  const loadUsers = () => {
    setIsLoading(true)
    userAPI.listUsers(pageSize, page*pageSize, "desc", "name", undefined, searchText).then(resp => {
      let r: User[] = []
      resp.users.forEach((user, _index) => {
        r.push(user)
      })
      setRows(r)
      setTotal(resp.total)
    }).then(() => {
      setIsLoading(false);
    })
  }

  useEffect(() => {
    loadUsers();
  }, [page, pageSize, searchText]); // Trigger fetching data when page or pageSize changes

  const handleRowsPerPageChange = (event: any) => {
    const newRowsPerPage = parseInt(event.target.value, 10); // Get selected value
    setPageSize(newRowsPerPage);
    setPage(0); // Reset to the first page
  };

  const allow = () => {
    const action = selectedAction ? selectedAction.label : "";
    if (selectedUser.id() === "" || action === "") return;
    if (!selectedUser.settings.actions.includes(action)) {
      selectedUser.settings.actions.push(action);
    }
    userAPI
      .updateUser(selectedUser.id(), selectedUser.protobuf())
      .then(() => {
        success("Allowed " + selectedUser.name() + " to " + action);
        setShowAllowAction(false);
        setSelectedAction({} as Option);
      })
      .catch(() => error("Failed to allow " + selectedUser.name() + " to " + action));
  };

  const enable = () => {
    const feature = selectedFeature ? selectedFeature.label : "";
    if (selectedUser.id() === "" || feature === "") return;
    if (!selectedUser.settings.features.includes(feature)) {
      selectedUser.settings.features.push(feature);
    }
    userAPI
      .updateUser(selectedUser.id(), selectedUser.protobuf())
      .then(() => {
        success("Enabled " + feature + " for " + selectedUser.name());
        setShowEnableFeature(false);
        setSelectedFeature({} as Option);
      })
      .catch(() => error("Failed to enable " + feature + " for " + selectedUser.name()));
  };

  const remove = (user: User, type: "action" | "feature", key: string) => {
    if (user.id() === "" || key === "") return;
    if (type === "action") {
      user.settings.actions = user.settings.actions.filter(v => v !== key);
    }
    if (type === "feature") {
      user.settings.features = user.settings.features.filter(v => v !== key);
    }
    userAPI
      .updateUser(user.id(), user.protobuf())
      .then(() => {
        if (type === "action") {
          success("Disallowed " + user.name() + " from " + key);
          setSelectedAction({} as Option);
        }
        if (type === "feature") {
          success("Disabled " + key + " for " + user.name());
          setSelectedFeature({} as Option);
        }
      })
      .catch(() => {
        if (type === "action") {
          error("Failed to disallow " + user.name() + " from " + key);
        }
        if (type === "feature") {
          error("Failed to disable " + key + " for " + user.name());
        }
      });
  };

  const flagChip = (flag: any) => {
    return (
      <Grid2 key={flag} size={{xs: 12}} >
        <Chip size="small" label={flag} color={"default"} />
      </Grid2>
    );
  };

  const columns = (): Column<User>[] => {
    return [
      {
        title: "Profile",
        render: user => {
          const avatarURL = user.settings.avatar;
          const avatar = avatarURL ? (
            <Avatar alt={user.name()} src={avatarURL} />
          ) : (
            <Avatar alt={user.name()}>
              <Face />
            </Avatar>
          );
          return (
            <ListItem sx={{ padding: 0 }}>
              <ListItemAvatar>{avatar}</ListItemAvatar>
              <ListItemText primary={user.name()} secondary={user.settings.email} />
            </ListItem>
          );
        }
      },
      {
        title: "Actions",
        cellStyle: { verticalAlign: "top" },
        render: user => {
          const actions = user.settings.actions;
          return (
            <Grid2 container spacing={1} className={classes.chipContainer} padding={1}>
              {actions.slice(0, 2).map(action => flagChip(action))}
              {actions.length > 3 && flagChip("+" + (actions.length - 3) + " more")}
            </Grid2>
          );
        }
      },
      {
        title: "Features",
        cellStyle: { verticalAlign: "top" },
        render: user => {
          const features = user.settings.features;
          return (
            <Grid2 container spacing={1} className={classes.chipContainer} padding={1}>
              {features.slice(0, 2).map(feature => flagChip(feature))}
              {features.length > 3 && flagChip("+" + (features.length - 3) + " more")}
            </Grid2>
          );
        }
      }
    ];
  };

  const details = (user: User) => {
    const item = (text: string, type: "action" | "feature") => (
      <ListItem key={text}>
        <ListItemIcon>
          <IconButton
            onClick={() => {
              setSelectedUser(user);
              remove(user, type, text);
            }}>
            <Remove className={classes.deleteIcon} />
          </IconButton>
        </ListItemIcon>
        <ListItemText>{text}</ListItemText>
      </ListItem>
    );
    const actions = user.settings.actions;
    const features = user.settings.features;
    return (
      <List disablePadding dense>
        <ListSubheader className={classes.gutter}>Actions</ListSubheader>
        {actions.map(action => item(action, "action"))}
        <ListItemButton
          onClick={() => {
            setSelectedUser(user);
            setShowAllowAction(true);
          }}>
          <ListItemIcon>
            <IconButton>
              <Add className={classes.addIcon} />
            </IconButton>
          </ListItemIcon>
          <ListItemText>Allow an action</ListItemText>
        </ListItemButton>
        <Divider />
        <ListSubheader className={classes.gutter}>Features</ListSubheader>
        {features.map(feature => item(feature, "feature"))}
        <ListItemButton
          onClick={() => {
            setSelectedUser(user);
            setShowEnableFeature(true);
          }}>
          <ListItemIcon>
            <IconButton>
              <Add className={classes.addIcon} />
            </IconButton>
          </ListItemIcon>
          <ListItemText>Enable a feature</ListItemText>
        </ListItemButton>
      </List>
    );
  };

  const renderMobile = (user: User) => {
    const avatarURL = user.settings.avatar;
    const avatar = avatarURL ? (
      <Avatar alt={user.name()} src={avatarURL} />
    ) : (
      <Avatar alt={user.name()}>
        <Face />
      </Avatar>
    );
    return (
      <Box sx={{padding: 1}}>
        <ListItem>
          <ListItemAvatar>{avatar}</ListItemAvatar>
          <ListItemText primary={user.name()} secondary={user.settings.email} />
        </ListItem>
      </Box>
    )
  }

  return (
    <PageContainer spacing={isMobile ? 0 : 2}>
      <ResponsiveTable<User> 
        title="Users"
        rows={rows}
        columns={columns}
        total={total}
        page={page}
        pageSize={pageSize}
        setPage={setPage}
        handleRowsPerPageChange={handleRowsPerPageChange}
        setSearchText={setSearchText}
        isLoading={isLoading}
        renderGutter={details}
        renderMobile={renderMobile}
        // multiGutter
      />
      <ResponsiveDialog
        maxWidth="sm"
        fullWidth
        open={showAllowAction}
        onClose={() => setShowAllowAction(false)}
        aria-labelledby="allow-action">
        <DialogTitle id="allow-action-title">Allow an action</DialogTitle>
        <DialogContent>
          <SearchSelect
            label="Select an action to allow"
            selected={selectedAction}
            options={actions
              .filter(a => !selectedUser.settings.actions.includes(a))
              .map(a => {
                return { value: a, label: a };
              })}
            changeSelection={(option: Option | null) =>
              setSelectedAction(option ? option : undefined)
            }
          />
        </DialogContent>
        <DialogActions>
          <Button color="primary" onClick={() => setShowAllowAction(false)}>
            Close
          </Button>
          <Button
            color="primary"
            disabled={
              !selectedAction || !actions.includes(selectedAction ? selectedAction.label : "")
            }
            onClick={allow}>
            Allow
          </Button>
        </DialogActions>
      </ResponsiveDialog>
      <ResponsiveDialog
        maxWidth="sm"
        fullWidth
        open={showEnableFeature}
        onClose={() => setShowEnableFeature(false)}
        aria-labelledby="enable-feature">
        <DialogTitle id="enable-feature-title">Enable a feature</DialogTitle>
        <DialogContent>
          <SearchSelect
            label="Select a feature to enable"
            selected={selectedFeature}
            options={features
              .filter(a => !selectedUser.settings.features.includes(a))
              .map(a => {
                return { value: a, label: a };
              })}
            changeSelection={(option: Option | null) =>
              setSelectedFeature(option ? option : undefined)
            }
          />
        </DialogContent>
        <DialogActions>
          <Button color="primary" onClick={() => setShowEnableFeature(false)}>
            Close
          </Button>
          <Button
            color="primary"
            disabled={
              !selectedFeature || !features.includes(selectedFeature ? selectedFeature.label : "")
            }
            onClick={enable}>
            Enable
          </Button>
        </DialogActions>
      </ResponsiveDialog>
    </PageContainer>
  );
}
