import { useCallback, useEffect, useRef, useState } from 'react';

export type NotificationCategory = 'bookings' | 'payments' | 'operations' | 'system' | 'customers';
export type NotificationFilter = NotificationCategory | 'all';

export interface AdminNotification {
    id: number;
    category: NotificationCategory;
    title: string;
    body: string;
    action_url: string | null;
    action_label: string | null;
    is_read: boolean;
    created_at: string;
}

interface NotificationsState {
    notifications: AdminNotification[];
    unreadCount: number;
    categoryCounts: Partial<Record<NotificationCategory, number>>;
    isLoading: boolean;
    activeFilter: NotificationFilter;
    setActiveFilter: (filter: NotificationFilter) => void;
    markRead: (id: number) => Promise<void>;
    markAllRead: () => Promise<void>;
    refresh: () => void;
}

const POLL_INTERVAL_MS = 30_000;

function getCsrfToken(): string {
    return (document.querySelector('meta[name="csrf-token"]') as HTMLMetaElement)?.content ?? '';
}

export function useNotifications(): NotificationsState {
    const [notifications, setNotifications] = useState<AdminNotification[]>([]);
    const [unreadCount, setUnreadCount] = useState(0);
    const [categoryCounts, setCategoryCounts] = useState<Partial<Record<NotificationCategory, number>>>({});
    const [isLoading, setIsLoading] = useState(true);
    const [activeFilter, setActiveFilter] = useState<NotificationFilter>('all');
    const intervalRef = useRef<ReturnType<typeof setInterval> | null>(null);

    const fetchNotifications = useCallback(async (filter: NotificationFilter = 'all') => {
        try {
            const url = filter === 'all'
                ? '/admin/notifications'
                : `/admin/notifications?category=${filter}`;

            const res = await fetch(url, {
                headers: { 'X-Requested-With': 'XMLHttpRequest' },
                credentials: 'same-origin',
            });

            if (!res.ok) return;

            const data = await res.json();
            setNotifications(data.notifications);
            setUnreadCount(data.unread_count);
            setCategoryCounts(data.category_counts ?? {});
        } catch {
            // network error — keep stale data
        } finally {
            setIsLoading(false);
        }
    }, []);

    const refresh = useCallback(() => {
        fetchNotifications(activeFilter);
    }, [activeFilter, fetchNotifications]);

    useEffect(() => {
        setIsLoading(true);
        fetchNotifications(activeFilter);
    }, [activeFilter, fetchNotifications]);

    // Poll every 30s
    useEffect(() => {
        intervalRef.current = setInterval(() => {
            fetchNotifications(activeFilter);
        }, POLL_INTERVAL_MS);

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

    const markRead = useCallback(async (id: number) => {
        // Optimistic update
        setNotifications((prev) =>
            prev.map((n) => (n.id === id ? { ...n, is_read: true } : n)),
        );
        setUnreadCount((prev) => Math.max(0, prev - 1));

        await fetch(`/admin/notifications/${id}/read`, {
            method: 'POST',
            headers: {
                'X-CSRF-TOKEN': getCsrfToken(),
                'X-Requested-With': 'XMLHttpRequest',
            },
            credentials: 'same-origin',
        });
    }, []);

    const markAllRead = useCallback(async () => {
        // Optimistic update
        setNotifications((prev) => prev.map((n) => ({ ...n, is_read: true })));
        setUnreadCount(0);
        setCategoryCounts({});

        await fetch('/admin/notifications/read-all', {
            method: 'POST',
            headers: {
                'X-CSRF-TOKEN': getCsrfToken(),
                'X-Requested-With': 'XMLHttpRequest',
            },
            credentials: 'same-origin',
        });
    }, []);

    return {
        notifications,
        unreadCount,
        categoryCounts,
        isLoading,
        activeFilter,
        setActiveFilter,
        markRead,
        markAllRead,
        refresh,
    };
}
