import { forwardRef } from "react";
import { Button, ButtonProps, CircularProgress } from "@mui/material";
import { alpha, keyframes, styled } from "@mui/material/styles";
import type { Theme } from "@mui/material/styles";

type AnimatedCircleButtonProps = ButtonProps & {
  disableAnimation?: boolean;
  loading?: boolean;
};

type StyledButtonProps = AnimatedCircleButtonProps & { theme: Theme };

const loadingPulse = keyframes`
  0% {
    transform: translate(-50%, -50%) scale(0.6);
    opacity: 0.35;
  }
  50% {
    transform: translate(-50%, -50%) scale(1.45);
    opacity: 0.15;
  }
  100% {
    transform: translate(-50%, -50%) scale(0.6);
    opacity: 0;
  }
`;

const StyledButton = styled(Button, {
  shouldForwardProp: (prop) =>
    prop !== "disableAnimation" && prop !== "loading",
})<AnimatedCircleButtonProps>((props: StyledButtonProps) => {
  const {
    theme,
    disableAnimation = false,
    color,
    variant = "text",
    disabled = false,
    loading = false,
  } = props;

  const shouldAnimate = !disableAnimation && (!disabled || loading);
  const pointerBlocked = loading;

  const paletteMainMap: Record<string, string> = {
    primary: theme.palette.primary.main,
    secondary: theme.palette.secondary.main,
    error: theme.palette.error.main,
    warning: theme.palette.warning.main,
    info: theme.palette.info.main,
    success: theme.palette.success.main,
    inherit: theme.palette.primary.main,
  };

  const paletteMain =
    (color && paletteMainMap[String(color)]) ?? theme.palette.primary.main;

  const pulseColor =
    variant === "outlined" || variant === "text"
      ? alpha(paletteMain, 0.18)
      : alpha(paletteMain, 0.3);

  return {
    position: "relative",
    overflow: "hidden",
    borderRadius: 5,
    zIndex: 0,
    transition: "transform 0.2s ease, box-shadow 0.2s ease",
    pointerEvents: pointerBlocked ? "none" : undefined,
    "&::after": shouldAnimate
      ? {
          content: '""',
          position: "absolute",
          width: "12px",
          height: "12px",
          backgroundColor: pulseColor,
          borderRadius: "50%",
          top: "50%",
          left: "50%",
          pointerEvents: "none",
          zIndex: 0,
          ...(loading
            ? {
                opacity: 0.35,
                transform: "translate(-50%, -50%) scale(0.6)",
                animation: `${loadingPulse} 1.2s ease-in-out infinite`,
              }
            : {
                opacity: 0,
                transform: "translate(-50%, -50%) scale(0)",
                transition: "transform 0.45s ease, opacity 0.45s ease",
              }),
        }
      : {},
    ...(loading
      ? {}
      : {
          "&:hover": {
            transform: "translateY(-1px)",
            boxShadow: theme.shadows[4],
          },
          "&:hover::after": shouldAnimate
            ? {
                transform: "translate(-50%, -50%) scale(15)",
                opacity: 1,
              }
            : {},
          "&:active": {
            transform: "translateY(0)",
            boxShadow: theme.shadows[2],
          },
          "&:active::after": shouldAnimate
            ? {
                transform: "translate(-50%, -50%) scale(18)",
                opacity: 0.4,
              }
            : {},
        }),
    "&.Mui-disabled": {
      boxShadow: "none",
      transform: "none",
      ...(loading && shouldAnimate
        ? {}
        : {
            "&::after": {
              opacity: 0,
            },
          }),
    },
    ...(disabled && {
      boxShadow: "none",
      transform: "none",
    }),
    "& > *": {
      position: "relative",
      zIndex: 1,
    },
  };
});

export const AnimatedCircleButton = forwardRef<
  HTMLButtonElement,
  AnimatedCircleButtonProps
>((props, ref) => {
  const {
    loading = false,
    disabled,
    children,
    startIcon,
    endIcon,
    ...rest
  } = props;

  const effectiveStartIcon = loading ? (
    <CircularProgress size={16} color="inherit" />
  ) : (
    startIcon
  );

  return (
    <StyledButton
      ref={ref}
      loading={loading}
      disabled={loading ? true : disabled}
      startIcon={effectiveStartIcon}
      endIcon={loading ? undefined : endIcon}
      {...rest}
    >
      {children}
    </StyledButton>
  );
});
