import { computed, ref } from 'vue';
import { defineStore } from 'pinia';
import {
    type ApiInAppNotification,
    deleteNotification,
    listNotifications,
    markAllNotificationsRead,
    markNotificationRead,
} from '../api/notifications';

/**
 * Pinia store для in-app уведомлений (bell-icon в AppLayout).
 *
 * Polling: AppLayout вызывает `load()` на mount + через `usePolling` каждые
 * 30 сек (как dealsState/admin views). Page Visibility API в usePolling
 * пускает paus'у при свёрнутой вкладке.
 *
 * Optimistic-updates: markRead уменьшает unreadCount + ставит read_at до
 * ответа API; на fail — silently revert (без toast'а, чтобы не спамить
 * пользователя при каждом sync-failure).
 */
export const useNotificationsStore = defineStore('notifications', () => {
    const items = ref<ApiInAppNotification[]>([]);
    const unreadCount = ref(0);
    const total = ref(0);
    const loading = ref(false);
    const fetchError = ref(false);

    const sortedItems = computed(() =>
        [...items.value].sort((a, b) => {
            const ta = a.created_at ? new Date(a.created_at).getTime() : 0;
            const tb = b.created_at ? new Date(b.created_at).getTime() : 0;
            return tb - ta;
        }),
    );

    async function load(limit = 50, unreadOnly = false): Promise<void> {
        loading.value = true;
        fetchError.value = false;
        try {
            const response = await listNotifications({ limit, unreadOnly });
            items.value = response.items;
            unreadCount.value = response.unread_count;
            total.value = response.total;
        } catch {
            fetchError.value = true;
        } finally {
            loading.value = false;
        }
    }

    async function markRead(id: number): Promise<void> {
        const item = items.value.find((n) => n.id === id);
        if (!item || item.read_at !== null) return;

        // Optimistic.
        const previousReadAt = item.read_at;
        const nowIso = new Date().toISOString();
        item.read_at = nowIso;
        unreadCount.value = Math.max(0, unreadCount.value - 1);

        try {
            const response = await markNotificationRead(id);
            item.read_at = response.read_at;
        } catch {
            // Revert.
            item.read_at = previousReadAt;
            unreadCount.value++;
        }
    }

    async function markAllRead(): Promise<void> {
        if (unreadCount.value === 0) return;

        // Optimistic.
        const previousReadAt = new Map<number, string | null>();
        const nowIso = new Date().toISOString();
        items.value.forEach((n) => {
            if (n.read_at === null) {
                previousReadAt.set(n.id, n.read_at);
                n.read_at = nowIso;
            }
        });
        const previousUnread = unreadCount.value;
        unreadCount.value = 0;

        try {
            await markAllNotificationsRead();
        } catch {
            // Revert.
            previousReadAt.forEach((readAt, id) => {
                const item = items.value.find((n) => n.id === id);
                if (item) item.read_at = readAt;
            });
            unreadCount.value = previousUnread;
        }
    }

    async function remove(id: number): Promise<void> {
        const item = items.value.find((n) => n.id === id);
        if (!item) return;
        const wasUnread = item.read_at === null;
        const previousItems = [...items.value];
        const previousTotal = total.value;
        const previousUnread = unreadCount.value;

        // Optimistic.
        items.value = items.value.filter((n) => n.id !== id);
        total.value = Math.max(0, total.value - 1);
        if (wasUnread) unreadCount.value = Math.max(0, unreadCount.value - 1);

        try {
            await deleteNotification(id);
        } catch {
            // Revert.
            items.value = previousItems;
            total.value = previousTotal;
            unreadCount.value = previousUnread;
        }
    }

    function reset(): void {
        items.value = [];
        unreadCount.value = 0;
        total.value = 0;
        fetchError.value = false;
    }

    return {
        items,
        unreadCount,
        total,
        loading,
        fetchError,
        sortedItems,
        load,
        markRead,
        markAllRead,
        remove,
        reset,
    };
});
