import {
    useImperativeHandle,
    forwardRef,
    useState,
    useRef
} from "react";
import {
    TextInput as NativeTextInput,
    TouchableOpacity,
    View
} from "react-native";
import type ITextInputProps from "./type";
import {
    type TextInputInstance,
    type ITextInputRef,
    type TextInputType
} from "./type";
import stylesheet, {
    getTextInputType,
    useStyles
} from "./stylesheet";
import {
    NCoreUIKitLocalize,
    NCoreUIKitTheme
} from "../../core/hooks";
import {
    type RefForwardingComponent,
    type INCoreUIKitIconProps,
    type NCoreUIKitIcon
} from "../../types";
import type ITextProps from "../text/type";
import {
    BadgeQuestionMarkIcon,
    BadgeSuccessIcon,
    BadgeDangerIcon,
    BadgeAlertIcon,
    BadgeInfoIcon,
    EyeOpenedIcon,
    EyeClosedIcon,
    CleanIcon
} from "../../assets/svg";
import Text from "../text";

const TextInputTypeIcon: Record<Exclude<TextInputType, "default">, NCoreUIKitIcon> = {
    "question": BadgeQuestionMarkIcon,
    "success": BadgeSuccessIcon,
    "warning": BadgeAlertIcon,
    "danger": BadgeDangerIcon,
    "info": BadgeInfoIcon
};

const TextInput: RefForwardingComponent<ITextInputRef, ITextInputProps> = ({
    rightIcon: RightIconComponentProp,
    hintTextIcon: HintTextIconProp,
    spreadBehaviour = "baseline",
    isShowHideTextButton = true,
    icon: IconComponentProp,
    hintTextContainerStyle,
    isCleanEnabled = false,
    contentContainerStyle,
    subTitle = "Optional",
    onFocus: onFocusProp,
    isRequired = false,
    isDisabled = false,
    onBlur: onBlurProp,
    hideTextIconStyle,
    variant = "text",
    type = "default",
    rightIconOnPress,
    rightIconStyle,
    isShowSubTitle,
    cleanIconStyle,
    onChangeText,
    initialValue,
    placeholder,
    iconOnPress,
    isOptional,
    validation,
    inputStyle,
    iconStyle,
    hintText,
    style,
    title,
    ...props
}, ref) => {
    const {
        inlineSpaces,
        typography,
        radiuses,
        borders,
        spaces,
        colors
    } = NCoreUIKitTheme.useContext();

    const {
        localize
    } = NCoreUIKitLocalize.useContext();

    const currentType = getTextInputType({
        type
    });

    const {
        hideTextIconContainer: hideTextIconContainerDynamicStyle,
        hintTextIcon: hintTextIconDynamicStyle,
        cleanButton: cleanButtonDynamicStyle,
        rightIcon: rightIconDynamicStyle,
        container: containerDynamicStyle,
        hintText: hintTextDynamicStyle,
        required: requiredDynamicStyle,
        subTitle: subTitleDynamicStyle,
        content: contentDynamicStyle,
        overlay: overlayDynamicStyle,
        title: titleDynamicStyle,
        input: inputDynamicStyle,
        icon: iconDynamicStyle
    } = useStyles({
        icon: IconComponentProp ? true : false,
        spreadBehaviour,
        inlineSpaces,
        currentType,
        isDisabled,
        typography,
        radiuses,
        borders,
        spaces,
        colors,
        title,
        type
    });

    const inputRef = useRef<TextInputInstance | null>(null);

    const styleType = type === "default" ? "neutral" : type === "question" ? "neutral" : type === "danger" ? "error" : type;

    const [
        value,
        setValue
    ] = useState(initialValue ? initialValue : "");

    const [
        hideValue,
        setHideValue
    ] = useState(true);

    useImperativeHandle(
        ref,
        () => ({
            updateValue,
            cleanText,
            focus,
            blur
        }),
        []
    );

    const titleProps: ITextProps = {
        color: currentType.titleColor,
        variant: "bodyLargeSize"
    };

    const iconProps: INCoreUIKitIconProps = {
        size: Number(typography.labelLargeSize.fontSize) + 6,
        color: currentType.iconColor
    };

    if(isDisabled) {
        iconProps.color = "disabled";
    }

    const blur = () => {
        inputRef.current?.blur();
    };

    const focus = () => {
        inputRef.current?.focus();
    };

    const cleanText = () => {
        setValue("");
        inputRef.current?.clear();
        if(onChangeText) {
            onChangeText("");
        }
    };

    const updateValue = (text: string) => {
        setValue(text);
        inputRef.current?.setNativeProps({
            text: text
        });
    };

    const onFocus = () => {
        if(onFocusProp) onFocusProp();
    };

    const onBlur = () => {
        if(onBlurProp) onBlurProp();
    };

    const toggleValueVisibility = () => {
        setHideValue(prevState => !prevState);
    };

    const renderCleanButton = () => {
        if(isDisabled) {
            return null;
        }

        if(variant !== "text") {
            return null;
        }

        if(!isCleanEnabled || !value.length) {
            return null;
        }

        return <View
            style={[
                cleanIconStyle,
                stylesheet.cleanButton,
                cleanButtonDynamicStyle
            ]}
            onClick={() => {
                if(onChangeText) {
                    onChangeText("");
                }
                setValue("");
            }}
        >
            <CleanIcon
                color="mid"
                size={20}
            />
        </View>;
    };

    const renderIcon = () => {
        if (!IconComponentProp) {
            return null;
        }

        return <View
            onClick={iconOnPress}
            style={[
                iconStyle,
                stylesheet.icon,
                iconDynamicStyle
            ]}
        >
            <IconComponentProp
                color={iconProps.color}
                size={iconProps.size}
            />
        </View>;
    };

    const renderRightIcon = () => {
        if (!RightIconComponentProp) {
            return null;
        }

        if(isShowHideTextButton && variant === "hidden") {
            return null;
        }

        if(isCleanEnabled && value.length > 0 && variant === "text") {
            return null;
        }

        return <View
            onClick={rightIconOnPress}
            style={[
                rightIconStyle,
                stylesheet.rightIcon,
                rightIconDynamicStyle
            ]}
        >
            <RightIconComponentProp
                color={iconProps.color}
                size={iconProps.size}
            />
        </View>;
    };

    const renderHideTextIcon = () => {
        if(!isShowHideTextButton) {
            return null;
        }

        if (variant !== "hidden") {
            return null;
        }

        return <View
            onClick={toggleValueVisibility}
            style={[
                hideTextIconStyle,
                stylesheet.hideTextIconContainer,
                hideTextIconContainerDynamicStyle
            ]}
        >
            {hideValue ?
                <EyeOpenedIcon
                    color={iconProps.color}
                    size={20}
                /> :
                <EyeClosedIcon
                    color={iconProps.color}
                    size={20}
                />
            }
        </View>;
    };

    const renderHintIcon = () => {
        if(!type) {
            return null;
        }

        if(HintTextIconProp) {
            return <HintTextIconProp
                color={isDisabled ? "disabled" : currentType.hideTextIconColor}
                size={20}
                style={[
                    stylesheet.hintTextIcon,
                    hintTextIconDynamicStyle
                ]}
            />;
        }

        const CurrentHintIcon = TextInputTypeIcon[type === "default" ? "question" : type];

        return <CurrentHintIcon
            customColor={isDisabled ? colors.system.state.content.disabled[styleType] : undefined}
            color={currentType.hideTextIconColor}
            size={20}
            style={[
                stylesheet.hintTextIcon,
                hintTextIconDynamicStyle
            ]}
        />;
    };

    const renderHintText = () => {
        if (!hintText) {
            return null;
        }

        return <View
            style={[
                hintTextContainerStyle,
                stylesheet.hintText,
                hintTextDynamicStyle
            ]}
        >
            {renderHintIcon()}
            <Text
                customColor={isDisabled ? colors.system.state.content.disabled[styleType] : undefined}
                color={currentType.hideTextColor}
                variant="labelSmallSize"
            >
                {hintText}
            </Text>
        </View>;
    };

    const renderRequired = () => {
        if(!isRequired) {
            return null;
        }

        return <Text
            color="danger"
            style={[
                stylesheet.required,
                requiredDynamicStyle
            ]}
        >*</Text>;
    };

    const renderSubtitle = () => {
        if(!isShowSubTitle && !isOptional) {
            return null;
        }

        return <Text
            variant="labelLargeSize"
            color={titleProps.color}
            style={[
                stylesheet.subTitle,
                subTitleDynamicStyle
            ]}
        >
            ( {isOptional ? localize("is-optional") : subTitle} )
        </Text>;
    };

    const renderTitle = () => {
        if (!title) {
            return null;
        }

        return <Text
            {...titleProps}
            variant={titleProps.variant}
            color={titleProps.color}
            style={[
                stylesheet.title,
                titleDynamicStyle
            ]}
        >
            {renderRequired()}
            {title}
            {renderSubtitle()}
        </Text>;
    };

    const renderInput = () => {
        return <NativeTextInput
            {...props}
            placeholderTextColor={currentType.placeholderColor}
            secureTextEntry={variant === "hidden" && hideValue}
            underlineColorAndroid="rgba(255,255,255,0)"
            placeholder={placeholder}
            allowFontScaling={false}
            editable={!isDisabled}
            multiline={false}
            onFocus={onFocus}
            onBlur={onBlur}
            ref={inputRef}
            value={value}
            onChangeText={(text) => {
                const inputValue = text.replace(/\n/g, "");

                if (inputValue === "") {
                    setValue("");
                    if(onChangeText) onChangeText("");
                    return;
                }

                if (validation) {
                    if (validation(inputValue)) {
                        setValue(inputValue);
                        if(onChangeText) onChangeText(inputValue);
                    }
                } else {
                    setValue(inputValue);
                    if(onChangeText) onChangeText(inputValue);
                }
            }}
            style={[
                inputStyle,
                stylesheet.input,
                inputDynamicStyle
            ]}
        />;
    };

    const renderOverlay = () => {
        return <View
            style={[
                stylesheet.overlay,
                overlayDynamicStyle
            ]}
        />;
    };

    return <TouchableOpacity
        disabled={isDisabled}
        style={[
            style,
            stylesheet.container,
            containerDynamicStyle
        ]}
        onPress={() => {
            if(!isDisabled) inputRef.current?.focus();
        }}
    >
        {renderTitle()}

        <View
            style={[
                contentContainerStyle,
                stylesheet.content,
                contentDynamicStyle
            ]}
        >
            {renderOverlay()}

            {renderIcon()}

            {renderInput()}

            {renderCleanButton()}
            {renderHideTextIcon()}
            {renderRightIcon()}
        </View>

        {renderHintText()}
    </TouchableOpacity>;
};
export default forwardRef(TextInput);
