import {useContext, useEffect, useRef, useState} from "@wordpress/element";
import {createHooks} from '@wordpress/hooks';
import {__} from "@wordpress/i18n";
import {NotificationsContext} from "../../contexts/notifications";
import useOnlineStatus from "../../pages/components/hooks/use-online-status";
import {convertLinksToHTML} from "../../../helpers";

if (!LimbChatbot?.Hooks) {
    LimbChatbot.Hooks = createHooks();
}

export const NOTIF_QUICK_AUTOCLOSE_TIMEOUT = 2400;
export const NOTIF_AUTOCLOSE_TIMEOUT = 6400;
export const NOTIF_ERROR_AUTOCLOSE_TIMEOUT = 30400;

export function Notification({type, title, desc, onClose, autoClose = true, ...props}) {
    const [isHiding, setIsHiding] = useState(false);
    const containerRef = useRef(null);

    useEffect(() => {
        if (autoClose) {
            const timeout = props?.timeout || (type === 'success' ? NOTIF_AUTOCLOSE_TIMEOUT : NOTIF_ERROR_AUTOCLOSE_TIMEOUT);
            const timer = setTimeout(() => setIsHiding(true), timeout);
            const removeTimer = setTimeout(onClose, timeout + 600);

            return () => {
                clearTimeout(timer);
                clearTimeout(removeTimer);
            };
        }
    }, [autoClose, props?.timeout]);

    useEffect(() => {
        // Handle navigation to keep SPA structure
        const handleClick = (e) => {
            const anchor = e.target.closest('a');
            if (
                anchor
                && anchor.href
                && anchor.origin === window.location.origin
                && !anchor.hasAttribute('target')
                && !e.defaultPrevented
            ) {
                e.preventDefault();
                const searchParams = new URLSearchParams(anchor.search);
                const configs = searchParams.get('check_errors') ? (
                    {
                        showErrors: true,
                    }
                ) : null;
                if (props.screen === 'settings') {
                    // Do action to navigate to the page
                    const path = anchor.pathname + anchor.search + anchor.hash;
                    LimbChatbot.Hooks.doAction('lbaic.settings.go-to-path', path, configs);
                } else if (props.screen === 'chatbot-cpt') {
                    // Do action to navigate to the menu (or tab for backward compatibility)
                    const menuParam = searchParams.get('menu') || searchParams.get('tab');
                    LimbChatbot.Hooks.doAction('lbaic.posts.chatbot.go-to-menu-tab', menuParam, configs)
                }
            }
        };

        const container = containerRef.current;

        container?.addEventListener('click', handleClick);

        return () => {
            container?.removeEventListener('click', handleClick);
        };
    }, []);

    const preparedTitle = title?.length ? convertLinksToHTML(title, true) : '';
    const preparedDescription = desc?.length ? convertLinksToHTML(desc, true) : '';

    return (
        <div className={`lbaic-settings-notification-item ${type}${isHiding ? ' lbaic-settings-notification-hide' : ''}`}>
            <div className='lbaic-settings-notification-header'>
                <svg className='lbaic-settings-notification-status' xmlns='http://www.w3.org/2000/svg' fill='none'
                     viewBox='0 0 24 24'>
                    <use href={`#lbaic-settings-notice-${type}`}/>
                </svg>
                <div className='lbaic-settings-notification-title'>
                    <div className='lbaic-settings-notification-title-in'
                         dangerouslySetInnerHTML={{__html: preparedTitle}}/>
                </div>
                <button type='button' className='lbaic-settings-notification-close lbaic-settings-button-reset' onClick={onClose}>
                    <svg className='lbaic-settings-notification-close-i' xmlns='http://www.w3.org/2000/svg' fill='none'
                         viewBox='0 0 24 24'>
                        <use href='#lbaic-settings-notification-close'/>
                    </svg>
                </button>
            </div>
            {preparedDescription && (
                <div ref={containerRef} className='lbaic-settings-notification-body'>
                    <div
                        className='lbaic-settings-notification-desc'
                        dangerouslySetInnerHTML={{__html: preparedDescription}}
                    />
                </div>
            )}
        </div>
    )
}

export default function NotificationLayout({screen = 'settings'}) {
    const notifications = useContext(NotificationsContext);
    const isOnline = useOnlineStatus();
    const prevIsOnline = useRef(isOnline);

    useEffect(() => {
        if (prevIsOnline.current !== isOnline || !isOnline) {
            // Online status changed
            if (isOnline) {
                notifications.set(prevState =>
                    [
                        ...prevState.filter(item => item.id !== 'online' && item.id !== 'offline'),
                        {
                            id: 'online',
                            type: 'success',
                            title: __("You're back online.", 'limb-chatbot'),
                        }
                    ]
                );
            } else {
                notifications.set(prevState =>
                    [
                        ...prevState.filter(item => item.id !== 'online' && item.id !== 'offline'),
                        {
                            id: 'offline',
                            type: 'error',
                            title: __("You are offline.", 'limb-chatbot'),
                            description: __("Changes made now will not be saved.", 'limb-chatbot'),
                            autoClose: false,
                        }
                    ]
                );
            }
        }

        prevIsOnline.current = isOnline;
    }, [isOnline]);

    /**
     * Remove notification
     *
     * @param {number} id Notification ID
     */
    const remove = (id) => {
        notifications.set((prev) => prev.filter((notification) => notification.id !== id));
    }

    return (
        <div className='lbaic-settings-notification-layout lbaic-settings-scroll-y lbaic-settings-scroll-style'>
            <div className='lbaic-settings-notification'>
                {notifications.get.map(({id, type, title, description, ...more}) => (
                    <Notification
                        key={id}
                        type={type}
                        title={title}
                        desc={description}
                        onClose={() => remove(id)}
                        screen={screen}
                        autoClose={more?.autoClose}
                        timeout={more?.timeout}
                    />
                ))}
            </div>
        </div>
    )
}