import { ExpandLess, ExpandMore } from "@mui/icons-material";
import HomeIcon from "@mui/icons-material/Home";
import PeopleIcon from "@mui/icons-material/People";
import SettingsIcon from "@mui/icons-material/Settings";
import { Collapse } from "@mui/material";
import Box from "@mui/material/Box";
import Divider from "@mui/material/Divider";
import Drawer, { DrawerProps } from "@mui/material/Drawer";
import List from "@mui/material/List";
import ListItem from "@mui/material/ListItem";
import ListItemButton from "@mui/material/ListItemButton";
import ListItemIcon from "@mui/material/ListItemIcon";
import ListItemText from "@mui/material/ListItemText";
import { PageID } from "codes/page";
import useAuth from "hooks/useAuth";
import useNavigateCustom from "hooks/useNavigateCustom";
import usePage from "hooks/usePage";
import * as React from "react";
import { getPath } from "routes/path";

type Group = {
  label: string;
  children: SubGroup[];
};

type SubGroup = {
  label: string;
  icon: React.ReactNode;
  children?: Child[];

  // 子要素を持たない場合は設定
  id?: PageID;
};

type Child = {
  label: string;
  id: PageID;
};

const categories: Group[] = [
  {
    label: "管理",
    children: [
      {
        label: "契約",
        icon: <PeopleIcon />,
        children: [
          {
            id: PageID.DASHBOARD_CONTRACT_LIST,
            label: "一覧",
          },
          {
            id: PageID.DASHBOARD_CONTRACT_DETAIL,
            label: "詳細",
          },
        ],
      },
      {
        label: "領収証発行依頼",
        icon: <PeopleIcon />,
        children: [
          {
            id: PageID.DASHBOARD_RECEIPT_ISSUING_ORDER_LIST_CUSTOM_HELLO_TECHNO,
            label: "一覧",
          },
          {
            id: PageID.DASHBOARD_RECEIPT_ISSUING_ORDER_CREATE_CUSTOM_HELLO_TECHNO,
            label: "新規",
          },
        ],
      },
    ],
  },
  {
    label: "アカウント",
    children: [
      { label: "ログアウト", icon: <SettingsIcon />, id: PageID.LOGOUT },
    ],
  },
];

const item = {
  py: "2px",
  px: 3,
  color: "rgba(255, 255, 255, 0.7)",
  "&:hover, &:focus": {
    bgcolor: "rgba(255, 255, 255, 0.08)",
  },
};

const itemCategory = {
  boxShadow: "0 -1px 0 rgb(255,255,255,0.1) inset",
  py: 1.5,
  px: 3,
};

export default function Navigator(props: DrawerProps) {
  const { ...other } = props;

  return (
    <Drawer variant="permanent" {...other}>
      <List disablePadding>
        <ListItem
          sx={{ ...item, ...itemCategory, fontSize: 22, color: "#fff" }}
        >
          SateReceipt
        </ListItem>
        <ListItem sx={{ ...item, ...itemCategory }}>
          <ListItemIcon>
            <HomeIcon />
          </ListItemIcon>
          <ListItemText>Project Overview</ListItemText>
        </ListItem>

        {categories.map((group, index) => {
          return <Group {...group} key={index} />;
        })}
      </List>
    </Drawer>
  );
}

function Group(group: Group) {
  const { label, children } = group;

  const elements = children.map((ele, index) => (
    <SubGroup {...ele} key={index} />
  ));

  if (elements.length === 0) return null;

  return (
    <Box sx={{ bgcolor: "#101F33" }}>
      <ListItem sx={{ py: 2, px: 3 }}>
        <ListItemText sx={{ color: "#fff" }}>{label}</ListItemText>
      </ListItem>
      {elements}
      <Divider sx={{ mt: 2 }} />
    </Box>
  );
}

function SubGroup({ icon, label, id, children }: SubGroup) {
  const { pageId } = usePage();
  const { navigateWhenChanged } = useNavigateCustom();

  const { elements, shouldOpen } = useContents(children ?? []);

  const [open, setOpen] = React.useState(false);

  React.useEffect(() => {
    setOpen(shouldOpen);
  }, [shouldOpen]);

  // 子要素ありの場合
  if (elements && elements.length !== 0) {
    const handleClick = () => {
      setOpen(!open);
    };
    return (
      <>
        <ListItemButton onClick={handleClick} sx={item} selected={false}>
          <ListItemIcon>{icon}</ListItemIcon>
          <ListItemText>{label}</ListItemText>
          {open ? <ExpandLess /> : <ExpandMore />}
        </ListItemButton>
        <Collapse in={open} timeout="auto" unmountOnExit>
          <List component="div" disablePadding>
            {elements}
          </List>
        </Collapse>
      </>
    );
  }
  // 子要素なしの場合
  if (id !== undefined) {
    const handleClick = () => {
      if (id) {
        const path = getPath(id);
        navigateWhenChanged(path);
      }
    };
    const selected = id === pageId;
    return (
      <ListItemButton onClick={handleClick} selected={selected} sx={item}>
        <ListItemIcon>{icon}</ListItemIcon>
        <ListItemText>{label}</ListItemText>
      </ListItemButton>
    );
  }
  return null;
}

function useContents(children: Child[]) {
  const { pageId } = usePage();
  const { navigateWhenChanged } = useNavigateCustom();
  const { canAccess, initialized } = useAuth();

  const [shouldOpen, setShouldOpen] = React.useState(false);

  const elements = React.useMemo(() => {
    setShouldOpen(false);
    return children
      .filter(({ id }) => canAccess(id))
      .map(({ label, id }, index) => {
        const selected = id === pageId;
        if (selected) {
          setShouldOpen(true);
        }

        const handleClick = () => {
          const path = getPath(id);
          navigateWhenChanged(path);
        };

        return (
          <ListItemButton
            selected={selected}
            sx={{ ...item, pl: 4 }}
            key={index}
            onClick={handleClick}
          >
            <ListItemText primary={label} />
          </ListItemButton>
        );
      });
  }, [pageId, initialized]);

  return {
    elements,
    shouldOpen,
  };
}
