import styled, {
  css,
  FlattenInterpolation,
  ThemeProps,
  DefaultTheme,
} from 'styled-components';
import { InputHTMLAttributes } from 'react';

const StyledInput = styled.input<
  {
    themeDisabled: boolean;
  } & InputHTMLAttributes<HTMLInputElement>
>`
  appearance: none;
  position: relative;
  height: ${({ theme }) => theme.sizes.radio.height};
  width: ${({ theme }) => theme.sizes.radio.width};
  flex-shrink: 0;
  border-radius: ${({ theme }) => theme.radii.radio.default};
  border: ${({ theme }) => theme.borderWidths.radio.default} solid
    ${({ theme }) => theme.colors.radio.defaultBorder};
  margin: 0;
  padding: 0;

  &:after {
    content: '';
    position: absolute;
    height: ${({ theme }) => theme.sizes.radio.checkmarkHeight};
    width: ${({ theme }) => theme.sizes.radio.checkmarkWidth};
    top: 50%;
    left: 50%;
    transform: translateX(-50%) translateY(-50%);
    border-radius: ${({ theme }) => theme.radii.radio.default};
  }

  &:focus {
    outline: none;
  }

  ${({ themeDisabled, theme }) => {
    switch (themeDisabled) {
      case false:
        return css`
          cursor: pointer;
          color: ${theme.colors.radio.defaultText};
          &:hover {
            border-color: ${theme.colors.radio.hoverBorder};
          }
          &:checked {
            border-color: ${theme.colors.radio.activeBorder};
            &::after {
              background-color: ${theme.colors.radio.defaultCheckmark};
            }
          }
        `;
      case true:
        return css`
          cursor: not-allowed;
          color: ${theme.colors.radio.disabledText};
          background-color: ${theme.colors.radio.disabledBackground};
          &:checked {
            border-color: ${theme.colors.radio.disabledBorder};
            &::after {
              background-color: ${theme.colors.radio.disabledCheckmark};
            }
          }
        `;
    }
  }};
`;

const StyledLabel = styled.label<{
  themeDisabled: boolean;
}>`
  font-size: ${({ theme }) => theme.fontSizes.radio.default};
  display: flex;
  align-items: center;
  line-height: ${({ theme }) => theme.lineHeights.radio.default};
  font-weight: ${({ theme }) => theme.fontWeights.radio.default};
  margin: 0;
  padding: 0;

  ${({ themeDisabled, theme }) => {
    switch (themeDisabled) {
      case false:
        return css`
          cursor: pointer;
          color: ${theme.colors.radio.defaultText};
        `;
      case true:
        return css`
          cursor: not-allowed;
          color: ${theme.colors.radio.disabledText};
        `;
    }
  }};

  > ${StyledInput} {
    margin: ${({ theme }) => theme.space.radio.margin};
  }
`;

const StyledText = styled.div`
  margin: 0;
  padding: 0;
`;

const StyledWrapper = styled.div<{ themeLayout: 'vertical' | 'horizontal' }>`
  margin: 0;
  padding: 0;

  ${({ themeLayout }) => {
    switch (themeLayout) {
      case 'vertical':
        return css``;
      case 'horizontal':
        return css`
          display: flex;
        `;
    }
  }};
`;

const Spacer = styled.div<{ themeLayout: 'vertical' | 'horizontal' }>`
  margin: 0;
  padding: 0;

  ${({ themeLayout, theme }) => {
    switch (themeLayout) {
      case 'vertical':
        return css`
          margin-top: ${theme.space.radio.groupVerticalMargin};
        `;
      case 'horizontal':
        return css`
          margin-left: ${theme.space.radio.groupHorizontalMargin};
        `;
    }
  }};
`;

const StyledRadioButton = styled.span<{
  themeSize: 'small' | 'medium' | 'large';
}>`
  display: inline-flex;
  align-items: center;
  box-sizing: border-box;
  border: ${({ theme }) => theme.borderWidths.radio.default} solid
    ${({ theme }) => theme.colors.radio.defaultBorder};
  border-radius: ${({ theme }) => theme.radii.radio.button};
  line-height: 100%;
  color: ${({ theme }) => theme.colors.radio.defaultText};
  background: transparent;
  cursor: pointer;
  font-weight: ${({ theme }) => theme.fontWeights.radio.default};
  margin: 0;
  padding: 0;

  &:hover {
    color: ${({ theme }) => theme.colors.radio.hoverText};
    border-color: ${({ theme }) => theme.colors.radio.hoverBorder};
  }

  ${({ themeSize, theme }) => {
    switch (themeSize) {
      case 'small':
        return css`
          font-size: ${theme.fontSizes.radio.buttonSmall};
          padding: ${theme.space.radio.buttonSmallPadding};
          height: ${theme.sizes.radio.buttonSmall};
        `;
      case 'medium':
        return css`
          font-size: ${theme.fontSizes.radio.buttonMedium};
          padding: ${theme.space.radio.buttonMediumPadding};
          height: ${theme.sizes.radio.buttonMedium};
        `;
      case 'large':
        return css`
          font-size: ${theme.fontSizes.radio.buttonLarge};
          padding: ${theme.space.radio.buttonLargePadding};
          height: ${theme.sizes.radio.buttonLarge};
        `;
    }
  }};
`;

type ThemeStatus = 'disabled' | 'enabled';

type AdvancedIntent = 'primary' | 'danger' | 'success' | 'warning' | 'error';

const HOVER_COLORS = {
  primary: 'hoverPrimary',
  danger: 'hoverDanger',
  success: 'hoverSuccess',
  warning: 'hoverWarning',
  error: 'hoverError',
} as const;

const getAdvancedIntentStyles = (
  intent: AdvancedIntent
): FlattenInterpolation<ThemeProps<DefaultTheme>> => css`
  & ~ ${StyledRadioButton} {
    border-color: ${({ theme }) => theme.colors.radio[HOVER_COLORS[intent]]};
    color: ${({ theme }) => theme.colors.radio[intent]};
  }

  &:checked ~ ${StyledRadioButton} {
    color: ${({ theme }) => theme.colors.radio.enabledSelectedText};
    border-color: ${({ theme }) => theme.colors.radio[HOVER_COLORS[intent]]};
    background-color: ${({ theme }) => theme.colors.radio[intent]};
  }

  &:hover ~ ${StyledRadioButton} {
    border-color: ${({ theme }) => theme.colors.radio[HOVER_COLORS[intent]]};
    background-color: ${({ theme }) => theme.colors.radio[intent]};
    color: ${({ theme }) => theme.colors.radio.enabledSelectedText};
  }
`;

const StyledRadioButtonInput = styled.input<{
  themeIntent: 'basic' | AdvancedIntent;
  themeStatus: ThemeStatus;
}>`
  display: none;
  margin: 0;
  padding: 0;

  ${({ themeIntent, theme }) => {
    switch (themeIntent) {
      case 'basic':
        return css`
          &:checked ~ ${StyledRadioButton} {
            color: ${theme.colors.radio.enabledSelectedText};
            border-color: ${theme.colors.radio.hoverBorder};
            background-color: ${theme.colors.radio.buttonCheckedBackground};
            &:hover {
              color: ${theme.colors.radio.enabledSelectedText};
            }
          }
        `;
      case 'primary':
        return getAdvancedIntentStyles('primary');
      case 'danger':
        return getAdvancedIntentStyles('danger');
      case 'success':
        return getAdvancedIntentStyles('success');
      case 'warning':
        return getAdvancedIntentStyles('warning');
      case 'error':
        return getAdvancedIntentStyles('error');
    }
  }};

  ${({ themeStatus, theme }) => {
    switch (themeStatus) {
      case 'disabled':
        return css`
          ~ ${StyledRadioButton} {
            cursor: not-allowed;
            color: ${theme.colors.radio.disabledText};
            background-color: ${theme.colors.radio.buttonDisabledBackground};
            &:hover {
              color: ${theme.colors.radio.disabledText};
              border-color: ${theme.colors.radio.disabledBorder};
            }
          }
          &:checked ~ ${StyledRadioButton} {
            color: ${theme.colors.radio.disabledSelectedText};
            background-color: ${theme.colors.radio
              .buttonDisabledCheckedBackground};
            border: none;
          }
        `;
      case 'enabled':
        return css``;
    }
  }};
`;

const StyledRadioButtonLabel = styled.label`
  display: inline-flex;
  align-items: center;
  margin: 0;
  padding: 0;
`;

const StyledRadioButtonGroupWrapper = styled.div<{
  preCheckedIndex: number;
  themeLayout: 'no-gap' | 'gap-small' | 'gap-medium' | 'gap-large';
}>`
  display: inline-flex;
  align-items: center;
  flex-wrap: wrap;
  margin: 0;
  padding: 0;

  ${({ themeLayout, theme, preCheckedIndex }) => {
    switch (themeLayout) {
      case 'no-gap':
        return css`
          > ${StyledRadioButtonLabel} > ${StyledRadioButton} {
            border-radius: 0;
          }

          > ${StyledRadioButtonLabel}:first-child > ${StyledRadioButton} {
            border-top-left-radius: ${theme.radii.radio.button};
            border-bottom-left-radius: ${theme.radii.radio.button};
          }

          > ${StyledRadioButtonLabel}:last-child > ${StyledRadioButton} {
            border-top-right-radius: ${theme.radii.radio.button};
            border-bottom-right-radius: ${theme.radii.radio.button};
          }

          > ${StyledRadioButtonLabel}:not(:first-child) > ${StyledRadioButton} {
            border-left-width: 0px;

            &:hover {
              border-left-width: ${theme.borderWidths.radio.default};
              margin-left: -${theme.borderWidths.radio.default};
            }
          }

          > ${StyledRadioButtonLabel}:nth-child(${preCheckedIndex + 1})
            > ${StyledRadioButton} {
            border-right-width: ${theme.borderWidths.radio.default};
            border-right-style: solid;
            border-right-color: ${theme.colors.radio.hoverBorder};
          }
        `;
      case 'gap-small':
        return css`
          margin: ${theme.space.radio.buttonGroupSmallMargin};
          width: ${theme.sizes.radio.buttonGroupSmallWidth};
          > * {
            margin: ${theme.space.radio.buttonSmallMargin};
          }
        `;
      case 'gap-medium':
        return css`
          margin: ${theme.space.radio.buttonGroupMediumMargin};
          width: ${theme.sizes.radio.buttonGroupMediumWidth};
          > * {
            margin: ${theme.space.radio.buttonMediumMargin};
          }
        `;
      case 'gap-large':
        return css`
          margin: ${theme.space.radio.buttonGroupLargeMargin};
          width: ${theme.sizes.radio.buttonGroupLargeWidth};
          > * {
            margin: ${theme.space.radio.buttonLargeMargin};
          }
        `;
    }
  }};
`;

export {
  StyledInput,
  StyledLabel,
  StyledText,
  StyledWrapper,
  Spacer,
  StyledRadioButton,
  StyledRadioButtonInput,
  StyledRadioButtonLabel,
  StyledRadioButtonGroupWrapper,
};
