import { css, cx } from '@emotion/css';
import React, { type ButtonHTMLAttributes } from 'react';

import { type GrafanaTheme2, type IconName, isIconName } from '@grafana/data';

import { useStyles2 } from '../../themes/ThemeContext';
import { getFocusStyles, getMouseFocusStyles } from '../../themes/mixins';
import { type ButtonVariant } from '../Button/Button';
import { Icon } from '../Icon/Icon';
import { Tooltip } from '../Tooltip/Tooltip';

import { useSidebarContext } from './useSidebar';

export interface Props extends ButtonHTMLAttributes<HTMLButtonElement> {
  icon: IconName;
  active?: boolean;
  tooltip?: string;
  title: string;
  variant?: ButtonVariant;
}

export const SidebarButton = React.forwardRef<HTMLButtonElement, Props>(
  ({ icon, active, onClick, title, tooltip, variant, ...restProps }, ref) => {
    const styles = useStyles2(getStyles);
    const sidebarContext = useSidebarContext();

    if (!sidebarContext) {
      throw new Error('Sidebar.Button must be used within a Sidebar component');
    }

    const buttonClass = cx(
      styles.button,
      sidebarContext.compact && styles.compact,
      sidebarContext.position === 'left' && styles.leftButton
    );

    return (
      <Tooltip ref={ref} content={tooltip ?? title} placement={sidebarContext.position === 'left' ? 'right' : 'left'}>
        <button
          className={buttonClass}
          aria-label={title}
          aria-expanded={active}
          type="button"
          onClick={onClick}
          {...restProps}
        >
          <div className={cx(styles.iconWrapper, variant, active && styles.iconActive)}>{renderIcon(icon)}</div>
          {!sidebarContext.compact && <div className={cx(styles.title, active && styles.titleActive)}>{title}</div>}
        </button>
      </Tooltip>
    );
  }
);

SidebarButton.displayName = 'SidebarButton';

function renderIcon(icon: IconName | React.ReactNode) {
  if (!icon) {
    return null;
  }

  if (isIconName(icon)) {
    return <Icon name={icon} size="lg" />;
  }

  return icon;
}

const getStyles = (theme: GrafanaTheme2) => {
  return {
    button: css({
      label: 'toolbar-button',
      position: 'relative',
      display: 'flex',
      flexDirection: 'column',
      minHeight: theme.spacing(theme.components.height.sm),
      padding: theme.spacing(0, 1),
      width: '100%',
      overflow: 'hidden',
      lineHeight: `${theme.components.height.sm * theme.spacing.gridSize - 2}px`,
      fontWeight: theme.typography.fontWeightMedium,
      color: theme.colors.text.secondary,
      background: 'transparent',
      border: `none`,

      '&:focus, &:focus-visible': {
        ...getFocusStyles(theme),
        zIndex: 1,
      },

      '&:focus:not(:focus-visible)': getMouseFocusStyles(theme),

      '&[disabled], &:disabled': {
        cursor: 'not-allowed',
        opacity: theme.colors.action.disabledOpacity,
      },
    }),
    compact: css({
      padding: theme.spacing(0, 1),
      width: theme.spacing(5),
    }),
    iconWrapper: css({
      padding: 3,
      display: 'inline-flex',
      alignItems: 'center',
      justifyContent: 'center',
      alignSelf: 'center',
      position: 'relative',
      borderRadius: theme.shape.radius.sm,
      '&:hover, &:focus-visible': {
        background: theme.colors.action.hover,
      },
      '&.primary': {
        background: theme.colors.primary.main,
        color: theme.colors.getContrastText(theme.colors.primary.main),
        '&:hover': {
          backgroundColor: theme.colors.primary.shade,
        },
      },
      [theme.transitions.handleMotion('no-preference', 'reduce')]: {
        ...getIconTransitionStyles(theme),
      },
    }),
    iconActive: css({
      color: theme.colors.text.primary,
      background: theme.colors.secondary.main,
      '&::before': {
        display: 'block',
        content: '" "',
        position: 'absolute',
        right: 0,
        bottom: 0,
        width: '100%',
        height: '2px',
        borderBottomLeftRadius: theme.shape.radius.sm,
        borderBottomRightRadius: theme.shape.radius.sm,
        backgroundImage: theme.colors.gradients.brandHorizontal,
        [theme.transitions.handleMotion('no-preference', 'reduce')]: {
          ...getIconTransitionStyles(theme),
        },
      },
      svg: {
        [theme.transitions.handleMotion('no-preference', 'reduce')]: {
          ...getIconTransitionStyles(theme),
        },
      },
    }),
    title: css({
      fontSize: theme.typography.bodySmall.fontSize,
      color: theme.colors.text.secondary,
      textOverflow: 'ellipsis',
      overflow: 'hidden',
      textAlign: 'center',
      whiteSpace: 'nowrap',
    }),
    titleActive: css({
      color: theme.colors.text.primary,
    }),
    leftButton: css({
      '&::before': {
        right: 'unset',
        left: 0,
        top: 0,
        height: '100%',
      },
    }),
  };
};

function getIconTransitionStyles(theme: GrafanaTheme2) {
  return {
    transition: theme.transitions.create(['background-color', 'color'], {
      duration: theme.transitions.duration.short,
    }),
  };
}
