import { useCallback, useEffect, useRef, useState } from "react";
import { api } from "~/shared/lib/api";
import type { ReviewGroup, ReviewGroupsResponse } from "~/shared/lib/types";
import { ColumnShell } from "./ColumnShell";
import { PipelineCard } from "./PipelineCard";
import { SeriesCard } from "./SeriesCard";

const PAGE_SIZE = 25;

interface ReviewColumnProps {
	initialResponse: ReviewGroupsResponse;
	totalItems: number;
	jellyfinUrl: string;
	onMutate: () => void;
}

export function ReviewColumn({ initialResponse, totalItems, jellyfinUrl, onMutate }: ReviewColumnProps) {
	const [groups, setGroups] = useState<ReviewGroup[]>(initialResponse.groups);
	const [hasMore, setHasMore] = useState(initialResponse.hasMore);
	const [loadingMore, setLoadingMore] = useState(false);
	const sentinelRef = useRef<HTMLDivElement | null>(null);

	// Reset when the parent refetches page 0 (after approve/skip actions).
	useEffect(() => {
		setGroups(initialResponse.groups);
		setHasMore(initialResponse.hasMore);
	}, [initialResponse]);

	const loadMore = useCallback(async () => {
		if (loadingMore || !hasMore) return;
		setLoadingMore(true);
		try {
			const res = await api.get<ReviewGroupsResponse>(`/api/review/groups?offset=${groups.length}&limit=${PAGE_SIZE}`);
			setGroups((prev) => [...prev, ...res.groups]);
			setHasMore(res.hasMore);
		} finally {
			setLoadingMore(false);
		}
	}, [groups.length, hasMore, loadingMore]);

	useEffect(() => {
		if (!hasMore || !sentinelRef.current) return;
		const observer = new IntersectionObserver(
			(entries) => {
				if (entries[0]?.isIntersecting) loadMore();
			},
			{ rootMargin: "200px" },
		);
		observer.observe(sentinelRef.current);
		return () => observer.disconnect();
	}, [hasMore, loadMore]);

	const skipAll = async () => {
		if (!confirm(`Skip all ${totalItems} pending items? They won't be processed unless you unskip them.`)) return;
		await api.post("/api/review/skip-all");
		onMutate();
	};

	const autoApprove = async () => {
		const res = await api.post<{ ok: boolean; count: number }>("/api/review/auto-approve");
		onMutate();
		if (res.count === 0) alert("No high-confidence items to auto-approve.");
	};

	const approveItem = async (itemId: number) => {
		await api.post(`/api/review/${itemId}/approve`);
		onMutate();
	};
	const skipItem = async (itemId: number) => {
		await api.post(`/api/review/${itemId}/skip`);
		onMutate();
	};
	const approveBatch = async (itemIds: number[]) => {
		if (itemIds.length === 0) return;
		await api.post<{ ok: boolean; count: number }>("/api/review/approve-batch", { itemIds });
		onMutate();
	};

	// Compute ids per visible group for "Approve above"
	const idsByGroup: number[][] = groups.map((g) =>
		g.kind === "movie" ? [g.item.item_id] : g.seasons.flatMap((s) => s.episodes.map((ep) => ep.item_id)),
	);
	const priorIds = (index: number): number[] => idsByGroup.slice(0, index).flat();

	const actions =
		totalItems > 0
			? [
					{ label: "Auto Review", onClick: autoApprove, primary: true },
					{ label: "Skip all", onClick: skipAll },
				]
			: undefined;

	return (
		<ColumnShell title="Review" count={totalItems} actions={actions}>
			<div className="space-y-2">
				{groups.map((group, index) => {
					const prior = index > 0 ? priorIds(index) : null;
					const onApproveUpToHere = prior && prior.length > 0 ? () => approveBatch(prior) : undefined;
					if (group.kind === "movie") {
						return (
							<PipelineCard
								key={group.item.id}
								item={group.item}
								jellyfinUrl={jellyfinUrl}
								onToggleStream={async (streamId, action) => {
									await api.patch(`/api/review/${group.item.item_id}/stream/${streamId}`, { action });
									onMutate();
								}}
								onApprove={() => approveItem(group.item.item_id)}
								onSkip={() => skipItem(group.item.item_id)}
								onApproveUpToHere={onApproveUpToHere}
							/>
						);
					}
					return (
						<SeriesCard
							key={group.seriesKey}
							seriesKey={group.seriesKey}
							seriesName={group.seriesName}
							jellyfinUrl={jellyfinUrl}
							seriesJellyfinId={group.seriesJellyfinId}
							seasons={group.seasons}
							episodeCount={group.episodeCount}
							originalLanguage={group.originalLanguage}
							onMutate={onMutate}
							onApproveUpToHere={onApproveUpToHere}
						/>
					);
				})}
				{groups.length === 0 && <p className="text-sm text-gray-400 text-center py-8">No items to review</p>}
				{hasMore && (
					<div ref={sentinelRef} className="py-4 text-center text-xs text-gray-400">
						{loadingMore ? "Loading more…" : ""}
					</div>
				)}
			</div>
		</ColumnShell>
	);
}
