import { TextInput, View, StyleSheet, Animated } from 'react-native';
import styled from '@emotion/native';
import type { Theme } from '@emotion/react';
import Typography from '../Typography';

export type State = 'default' | 'filled' | 'disabled' | 'readonly' | 'error';
type Variant = 'text' | 'textarea';

const genBorderWidth = (
  theme: Theme,
  themeState: State,
  themeFocused: boolean
): number => {
  if (themeState === 'readonly') return 0;
  return themeFocused
    ? theme.__hd__.textInput.borderWidths.container.focused
    : theme.__hd__.textInput.borderWidths.container.normal;
};

const genBorderColor = (
  theme: Theme,
  themeState: State,
  themeFocused: boolean,
  themeFilled: boolean
): string => {
  if (themeState === 'error' && !themeFilled) {
    return theme.__hd__.textInput.colors.borders.default;
  }
  if (themeState === 'error' && themeFilled) {
    return theme.__hd__.textInput.colors.borders.error;
  }
  if (themeFocused) {
    return (
      theme.__hd__.textInput.colors.borders.focused ??
      theme.__hd__.textInput.colors.borders.default
    );
  }
  return (
    theme.__hd__.textInput.colors.borders[themeState] ??
    theme.__hd__.textInput.colors.borders.default
  );
};

const StyledContainer = styled(View)(({ theme }) => ({
  width: '100%',
  marginTop: theme.__hd__.textInput.space.containerMarginTop,
}));

const StyledLabelContainerInsideTextInput = styled(Animated.View)<{
  themeVariant: Variant;
}>(({ themeVariant, theme }) => ({
  flexDirection: 'row',
  alignItems: themeVariant === 'text' ? 'center' : 'flex-start',
  position: 'absolute',
  zIndex: 1,
  left: 0,
  right: theme.space.medium,
  top: 0,
}));

const StyledLabelInsideTextInput = styled(View)<{
  themeState: State;
}>(({ theme, themeState }) => ({
  textAlignVertical: 'center',
  alignContent: 'center',
  alignItems: 'center',
  color: theme.__hd__.textInput.colors.labelsInsideTextInput[themeState],
  marginTop: theme.__hd__.textInput.space.labelInsideTextInputMarginTop,
  flexDirection: 'row',
}));

const StyledAsteriskLabelInsideTextInput = styled(Typography.Body)<{
  themeState: State;
}>(({ theme, themeState }) => ({
  color: theme.__hd__.textInput.colors.asterisks[themeState],
}));

const StyledErrorContainer = styled(View)(({ theme }) => ({
  marginRight: theme.__hd__.textInput.space.errorContainerMarginRight,
  flexDirection: 'row',
  alignItems: 'center',
  flex: 1,
  flexGrow: 4,
}));

const StyledError = styled(Typography.Caption)(({ theme }) => ({
  color: theme.__hd__.textInput.colors.error,
}));

const StyledMaxLengthMessage = styled(Typography.Caption)<{
  themeState: State;
}>(({ theme, themeState }) => ({
  color: theme.__hd__.textInput.colors.maxLengthLabels[themeState],
  flex: 1,
  flexGrow: 1,
  textAlign: 'right',
}));

const StyledHelperText = Typography.Caption;
const StyledTextInput = styled(TextInput)<{ themeVariant: Variant }>(
  ({ theme, themeVariant }) => ({
    textAlignVertical: themeVariant === 'text' ? 'center' : 'top',
    fontSize: theme.__hd__.textInput.fontSizes.text,
    alignSelf: 'stretch',
    flexGrow: 2,
    marginHorizontal: 0,
    paddingVertical: 0,
    maxHeight: theme.__hd__.textInput.sizes.textInputMaxHeight,
    height:
      themeVariant === 'text'
        ? undefined
        : theme.__hd__.textInput.sizes.textareaHeight,
    fontFamily: theme.__hd__.textInput.fonts.text,
  })
);

const StyledBorderBackDrop = styled(View)<{
  themeState: State;
  themeFocused: boolean;
  themeFilled: boolean;
}>(({ theme, themeFocused, themeState, themeFilled }) => ({
  ...StyleSheet.absoluteFillObject,
  borderWidth: genBorderWidth(theme, themeState, themeFocused),
  borderRadius: theme.__hd__.textInput.radii.container,
  borderColor: genBorderColor(theme, themeState, themeFocused, themeFilled),
}));

const StyledTextInputContainer = styled(View)<{
  themeVariant: Variant;
  themeState: State;
}>(({ theme, themeVariant, themeState }) => ({
  flexDirection: 'row',
  alignItems: 'center',
  paddingHorizontal: theme.__hd__.textInput.space.containerHorizontalPadding,
  paddingVertical: theme.__hd__.textInput.space.containerVerticalPadding,
  borderRadius: theme.__hd__.textInput.radii.container,
  ...(themeVariant === 'text' && {
    minHeight: theme.__hd__.textInput.sizes.containerMinHeight,
  }),
  ...(themeState === 'disabled' && { opacity: 0.5 }),
  gap: theme.space.smallMedium,
}));

// Outer wrapper that owns flex-grow/shrink and provides the positioning context
// for StyledLabelContainerInsideTextInput (position: absolute).
const StyledInputContentContainer = styled(View)<{ themeHasLabel: boolean }>(
  ({ themeHasLabel }) => ({
    flexGrow: 2,
    flexShrink: 1,
    alignSelf: 'stretch',
    justifyContent: themeHasLabel ? 'flex-start' : 'center',
  })
);

const StyledTextInputAndLabelContainer = styled(View)<{
  themeHasLabel: boolean;
}>(({ theme, themeHasLabel }) => ({
  flexDirection: 'row',
  alignItems: 'center',
  alignSelf: 'stretch',
  ...(themeHasLabel && {
    paddingTop: theme.__hd__.textInput.space.inputAndLabelContainerPaddingTop,
  }),
}));

const StyledErrorAndHelpTextContainer = styled(View)(({ theme }) => ({
  minHeight: theme.__hd__.textInput.sizes.errorAndHelpTextContainerMinHeight,
  paddingTop: theme.__hd__.textInput.space.errorAndHelpTextContainerPaddingTop,
}));

const StyledErrorAndMaxLengthContainer = styled(View)(({ theme }) => ({
  flexDirection: 'row',
  justifyContent: 'space-between',
  alignItems: 'flex-start',
  marginTop: theme.__hd__.textInput.space.errorAndHelpTextContainerMarginTop,
}));

export {
  StyledTextInputContainer,
  StyledAsteriskLabelInsideTextInput,
  StyledTextInput,
  StyledError,
  StyledMaxLengthMessage,
  StyledLabelInsideTextInput,
  StyledContainer,
  StyledErrorContainer,
  StyledHelperText,
  StyledInputContentContainer,
  StyledTextInputAndLabelContainer,
  StyledLabelContainerInsideTextInput,
  StyledErrorAndHelpTextContainer,
  StyledBorderBackDrop,
  StyledErrorAndMaxLengthContainer,
};
