import {
    useImperativeHandle,
    forwardRef,
    useEffect,
    useRef
} from "react";
import {
    Animated,
    Easing,
    View
} from "react-native";
import type IDialogProps from "./type";
import type {
    IDialogRef
} from "./type";
import stylesheet, {
    useStyles
} from "./stylesheet";
import {
    NCoreUIKitLocalize,
    NCoreUIKitTheme
} from "../../core/hooks";
import type {
    RefForwardingComponent
} from "../../types";
import type {
    IModalRef
} from "../modal/type";
import {
    X as XIcon
} from "lucide-react-native";
import Button from "../button";
import Modal from "../modal";
import Text from "../text";
import {
    uuid
} from "../../utils";

const Dialog: RefForwardingComponent<IDialogRef, IDialogProps> = ({
    bottomContentContainerStyle,
    contentJustify = "centered",
    closeAnimationDelay = 100,
    openAnimationDelay = 100,
    contentContainerStyle,
    bottomContainerStyle,
    headerContainerStyle,
    secondaryButtonStyle,
    secondaryButtonProps,
    primaryButtonStyle,
    primaryButtonProps,
    closeIconProps = {
        color: "low",
        size: 22
    },
    isVisible = false,
    withModal = true,
    headerComponent,
    bottomComponent,
    onOverlayPress,
    variant = "ok",
    modalProps,
    id: outID,
    onClosed,
    children,
    content,
    style,
    title
}, ref) => {
    const {
        radiuses,
        colors,
        spaces
    } = NCoreUIKitTheme.useContext();

    const {
        localize
    } = NCoreUIKitLocalize.useContext();

    const id = useRef(outID ? outID : uuid());

    const {
        bottomContentContainer: bottomContentContainerDynamicStyle,
        headerContainer: headerContainerDynamicStyle,
        bottomContainer: bottomContainerDynamicStyle,
        primaryButton: primaryButtonDynamicStyle,
        contentText: contentTextDynamicStyle,
        headerTitle: headerTitleDynamicStyle,
        container: containerDynamicStyle,
        closeIcon: closeIconDynamicStyle,
        content: contentDynamicStyle
    } = useStyles({
        contentJustify,
        isVisible,
        radiuses,
        variant,
        colors,
        spaces
    });

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

    const modalRef = useRef<IModalRef>(null);

    useEffect(() => {
        if(isVisible) {
            Animated.timing(scaleAnim, {
                duration: openAnimationDelay,
                useNativeDriver: true,
                easing: Easing.linear,
                toValue: 1
            }).start();
        }
    }, [isVisible]);

    useImperativeHandle(
        ref,
        () => ({
            closeAnimation
        }),
        []
    );

    const closeAnimation = (_onClosed?: (props: {
        id: string;
    }) => void) => {
        Animated.timing(scaleAnim, {
            duration: closeAnimationDelay,
            useNativeDriver: true,
            easing: Easing.linear,
            toValue: 0
        }).start(({
            finished
        }) => {
            if(finished) {
                if(_onClosed) _onClosed({
                    id: id.current
                });

                if(onClosed) onClosed({
                    id: id.current
                });

                if(modalRef && modalRef.current) modalRef.current.closeAnimation();
            }
        });
    };

    const renderHeader = () => {
        return <View
            style={[
                headerContainerStyle,
                stylesheet.headerContainer,
                headerContainerDynamicStyle
            ]}
        >
            {headerComponent || <Text
                style={[
                    stylesheet.headerTitle,
                    headerTitleDynamicStyle
                ]}
                variant="titleLargeSize"
                color="mid"
            >
                {title}
            </Text>}
        </View>;
    };

    const renderBottom = () => {
        if(variant === "info") {
            return null;
        }

        return <View
            style={[
                bottomContainerStyle,
                stylesheet.bottomContainer,
                bottomContainerDynamicStyle
            ]}
        >
            {bottomComponent || <View
                style={[
                    bottomContentContainerStyle,
                    stylesheet.bottomContentContainer,
                    bottomContentContainerDynamicStyle
                ]}
            >
                {secondaryButton()}
                {primaryButton()}
            </View>}
        </View>;
    };

    const secondaryButton = () => {
        if(variant !== "yes-no") {
            return null;
        }

        return <Button
            onPress={() => {
                if(secondaryButtonProps?.onPress) secondaryButtonProps.onPress({
                    closeAnimation: (onClosed?: (props: {
                        id: string;
                    }) => void) => {
                        closeAnimation(onClosed);
                    }
                });
            }}
            spreadBehaviour={contentJustify === "centered" ? "stretch" : "free"}
            title={secondaryButtonProps?.title || localize("cancel")}
            isLoading={secondaryButtonProps?.isLoading}
            style={secondaryButtonStyle}
            variant="outline"
            type="neutral"
        />;
    };

    const primaryButton = () => {
        return <Button
            displayBehaviourWhileLoading={primaryButtonProps?.displayBehaviourWhileLoading}
            spreadBehaviour={contentJustify === "centered" ? "stretch" : "free"}
            onPress={() => {
                if(primaryButtonProps?.onPress) primaryButtonProps?.onPress({
                    closeAnimation: (onClosed?: (props: {
                        id: string;
                    }) => void) => {
                        closeAnimation(onClosed);
                    }
                });
            }}
            title={primaryButtonProps?.title || localize("ok")}
            isLoading={primaryButtonProps?.isLoading}
            style={[
                primaryButtonStyle,
                stylesheet.primaryButton,
                primaryButtonDynamicStyle
            ]}
            variant="filled"
            type="primary"
            size="medium"
        />;
    };

    const renderCloseIcon = () => {
        if(variant !== "info") {
            return null;
        }

        if(contentJustify === "centered") {
            return null;
        }

        return <Button
            onPress={() => {
                if(onOverlayPress) onOverlayPress({
                    closeAnimation: (onClosed?: (props: {
                        id: string;
                    }) => void) => {
                        closeAnimation(onClosed);
                    }
                });
            }}
            icon={() => <XIcon
                color={closeIconProps.color}
                size={closeIconProps.size}
            />}
            style={[
                stylesheet.closeIcon,
                closeIconDynamicStyle
            ]}
            isCustomPadding={true}
            variant="ghost"
        />;
    };

    const renderDialog = () => {
        if(!isVisible) {
            return null;
        }

        return <Animated.View
            style={[
                style,
                stylesheet.container,
                containerDynamicStyle,
                {
                    transform: [{
                        scale: scaleAnim
                    }]
                }
            ]}
        >
            {renderCloseIcon()}
            {renderHeader()}
            <View
                style={[
                    contentContainerStyle,
                    stylesheet.content,
                    contentDynamicStyle
                ]}
            >
                {children || <Text
                    style={[
                        stylesheet.contentText,
                        contentTextDynamicStyle
                    ]}
                    variant="bodyLargeSize"
                >
                    {content}
                </Text>}
            </View>
            {renderBottom()}
        </Animated.View>;
    };

    if(!isVisible) {
        return null;
    }

    return withModal ? <Modal
        {...modalProps}
        id={`${id.current}-modal`}
        ref={modalRef}
        onOverlayPress={() => {
            if(onOverlayPress) onOverlayPress({
                closeAnimation: (onClosed?: (props: {
                    id: string;
                }) => void) => {
                    closeAnimation(onClosed);
                }
            });
        }}
    >
        {renderDialog()}
    </Modal> : renderDialog();
};
export default forwardRef(Dialog);
