import { type Component, createEffect, onCleanup } from 'solid-js';
import { useRegisterSW } from 'virtual:pwa-register/solid';
import { toast } from 'solid-sonner';

// We export a function so other parts of the app can manually trigger an update
let manualUpdateFn: (() => void) | undefined;
let updateAndReloadFn: (() => void) | undefined;

export const forceServiceWorkerUpdate = () => {
    if (manualUpdateFn) {
        manualUpdateFn();
    } else {
        console.warn("PWA Updater not initialized yet");
    }
};

export const updateAndReloadApp = () => {
    if (updateAndReloadFn) {
        updateAndReloadFn();
    } else {
        console.warn("PWA Updater not initialized yet; reloading directly.");
        window.location.reload();
    }
};

export const PwaUpdater: Component = () => {
    let registration: ServiceWorkerRegistration | undefined;

    const {
        needRefresh: [needRefresh],
        updateServiceWorker,
    } = useRegisterSW({
        onRegistered(r: ServiceWorkerRegistration | undefined) {
            console.log('SW Registered:', r);
            registration = r;

            // Periodically check for updates (every 1 hour)
            if (r) {
                setInterval(() => {
                    console.log('Periodic SW update check...');
                    r.update();
                }, 60 * 60 * 1000);
            }
        },
        onRegisterError(error: Error | any) {
            console.error('SW registration error', error);
        },
    });

    createEffect(() => {
        // Expose function globally
        manualUpdateFn = () => {
            if (needRefresh()) {
                console.log('User manually forced an update. Reloading now...');
                updateServiceWorker(true);
            } else if (registration) {
                console.log('User manually asked to check for updates...');
                registration.update();
            }
        };

        updateAndReloadFn = () => {
            if (needRefresh()) {
                console.log('Update ready. Reloading now...');
                updateServiceWorker(true);
                return;
            }

            if (registration) {
                console.log('Checking for updates before reload...');
                registration.update();
            }

            const start = Date.now();
            const timeoutMs = 5000;
            const poll = window.setInterval(() => {
                if (needRefresh()) {
                    console.log('Update found. Reloading with new SW...');
                    window.clearInterval(poll);
                    updateServiceWorker(true);
                } else if (Date.now() - start > timeoutMs) {
                    console.log('No update detected quickly. Reloading now...');
                    window.clearInterval(poll);
                    toast.info("No update found");
                }
            }, 250);
        };
    });

    createEffect(() => {
        // Check for updates when the app regains focus/visibility
        const handleVisibilityFocus = () => {
            if (document.visibilityState === 'visible' && registration) {
                console.log('App became visible, checking for SW updates...');
                registration.update();
            }
        };

        document.addEventListener('visibilitychange', handleVisibilityFocus);
        window.addEventListener('focus', handleVisibilityFocus);

        onCleanup(() => {
            document.removeEventListener('visibilitychange', handleVisibilityFocus);
            window.removeEventListener('focus', handleVisibilityFocus);
        });
    });

    createEffect(() => {
        if (needRefresh()) {
            console.log('New PWA version available. Monitoring for idle/hidden state to update...');

            let idleTimeout: number | undefined;

            const triggerUpdate = () => {
                console.log('Triggering PWA update...');
                updateServiceWorker(true);
            };

            const resetIdle = () => {
                if (idleTimeout) window.clearTimeout(idleTimeout);
                // 10 minutes idle
                idleTimeout = window.setTimeout(triggerUpdate, 10 * 60 * 1000);
            };

            const handleVisibility = () => {
                if (document.visibilityState === 'hidden') {
                    triggerUpdate();
                }
            };

            // Start idle timer
            resetIdle();

            // Listen for user activity
            const events = ['mousedown', 'mousemove', 'keydown', 'scroll', 'touchstart'];
            events.forEach(e => window.addEventListener(e, resetIdle, { passive: true }));
            document.addEventListener('visibilitychange', handleVisibility);

            onCleanup(() => {
                if (idleTimeout) window.clearTimeout(idleTimeout);
                events.forEach(e => window.removeEventListener(e, resetIdle));
                document.removeEventListener('visibilitychange', handleVisibility);
            });
        }
    });

    return null;
};
