import { Head, usePage } from '@inertiajs/react';
import { Bell, Camera, MapPin } from 'lucide-react';
import { useCallback, useEffect, useState } from 'react';
import { Alert, AlertDescription, AlertTitle } from '@/components/ui/alert';
import { Switch } from '@/components/ui/switch';
import { usePushNotification } from '@/hooks/use-push-notification';
import { edit } from '@/routes/permissions';

type PermissionStatus = 'granted' | 'denied' | 'prompt' | 'unknown';

const isPWA = () => {
    return (
        window.matchMedia('(display-mode: standalone)').matches ||
        (window.navigator as { standalone?: boolean }).standalone === true
    );
};

const getPlatform = (): 'android' | 'ios' | 'desktop' => {
    const ua = navigator.userAgent.toLowerCase();

    if (/android/.test(ua)) {
        return 'android';
    }

    if (/iphone|ipad|ipod/.test(ua)) {
        return 'ios';
    }

    return 'desktop';
};

const getDeniedMessage = (appName: string): string => {
    if (!isPWA()) {
        return 'Izin ditolak. Klik ikon gembok di address bar untuk mengaktifkannya.';
    }

    const platform = getPlatform();

    switch (platform) {
        case 'android':
            return `Izin ditolak. Buka Pengaturan > Aplikasi > ${appName} > Izin untuk mengaktifkannya.`;
        case 'ios':
            return `Izin ditolak. Buka Pengaturan > ${appName} > Safari > Izin untuk mengaktifkannya.`;
        default:
            return `Izin ditolak. Buka Pengaturan sistem untuk mengaktifkan izin ${appName}.`;
    }
};

function getInitialNotificationPermission(): PermissionStatus {
    if (!('Notification' in window)) {
        return 'denied';
    }

    return Notification.permission as PermissionStatus;
}

function getInitialCameraPermission(): PermissionStatus {
    if (!navigator.mediaDevices) {
        return 'denied';
    }

    return 'unknown';
}

function getInitialLocationPermission(): PermissionStatus {
    if (!('geolocation' in navigator)) {
        return 'denied';
    }

    return 'unknown';
}

export default function Permissions() {
    const { vapidPublicKey } = usePage().props as { vapidPublicKey?: string };
    const [notifications, setNotifications] = useState<PermissionStatus>(
        getInitialNotificationPermission,
    );
    const [camera, setCamera] = useState<PermissionStatus>(
        getInitialCameraPermission,
    );
    const [location, setLocation] = useState<PermissionStatus>(
        getInitialLocationPermission,
    );
    const [isSubscribing, setIsSubscribing] = useState(false);

    const { isSupported, requestPermission, subscribe, unsubscribe } =
        usePushNotification();

    const appName = 'DST Collection';

    const checkCameraPermission = useCallback(async () => {
        if (!navigator.mediaDevices) {
            setCamera('denied');

            return;
        }

        try {
            const stream = await navigator.mediaDevices.getUserMedia({
                video: true,
            });
            stream.getTracks().forEach((track) => track.stop());
            setCamera('granted');
        } catch {
            if ('permissions' in navigator) {
                try {
                    const result = await navigator.permissions.query({
                        name: 'camera' as PermissionName,
                    });
                    setCamera(result.state as PermissionStatus);
                } catch {
                    setCamera('denied');
                }
            } else {
                setCamera('denied');
            }
        }
    }, []);

    const checkLocationPermission = useCallback(async () => {
        if (!('geolocation' in navigator)) {
            setLocation('denied');

            return;
        }

        navigator.geolocation.getCurrentPosition(
            () => setLocation('granted'),
            async () => {
                if ('permissions' in navigator) {
                    try {
                        const result = await navigator.permissions.query({
                            name: 'geolocation',
                        });
                        setLocation(result.state as PermissionStatus);
                    } catch {
                        setLocation('denied');
                    }
                } else {
                    setLocation('denied');
                }
            },
        );
    }, []);

    useEffect(() => {
        // eslint-disable-next-line react-hooks/set-state-in-effect -- permission check on mount is safe
        checkCameraPermission();
         
        checkLocationPermission();
    }, [checkCameraPermission, checkLocationPermission]);

    const handleNotifications = async (checked: boolean) => {
        if (isSubscribing) {
            return;
        }

        if (checked) {
            if (!isSupported || !('Notification' in window)) {
                return;
            }

            if (Notification.permission === 'denied') {
                setNotifications('denied');

                return;
            }

            setIsSubscribing(true);

            try {
                const result = await requestPermission();
                setNotifications(result);

                if (result === 'granted' && vapidPublicKey) {
                    await subscribe(vapidPublicKey);
                }
            } finally {
                setIsSubscribing(false);
            }
        } else {
            await unsubscribe();
            setNotifications('prompt');
        }
    };

    const handleCamera = async (checked: boolean) => {
        if (checked) {
            try {
                const stream = await navigator.mediaDevices.getUserMedia({
                    video: true,
                });
                stream.getTracks().forEach((track) => track.stop());
                setCamera('granted');
            } catch {
                setCamera('denied');
            }
        } else {
            setCamera('prompt');
        }
    };

    const handleLocation = async (checked: boolean) => {
        if (checked) {
            navigator.geolocation.getCurrentPosition(
                () => setLocation('granted'),
                () => setLocation('denied'),
            );
        } else {
            setLocation('prompt');
        }
    };

    const isDenied = (status: PermissionStatus) => status === 'denied';
    const deniedMessage = getDeniedMessage(appName);

    return (
        <>
            <Head title="Izin" />

            <h1 className="sr-only">Izin</h1>

            <div className="flex h-full flex-1 flex-col gap-4 overflow-x-auto px-4 md:px-6">
                <Alert
                    variant={
                        isDenied(notifications) ? 'destructive' : 'default'
                    }
                >
                    <Bell className="h-4 w-4" />
                    <div className="flex items-center justify-between">
                        <div className="flex-1">
                            <AlertTitle>Notifikasi</AlertTitle>
                            <AlertDescription>
                                Izinkan aplikasi mengirimkan notifikasi push ke
                                perangkat Anda.
                            </AlertDescription>
                            {isDenied(notifications) && (
                                <p className="mt-1 text-sm text-destructive">
                                    {deniedMessage}
                                </p>
                            )}
                        </div>
                        <div className="flex items-center gap-2">
                            <Switch
                                checked={notifications === 'granted'}
                                onCheckedChange={handleNotifications}
                                disabled={
                                    isDenied(notifications) || isSubscribing
                                }
                            />
                        </div>
                    </div>
                </Alert>

                <Alert variant={isDenied(camera) ? 'destructive' : 'default'}>
                    <Camera className="h-4 w-4" />
                    <div className="flex items-center justify-between">
                        <div className="flex-1">
                            <AlertTitle>Kamera</AlertTitle>
                            <AlertDescription>
                                Izinkan aplikasi mengakses kamera perangkat Anda
                                untuk mengambil foto atau video.
                            </AlertDescription>
                            {isDenied(camera) && (
                                <p className="mt-1 text-sm text-destructive">
                                    {deniedMessage}
                                </p>
                            )}
                        </div>
                        <div className="flex items-center gap-2">
                            <Switch
                                checked={camera === 'granted'}
                                onCheckedChange={handleCamera}
                                disabled={isDenied(camera)}
                            />
                        </div>
                    </div>
                </Alert>

                <Alert variant={isDenied(location) ? 'destructive' : 'default'}>
                    <MapPin className="h-4 w-4" />
                    <div className="flex items-center justify-between">
                        <div className="flex-1">
                            <AlertTitle>Lokasi</AlertTitle>
                            <AlertDescription>
                                Izinkan aplikasi mengakses lokasi perangkat Anda
                                untuk menyediakan layanan berbasis lokasi.
                            </AlertDescription>
                            {isDenied(location) && (
                                <p className="mt-1 text-sm text-destructive">
                                    {deniedMessage}
                                </p>
                            )}
                        </div>
                        <div className="flex items-center gap-2">
                            <Switch
                                checked={location === 'granted'}
                                onCheckedChange={handleLocation}
                                disabled={isDenied(location)}
                            />
                        </div>
                    </div>
                </Alert>
            </div>
        </>
    );
}
