"use client";

import { useCallback } from "react";
import { useQuery, useMutation, useQueryClient } from "@tanstack/react-query";
import { api } from "@/lib/api";

export interface Notification {
    id: string;
    userId: string;
    type: string;
    title: string;
    message?: string;
    metadata?: Record<string, unknown>;
    read: boolean;
    cleared: boolean;
    createdAt: string;
}

export interface DownloadHistoryItem {
    id: string;
    subject: string;
    type: string;
    status: string;
    error?: string;
    createdAt: string;
    updatedAt: string;
    completedAt?: string;
    metadata?: Record<string, unknown>;
}

/**
 * Hook for managing notifications using React Query as single source of truth.
 * All components using this hook share the same cache and update together.
 */
export function useNotifications() {
    const queryClient = useQueryClient();

    // Single source of truth - React Query cache
    const {
        data: notifications = [],
        isLoading,
        error,
        refetch,
    } = useQuery<Notification[]>({
        queryKey: ["notifications"],
        queryFn: () => api.get<Notification[]>("/notifications"),
        refetchInterval: 30000,
    });

    // Derive unread count from data (computed, not stored)
    const unreadCount = notifications.filter((n) => !n.read).length;

    // Mark as read mutation with optimistic update
    const markAsReadMutation = useMutation({
        mutationFn: (id: string) => api.post(`/notifications/${id}/read`),
        onMutate: async (id: string) => {
            await queryClient.cancelQueries({ queryKey: ["notifications"] });
            const previous = queryClient.getQueryData<Notification[]>(["notifications"]);

            queryClient.setQueryData<Notification[]>(["notifications"], (old) =>
                old?.map((n) => (n.id === id ? { ...n, read: true } : n)) || []
            );

            return { previous };
        },
        onError: (_err, _id, context) => {
            if (context?.previous) {
                queryClient.setQueryData(["notifications"], context.previous);
            }
        },
    });

    // Mark all as read mutation with optimistic update
    const markAllAsReadMutation = useMutation({
        mutationFn: () => api.post("/notifications/read-all"),
        onMutate: async () => {
            await queryClient.cancelQueries({ queryKey: ["notifications"] });
            const previous = queryClient.getQueryData<Notification[]>(["notifications"]);

            queryClient.setQueryData<Notification[]>(["notifications"], (old) =>
                old?.map((n) => ({ ...n, read: true })) || []
            );

            return { previous };
        },
        onError: (_err, _vars, context) => {
            if (context?.previous) {
                queryClient.setQueryData(["notifications"], context.previous);
            }
        },
    });

    // Clear notification mutation with optimistic update
    const clearMutation = useMutation({
        mutationFn: (id: string) => api.post(`/notifications/${id}/clear`),
        onMutate: async (id: string) => {
            await queryClient.cancelQueries({ queryKey: ["notifications"] });
            const previous = queryClient.getQueryData<Notification[]>(["notifications"]);

            queryClient.setQueryData<Notification[]>(["notifications"], (old) =>
                old?.filter((n) => n.id !== id) || []
            );

            return { previous };
        },
        onError: (_err, _id, context) => {
            if (context?.previous) {
                queryClient.setQueryData(["notifications"], context.previous);
            }
        },
    });

    // Clear all mutation with optimistic update
    const clearAllMutation = useMutation({
        mutationFn: () => api.post("/notifications/clear-all"),
        onMutate: async () => {
            await queryClient.cancelQueries({ queryKey: ["notifications"] });
            const previous = queryClient.getQueryData<Notification[]>(["notifications"]);

            queryClient.setQueryData<Notification[]>(["notifications"], []);

            return { previous };
        },
        onError: (_err, _vars, context) => {
            if (context?.previous) {
                queryClient.setQueryData(["notifications"], context.previous);
            }
        },
    });

    return {
        notifications,
        unreadCount,
        isLoading,
        error: error instanceof Error ? error.message : null,
        refetch,
        markAsRead: (id: string) => markAsReadMutation.mutate(id),
        markAllAsRead: () => markAllAsReadMutation.mutate(),
        clearNotification: (id: string) => clearMutation.mutate(id),
        clearAll: () => clearAllMutation.mutate(),
    };
}

/**
 * Hook for download history - unchanged from original
 */
export function useDownloadHistory() {
    const fetchHistory = useCallback(async () => {
        return api.get<DownloadHistoryItem[]>("/notifications/downloads/history");
    }, []);

    const {
        data: history = [],
        isLoading,
        error,
        refetch,
    } = useQuery<DownloadHistoryItem[]>({
        queryKey: ["download-history"],
        queryFn: fetchHistory,
        refetchInterval: 10000,
    });

    const queryClient = useQueryClient();

    const clearDownload = useCallback(async (id: string) => {
        try {
            await api.post(`/notifications/downloads/${id}/clear`);
            queryClient.setQueryData<DownloadHistoryItem[]>(
                ["download-history"],
                (old) => old?.filter((d) => d.id !== id) || []
            );
        } catch (err: unknown) {
            console.error("Failed to clear download:", err);
        }
    }, [queryClient]);

    const clearAll = useCallback(async () => {
        try {
            await api.post("/notifications/downloads/clear-all");
            queryClient.setQueryData<DownloadHistoryItem[]>(["download-history"], []);
        } catch (err: unknown) {
            console.error("Failed to clear all:", err);
        }
    }, [queryClient]);

    const retryDownload = useCallback(async (id: string) => {
        try {
            await api.post(`/notifications/downloads/${id}/retry`);
            queryClient.setQueryData<DownloadHistoryItem[]>(
                ["download-history"],
                (old) => old?.filter((d) => d.id !== id) || []
            );
        } catch (err: unknown) {
            console.error("Failed to retry download:", err);
        }
    }, [queryClient]);

    return {
        history,
        isLoading,
        error: error instanceof Error ? error.message : null,
        refetch,
        clearDownload,
        clearAll,
        retryDownload,
    };
}

/**
 * Hook for active downloads - unchanged from original
 */
export function useActiveDownloads() {
    const fetchDownloads = useCallback(async () => {
        return api.get<DownloadHistoryItem[]>("/notifications/downloads/active");
    }, []);

    const {
        data: downloads = [],
        isLoading,
        error,
        refetch,
    } = useQuery<DownloadHistoryItem[]>({
        queryKey: ["active-downloads"],
        queryFn: fetchDownloads,
        refetchInterval: 3000,
    });

    return {
        downloads,
        isLoading,
        error: error instanceof Error ? error.message : null,
        refetch,
    };
}
