import { useRef, useState } from 'react';
import {
  Controller,
  type ControllerRenderProps,
  type FieldValues,
  useFormContext,
} from 'react-hook-form';
import { useMutation, useQueryClient } from 'react-query';

import Picker, {
  type EmojiClickData,
  SkinTones,
  Theme as EmojiPickerTheme,
} from 'emoji-picker-react';
import { useModal } from '@material-hu/hooks/useModal';
import { IconChevronRight } from '@material-hu/icons/tabler';
import ClickAwayListener from '@material-hu/mui/ClickAwayListener';
import Divider from '@material-hu/mui/Divider';
import FormControl, {
  type FormControlProps,
} from '@material-hu/mui/FormControl';
import Grow from '@material-hu/mui/Grow';
import IconButton from '@material-hu/mui/IconButton';
import { Box } from '@material-hu/mui/index';
import Paper from '@material-hu/mui/Paper';
import Popper from '@material-hu/mui/Popper';
import Stack from '@material-hu/mui/Stack';
import { useTheme } from '@material-hu/mui/styles';
import Tab from '@material-hu/mui/Tab';
import Tabs from '@material-hu/mui/Tabs';

import useHuSnackbar from '@material-hu/components/design-system/Snackbar';

import useGeneralError from 'src/hooks/useGeneralError';
import useHuGoTheme from 'src/hooks/useHuGoTheme';
import { appsKeys } from 'src/pages/dashboard/Apps/queries';
import * as iconsService from 'src/services/iconsService';
import { type IconInterface, IconType } from 'src/types/icons';
import { useLokaliseTranslation } from 'src/utils/i18n';
import { getIcons } from 'src/utils/icons';

import Cropping from 'src/components/Cropping';
import CustomIcon from 'src/components/CustomIcon';

import FormImageSelect from '../FormImageSelect';

type Props = FormControlProps & {
  name: string;
  width?: number;
  selectorHandler?: (icon: { value: string; type: IconType }) => void;
  defaultIcon?: IconInterface | null;
  disabled?: boolean;
  withArrow?: boolean;
  selectOnUpload?: boolean;
  anchorRenderer?: (props: {
    disabled: boolean;
    handleToggle: () => void;
    anchorRef: React.RefObject<HTMLButtonElement>;
    defaultIcon: IconInterface;
    field: ControllerRenderProps<FieldValues, string>;
    withArrow: boolean;
  }) => JSX.Element;
};

function FormImageMenu({
  anchorRenderer,
  name,
  width = 600,
  selectorHandler,
  defaultIcon = null,
  disabled = false,
  withArrow = true,
  selectOnUpload,
  ...formControlProps
}: Props) {
  const { control, setValue } = useFormContext();
  const { t } = useLokaliseTranslation('backoffice_only');
  const { enqueueSnackbar } = useHuSnackbar();
  const showGeneralError = useGeneralError();
  const queryClient = useQueryClient();
  const muiTheme = useTheme();

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

  const anchorRef = useRef<HTMLButtonElement | null>(null);
  const imageSelectRef = useRef<HTMLDivElement>(null);

  const handleToggle = () => {
    setOpen(prevOpen => !prevOpen);
  };

  const handleClose = (event: MouseEvent | TouchEvent) => {
    if (anchorRef.current?.contains(event.target as Node)) {
      return;
    }
    setOpen(false);
  };

  const onEmojiClick = (emojiObject: EmojiClickData) => {
    setValue(name, { value: emojiObject.emoji, type: IconType.EMOJI });
    if (selectorHandler)
      selectorHandler({ value: emojiObject.emoji, type: IconType.EMOJI });
    setOpen(false);
  };

  const uploadLogo = useMutation(
    async (file: File) => iconsService.uploadLogo(file),
    {
      onSuccess: async data => {
        enqueueSnackbar({
          title: t('backoffice_only:form_image_menu.image_success'),
          variant: 'success',
        });
        await queryClient.refetchQueries(appsKeys.icons());
        if (imageSelectRef?.current) {
          imageSelectRef.current.scrollTop =
            imageSelectRef.current.scrollHeight;
        }
        if (selectOnUpload) {
          setValue(name, { value: data.data.source, type: IconType.IMAGE });
        }
      },
      onError: (err: any) => {
        if (err?.response?.data?.code === 'INVALID_ASPECT_RATIO') {
          enqueueSnackbar({
            title: t('backoffice_only:form_image_menu.error_aspect'),
            variant: 'error',
          });
        } else if (err?.response?.data?.code === 'INVALID_DATA') {
          enqueueSnackbar({
            title: t('backoffice_only:form_image_menu.error_data'),
            variant: 'error',
          });
        } else {
          showGeneralError(err);
        }
      },
    },
  );

  const {
    modal: croppingModal,
    showModal: showCroppingModal,
    closeModal,
  } = useModal(
    Cropping,
    { fullWidth: true, maxWidth: 'md' },
    {
      onSave: nextFile => uploadLogo.mutate(nextFile),
      onClose: () => closeModal(),
      recommendedWidth: 1000,
      recommendedHeight: 1000,
      title: t('backoffice_only:form_image_menu.crop_icon'),
    },
  );

  const formImageSelect = (
    <FormImageSelect
      name={name}
      options={getIcons()}
      upload={file => showCroppingModal({ file })}
      closePopup={handleClose}
      width={width}
      selectorHandler={selectorHandler}
      ref={imageSelectRef}
    />
  );

  const emojis = (
    <div>
      <Picker
        onEmojiClick={onEmojiClick}
        style={{ width: '100%' }}
        theme={
          muiTheme.palette.mode === 'dark'
            ? EmojiPickerTheme.DARK
            : EmojiPickerTheme.LIGHT
        }
        skinTonesDisabled
        defaultSkinTone={SkinTones.NEUTRAL}
      />
    </div>
  );

  const tabs = [
    {
      label: t('backoffice_only:form_image_menu.icons'),
      component: formImageSelect,
    },
    { label: t('backoffice_only:form_image_menu.emojis'), component: emojis },
  ];

  const [currentTab, setCurrentTab] = useState(0);
  const { component } = tabs[currentTab];

  const renderSelectedIcon = (
    field: ControllerRenderProps<FieldValues, string>,
  ) => {
    const icon = defaultIcon ?? field.value;
    if (!icon) return null;
    return (
      <Box
        sx={{
          backgroundColor: theme =>
            theme.palette.hugoBackground?.neutralBgSecondary,
          p: 1.5,
          borderRadius: theme => theme.shape.borderRadiusM,
          display: 'inline-flex',
        }}
      >
        <CustomIcon
          icon={icon}
          size={40}
        />
      </Box>
    );
  };

  return (
    <FormControl
      sx={{
        display: 'block',
        ...formControlProps?.sx,
      }}
      {...formControlProps}
    >
      {croppingModal}
      <Controller
        control={control}
        name={name}
        render={({ field }) => (
          <>
            {anchorRenderer &&
              anchorRenderer({
                disabled,
                handleToggle,
                anchorRef,
                defaultIcon: defaultIcon!,
                field,
                withArrow,
              })}
            {!anchorRenderer && (
              <Stack
                sx={{
                  display: 'flex',
                  flexDirection: 'row',
                  alignItems: 'center',
                }}
              >
                {withArrow ? (
                  <Stack
                    sx={{
                      display: 'flex',
                      flexDirection: 'row',
                      alignItems: 'center',
                      gap: 2,
                    }}
                  >
                    {renderSelectedIcon(field)}
                    <IconButton
                      disabled={disabled}
                      onClick={handleToggle}
                      ref={anchorRef}
                    >
                      <IconChevronRight size={24} />
                    </IconButton>
                  </Stack>
                ) : (
                  <IconButton
                    disabled={disabled}
                    onClick={handleToggle}
                    ref={anchorRef}
                  >
                    {renderSelectedIcon(field)}
                  </IconButton>
                )}
              </Stack>
            )}
            <ClickAwayListener onClickAway={handleClose}>
              <Popper
                open={open}
                anchorEl={anchorRef.current}
                role={undefined}
                transition
                placement="bottom-start"
                sx={{ zIndex: 10000 }}
              >
                {({ TransitionProps }) => (
                  <Grow
                    {...TransitionProps}
                    style={{
                      transformOrigin: 'top left',
                    }}
                  >
                    <Paper
                      sx={{
                        width,
                        '& .MuiFormGroup-root': {
                          width: '100%',
                          p: 2,
                        },
                      }}
                    >
                      <Tabs
                        value={currentTab}
                        onChange={(_, val) => {
                          setCurrentTab(val);
                        }}
                        variant="scrollable"
                        sx={{
                          px: 2,
                          pt: 2,
                          '& .MuiTabs-flexContainer': {
                            gap: 0.5,
                          },
                          '& .MuiTab-root': {
                            textTransform: 'none',
                            borderRadius: theme => theme.shape.borderRadiusM,
                          },
                          '& .Mui-selected': {
                            backgroundColor: theme =>
                              theme.palette.hugoBackground?.neutralBg,
                          },
                        }}
                      >
                        {tabs.map(tab => (
                          <Tab
                            sx={{
                              minWidth: 'fit-content',
                            }}
                            key={tab.label}
                            label={tab.label}
                            disableRipple
                          />
                        ))}
                      </Tabs>
                      <Divider sx={{ mx: 2 }} />
                      {component}
                    </Paper>
                  </Grow>
                )}
              </Popper>
            </ClickAwayListener>
          </>
        )}
      />
    </FormControl>
  );
}

const HuFormImageMenu = (props: Props) => {
  const HuGoThemeProvider = useHuGoTheme();
  return (
    <HuGoThemeProvider>
      <FormImageMenu {...props} />
    </HuGoThemeProvider>
  );
};

export default HuFormImageMenu;
