import React, { useRef } from 'react';
import styled from '@emotion/native';
import { ColorName, ViewStyle } from '@emotion/react';
import { useHover } from 'react-native-web-hooks';
import { Text } from 'components/text';
import {
  StyleSystemThemedProps,
  Row,
  TouchableHighlight,
  Container,
  ActivityIndicator,
} from 'components/layout';
import { TouchableHighlightProps as TouchableHighlightPropsBase } from 'react-native';
import { variant } from 'styled-system';
import { COLOR_VALUES } from 'theme/color';
import { TFunctionResult } from 'i18next';
import { TextVariant, TextWeightVariant } from 'components/text/Text';
import { Visible } from 'components/visible';

const variants: Record<ButtonVariant, ViewStyle> = {
  outline: {
    borderWidth: 1,
  },
  underline: {
    borderBottomWidth: 2,
  },
  'underline-inactive': {
    borderColor: 'transparent',
    borderBottomWidth: 2,
  },
};

const colorVariants: Record<ButtonColorVariant, ViewStyle> = {
  primary: {
    backgroundColor: 'primary',
  },
  'primary-hover': {
    backgroundColor: 'primary-hover',
  },
  secondary: {
    backgroundColor: 'secondary',
  },
  'secondary-hover': {
    backgroundColor: 'secondary-hover',
  },
  body: {
    backgroundColor: 'body',
  },
  caption: {
    backgroundColor: 'caption',
  },
  divider: {
    backgroundColor: 'divider',
  },
  title: {
    backgroundColor: 'title',
  },
  base: {
    backgroundColor: 'base',
  },
  transparent: {
    borderRadius: 'button',
    backgroundColor: 'transparent',
  },
  'base-01': {
    backgroundColor: 'base-01',
  },
  'base-02': {
    backgroundColor: 'base-02',
  },
  'base-02-hover': {
    backgroundColor: 'base-02-hover',
  },
  'base-03': {
    backgroundColor: 'base-03',
  },
};

const borderColorVariants: Record<ButtonColorVariant, ViewStyle> = {
  primary: {
    borderColor: 'primary',
  },
  'primary-hover': {
    borderColor: 'primary-hover',
  },
  secondary: {
    borderColor: 'secondary',
  },
  'secondary-hover': {
    borderColor: 'secondary-hover',
  },
  body: {
    borderColor: 'body',
  },
  caption: {
    borderColor: 'caption',
  },
  divider: {
    borderColor: 'divider',
  },
  title: {
    borderColor: 'title',
  },
  base: {
    borderColor: 'base',
  },
  transparent: {
    borderColor: 'transparent',
  },
  'base-01': {
    borderColor: 'base-01',
  },
  'base-02': {
    borderColor: 'base-02',
  },
  'base-02-hover': {
    borderColor: 'base-02-hover',
  },
  'base-03': {
    borderColor: 'base-03',
  },
};

const sizeVariants: Record<ButtonSizeVariant, ViewStyle> = {
  undefined: {
    height: undefined,
    px: undefined,
  },
  content: {
    height: undefined,
    px: '3xs',
  },
  'extra-small': {
    height: 25,
    px: 'xs',
  },
  small: {
    height: 30,
    px: 'xs',
  },
  medium: {
    px: 's',
    height: 35,
  },
  large: {
    px: 'm',
    height: 40,
  },
  'extra-large': {
    px: 'm',
    height: 45,
  },
  '2-extra-large': {
    px: 'm',
    height: 50,
  },
};

const shapeVariants: Record<ButtonShapeVariant, ViewStyle> = {
  square: {
    borderRadius: 0,
  },
  round: {
    borderRadius: 'button',
  },
};

const ButtonLocal = styled(TouchableHighlight)<TouchableHighlightProps>(
  variant({
    prop: 'colorVariant',
    variants: colorVariants,
  }),
  variant({
    variants,
  }),
  variant({
    prop: 'sizeVariant',
    variants: sizeVariants,
  }),
  variant({
    prop: 'shapeVariant',
    variants: shapeVariants,
  }),
  variant({
    prop: 'borderColorVariant',
    variants: borderColorVariants,
  }),

  {
    alignItems: 'center',
    justifyContent: 'center',
  }
);

const UnderlayColors: Record<ButtonVariant, string> = {
  outline: COLOR_VALUES['underlay-primary'],
  underline: 'transparent',
  'underline-inactive': 'transparent',
};

export const Button: React.FC<ButtonType> = ({
  title,
  loading,
  leftElement,
  titleColor,
  titleWeight = 'normal',
  colorVariant,
  borderColorVariant,
  titleVariant,
  centerElement,
  rightElement,
  collapsedWidth,
  collapsedElement,
  shapeVariant = 'round',
  underlayColorVariant,
  hoverColorVariant = colorVariant,
  hoverTitleColorVariant = titleColor,
  hoverBorderColor = borderColorVariant,
  isCollapsed,
  ...props
}) => {
  const buttonRef = useRef(null);
  const isHovered = useHover(buttonRef);

  const width = isCollapsed ? collapsedWidth : undefined;
  const localColorVariant = isHovered ? hoverColorVariant : colorVariant;
  const localBorderColorVariant = isHovered ? hoverBorderColor : borderColorVariant;

  const notHoveredColor = localColorVariant === 'primary' ? 'white' : titleColor;
  const localTitleColor = isHovered ? hoverTitleColorVariant : notHoveredColor;
  const func = loading ? undefined : props.onPress;

  return (
    <ButtonLocal
      ref={buttonRef}
      underlayColor={underlayColorVariant || UnderlayColors[props.variant as ButtonVariant]}
      shapeVariant={shapeVariant}
      width={width}
      colorVariant={localColorVariant}
      borderColorVariant={localBorderColorVariant}
      onPress={func}
      {...props}
    >
      <>
        <Visible if={loading}>
          <ActivityIndicator />
        </Visible>

        <Visible if={!loading}>
          <Row alignItems="center">
            <Visible if={isCollapsed}>
              <Visible if={!!collapsedElement}>
                <Container>{collapsedElement}</Container>
              </Visible>
            </Visible>
            <Visible if={!isCollapsed}>
              <>
                <Visible if={!!leftElement}>
                  <Container mr="xs">{leftElement}</Container>
                </Visible>
                {centerElement || (
                  <Text
                    variant={titleVariant || 'body'}
                    weightVariant={titleWeight}
                    color={localTitleColor || titleColor}
                  >
                    {title as string}
                  </Text>
                )}
                <Visible if={!!rightElement}>
                  <Container ml="xs">{rightElement}</Container>
                </Visible>
              </>
            </Visible>
          </Row>
        </Visible>
      </>
    </ButtonLocal>
  );
};

export type ButtonVariant = 'outline' | 'underline' | 'underline-inactive';

export type ButtonColorVariant =
  | 'primary'
  | 'primary-hover'
  | 'secondary'
  | 'secondary-hover'
  | 'base'
  | 'title'
  | 'base-01'
  | 'base-02'
  | 'base-02-hover'
  | 'base-03'
  | 'body'
  | 'divider'
  | 'caption'
  | 'transparent';
export type ButtonSizeVariant =
  | 'undefined'
  | 'content'
  | 'extra-small'
  | 'small'
  | 'medium'
  | 'large'
  | 'extra-large'
  | '2-extra-large';
type ButtonShapeVariant = 'square' | 'round';
export type ButtonType = StyleSystemThemedProps & TouchableHighlightProps & ButtonProps;
export interface TouchableHighlightProps extends TouchableHighlightPropsBase {
  variant?: ButtonVariant;
  sizeVariant?: ButtonSizeVariant;
  colorVariant?: ButtonColorVariant;
  borderColorVariant?: ButtonColorVariant;
  shapeVariant?: ButtonShapeVariant;
}

export interface ButtonProps {
  title?: string | number | TFunctionResult;
  centerElement?: JSX.Element;
  titleColor?: ColorName;
  titleWeight?: TextWeightVariant;
  titleVariant?: TextVariant;
  leftElement?: JSX.Element;
  rightElement?: JSX.Element;
  collapsedElement?: JSX.Element;
  collapsedWidth?: number;
  isCollapsed?: boolean;
  loading?: boolean;
  underlayColorVariant?: ColorName;
  hoverColorVariant?: ButtonColorVariant;
  hoverBorderColor?: ButtonColorVariant;
  hoverTitleColorVariant?: ColorName;
}
