import { useMutation, useQuery } from "@tanstack/react-query";
import { useEffect, useRef } from "react";
import { toast } from "sonner";
import type { AudioCodec, VideoCodec } from "@/utils/codec-detection";
import { useTRPCClient } from "@/utils/trpc";

interface UsePlaybackSessionOptions {
	titleId?: string;
	episodeId?: string;
	supportedCodecs: {
		video: VideoCodec[];
		audio: AudioCodec[];
	};
	selectedTracks?: {
		audio?: number;
		subtitle?: number;
	};
	maxResolution?: "480p" | "720p" | "1080p" | "2160p";
}

export function usePlaybackSession(options: UsePlaybackSessionOptions) {
	const trpcClient = useTRPCClient();
	const hasCreatedSession = useRef(false);
	const shouldCreateRef = useRef(!sessionStorage.getItem("activeSessionId"));

	// Create session using useQuery (only runs when shouldCreate is true)
	// selectedTracks removed from queryKey - subtitle switching handled client-side
	const createSession = useQuery({
		queryKey: ["playback-session", options.titleId, options.episodeId],
		queryFn: async () => {
			// Prevent duplicate session creation
			if (hasCreatedSession.current) {
				throw new Error("Session already created");
			}

			const result = await trpcClient.playback.createSession.mutate({
				titleId: options.titleId,
				episodeId: options.episodeId,
				supportedVideoCodecs: options.supportedCodecs.video,
				supportedAudioCodecs: options.supportedCodecs.audio,
				audioStreamIndex: options.selectedTracks?.audio,
				subtitleStreamIndex: options.selectedTracks?.subtitle,
				// burnInSubtitle: true,
				maxResolution: options.maxResolution || "1080p",
			});

			// Store session ID for cleanup
			sessionStorage.setItem("activeSessionId", result.sessionId);
			hasCreatedSession.current = true;
			shouldCreateRef.current = false;

			return result;
		},
		enabled: shouldCreateRef.current && !!options.titleId,
		retry: 0,
		staleTime: Number.POSITIVE_INFINITY,
		gcTime: Number.POSITIVE_INFINITY,
	});

	// Show error toast when session creation fails
	useEffect(() => {
		if (createSession.error) {
			toast.error(
				`Failed to create playback session: ${createSession.error.message}`,
			);
		}
	}, [createSession.error]);

	// Seek mutation
	const seekMutation = useMutation({
		mutationFn: async (seekTime: number) => {
			if (!createSession.data?.sessionId) {
				throw new Error("No active session");
			}

			return await trpcClient.playback.seekSession.mutate({
				sessionId: createSession.data.sessionId,
				seekTime,
			});
		},
		onError: (error) => {
			toast.error(`Seek failed: ${error.message}`);
		},
	});

	// Cleanup on unmount
	useEffect(() => {
		return () => {
			const sessionId = sessionStorage.getItem("activeSessionId");
			if (sessionId) {
				// Fire-and-forget cleanup
				trpcClient.playback.stopSession
					.mutate({
						sessionId,
					})
					.catch(console.error);
				sessionStorage.removeItem("activeSessionId");
				hasCreatedSession.current = false;
				shouldCreateRef.current = true;
			}
		};
	}, [trpcClient]);

	return {
		isLoading: createSession.isPending,
		error: createSession.error,
		data: createSession.data,
		seek: seekMutation.mutateAsync,
		isRestarting: seekMutation.isPending,
	};
}
