import { forwardRef } from 'react';
import { useFormContext, Controller, type FieldValues } from 'react-hook-form';

import { IconPlus } from '@material-hu/icons/tabler';
import Box from '@material-hu/mui/Box';
import ButtonBase from '@material-hu/mui/ButtonBase';
import IconButton from '@material-hu/mui/IconButton';
import RadioGroup, { type RadioGroupProps } from '@material-hu/mui/RadioGroup';

import { IconType, type ImageIconOption } from 'src/types/icons';

type Props = RadioGroupProps & {
  name: string;
  options: ImageIconOption[];
  disabled?: boolean;
  upload?: (file: File) => void;
  width?: number;
  closePopup?: (e: any) => void;
  selectorHandler?: (icon: { value: string; type: IconType }) => void;
};

const FormImageSelect = forwardRef(
  (
    {
      name,
      options,
      disabled,
      upload,
      width = 600,
      closePopup,
      selectorHandler,
      ...other
    }: Props,
    ref,
  ) => {
    const { control } = useFormContext();

    const handleSelect = (
      e: React.MouseEvent<HTMLButtonElement>,
      field: FieldValues,
      option: ImageIconOption,
    ) => {
      field.onChange({
        value: option.source,
        type: IconType.IMAGE,
      });
      if (selectorHandler) {
        selectorHandler({
          value: option.source,
          type: IconType.IMAGE,
        });
      }
      closePopup?.(e);
    };

    return (
      <Controller
        render={({ field }) => (
          <RadioGroup
            {...other}
            {...field}
            ref={ref}
            sx={{
              flexDirection: 'row',
              backgroundColor: theme =>
                theme.palette.new.background.layout.default,
              height: 270,
              width,
              gap: 1,
              overflowY: 'auto',
              borderRadius: 1,
              opacity: disabled ? 0.5 : 1,
            }}
          >
            {options.map(option => {
              /* field.value.value ~= https://the-image-host.com/images/NN-Option.png
               * option.name ~= Option
               * so checking if option.name is in the field.value.value is good enough
               */
              const isSelected =
                field.value?.value?.includes(option.name) ?? false;
              const imageHeight = 40;
              return (
                <ButtonBase
                  onClick={e => handleSelect(e, field, option)}
                  sx={{
                    p: '10px',
                    m: 0,
                    borderRadius: theme => theme.shape.borderRadiusM,
                    border: theme =>
                      isSelected
                        ? `1px solid ${theme.palette.primary.main}`
                        : '1px solid transparent',
                    backgroundColor: theme =>
                      isSelected
                        ? theme.palette.new.action.background.brand.default
                        : theme.palette.new.background.elements.grey,
                    ':hover': {
                      backgroundColor: theme =>
                        theme.palette.new.action.background.neutral.hover,
                    },
                    borderStyle: 'solid',
                  }}
                  key={option.name}
                  disabled={disabled}
                >
                  <Box
                    component="img"
                    src={option.source}
                    key={option.name}
                    alt="icon"
                    sx={{
                      width: imageHeight,
                      height: imageHeight,
                      objectFit: 'contain',
                    }}
                  />
                </ButtonBase>
              );
            })}
            {upload && (
              <Box
                sx={{
                  p: '10px',
                  m: 0,
                  display: 'flex',
                  flexDirection: 'column',
                  justifyContent: 'center',
                  borderRadius: theme => theme.shape.borderRadiusM,
                  border: theme =>
                    `2px solid ${theme.palette.new.border.neutral.default}`,
                  '&:hover': {
                    backgroundColor: theme =>
                      theme.palette.new.action.background.neutral.hover,
                  },
                  cursor: 'pointer',
                }}
              >
                <label htmlFor="contained-button-file-icon">
                  <input
                    accept="image/*"
                    id="contained-button-file-icon"
                    type="file"
                    style={{ display: 'none' }}
                    onChange={e => {
                      if (e.target.files?.[0]) {
                        upload?.(e.target.files[0]);
                      }
                      closePopup?.(e);
                    }}
                  />
                  <IconButton
                    component="span"
                    sx={{ p: 0, ':hover': { backgroundColor: 'transparent' } }}
                  >
                    <IconPlus size={40} />
                  </IconButton>
                </label>
              </Box>
            )}
          </RadioGroup>
        )}
        name={name}
        control={control}
      />
    );
  },
);

FormImageSelect.displayName = 'FormImageSelect';

export default FormImageSelect;
