import React, { ComponentProps, forwardRef, useEffect, useRef, useState } from 'react';
import classNames from 'clsx';
import type { RgbaColor } from 'colord';
import { colord } from 'colord';
import type { PopperPlacementType } from '@mui/material';
import { useTheme } from '@mui/material/styles';
import { KeyboardArrowDownRounded } from '@mui/icons-material';

import type { ShapeProp } from '@/mui/types';

import Button from '../../Button/Button';
import ClickAwayListener from '../../ClickAwayListener/ClickAwayListener';
import Popper from '../../Popper/Popper';
import StaticColorPicker from './StaticColorPicker';

import styles from './ColorPicker.module.scss';

type ButtonProps = ComponentProps<typeof Button>;

type ButtonColorPickerProps = {
  color?: string;
  open?: boolean;
  shape?: ShapeProp;
  disabled?: boolean;
  size?: ButtonProps['size'];
  dense?: 'margin' | 'padding';
  placement?: PopperPlacementType;
  disableAlpha?: boolean;
  presetColors?: string[];
  onClick?: (event: React.MouseEvent<HTMLButtonElement>) => void;
  onPickerChange?: (color: { hex: string; rgb: RgbaColor }) => void;
};

const ButtonColorPicker = forwardRef<HTMLButtonElement, ButtonColorPickerProps>((props, ref) => {
  const theme = useTheme();
  const color = props.color && colord(props.color).isValid() ? props.color : '#fff';
  const contrastText = theme.palette.getContrastText(color);

  const buttonRef = useRef<HTMLButtonElement | null>(null);
  const [open, setOpen] = useState<boolean>(props.open || false);
  const isControlled = typeof props.open === 'boolean';

  useEffect(() => {
    if (isControlled) setOpen(props.open || false);
  }, [props.open]);

  return (
    <>
      <Button
        shape={props.shape}
        disabled={props.disabled}
        size={props.size}
        square
        color="neutral"
        variant="outlined"
        ref={(node) => {
          if (typeof ref === 'function') {
            ref(node);
          } else if (ref) {
            ref.current = node;
          }
          buttonRef.current = node;
        }}
        onClick={(event) => {
          if (props.onClick) props.onClick(event);
          if (!isControlled) setOpen((prev) => !prev);
        }}
        style={{
          color: contrastText,
          backgroundColor: color,
          borderColor: contrastText,
        }}
        className={classNames(styles.Button, {
          [styles.Button___dense]: props.dense === 'margin',
        })}
        endIcon={!props.disabled ? <KeyboardArrowDownRounded /> : null}
      />
      {open && buttonRef.current && (
        <ClickAwayListener mouseEvent={!isControlled ? 'onClick' : false} onClickAway={() => setOpen(false)}>
          <Popper open={open} anchorEl={buttonRef.current} placement={props.placement}>
            <StaticColorPicker
              color={color}
              disabled={props.disabled}
              disableAlpha={props.disableAlpha}
              presetColors={props.presetColors}
              elevation={15}
              onChange={(...args) => {
                if (props.onPickerChange) {
                  props.onPickerChange(...args);
                }
              }}
            />
          </Popper>
        </ClickAwayListener>
      )}
    </>
  );
});

ButtonColorPicker.displayName = 'ButtonColorPicker';

export default ButtonColorPicker;
