"use client";

import { useQuery, useQueryClient } from "@tanstack/react-query";
import { useAtomValue, useSetAtom } from "jotai";
import { Logs, SquareLibrary, Trash2 } from "lucide-react";
import { useParams, usePathname, useRouter } from "next/navigation";
import { useTranslations } from "next-intl";
import { useTheme } from "next-themes";
import { useCallback, useMemo, useState } from "react";
import { hasUnsavedEditorChangesAtom, pendingEditorNavigationAtom } from "@/atoms/editor/ui.atoms";
import { searchSpacesAtom } from "@/atoms/search-spaces/search-space-query.atoms";
import { currentUserAtom } from "@/atoms/user/user-query.atoms";
import { Button } from "@/components/ui/button";
import {
	Dialog,
	DialogContent,
	DialogDescription,
	DialogFooter,
	DialogHeader,
	DialogTitle,
} from "@/components/ui/dialog";
import { useLogsSummary } from "@/hooks/use-logs";
import { notesApiService } from "@/lib/apis/notes-api.service";
import { searchSpacesApiService } from "@/lib/apis/search-spaces-api.service";
import { deleteThread, fetchThreads } from "@/lib/chat/thread-persistence";
import { resetUser, trackLogout } from "@/lib/posthog/events";
import { cacheKeys } from "@/lib/query-client/cache-keys";
import type { ChatItem, NavItem, NoteItem, Workspace } from "../types/layout.types";
import { LayoutShell } from "../ui/shell";
import { AllChatsSidebar } from "../ui/sidebar/AllChatsSidebar";
import { AllNotesSidebar } from "../ui/sidebar/AllNotesSidebar";

interface LayoutDataProviderProps {
	searchSpaceId: string;
	children: React.ReactNode;
	breadcrumb?: React.ReactNode;
	languageSwitcher?: React.ReactNode;
}

export function LayoutDataProvider({
	searchSpaceId,
	children,
	breadcrumb,
	languageSwitcher,
}: LayoutDataProviderProps) {
	const t = useTranslations("dashboard");
	const tCommon = useTranslations("common");
	const router = useRouter();
	const params = useParams();
	const pathname = usePathname();
	const queryClient = useQueryClient();
	const { theme, setTheme } = useTheme();

	// Atoms
	const { data: user } = useAtomValue(currentUserAtom);
	const { data: searchSpacesData } = useAtomValue(searchSpacesAtom);
	const hasUnsavedEditorChanges = useAtomValue(hasUnsavedEditorChangesAtom);
	const setPendingNavigation = useSetAtom(pendingEditorNavigationAtom);

	// Current IDs from URL
	const currentChatId = params?.chat_id
		? Number(Array.isArray(params.chat_id) ? params.chat_id[0] : params.chat_id)
		: null;
	const currentNoteId = params?.note_id
		? Number(Array.isArray(params.note_id) ? params.note_id[0] : params.note_id)
		: null;

	// Fetch current search space
	const { data: searchSpace } = useQuery({
		queryKey: cacheKeys.searchSpaces.detail(searchSpaceId),
		queryFn: () => searchSpacesApiService.getSearchSpace({ id: Number(searchSpaceId) }),
		enabled: !!searchSpaceId,
	});

	// Fetch threads
	const { data: threadsData, refetch: refetchThreads } = useQuery({
		queryKey: ["threads", searchSpaceId, { limit: 4 }],
		queryFn: () => fetchThreads(Number(searchSpaceId), 4),
		enabled: !!searchSpaceId,
	});

	// Fetch notes
	const { data: notesData, refetch: refetchNotes } = useQuery({
		queryKey: ["notes", searchSpaceId],
		queryFn: () =>
			notesApiService.getNotes({
				search_space_id: Number(searchSpaceId),
				page_size: 4,
			}),
		enabled: !!searchSpaceId,
	});

	// Poll for active reindexing tasks to show inline loading indicators
	const { summary } = useLogsSummary(searchSpaceId ? Number(searchSpaceId) : 0, 24, {
		enablePolling: true,
		refetchInterval: 5000,
	});

	// Create a Set of document IDs that are currently being reindexed
	const reindexingDocumentIds = useMemo(() => {
		if (!summary?.active_tasks) return new Set<number>();
		return new Set(
			summary.active_tasks
				.filter((task) => task.document_id != null)
				.map((task) => task.document_id as number)
		);
	}, [summary?.active_tasks]);

	// All chats/notes sidebars state
	const [isAllChatsSidebarOpen, setIsAllChatsSidebarOpen] = useState(false);
	const [isAllNotesSidebarOpen, setIsAllNotesSidebarOpen] = useState(false);

	// Delete dialogs state
	const [showDeleteChatDialog, setShowDeleteChatDialog] = useState(false);
	const [chatToDelete, setChatToDelete] = useState<{ id: number; name: string } | null>(null);
	const [isDeletingChat, setIsDeletingChat] = useState(false);

	const [showDeleteNoteDialog, setShowDeleteNoteDialog] = useState(false);
	const [noteToDelete, setNoteToDelete] = useState<{
		id: number;
		name: string;
		search_space_id: number;
	} | null>(null);
	const [isDeletingNote, setIsDeletingNote] = useState(false);

	// Transform workspaces (API returns array directly, not { items: [...] })
	const workspaces: Workspace[] = useMemo(() => {
		if (!searchSpacesData || !Array.isArray(searchSpacesData)) return [];
		return searchSpacesData.map((space) => ({
			id: space.id,
			name: space.name,
			description: space.description,
			isOwner: space.is_owner,
			memberCount: space.member_count || 0,
		}));
	}, [searchSpacesData]);

	// Use searchSpace query result for current workspace (more reliable than finding in list)
	const activeWorkspace: Workspace | null = searchSpace
		? {
				id: searchSpace.id,
				name: searchSpace.name,
				description: searchSpace.description,
				isOwner: searchSpace.is_owner,
				memberCount: searchSpace.member_count || 0,
			}
		: null;

	// Transform chats
	const chats: ChatItem[] = useMemo(() => {
		if (!threadsData?.threads) return [];
		return threadsData.threads.map((thread) => ({
			id: thread.id,
			name: thread.title || `Chat ${thread.id}`,
			url: `/dashboard/${searchSpaceId}/new-chat/${thread.id}`,
		}));
	}, [threadsData, searchSpaceId]);

	// Transform notes
	const notes: NoteItem[] = useMemo(() => {
		if (!notesData?.items) return [];
		const sortedNotes = [...notesData.items].sort((a, b) => {
			const dateA = a.updated_at
				? new Date(a.updated_at).getTime()
				: new Date(a.created_at).getTime();
			const dateB = b.updated_at
				? new Date(b.updated_at).getTime()
				: new Date(b.created_at).getTime();
			return dateB - dateA;
		});
		return sortedNotes.slice(0, 4).map((note) => ({
			id: note.id,
			name: note.title,
			url: `/dashboard/${note.search_space_id}/editor/${note.id}`,
			isReindexing: reindexingDocumentIds.has(note.id),
		}));
	}, [notesData, reindexingDocumentIds]);

	// Navigation items
	const navItems: NavItem[] = useMemo(
		() => [
			{
				title: "Documents",
				url: `/dashboard/${searchSpaceId}/documents`,
				icon: SquareLibrary,
				isActive: pathname?.includes("/documents"),
			},
			{
				title: "Logs",
				url: `/dashboard/${searchSpaceId}/logs`,
				icon: Logs,
				isActive: pathname?.includes("/logs"),
			},
		],
		[searchSpaceId, pathname]
	);

	// Handlers
	const handleWorkspaceSelect = useCallback(
		(id: number) => {
			router.push(`/dashboard/${id}/new-chat`);
		},
		[router]
	);

	const handleAddWorkspace = useCallback(() => {
		router.push("/dashboard/searchspaces");
	}, [router]);

	const handleSeeAllWorkspaces = useCallback(() => {
		router.push("/dashboard");
	}, [router]);

	const handleNavItemClick = useCallback(
		(item: NavItem) => {
			router.push(item.url);
		},
		[router]
	);

	const handleNewChat = useCallback(() => {
		router.push(`/dashboard/${searchSpaceId}/new-chat`);
	}, [router, searchSpaceId]);

	const handleChatSelect = useCallback(
		(chat: ChatItem) => {
			router.push(chat.url);
		},
		[router]
	);

	const handleChatDelete = useCallback((chat: ChatItem) => {
		setChatToDelete({ id: chat.id, name: chat.name });
		setShowDeleteChatDialog(true);
	}, []);

	const handleNoteSelect = useCallback(
		(note: NoteItem) => {
			if (hasUnsavedEditorChanges) {
				setPendingNavigation(note.url);
			} else {
				router.push(note.url);
			}
		},
		[router, hasUnsavedEditorChanges, setPendingNavigation]
	);

	const handleNoteDelete = useCallback(
		(note: NoteItem) => {
			setNoteToDelete({ id: note.id, name: note.name, search_space_id: Number(searchSpaceId) });
			setShowDeleteNoteDialog(true);
		},
		[searchSpaceId]
	);

	const handleAddNote = useCallback(() => {
		const newNoteUrl = `/dashboard/${searchSpaceId}/editor/new`;
		if (hasUnsavedEditorChanges) {
			setPendingNavigation(newNoteUrl);
		} else {
			router.push(newNoteUrl);
		}
	}, [router, searchSpaceId, hasUnsavedEditorChanges, setPendingNavigation]);

	const handleSettings = useCallback(() => {
		router.push(`/dashboard/${searchSpaceId}/settings`);
	}, [router, searchSpaceId]);

	const handleInviteMembers = useCallback(() => {
		router.push(`/dashboard/${searchSpaceId}/team`);
	}, [router, searchSpaceId]);

	const handleLogout = useCallback(() => {
		try {
			trackLogout();
			resetUser();
			if (typeof window !== "undefined") {
				localStorage.removeItem("surfsense_bearer_token");
				router.push("/");
			}
		} catch (error) {
			console.error("Error during logout:", error);
			router.push("/");
		}
	}, [router]);

	const handleToggleTheme = useCallback(() => {
		setTheme(theme === "dark" ? "light" : "dark");
	}, [theme, setTheme]);

	const handleViewAllChats = useCallback(() => {
		setIsAllChatsSidebarOpen(true);
	}, []);

	const handleViewAllNotes = useCallback(() => {
		setIsAllNotesSidebarOpen(true);
	}, []);

	// Delete handlers
	const confirmDeleteChat = useCallback(async () => {
		if (!chatToDelete) return;
		setIsDeletingChat(true);
		try {
			await deleteThread(chatToDelete.id);
			queryClient.invalidateQueries({ queryKey: ["threads", searchSpaceId] });
			if (currentChatId === chatToDelete.id) {
				router.push(`/dashboard/${searchSpaceId}/new-chat`);
			}
		} catch (error) {
			console.error("Error deleting thread:", error);
		} finally {
			setIsDeletingChat(false);
			setShowDeleteChatDialog(false);
			setChatToDelete(null);
		}
	}, [chatToDelete, queryClient, searchSpaceId, router, currentChatId]);

	const confirmDeleteNote = useCallback(async () => {
		if (!noteToDelete) return;
		setIsDeletingNote(true);
		try {
			await notesApiService.deleteNote({
				search_space_id: noteToDelete.search_space_id,
				note_id: noteToDelete.id,
			});
			refetchNotes();
		} catch (error) {
			console.error("Error deleting note:", error);
		} finally {
			setIsDeletingNote(false);
			setShowDeleteNoteDialog(false);
			setNoteToDelete(null);
		}
	}, [noteToDelete, refetchNotes]);

	// Page usage
	const pageUsage = user
		? {
				pagesUsed: user.pages_used,
				pagesLimit: user.pages_limit,
			}
		: undefined;

	// Detect if we're on the chat page (needs overflow-hidden for chat's own scroll)
	const isChatPage = pathname?.includes("/new-chat") ?? false;

	return (
		<>
			<LayoutShell
				workspaces={workspaces}
				activeWorkspaceId={Number(searchSpaceId)}
				onWorkspaceSelect={handleWorkspaceSelect}
				onAddWorkspace={handleAddWorkspace}
				workspace={activeWorkspace}
				navItems={navItems}
				onNavItemClick={handleNavItemClick}
				chats={chats}
				activeChatId={currentChatId}
				onNewChat={handleNewChat}
				onChatSelect={handleChatSelect}
				onChatDelete={handleChatDelete}
				onViewAllChats={handleViewAllChats}
				notes={notes}
				activeNoteId={currentNoteId}
				onNoteSelect={handleNoteSelect}
				onNoteDelete={handleNoteDelete}
				onAddNote={handleAddNote}
				onViewAllNotes={handleViewAllNotes}
				user={{ email: user?.email || "", name: user?.email?.split("@")[0] }}
				onSettings={handleSettings}
				onInviteMembers={handleInviteMembers}
				onSeeAllWorkspaces={handleSeeAllWorkspaces}
				onLogout={handleLogout}
				pageUsage={pageUsage}
				breadcrumb={breadcrumb}
				languageSwitcher={languageSwitcher}
				theme={theme}
				onToggleTheme={handleToggleTheme}
				isChatPage={isChatPage}
			>
				{children}
			</LayoutShell>

			{/* Delete Chat Dialog */}
			<Dialog open={showDeleteChatDialog} onOpenChange={setShowDeleteChatDialog}>
				<DialogContent className="sm:max-w-md">
					<DialogHeader>
						<DialogTitle className="flex items-center gap-2">
							<Trash2 className="h-5 w-5 text-destructive" />
							<span>{t("delete_chat")}</span>
						</DialogTitle>
						<DialogDescription>
							{t("delete_chat_confirm")} <span className="font-medium">{chatToDelete?.name}</span>?{" "}
							{t("action_cannot_undone")}
						</DialogDescription>
					</DialogHeader>
					<DialogFooter className="flex gap-2 sm:justify-end">
						<Button
							variant="outline"
							onClick={() => setShowDeleteChatDialog(false)}
							disabled={isDeletingChat}
						>
							{tCommon("cancel")}
						</Button>
						<Button
							variant="destructive"
							onClick={confirmDeleteChat}
							disabled={isDeletingChat}
							className="gap-2"
						>
							{isDeletingChat ? (
								<>
									<span className="h-4 w-4 animate-spin rounded-full border-2 border-current border-t-transparent" />
									{t("deleting")}
								</>
							) : (
								<>
									<Trash2 className="h-4 w-4" />
									{tCommon("delete")}
								</>
							)}
						</Button>
					</DialogFooter>
				</DialogContent>
			</Dialog>

			{/* All Chats Sidebar */}
			<AllChatsSidebar
				open={isAllChatsSidebarOpen}
				onOpenChange={setIsAllChatsSidebarOpen}
				searchSpaceId={searchSpaceId}
			/>

			{/* All Notes Sidebar */}
			<AllNotesSidebar
				open={isAllNotesSidebarOpen}
				onOpenChange={setIsAllNotesSidebarOpen}
				searchSpaceId={searchSpaceId}
				onAddNote={handleAddNote}
			/>

			{/* Delete Note Dialog */}
			<Dialog open={showDeleteNoteDialog} onOpenChange={setShowDeleteNoteDialog}>
				<DialogContent className="sm:max-w-md">
					<DialogHeader>
						<DialogTitle className="flex items-center gap-2">
							<Trash2 className="h-5 w-5 text-destructive" />
							<span>{t("delete_note")}</span>
						</DialogTitle>
						<DialogDescription>
							{t("delete_note_confirm")} <span className="font-medium">{noteToDelete?.name}</span>?{" "}
							{t("action_cannot_undone")}
						</DialogDescription>
					</DialogHeader>
					<DialogFooter className="flex gap-2 sm:justify-end">
						<Button
							variant="outline"
							onClick={() => setShowDeleteNoteDialog(false)}
							disabled={isDeletingNote}
						>
							{tCommon("cancel")}
						</Button>
						<Button
							variant="destructive"
							onClick={confirmDeleteNote}
							disabled={isDeletingNote}
							className="gap-2"
						>
							{isDeletingNote ? (
								<>
									<span className="h-4 w-4 animate-spin rounded-full border-2 border-current border-t-transparent" />
									{t("deleting")}
								</>
							) : (
								<>
									<Trash2 className="h-4 w-4" />
									{tCommon("delete")}
								</>
							)}
						</Button>
					</DialogFooter>
				</DialogContent>
			</Dialog>
		</>
	);
}
