import { Head, Link, router, usePage } from '@inertiajs/react';
import { useCallback, useEffect, useState } from 'react';
import {
    getCurrentPushSubscription,
    isPushSupported,
    serializePushSubscription,
    subscribeCurrentBrowser,
} from '../../pwa/push';
import '../../../css/notifications.css';

type NotificationSettingsProps = {
    wedding: { name: string };
    push: {
        publicKey: string | null;
        subscribedDeviceCount: number;
    };
};

type RetryAction = 'check' | 'activate' | 'deactivate';

const firstError = (errors: Record<string, string>): string => (
    Object.values(errors)[0] ?? 'Die Änderung konnte nicht gespeichert werden. Bitte versuche es erneut.'
);

export default function NotificationSettings() {
    const { wedding, push } = usePage<NotificationSettingsProps>().props;
    const supported = isPushSupported();
    const [permission, setPermission] = useState<NotificationPermission>(() => (
        supported ? Notification.permission : 'default'
    ));
    const [subscription, setSubscription] = useState<PushSubscription | null>(null);
    const [checking, setChecking] = useState(supported);
    const [processing, setProcessing] = useState(false);
    const [message, setMessage] = useState<string | null>(null);
    const [error, setError] = useState<string | null>(null);
    const [retryAction, setRetryAction] = useState<RetryAction>('check');

    const checkSubscription = useCallback(async () => {
        if (!supported) return;

        setChecking(true);
        setError(null);
        setRetryAction('check');

        try {
            setPermission(Notification.permission);
            setSubscription(await getCurrentPushSubscription());
        } catch {
            setError('Der Status dieses Browsers konnte nicht geladen werden.');
        } finally {
            setChecking(false);
        }
    }, [supported]);

    useEffect(() => {
        void checkSubscription();
    }, [checkSubscription]);

    const activate = async () => {
        setMessage(null);
        setError(null);
        setRetryAction('activate');

        if (!supported) {
            setError('Dieser Browser unterstützt Push-Benachrichtigungen nicht.');
            return;
        }

        if (!push.publicKey) {
            setError('Push-Benachrichtigungen sind derzeit noch nicht eingerichtet.');
            return;
        }

        setProcessing(true);

        try {
            let currentPermission = Notification.permission;
            if (currentPermission === 'default') {
                currentPermission = await Notification.requestPermission();
                setPermission(currentPermission);
            }

            if (currentPermission !== 'granted') {
                setProcessing(false);
                return;
            }

            const nextSubscription = await subscribeCurrentBrowser(push.publicKey);
            const payload = serializePushSubscription(nextSubscription);

            router.post('/benachrichtigungen/abonnements', payload, {
                preserveScroll: true,
                onSuccess: () => {
                    setSubscription(nextSubscription);
                    setMessage('Push-Benachrichtigungen wurden für diesen Browser aktiviert.');
                },
                onError: (errors) => setError(firstError(errors)),
                onFinish: () => setProcessing(false),
            });
        } catch {
            setError('Die Aktivierung ist technisch fehlgeschlagen. Bitte versuche es erneut.');
            setProcessing(false);
        }
    };

    const deactivate = async () => {
        setMessage(null);
        setError(null);
        setRetryAction('deactivate');
        setProcessing(true);

        try {
            const currentSubscription = subscription ?? await getCurrentPushSubscription();
            if (!currentSubscription) {
                setSubscription(null);
                setMessage('Für diesen Browser war kein Push-Abonnement aktiv.');
                setProcessing(false);
                return;
            }

            router.delete('/benachrichtigungen/abonnements', {
                data: { endpoint: currentSubscription.endpoint },
                preserveScroll: true,
                onSuccess: async () => {
                    try {
                        await currentSubscription.unsubscribe();
                        setSubscription(null);
                        setMessage('Push-Benachrichtigungen wurden für diesen Browser deaktiviert.');
                    } catch {
                        setError('Die Registrierung wurde entfernt, das Browser-Abonnement aber nicht vollständig beendet. Bitte versuche es erneut.');
                    }
                },
                onError: (errors) => setError(firstError(errors)),
                onFinish: () => setProcessing(false),
            });
        } catch {
            setError('Die Deaktivierung ist technisch fehlgeschlagen. Bitte versuche es erneut.');
            setProcessing(false);
        }
    };

    const retry = () => {
        if (retryAction === 'activate') void activate();
        else if (retryAction === 'deactivate') void deactivate();
        else void checkSubscription();
    };

    const isRegistered = Boolean(subscription);
    const status = !supported
        ? { label: 'Nicht unterstützt', copy: 'Dieser Browser kann keine Push-Benachrichtigungen von Wedster empfangen.', tone: 'muted' }
        : checking
            ? { label: 'Status wird geprüft', copy: 'Wir prüfen das Abonnement dieses Browsers.', tone: 'info' }
            : permission === 'denied'
                ? { label: 'Im Browser blockiert', copy: 'Erlaube Benachrichtigungen in den Website-Einstellungen deines Browsers, um sie hier zu aktivieren.', tone: 'warning' }
                : isRegistered
                    ? { label: 'Auf diesem Gerät aktiv', copy: 'Dieser Browser ist registriert und kann Push-Benachrichtigungen empfangen.', tone: 'success' }
                    : !push.publicKey
                        ? { label: 'Noch nicht verfügbar', copy: 'Die technische Push-Konfiguration fehlt derzeit.', tone: 'warning' }
                        : permission === 'granted'
                            ? { label: 'Noch nicht registriert', copy: 'Die Berechtigung ist erteilt. Registriere jetzt diesen Browser.', tone: 'info' }
                            : { label: 'Noch nicht angefragt', copy: 'Die Browser-Abfrage erscheint erst, wenn du ausdrücklich auf „Aktivieren“ klickst.', tone: 'info' };

    return (
        <>
            <Head title="Benachrichtigungen" />
            <main className="notifications-shell">
                <header className="notifications-header">
                    <Link className="notifications-back" href="/dashboard">Zurück zur Übersicht</Link>
                    <span className="notifications-eyebrow">{wedding.name}</span>
                    <h1>Push-Benachrichtigungen</h1>
                    <p>Bestimme, ob dieser Browser Hinweise von Wedster empfangen darf.</p>
                </header>

                {message && <div className="notifications-alert notifications-alert--success" role="status">{message}</div>}
                {error && (
                    <div className="notifications-alert notifications-alert--error" role="alert">
                        <span>{error}</span>
                        <button type="button" onClick={retry} disabled={processing}>Erneut versuchen</button>
                    </div>
                )}

                <section className="notifications-card" aria-labelledby="notifications-device-title">
                    <div className={`notifications-status notifications-status--${status.tone}`} role="status" aria-live="polite">
                        <span className="notifications-status__marker" aria-hidden="true" />
                        <div>
                            <strong>{status.label}</strong>
                            <p>{status.copy}</p>
                        </div>
                    </div>

                    <div className="notifications-device">
                        <div>
                            <span className="notifications-eyebrow">Aktueller Browser</span>
                            <h2 id="notifications-device-title">Benachrichtigungen auf diesem Gerät</h2>
                            <p>Diese Einstellung gilt nur für den Browser, den du gerade verwendest. Andere Geräte werden nicht verändert.</p>
                        </div>

                        {processing && <p className="notifications-processing" role="status">Änderung wird gespeichert …</p>}

                        <div className="notifications-actions">
                            {isRegistered ? (
                                <button className="notifications-button notifications-button--secondary" type="button" onClick={() => void deactivate()} disabled={processing || checking}>
                                    {processing ? 'Wird deaktiviert …' : 'Für diesen Browser deaktivieren'}
                                </button>
                            ) : (
                                <button
                                    className="notifications-button notifications-button--primary"
                                    type="button"
                                    onClick={() => void activate()}
                                    disabled={processing || checking || !supported || !push.publicKey || permission === 'denied'}
                                >
                                    {processing ? 'Wird aktiviert …' : 'Benachrichtigungen aktivieren'}
                                </button>
                            )}
                        </div>
                    </div>
                </section>

                <aside className="notifications-count" aria-label="Registrierte Geräte">
                    <span>Für dieses Konto registriert</span>
                    <strong>{push.subscribedDeviceCount}</strong>
                    <span>{push.subscribedDeviceCount === 1 ? 'Gerät' : 'Geräte'}</span>
                </aside>
            </main>
        </>
    );
}
