import { alpha, type SxProps, type Theme } from '@mui/material';

import { AI_SPARKLE_PART_CLASS, SPARKLE_PARTS } from '../AISpinner/constants';

import {
  AI_BORDER_WIDTH,
  AI_SECONDARY_BORDER_GLOW_DURATION_S,
  aiBorderGlowKeyframes,
  aiConicBorder,
  aiGradient,
  aiGradientStopKeyframes,
  aiPrimaryGradient,
} from './constants';
import { type AIButtonVariant } from './types';

/** Sparkle stays static at rest and only twinkles while the button is hovered. */
const SPARKLE_REST = {
  [`& .${AI_SPARKLE_PART_CLASS}`]: { animation: 'none', fillOpacity: 1 },
};

const SPARKLE_HOVER = Object.fromEntries(
  SPARKLE_PARTS.map(({ id, animationName, durationS, delayS }) => [
    `&:hover:not(.Mui-disabled) .${AI_SPARKLE_PART_CLASS}--${id}`,
    {
      animation: `${animationName} ${durationS}s ease-in-out ${delayS}s infinite`,
      '@media (prefers-reduced-motion: reduce)': {
        animation: 'none',
        fillOpacity: 1,
      },
    },
  ]),
);

const secondaryLayers = (face: string, border: string) =>
  `linear-gradient(${face}, ${face}) padding-box, ${border} border-box`;

const getFocusRing = (theme: Theme) => ({
  outline: 'none',
  boxShadow: `0 0 0 3px ${alpha(theme.palette.new.text.neutral.brand, 0.4)}`,
});

export const getAIVariantSx = (
  theme: Theme,
  variant: AIButtonVariant,
): SxProps<Theme> => {
  const { palette } = theme;

  const inverted = palette.new.text.neutral.inverted;
  const brand = palette.new.text.neutral.brand;
  const disabledText = palette.new.action.button.text.disabled.darker;

  const gradientFrom = palette.new.graphics.brand[500];
  const gradientTo = palette.new.graphics.purple[400];
  const gradient = aiGradient(gradientFrom, gradientTo);
  const primaryGradient = aiPrimaryGradient(gradientFrom, gradientTo);

  if (variant === 'primary') {
    return {
      color: inverted,
      border: 'none',
      background: primaryGradient,
      animation: `${aiGradientStopKeyframes} 2.5s ease-in-out infinite`,
      '@media (prefers-reduced-motion: reduce)': { animation: 'none' },
      '&:hover': {
        background: primaryGradient,
      },
      '&.Mui-focusVisible': getFocusRing(theme),
      '&.Mui-disabled': {
        color: disabledText,
        border: 'none',
        background: palette.new.action.button.background.primary.disabled,
        animation: 'none',
      },
      ...SPARKLE_REST,
      ...SPARKLE_HOVER,
    };
  }

  if (variant === 'secondary') {
    const face = palette.new.action.button.background.secondary.default;
    const faceHover = palette.new.action.button.background.secondary.hover;
    const border = `${AI_BORDER_WIDTH}px solid transparent`;
    const borderHighlight =
      theme.palette.mode === 'dark'
        ? palette.new.graphics.brand[200]
        : inverted;
    const conicBorder = aiConicBorder(
      gradientFrom,
      gradientTo,
      borderHighlight,
    );

    return {
      color: brand,
      border,
      background: secondaryLayers(face, conicBorder),
      animation: `${aiBorderGlowKeyframes} ${AI_SECONDARY_BORDER_GLOW_DURATION_S}s linear infinite`,
      '@media (prefers-reduced-motion: reduce)': {
        animation: 'none',
        background: secondaryLayers(face, gradient),
      },
      '&:hover': {
        border,
        background: secondaryLayers(faceHover, conicBorder),
        '@media (prefers-reduced-motion: reduce)': {
          background: secondaryLayers(faceHover, gradient),
        },
      },
      '&.Mui-focusVisible': { ...getFocusRing(theme), border },
      '&.Mui-disabled': {
        color: disabledText,
        border,
        background: secondaryLayers(face, palette.new.border.neutral.default),
        animation: 'none',
      },
      ...SPARKLE_REST,
      ...SPARKLE_HOVER,
    };
  }

  return {
    color: brand,
    background: 'transparent',
    '&:hover': {
      background: palette.new.action.button.background.tertiary.hover,
    },
    '&.Mui-focusVisible': getFocusRing(theme),
    '&.Mui-disabled': { color: disabledText, background: 'transparent' },
    ...SPARKLE_REST,
    ...SPARKLE_HOVER,
  };
};
