import {
    useImperativeHandle,
    forwardRef,
    useState,
    useRef
} from "react";
import {
    TextInput as NativeTextInput,
    TouchableOpacity,
    Keyboard,
    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
} from "../../types";
import type ITextProps from "../text/type";
import {
    BadgeQuestionMark as BadgeQuestionMarkIcon,
    BadgeAlert as BadgeAlertIcon,
    BadgeCheck as BadgeCheckIcon,
    BadgeInfo as BadgeInfoIcon,
    EyeClosed as EyeClosedIcon,
    CircleX as CircleXIcon,
    BadgeX as BadgeXIcon,
    type LucideIcon,
    Eye as EyeIcon
} from "lucide-react-native";
import Text from "../text";

const TextInputTypeIcon: Record<Exclude<TextInputType, "default">, LucideIcon> = {
    "question": BadgeQuestionMarkIcon,
    "success": BadgeCheckIcon,
    "warning": BadgeAlertIcon,
    "info": BadgeInfoIcon,
    "danger": BadgeXIcon
};

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

    const {
        localize
    } = NCoreUIKitLocalize.useContext(customLocalize);

    const currentType = getTextInputType({
        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);

    const [
        isFocused,
        setIsFocused
    ] = useState(false);

    const {
        hideTextIconContainer: hideTextIconContainerDynamicStyle,
        titleContainer: titleContainerDynamicStyle,
        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,
        isFocused,
        radiuses,
        borders,
        spaces,
        colors,
        title,
        type
    });

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

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

    const iconProps: NCoreUIKit.IconCallbackProps = {
        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 = () => {
        setIsFocused(true);

        if(onFocusProp) onFocusProp();
    };

    const onBlur = () => {
        setIsFocused(false);

        inputRef.current?.blur();

        if(isAutoKeyboardDismissOnBlur) {
            Keyboard.dismiss();
        }

        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 <TouchableOpacity
            style={[
                cleanIconStyle,
                stylesheet.cleanButton,
                cleanButtonDynamicStyle
            ]}
            onPress={() => {
                if(inputRef.current) inputRef.current.clear();

                if(onChangeText) {
                    onChangeText("");
                }

                setValue("");
            }}
        >
            <CircleXIcon
                color={colors.content.icon[currentType.iconColor]}
                size={20}
            />
        </TouchableOpacity>;
    };

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

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

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

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

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

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

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

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

        return <TouchableOpacity
            onPress={toggleValueVisibility}
            style={[
                hideTextIconStyle,
                stylesheet.hideTextIconContainer,
                hideTextIconContainerDynamicStyle
            ]}
        >
            {hideValue ?
                <EyeIcon
                    color={colors.content.icon[iconProps.color]}
                    size={20}
                /> :
                <EyeClosedIcon
                    color={colors.content.icon[iconProps.color]}
                    size={20}
                />
            }
        </TouchableOpacity>;
    };

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

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

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

        let hintIconColor = colors.content.icon[currentType.hintTextIconColor];

        if(isDisabled) {
            hintIconColor = colors.system.state.content.disabled[styleType];
        }

        return <CurrentHintIcon
            color={hintIconColor}
            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.hintTextColor}
                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 <View
            style={[
                stylesheet.titleContainer,
                titleContainerDynamicStyle
            ]}
        >
            {renderRequired()}
            <Text
                {...titleProps}
                variant={titleProps.variant}
                color={titleProps.color}
                style={[
                    stylesheet.title,
                    titleDynamicStyle
                ]}
            >
                {title}
            </Text>
            {renderSubtitle()}
        </View>;
    };

    const renderInput = () => {
        return <NativeTextInput
            {...props}
            placeholderTextColor={colors.content.text[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}
            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
            ]}
        >
            {renderIcon()}

            {renderInput()}

            {renderCleanButton()}
            {renderHideTextIcon()}
            {renderRightIcon()}

            {renderOverlay()}
        </View>

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