import { router } from '@inertiajs/react';
import { Bell, Check, Trash2 } from 'lucide-react';
import { useCallback, useEffect, useRef, useState } from 'react';
import { Badge } from '@/components/ui/badge';
import { Button } from '@/components/ui/button';
import {
    DropdownMenu,
    DropdownMenuContent,
    DropdownMenuItem,
    DropdownMenuSeparator,
    DropdownMenuTrigger,
} from '@/components/ui/dropdown-menu';

interface Notification {
    id: number;
    title: string;
    body: string | null;
    url: string | null;
    is_read: boolean;
    created_at: string;
}

export function NotificationBell() {
    const [notifications, setNotifications] = useState<Notification[]>([]);
    const [unreadCount, setUnreadCount] = useState(0);
    const [isOpen, setIsOpen] = useState(false);
    const intervalRef = useRef<ReturnType<typeof setInterval> | null>(null);
    const mountedRef = useRef(true);

    useEffect(() => {
        mountedRef.current = true;

        return () => {
            mountedRef.current = false;
        };
    }, []);

    const fetchUnreadCount = useCallback(async () => {
        try {
            const response = await fetch('/api/notifications/unread-count', {
                headers: {
                    'X-Requested-With': 'XMLHttpRequest',
                },
            });

            if (response.ok && mountedRef.current) {
                const data = await response.json();
                setUnreadCount(data.count);
            }
        } catch {
            // Silently fail
        }
    }, []);

    const fetchNotifications = useCallback(async () => {
        try {
            const response = await fetch('/api/notifications', {
                headers: {
                    'X-Requested-With': 'XMLHttpRequest',
                },
            });

            if (response.ok && mountedRef.current) {
                const data = await response.json();
                setNotifications(data);
            }
        } catch {
            // Silently fail
        }
    }, []);

    const markAsRead = useCallback(async (id: number) => {
        try {
            await fetch(`/api/notifications/${id}/read`, {
                method: 'PATCH',
                headers: {
                    'X-Requested-With': 'XMLHttpRequest',
                },
            });

            setNotifications((prev) =>
                prev.map((n) => (n.id === id ? { ...n, is_read: true } : n)),
            );
            setUnreadCount((prev) => Math.max(0, prev - 1));
        } catch {
            // Silently fail
        }
    }, []);

    const deleteNotification = useCallback(async (id: number) => {
        try {
            await fetch(`/api/notifications/${id}`, {
                method: 'DELETE',
                headers: {
                    'X-Requested-With': 'XMLHttpRequest',
                },
            });

            setNotifications((prev) => prev.filter((n) => n.id !== id));
            setUnreadCount((prev) => Math.max(0, prev - 1));
        } catch {
            // Silently fail
        }
    }, []);

    const markAllAsRead = useCallback(async () => {
        try {
            await fetch('/api/notifications/read-all', {
                method: 'PATCH',
                headers: {
                    'X-Requested-With': 'XMLHttpRequest',
                },
            });

            setNotifications((prev) =>
                prev.map((n) => ({ ...n, is_read: true })),
            );
            setUnreadCount(0);
        } catch {
            // Silently fail
        }
    }, []);

    useEffect(() => {
        // eslint-disable-next-line react-hooks/set-state-in-effect -- initial data fetch is safe
        void fetchUnreadCount();
        intervalRef.current = setInterval(() => {
            void fetchUnreadCount();
        }, 30000);

        return () => {
            if (intervalRef.current) {
                clearInterval(intervalRef.current);
            }
        };
    }, [fetchUnreadCount]);

    useEffect(() => {
        if (isOpen) {
            // eslint-disable-next-line react-hooks/set-state-in-effect -- fetch on dropdown open is safe
            void fetchNotifications();
        }
    }, [isOpen, fetchNotifications]);

    return (
        <DropdownMenu onOpenChange={setIsOpen}>
            <DropdownMenuTrigger asChild>
                <Button
                    variant="ghost"
                    size="icon"
                    className="relative h-9 w-9"
                >
                    <Bell className="h-4 w-4" />
                    {unreadCount > 0 && (
                        <Badge
                            variant="destructive"
                            className="absolute -top-1 -right-1 flex h-5 min-w-5 items-center justify-center rounded-full px-1 text-xs"
                        >
                            {unreadCount > 99 ? '99+' : unreadCount}
                        </Badge>
                    )}
                    <span className="sr-only">Notifikasi</span>
                </Button>
            </DropdownMenuTrigger>
            <DropdownMenuContent align="end" className="max-h-[350px] w-80">
                <div className="flex items-center justify-between border-b px-4 py-2">
                    <span className="text-sm font-semibold">Notifikasi</span>
                    {unreadCount > 0 && (
                        <button
                            onClick={() => {
                                void markAllAsRead();
                            }}
                            className="text-xs text-muted-foreground hover:text-foreground"
                        >
                            Tandai semua dibaca
                        </button>
                    )}
                </div>
                {notifications.length === 0 ? (
                    <div className="px-4 py-6 text-center text-sm text-muted-foreground">
                        Tidak ada notifikasi
                    </div>
                ) : (
                    notifications.map((notification) => (
                        <div key={notification.id}>
                            <div
                                className={`flex items-start gap-2 px-4 py-3 ${
                                    !notification.is_read
                                        ? 'border-l-2 border-l-primary bg-primary/5'
                                        : 'opacity-60'
                                }`}
                            >
                                <div
                                    className="min-w-0 flex-1 cursor-pointer"
                                    onClick={() => {
                                        if (notification.url) {
                                            router.visit(notification.url);
                                        }
                                    }}
                                >
                                    <span
                                        className={`text-sm ${
                                            !notification.is_read
                                                ? 'font-semibold'
                                                : 'font-medium'
                                        }`}
                                    >
                                        {notification.title}
                                    </span>
                                    {notification.body && (
                                        <span className="mt-0.5 line-clamp-2 block text-xs text-muted-foreground">
                                            {notification.body}
                                        </span>
                                    )}
                                    <span className="mt-0.5 block text-xs text-muted-foreground">
                                        {new Date(
                                            notification.created_at,
                                        ).toLocaleDateString('id-ID', {
                                            day: 'numeric',
                                            month: 'short',
                                            hour: '2-digit',
                                            minute: '2-digit',
                                        })}
                                    </span>
                                </div>
                                <div className="flex shrink-0 flex-col gap-1 pt-0.5">
                                    {!notification.is_read && (
                                        <Button
                                            variant="ghost"
                                            size="icon"
                                            className="h-6 w-6"
                                            title="Tandai sudah dibaca"
                                            onClick={() => {
                                                void markAsRead(
                                                    notification.id,
                                                );
                                            }}
                                        >
                                            <Check className="h-3 w-3" />
                                        </Button>
                                    )}
                                    <Button
                                        variant="ghost"
                                        size="icon"
                                        className="h-6 w-6 text-destructive hover:text-destructive"
                                        title="Hapus"
                                        onClick={() => {
                                            void deleteNotification(
                                                notification.id,
                                            );
                                        }}
                                    >
                                        <Trash2 className="h-3 w-3" />
                                    </Button>
                                </div>
                            </div>
                            <DropdownMenuSeparator />
                        </div>
                    ))
                )}
            </DropdownMenuContent>
        </DropdownMenu>
    );
}
