import { Avatar } from '@/components/@extended/Avatar';
import { useThemeConfig } from '@/components/Layout/ThemeProvider';
import { useSetActiveItem, useSyncWithLocation } from '@/components/ra-forms/LongForm/Provider';
import { useChildren, useIsActive, useNavigateForm } from '@/components/ra-forms/LongForm/hooks';
import { IItem } from '@/components/ra-forms/LongForm/types';
import { getLevel } from '@/components/ra-forms/LongForm/utils';
import { ExpandLess, ExpandMore } from '@mui/icons-material';
import {
  Badge,
  Card,
  Collapse,
  List,
  ListItem,
  ListItemAvatar,
  ListItemButton,
  ListItemIcon,
  ListItemProps,
  ListItemText
} from '@mui/material';
import _ from 'lodash';
import { useTranslate } from 'ra-core';
import { useCallback, useEffect, useMemo, useState } from 'react';

type IBaseNavMenuItemProps = React.PropsWithChildren<{
  id: string;
  onClick?: React.MouseEventHandler<HTMLDivElement>;
}>;
type INavMenuItemProps = IItem & ListItemProps & IBaseNavMenuItemProps;

function NavMenu() {
  const items = useChildren();

  return (
    <Card variant="outlined">
      <List
        sx={{
          '& .MuiListItemButton-root.Mui-selected': {
            borderColor: 'palette.primary.main',
            borderRightStyle: 'solid',
            borderRightWidth: 2
          },
          '& .MuiListItemAvatar-root': {
            minWidth: 24
          }
        }}
      >
        {_.map(items, (item, index) => {
          return <NavMenuItem key={index} {...item} />;
        })}
      </List>
    </Card>
  );
}

function NavMenuItem(props: INavMenuItemProps) {
  const translate = useTranslate() ?? _.identity;
  const navMenuItemProps = useNavMenuItem(props);
  const { selected, label, icon, onClick: _onClick, badge, items, isGroup, level, errors = 0 } = navMenuItemProps;
  const { spacing } = useThemeConfig();
  const [open, setOpen] = useState(selected);
  const onClick = useCallback(
    (e: React.MouseEvent<HTMLDivElement>) => {
      setOpen(!open);
      _onClick(e);
    },
    [_onClick, open]
  );
  const hasIcon = icon !== undefined;
  const listItemProps = _.omit(props, ['label', 'icon', 'selected', 'badge']);

  useEffect(() => {
    if (selected && !open) {
      setOpen(selected);
    }
  }, [selected, open, setOpen]);

  return (
    <>
      <ListItem {...listItemProps} disablePadding>
        {/* @ts-ignore */}
        <ListItemButton selected={selected ? !isGroup : null} onClick={onClick} sx={{ pl: spacing * level }}>
          {hasIcon ? <ListItemIcon>{icon}</ListItemIcon> : null}
          <ListItemText
            inset={!hasIcon}
            primary={
              errors === 0 ? (
                translate(label)
              ) : (
                <Badge
                  variant="dot"
                  color="error"
                  sx={{ '& > .MuiBadge-badge': { transform: 'scale(1) translate(125%, 0)' } }}
                >
                  {translate(label)}
                </Badge>
              )
            }
          />
          {badge ? (
            <ListItemAvatar>
              {/* @ts-ignore */}
              <Avatar type="filled" size="xs" color={badge.color ?? 'default'}>
                {badge.content}
              </Avatar>
            </ListItemAvatar>
          ) : null}
          {isGroup ? open ? <ExpandLess /> : <ExpandMore /> : null}
        </ListItemButton>
      </ListItem>
      {isGroup ? (
        <Collapse in={open} timeout="auto">
          <List>
            {_.map(items, (item: IItem, index: number) => {
              return <NavMenuItem key={index} {...item} />;
            })}
          </List>
        </Collapse>
      ) : null}
    </>
  );
}

function useNavMenuItem(item: INavMenuItemProps): IItem & {
  selected: boolean;
  onClick: React.MouseEventHandler<HTMLDivElement>;
  items: Array<IItem>;
  isGroup: boolean;
  level: number;
} {
  const { id } = item;
  const isActive = useIsActive(id);
  const level = getLevel(id);
  const navigate = useNavigateForm();
  const syncWithLocation = useSyncWithLocation();
  const setActiveItem = useSetActiveItem();
  const items = useChildren(id);
  const isGroup = !_.isEmpty(items);
  const onClick = useCallback(
    (e: React.MouseEvent<HTMLDivElement>) => {
      if (!isGroup) {
        if (syncWithLocation) {
          navigate(item.id);
        } else {
          setActiveItem(item.id);
        }
      }
      if (_.isFunction(item.onClick)) {
        item.onClick(e);
      }
    },
    [setActiveItem, navigate, item, syncWithLocation, isGroup]
  );
  const navMenuItem = useMemo(() => {
    return {
      ...item,
      selected: isActive,
      onClick: onClick,
      items: items,
      isGroup: isGroup,
      level: level
    };
  }, [item, isActive, onClick, items, isGroup, level]);

  return navMenuItem;
}

export { NavMenu, NavMenuItem, useNavMenuItem };
