import { router } from '@inertiajs/react';
import { useCallback, useEffect, useRef, useState } from 'react';

/**
 * Tell an operator that a chat just started, so they can jump in.
 *
 * Opt-in and off by default: browsers require a user gesture before the
 * permission prompt, and an alert nobody asked for is worse than none.
 * The preference is a UI setting, not data, so it lives in
 * localStorage — per browser, which is what an operator expects from
 * "notify me on this machine".
 *
 * Fires only while the tab is in the background. A visible tab already
 * shows the sidebar badge and the live list; interrupting someone who is
 * looking straight at the answer is noise.
 */
const PREF_KEY = 'pitchbar:new-chat-alerts';

const canNotify = (): boolean =>
    typeof window !== 'undefined' && 'Notification' in window;

export function newChatAlertsEnabled(): boolean {
    if (!canNotify()) {
        return false;
    }

    return (
        window.localStorage.getItem(PREF_KEY) === '1' &&
        Notification.permission === 'granted'
    );
}

/**
 * Ask for permission and remember the answer. Returns what the operator
 * actually ended up with, so the caller can explain a denial rather than
 * showing a toggle that silently does nothing.
 */
export async function requestNewChatAlerts(): Promise<
    'granted' | 'denied' | 'unsupported'
> {
    if (!canNotify()) {
        return 'unsupported';
    }

    const permission =
        Notification.permission === 'granted'
            ? 'granted'
            : await Notification.requestPermission();

    if (permission !== 'granted') {
        window.localStorage.removeItem(PREF_KEY);

        return 'denied';
    }

    window.localStorage.setItem(PREF_KEY, '1');

    return 'granted';
}

export function disableNewChatAlerts(): void {
    if (canNotify()) {
        window.localStorage.removeItem(PREF_KEY);
    }
}

/** Re-read the stored preference, including changes from another tab. */
export function useNewChatAlertPref(): boolean {
    const [on, setOn] = useState(() => newChatAlertsEnabled());

    useEffect(() => {
        const sync = () => setOn(newChatAlertsEnabled());
        window.addEventListener('storage', sync);
        window.addEventListener('focus', sync);

        return () => {
            window.removeEventListener('storage', sync);
            window.removeEventListener('focus', sync);
        };
    }, []);

    return on;
}

/**
 * Raise one notification per newly-arrived conversation.
 *
 * `latestId` comes from the shared live counts, which the sidebar polls
 * from every admin page. The first value seen is only recorded, never
 * announced — otherwise switching the toggle on would fire an alert for
 * a conversation that started an hour ago.
 */
export function useNewChatAlerts(
    latestId: string | null,
    title: string,
    body: string,
): void {
    const seen = useRef<string | null>(null);
    const seeded = useRef(false);

    const open = useCallback((id: string) => {
        window.focus();
        router.visit(`/app/conversations/${id}`);
    }, []);

    useEffect(() => {
        if (!latestId) {
            return;
        }

        if (!seeded.current) {
            seeded.current = true;
            seen.current = latestId;

            return;
        }

        if (latestId === seen.current) {
            return;
        }

        seen.current = latestId;

        if (!newChatAlertsEnabled()) {
            return;
        }

        // A visible tab already shows the badge and the live list.
        if (document.visibilityState === 'visible') {
            return;
        }

        const note = new Notification(title, {
            body,
            tag: `pitchbar-chat-${latestId}`,
        });

        note.onclick = () => {
            note.close();
            open(latestId);
        };
    }, [latestId, title, body, open]);
}
