import React from 'react';
import type { ReactElement, ReactText } from 'react';
import {
  TouchableOpacity,
  View,
  type TouchableOpacityProps,
} from 'react-native';
import { Text, TextCategoryEnum } from './text';
import { classNames } from '../utils';

export enum AppearanceEnum {
  FILLED = 'FILLED',
  OUTLINE = 'OUTLINE',
  GHOST = 'GHOST',
}

export enum SizeEnum {
  SMALL = 'SMALL',
  MEDIUM = 'MEDIUM',
  LARGE = 'LARGE',
}

export interface ButtonProps extends TouchableOpacityProps {
  appearance?: AppearanceEnum;
  accessoryLeft?: ReactElement | (() => ReactElement);
  accessoryRight?: ReactElement | (() => ReactElement);
  size?: SizeEnum;
  text: string | ReactText | (() => ReactText);
  className?: string;
}

const RenderLeftAcc = ({
  component,
}: {
  component: ButtonProps['accessoryRight'];
}) => {
  return (
    <View className="mr-2">
      {/* @ts-ignore */}
      {typeof component === 'function' ? component() : component}
    </View>
  );
};

const RenderRightAcc = ({
  component,
}: {
  component: ButtonProps['accessoryRight'];
}) => {
  return (
    <View className="ml-2">
      {/* @ts-ignore */}
      {typeof component === 'function' ? component() : component}
    </View>
  );
};

// @ts-ignore
const RenderText: React.FC<{
  component: ButtonProps['text'];
  size: SizeEnum;
  appearance: AppearanceEnum;
}> = ({ component, size, appearance }) => {
  switch (typeof component) {
    case 'function':
      return component();
    case 'object':
      return component;
    default: // string
      let category = TextCategoryEnum.MEDIUM_PARAGRAPH;

      if (size === SizeEnum.LARGE) {
        category = TextCategoryEnum.LARGE_PARAGRAPH;
      }

      if (size === SizeEnum.SMALL) {
        category = TextCategoryEnum.SMALL_PARAGRAPH;
      }

      return (
        <Text
          category={category}
          className={classNames(
            'text-white',
            appearance !== AppearanceEnum.FILLED ? 'text-brand-500' : ''
          )}
        >
          {component}
        </Text>
      );
  }
};

export const Button: React.FC<ButtonProps> = (props) => {
  const {
    text,
    appearance = AppearanceEnum.FILLED,
    accessoryLeft,
    accessoryRight,
    size = SizeEnum.MEDIUM,
    className,
    ...restOfProps
  } = props;

  return (
    <TouchableOpacity
      className={classNames(
        'bg-brand-500 flex-row py-4 px-8 rounded-xl items-center justify-center w-[210px]',
        appearance === AppearanceEnum.OUTLINE
          ? 'bg-transparent border border-brand-500'
          : '',
        appearance === AppearanceEnum.GHOST
          ? 'bg-transparent text-brand-500'
          : '',
        size === SizeEnum.SMALL ? 'w-[155px]' : '',
        size === SizeEnum.LARGE ? 'w-[230px]' : '',
        className
      )}
      {...restOfProps}
    >
      {accessoryLeft && <RenderLeftAcc component={accessoryLeft} />}
      {text && (
        <RenderText component={text} size={size} appearance={appearance} />
      )}
      {accessoryRight && <RenderRightAcc component={accessoryRight} />}
    </TouchableOpacity>
  );
};
