import { Combobox as ComboboxPrimitive } from '@base-ui/react';
import { router, usePage, WhenVisible } from '@inertiajs/react';
import { format } from 'date-fns';
import { Bell, CheckCheck, Loader2, Trash2 } from 'lucide-react';
import { useState } from 'react';
import { ConfirmDialog } from '@/components/confirm-dialog';
import { Button } from '@/components/ui/button';
import { Combobox, ComboboxContent } from '@/components/ui/combobox';
import { cn } from '@/lib/utils';
import { destroy, markAllRead, clearAll, read } from '@/routes/notifications';
import type { Notification, NotificationPage } from '@/types/notification';

export function NotificationBell() {
    const { props } = usePage<{ notifications?: NotificationPage }>();
    const unreadCount = props.unreadNotificationsCount ?? 0;
    const notifications = props.notifications ?? {
        data: [],
        current_page: 1,
        last_page: 1,
        per_page: 15,
        total: 0,
    };

    const [open, setOpen] = useState(false);
    const [clearAllOpen, setClearAllOpen] = useState(false);

    const hasMore = notifications.current_page < notifications.last_page;
    const hasNotifications = notifications.data.length > 0;
    const hasUnread = notifications.data.some((n) => !n.is_read);

    function handleMarkAllRead() {
        router.patch(markAllRead().url, {}, { preserveScroll: true });
    }

    function handleClearAll() {
        router.delete(clearAll().url, {
            preserveScroll: true,
            onSuccess: () => setClearAllOpen(false),
        });
    }

    function handleMarkRead(notification: Notification) {
        router.patch(read(notification.id).url, {}, { preserveScroll: true });
    }

    function handleDelete(notification: Notification) {
        router.delete(destroy(notification.id).url, { preserveScroll: true });
    }

    return (
        <>
            <Combobox open={open} onOpenChange={setOpen}>
                <ComboboxPrimitive.Trigger
                    render={
                        <Button
                            variant="ghost"
                            size="icon"
                            className="relative"
                        />
                    }
                >
                    <Bell className="h-5 w-5" />
                    {unreadCount > 0 && (
                        <span className="absolute top-1 right-1 flex h-4 min-w-4 items-center justify-center rounded-full bg-destructive px-1 text-[10px] font-medium text-white">
                            {unreadCount > 99 ? '99+' : unreadCount}
                        </span>
                    )}
                    <span className="sr-only">Notifikasi</span>
                </ComboboxPrimitive.Trigger>

                <ComboboxContent
                    align="end"
                    className="w-96 max-w-[90vw] min-w-96 p-0"
                >
                    <div className="flex items-center justify-between border-b p-3">
                        <span className="font-medium">Notifikasi</span>
                        <div className="flex gap-1">
                            <Button
                                variant="ghost"
                                size="icon"
                                title="Tandai semua dibaca"
                                disabled={!hasUnread}
                                onClick={handleMarkAllRead}
                            >
                                <CheckCheck className="h-4 w-4" />
                            </Button>
                            <Button
                                variant="ghost"
                                size="icon"
                                title="Hapus semua"
                                disabled={!hasNotifications}
                                onClick={() => setClearAllOpen(true)}
                            >
                                <Trash2 className="h-4 w-4" />
                            </Button>
                        </div>
                    </div>

                    <div className="max-h-96 overflow-y-auto">
                        {hasNotifications ? (
                            <div className="flex flex-col divide-y">
                                {notifications.data.map((notification) => (
                                    <div
                                        key={notification.id}
                                        className={cn(
                                            'flex items-start justify-between gap-2 p-3',
                                            !notification.is_read &&
                                                'bg-primary/5',
                                        )}
                                    >
                                        <div className="flex items-start gap-2">
                                            {!notification.is_read && (
                                                <span className="mt-1.5 h-2 w-2 shrink-0 rounded-full bg-primary" />
                                            )}
                                            <div>
                                                <p className="text-sm font-medium">
                                                    {notification.title ?? '-'}
                                                </p>
                                                {notification.content && (
                                                    <p className="mt-0.5 text-xs text-muted-foreground">
                                                        {notification.content}
                                                    </p>
                                                )}
                                                <p className="mt-1 text-xs text-muted-foreground">
                                                    {format(
                                                        new Date(
                                                            notification.created_at,
                                                        ),
                                                        'd MMM yyyy, HH:mm',
                                                    )}
                                                </p>
                                            </div>
                                        </div>
                                        <div className="flex shrink-0 items-center gap-1">
                                            {!notification.is_read && (
                                                <Button
                                                    variant="ghost"
                                                    size="icon"
                                                    className="h-7 w-7"
                                                    title="Tandai dibaca"
                                                    onClick={() =>
                                                        handleMarkRead(
                                                            notification,
                                                        )
                                                    }
                                                >
                                                    <CheckCheck className="h-3.5 w-3.5" />
                                                </Button>
                                            )}
                                            <Button
                                                variant="ghost"
                                                size="icon"
                                                className="h-7 w-7"
                                                title="Hapus"
                                                onClick={() =>
                                                    handleDelete(notification)
                                                }
                                            >
                                                <Trash2 className="h-3.5 w-3.5 text-destructive" />
                                            </Button>
                                        </div>
                                    </div>
                                ))}

                                {hasMore && (
                                    <WhenVisible
                                        always
                                        data="notifications"
                                        params={{
                                            data: {
                                                page:
                                                    notifications.current_page +
                                                    1,
                                            },
                                        }}
                                        fallback={
                                            <div className="flex justify-center py-3">
                                                <Loader2 className="h-4 w-4 animate-spin text-muted-foreground" />
                                            </div>
                                        }
                                    >
                                        <div className="flex justify-center py-3">
                                            <Loader2 className="h-4 w-4 animate-spin text-muted-foreground" />
                                        </div>
                                    </WhenVisible>
                                )}
                            </div>
                        ) : (
                            <div className="flex h-24 items-center justify-center text-sm text-muted-foreground">
                                Belum ada notifikasi.
                            </div>
                        )}
                    </div>
                </ComboboxContent>
            </Combobox>

            <ConfirmDialog
                open={clearAllOpen}
                onOpenChange={setClearAllOpen}
                title="Hapus Semua Notifikasi"
                description="Apakah Anda yakin ingin menghapus semua notifikasi? Tindakan ini tidak dapat dibatalkan."
                confirmLabel="Hapus"
                onConfirm={handleClearAll}
            />
        </>
    );
}
