import {
    useImperativeHandle,
    forwardRef,
    useEffect,
    useState,
    useRef
} from "react";
import {
    TextInput as NativeTextInput,
    TouchableOpacity,
    Keyboard,
    Platform,
    View
} from "react-native";
import type ITextAreaInputProps from "./type";
import {
    type TextAreaInputInstance,
    type ITextAreaInputRef,
    type TextAreaInputType
} from "./type";
import stylesheet, {
    getTextAreaInputType,
    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,
    CircleX as CircleXIcon,
    BadgeX as BadgeXIcon,
    type LucideIcon
} from "lucide-react-native";
import Text from "../text";

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

const TextAreaInput: RefForwardingComponent<ITextAreaInputRef, ITextAreaInputProps> = ({
    isAutoKeyboardDismissOnBlur = true,
    rightIcon: RightIconComponentProp,
    hintTextIcon: HintTextIconProp,
    spreadBehaviour = "baseline",
    isShowHintTextIcon = false,
    isShowLengthLimiter = true,
    isUpdateOnRealtime = false,
    icon: IconComponentProp,
    hintTextContainerStyle,
    isCleanEnabled = false,
    contentContainerStyle,
    subTitle = "Optional",
    onFocus: onFocusProp,
    isDisabled = false,
    isRequired = false,
    onBlur: onBlurProp,
    customBorderColor,
    customTitleColor,
    rightIconOnPress,
    type = "default",
    customIconColor,
    maxHeight = 350,
    minHeight = 250,
    cleanIconStyle,
    customLocalize,
    isShowSubTitle,
    rightIconStyle,
    initialValue,
    onChangeText,
    customColor,
    customTheme,
    iconOnPress,
    placeholder,
    inputStyle,
    isOptional,
    validation,
    iconStyle,
    maxLength,
    hintText,
    style,
    title,
    ...props
}, ref) => {
    const {
        inlineSpaces,
        typography,
        radiuses,
        borders,
        spaces,
        colors
    } = NCoreUIKitTheme.useContext(customTheme);

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

    const currentType = getTextAreaInputType({
        type
    });

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

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

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

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

    const {
        lengthLimiterContainer: lengthLimiterContainerDynamicStyle,
        inputContainer: inputContainerDynamicStyle,
        titleContainer: titleContainerDynamicStyle,
        hintTextIcon: hintTextIconDynamicStyle,
        cleanButton: cleanButtonDynamicStyle,
        container: containerDynamicStyle,
        rightIcon: rightIconDynamicStyle,
        hintText: hintTextDynamicStyle,
        required: requiredDynamicStyle,
        subTitle: subTitleDynamicStyle,
        content: contentDynamicStyle,
        overlay: overlayDynamicStyle,
        input: inputDynamicStyle,
        title: titleDynamicStyle,
        icon: iconDynamicStyle
    } = useStyles({
        icon: IconComponentProp ? true : false,
        customBorderColor,
        spreadBehaviour,
        inlineSpaces,
        currentType,
        customColor,
        isDisabled,
        typography,
        isFocused,
        maxHeight,
        minHeight,
        radiuses,
        borders,
        spaces,
        colors,
        title,
        type
    });

    useEffect(() => {
        if(initialValue) {
            if (Platform.OS !== "web") {
                inputRef.current?.setNativeProps({
                    text: initialValue
                });
            } else if (inputRef.current) {
                (inputRef.current as unknown as { value: string }).value = initialValue;
            }
        }
    }, []);

    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);

        if (Platform.OS !== "web") {
            inputRef.current?.setNativeProps({
                text: text
            });
        } else if (inputRef.current) {
            (inputRef.current as unknown as { value: string }).value = text;
        }
    };

    const onFocus = () => {
        setIsFocused(true);

        if(onFocusProp) onFocusProp();
    };

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

        inputRef.current?.blur();

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

        if(onBlurProp) onBlurProp();
    };

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

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

        return <TouchableOpacity
            onPress={() => {
                if(inputRef.current) inputRef.current?.clear();

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

                setValue("");
            }}
            style={[
                cleanIconStyle,
                stylesheet.cleanButton,
                cleanButtonDynamicStyle
            ]}
        >
            <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
                customColor={customIconColor}
                color={iconProps.color}
                size={iconProps.size}
            />
        </TouchableOpacity>;
    };

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

        if(isCleanEnabled && value.length > 0) {
            return null;
        }

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

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

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

        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
            style={[
                stylesheet.hintTextIcon,
                hintTextIconDynamicStyle
            ]}
            color={hintIconColor}
            size={20}
        />;
    };

    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
            style={[
                stylesheet.required,
                requiredDynamicStyle
            ]}
            color="danger"
        >
            *
        </Text>;
    };

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

        return <Text
            customColor={customTitleColor}
            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}
                customColor={customTitleColor}
                variant={titleProps.variant}
                color={titleProps.color}
                style={[
                    stylesheet.title,
                    titleDynamicStyle
                ]}
            >
                {title}
            </Text>
            {renderSubtitle()}
        </View>;
    };

    const renderLengthLimiter = () => {
        if(!isShowLengthLimiter || !maxLength) {
            return null;
        }

        return <View
            style={[
                stylesheet.lengthLimiterContainer,
                lengthLimiterContainerDynamicStyle
            ]}
        >
            <Text>
                {value.length} / {maxLength}
            </Text>
        </View>;
    };

    const renderInput = () => {
        return <View
            style={[
                stylesheet.inputContainer,
                inputContainerDynamicStyle
            ]}
        >
            <NativeTextInput
                {...props}
                placeholderTextColor={colors.content.text[currentType.placeholderColor]}
                onEndEditing={(t) => {
                    const text = t.nativeEvent.text;

                    if(!isUpdateOnRealtime) {
                        if (validation) {
                            if (validation(text)) {
                                setValue(text);

                                if(onChangeText) onChangeText(text);
                            }
                        } else {
                            setValue(text);

                            if(onChangeText) onChangeText(text);
                        }
                    }
                }}
                onChangeText={(text) => {
                    if(isUpdateOnRealtime) {
                        if (validation) {
                            if (validation(text)) {
                                setValue(text);

                                if(onChangeText) onChangeText(text);
                            }
                        } else {
                            setValue(text);

                            if(onChangeText) onChangeText(text);
                        }
                    }
                }}
                value={isUpdateOnRealtime ? value : undefined}
                underlineColorAndroid="rgba(255,255,255,0)"
                placeholder={placeholder}
                allowFontScaling={false}
                editable={!isDisabled}
                maxLength={maxLength}
                style={[
                    inputStyle,
                    stylesheet.input,
                    inputDynamicStyle
                ]}
                onFocus={onFocus}
                multiline={true}
                onBlur={onBlur}
                ref={inputRef}
            />
            {renderLengthLimiter()}
        </View>;
    };

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

    return <View
        style={[
            style,
            stylesheet.container,
            containerDynamicStyle
        ]}
        {...Platform.select({
            default: {
                onResponderRelease: () => {
                    if (!isDisabled) inputRef.current?.focus();
                },
                onStartShouldSetResponder: () => false
            },
            web: {
                onClick: () => {
                    if (!isDisabled) inputRef.current?.focus();
                },
                style: {
                    cursor: isDisabled ? "default" : "text"
                }
            } as Record<string, unknown>
        })}
    >
        {renderTitle()}
        <View
            style={[
                contentContainerStyle,
                stylesheet.content,
                contentDynamicStyle
            ]}
        >
            {renderOverlay()}
            {renderIcon()}
            {renderInput()}
            {renderCleanButton()}
            {renderRightIcon()}
        </View>
        {renderHintText()}
    </View>;
};
export default forwardRef(TextAreaInput);
