import {
    useEffect,
    useState,
    type FC,
    useRef
} from "react";
import {
    TouchableWithoutFeedback,
    type ViewStyle,
    Animated,
    Easing,
    View
} from "react-native";
import type ITooltipProps from "./type";
import stylesheet, {
    getTooltipType,
    useStyles
} from "./stylesheet";
import {
    NCoreUIKitTheme
} from "../../core/hooks";
import {
    X as XIcon
} from "lucide-react-native";
import Button from "../button";
import Text from "../text";

const Tooltip: FC<ITooltipProps> = ({
    isCloseOnPressActionButton = true,
    location = {
        horizontal: "center",
        vertical: "top"
    },
    isCloseOnPress = false,
    icon: CustomIcon,
    type = "neutral",
    customTheme,
    isVisible,
    onClosed,
    subTitle,
    children,
    onClose,
    onOpen,
    content,
    action,
    style,
    title
}) => {
    const {
        radiuses,
        colors,
        spaces
    } = NCoreUIKitTheme.useContext(customTheme);

    const [
        wrapperSize,
        setWrapperSize
    ] = useState({
        height: 0,
        width: 0
    });

    const [
        tooltipSize,
        setTooltipSize
    ] = useState({
        height: 0,
        width: 0
    });

    const [
        isInternalVisible,
        setIsInternalVisible
    ] = useState(false);

    const opacityAnim = useRef(new Animated.Value(0)).current;

    const currentType = getTooltipType({
        type
    });

    const {
        containerObject: containerObjectDynamicStyle,
        contentContainer: contentContainerDynamicStyle,
        iconContainer: iconContainerDynamicStyle,
        container: containerDynamicStyle,
        subTitle: subTitleDynamicStyle,
        action: actionDynamicStyle,
        title: titleDynamicStyle,
        caret: caretDynamicStyle
    } = useStyles({
        currentType,
        radiuses,
        colors,
        spaces,
        type
    });

    const isShow = isVisible !== undefined ? isVisible : isInternalVisible;

    useEffect(() => {
        if(isShow) {
            if(onOpen) onOpen();

            Animated.timing(opacityAnim, {
                useNativeDriver: true,
                easing: Easing.linear,
                duration: 200,
                toValue: 1
            }).start();
        } else {
            Animated.timing(opacityAnim, {
                useNativeDriver: true,
                easing: Easing.linear,
                duration: 200,
                toValue: 0
            }).start(({
                finished
            }) => {
                if(finished && onClosed) {
                    onClosed();
                }
            });
        }
    }, [
        isShow
    ]);

    const handleClose = () => {
        if(isVisible === undefined) {
            setIsInternalVisible(false);
        }
        if(onClose) onClose();
    };

    const handleToggle = () => {
        if(isVisible === undefined) {
            setIsInternalVisible(!isInternalVisible);
        }
        if(!isShow && onOpen) {
            onOpen();
        } else if (isShow && onClose) {
            onClose();
        }
    };

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

        return <View
            style={[
                stylesheet.iconContainer,
                iconContainerDynamicStyle
            ]}
        >
            <CustomIcon
                color={currentType.iconColor}
                size={16}
            />
        </View>;
    };

    const renderContent = () => {
        if(content) {
            if(typeof content === "function") {
                return content();
            }

            return content;
        }

        return <View
            style={[
                stylesheet.contentContainer,
                contentContainerDynamicStyle
            ]}
        >
            {
                title ?
                    <Text
                        style={{
                            ...stylesheet.title,
                            ...titleDynamicStyle
                        }}
                        color={currentType.titleColor}
                        variant="labelMediumSize"
                        numberOfLines={3}
                    >
                        {title}
                    </Text>
                :
                    null
            }
            {
                subTitle ?
                    <Text
                        style={{
                            ...stylesheet.subTitle,
                            ...subTitleDynamicStyle
                        }}
                        color={currentType.subTitleColor}
                        variant="labelSmallSize"
                        numberOfLines={2}
                    >
                        {subTitle}
                    </Text>
                :
                    null
            }
        </View>;
    };

    const renderAction = () => {
        if(!action) {
            return null;
        }

        return <Button
            onPress={() => {
                if(isCloseOnPressActionButton) handleClose();

                if(action.onPress) {
                    action.onPress({
                        closeAnimation: handleClose
                    });
                }
            }}
            icon={() => {
                if(action.title) {
                    return null;
                }

                return <XIcon
                    color={colors.content.text[currentType.actionColor]}
                    size={16}
                />;
            }}
            style={{
                ...action.style,
                ...actionDynamicStyle
            }}
            title={action.title ? action.title : undefined}
            spreadBehaviour="free"
            isCustomPadding={true}
            variant="ghost"
            size="small"
            type={type}
        />;
    };

    const getTooltipStyle = (): ViewStyle => {
        const _style: ViewStyle = {};

        if(tooltipSize.width > 0 && wrapperSize.width > 0) {
            if(location.vertical === "top") {
                _style.bottom = wrapperSize.height + 8;
            } else if (location.vertical === "bottom") {
                _style.top = wrapperSize.height + 8;
            } else {
                _style.top = (wrapperSize.height - tooltipSize.height) / 2;
            }

            if(location.horizontal === "left") {
                _style.right = wrapperSize.width + 8;
            } else if (location.horizontal === "right") {
                _style.left = wrapperSize.width + 8;
            } else {
                _style.left = (wrapperSize.width - tooltipSize.width) / 2;
            }
        } else {
            _style.opacity = 0;
        }

        return _style;
    };

    const getCaretStyle = (): ViewStyle => {
        const _style: ViewStyle = {};

        if(location.vertical === "top") {
            _style.bottom = -4;
        } else if (location.vertical === "bottom") {
            _style.top = -4;
        } else {
            _style.top = (tooltipSize.height - 12) / 2;
        }

        if(location.horizontal === "left") {
            _style.right = -4;
        } else if (location.horizontal === "right") {
            _style.left = -4;
        } else {
            _style.left = (tooltipSize.width - 12) / 2;
        }

        if (location.vertical === "top" && location.horizontal === "right") {
            _style.left = 12;
        } else if (location.vertical === "top" && location.horizontal === "left") {
            _style.right = 12;
        } else if (location.vertical === "bottom" && location.horizontal === "right") {
            _style.left = 12;
        } else if (location.vertical === "bottom" && location.horizontal === "left") {
            _style.right = 12;
        }

        return _style;
    };

    return <View
        onLayout={(e) => {
            const {
                height,
                width
            } = e.nativeEvent.layout;

            setWrapperSize(prev => {
                if (prev.height === height && prev.width === width) {
                    return prev;
                }
                return {
                    height,
                    width
                };
            });
        }}
        style={[
            stylesheet.wrapper,
            style
        ]}
    >
        <TouchableWithoutFeedback
            onPress={() => {
                if(!isCloseOnPress) {
                    handleToggle();
                } else if(isShow) {
                    handleClose();
                } else {
                    handleToggle();
                }
            }}
        >
            <View>
                {children}
            </View>
        </TouchableWithoutFeedback>
        {
            isShow || opacityAnim !== undefined ?
                <Animated.View
                    onLayout={(e) => {
                        const {
                            height,
                            width
                        } = e.nativeEvent.layout;

                        setTooltipSize(prev => {
                            if (prev.height === height && prev.width === width) {
                                return prev;
                            }
                            return {
                                height,
                                width
                            };
                        });
                    }}
                    style={[
                        stylesheet.container,
                        containerDynamicStyle,
                        getTooltipStyle(),
                        {
                            opacity: opacityAnim
                        }
                    ]}
                    pointerEvents={isShow ? "auto" : "none"}
                >
                    <View
                        style={[
                            stylesheet.caret,
                            caretDynamicStyle,
                            getCaretStyle()
                        ]}
                    />
                    <View
                        style={[
                            stylesheet.containerObject,
                            containerObjectDynamicStyle
                        ]}
                    >
                        {renderIcon()}
                        {renderContent()}
                        {renderAction()}
                    </View>
                </Animated.View>
            :
                null
        }
    </View>;
};
export default Tooltip;
