import { ArrowLeft, ChevronLeft, ChevronRight, Home } from "lucide-react";
import { useEffect, useRef, useState } from "react";
import { useNavigate, useParams } from "react-router";
import { useGetMangaContentImages } from "@/api/generated/content/content.ts";
import { useMarkContentAsRead } from "@/api/generated/user-interaction/user-interaction.ts";
import { Button } from "@/components/ui/button";
import {
	Dialog,
	DialogContent,
	DialogDescription,
	DialogFooter,
	DialogHeader,
	DialogTitle,
} from "@/components/ui/dialog";
import { useReadingProgressSync } from "@/features/chapter/hooks/useReadingProgressSync.ts";
import { MangaLoadingState } from "@/components/MangaLoadingState.tsx";

const Chapter = () => {
	const navigate = useNavigate();
	const params = useParams();
	const mangaId = Number(params.mangaId);
	const chapterNumber = Number(params.chapterId);

	const {
		currentPage: savedPage,
		serverProgress,
		isLoadingProgress,
		saveLocalProgress,
		applyServerProgress,
	} = useReadingProgressSync(mangaId, chapterNumber);

	const [currentPage, setCurrentPage] = useState(1);
	const [hasInitialized, setHasInitialized] = useState(false);
	const [showConflictDialog, setShowConflictDialog] = useState(false);
	const [isAutoScrolling, setIsAutoScrolling] = useState(false);
	const initialJumpDone = useRef(false);
	const isFirstMount = useRef(true);

	const [infiniteScroll, setInfiniteScroll] = useState(true);

	const { data, isLoading } = useGetMangaContentImages(chapterNumber);
	const { mutate } = useMarkContentAsRead();

	// For infinite scroll mode
	const [visibleCount, setVisibleCount] = useState(1);
	const loadMoreRef = useRef(null);

	/** Conflict Resolution & Initial Sync */
	useEffect(() => {
		if (isLoadingProgress || hasInitialized) return;

		const localPage = savedPage;
		const serverPage = serverProgress?.pageNumber;

		if (localPage === null) {
			// No local history for this chapter, use server or default to 1
			const targetPage = serverPage || 1;
			setCurrentPage(targetPage);
			setVisibleCount(targetPage);
			if (targetPage > 1) {
				setIsAutoScrolling(true);
			}
			setHasInitialized(true);
			return;
		}

		if (serverPage && localPage !== serverPage) {
			// If local is just starting out (page 1), just take server
			if (localPage <= 1) {
				const targetPage = serverPage;
				setCurrentPage(targetPage);
				setVisibleCount(targetPage);
				if (targetPage > 1) {
					setIsAutoScrolling(true);
				}
				setHasInitialized(true);
			} else {
				setShowConflictDialog(true);
			}
		} else {
			const targetPage = localPage || 1;
			setCurrentPage(targetPage);
			setVisibleCount(targetPage);
			if (targetPage > 1) {
				setIsAutoScrolling(true);
			}
			setHasInitialized(true);
		}
	}, [isLoadingProgress, savedPage, serverProgress, hasInitialized]);

	/** Mark chapter as read when last page reached */
	useEffect(() => {
		if (!data || isLoading || !hasInitialized || isAutoScrolling) return;

		if (currentPage === data.data?.contentImageKeys.length) {
			mutate({ mangaContentId: chapterNumber });
		}
	}, [data, mutate, currentPage, hasInitialized, isAutoScrolling]);

	/** Persist reading progress */
	useEffect(() => {
		if (hasInitialized && !isAutoScrolling && initialJumpDone.current) {
			saveLocalProgress(currentPage);
		}
	}, [currentPage, hasInitialized, isAutoScrolling, saveLocalProgress]);

	/** Auto-scroll to restored page */
	useEffect(() => {
		if (!hasInitialized || isLoading || !data?.data || initialJumpDone.current)
			return;

		if (infiniteScroll && currentPage > 1) {
			setIsAutoScrolling(true);
			setVisibleCount(currentPage);

			let attempts = 0;
			const maxAttempts = 10;

			const attemptJump = () => {
				const el = document.querySelector(`[data-page="${currentPage}"]`);
				if (el && (el as HTMLElement).offsetTop > 0) {
					el.scrollIntoView({ behavior: "auto", block: "start" });
					setTimeout(() => {
						initialJumpDone.current = true;
						setIsAutoScrolling(false);
						isFirstMount.current = false;
					}, 300);
				} else if (attempts < maxAttempts) {
					attempts++;
					setTimeout(attemptJump, 50);
				} else {
					initialJumpDone.current = true;
					setIsAutoScrolling(false);
					isFirstMount.current = false;
				}
			};

			attemptJump();
		} else {
			initialJumpDone.current = true;
			isFirstMount.current = false;
		}
	}, [hasInitialized, isLoading, data?.data, infiniteScroll, currentPage]);

	/** Infinite scroll observer (load more) */
	useEffect(() => {
		if (!infiniteScroll || !hasInitialized) return;
		if (!loadMoreRef.current) return;

		const obs = new IntersectionObserver((entries) => {
			if (entries[0].isIntersecting) {
				setVisibleCount((count) =>
					Math.min(count + 2, data?.data?.contentImageKeys.length ?? 0),
				);
			}
		});

		obs.observe(loadMoreRef.current);
		return () => obs.disconnect();
	}, [infiniteScroll, data?.data, hasInitialized]);

	/** Track which image is currently visible (for progress update) */
	useEffect(() => {
		if (!infiniteScroll || !hasInitialized || isAutoScrolling) return;

		const imgs = document.querySelectorAll("[data-page]");
		const observer = new IntersectionObserver(
			(entries) => {
				for (const entry of entries) {
					if (entry.isIntersecting) {
						const el = entry.target as HTMLElement;
						const pageNum = Number(el.dataset.page);
						setCurrentPage(pageNum);
						// We only need the first one that intersects the top area
						break;
					}
				}
			},
			{ threshold: 0, rootMargin: "-20% 0px -70% 0px" },
		);

		imgs.forEach((img) => observer.observe(img));
		return () => observer.disconnect();
	}, [infiniteScroll, visibleCount, hasInitialized, isAutoScrolling]);

	useEffect(() => {
		if (!data?.data || !hasInitialized || isFirstMount.current) return;

		// When manually switching modes:
		if (infiniteScroll) {
			setVisibleCount(currentPage);
			setTimeout(() => {
				const el = document.querySelector(`[data-page="${currentPage}"]`);
				el?.scrollIntoView({ behavior: "smooth", block: "start" });
			}, 50);
		} else {
			window.scrollTo({ top: 0 });
		}
	}, [infiniteScroll]);

	if (isLoading || (isLoadingProgress && !hasInitialized)) {
		return (
			<div className="flex min-h-screen items-center justify-center bg-background">
				<MangaLoadingState />
			</div>
		);
	}

	if (!data?.data) {
		return (
			<div className="flex min-h-screen items-center justify-center bg-background">
				<div className="text-center">
					<h1 className="text-2xl font-bold text-foreground">
						Manga not found
					</h1>
					<Button onClick={() => navigate("/")} className="mt-4">
						Go back home
					</Button>
				</div>
			</div>
		);
	}

	const images = data.data.contentImageKeys;
	const previousContentId = data.data.previousContentId;
	const nextContentId = data.data.nextContentId;

	const goToNextChapter = () => {
		if (nextContentId) {
			setCurrentPage(1);
			setVisibleCount(1);
			window.scrollTo({ top: 0 });
			navigate(`/manga/${mangaId}/chapter/${nextContentId}`);
		}
	};
	const goToPreviousChapter = () => {
		if (previousContentId) {
			setCurrentPage(1);
			setVisibleCount(1);
			window.scrollTo({ top: 0 });
			navigate(`/manga/${mangaId}/chapter/${previousContentId}`);
		}
	};

	/** Standard navigation (non-infinite mode) */
	const goToNextPage = () => {
		if (currentPage < images.length) {
			setCurrentPage((p) => p + 1);
			window.scrollTo({ top: 0, behavior: "smooth" });
		}
	};
	const goToPreviousPage = () => {
		if (currentPage > 1) {
			setCurrentPage((p) => p - 1);
			window.scrollTo({ top: 0, behavior: "smooth" });
		}
	};

	return (
		<div className="min-h-screen bg-background">
			{/* Conflict Resolution Dialog */}
			<Dialog open={showConflictDialog} onOpenChange={setShowConflictDialog}>
				<DialogContent>
					<DialogHeader>
						<DialogTitle>Reading Progress Conflict</DialogTitle>
						<DialogDescription>
							You have different progress saved locally and on the server for
							this chapter.
							<br />
							<span className="mt-2 block">
								Local: <strong>Page {savedPage}</strong>
							</span>
							<span className="block">
								Server: <strong>Page {serverProgress?.pageNumber}</strong>
							</span>
						</DialogDescription>
					</DialogHeader>
					<DialogFooter className="flex flex-row justify-end gap-3">
						<Button
							variant="outline"
							onClick={() => {
								if (savedPage && savedPage > 1) {
									setCurrentPage(savedPage);
									setVisibleCount(savedPage);
									setIsAutoScrolling(true);
									initialJumpDone.current = false;
									saveLocalProgress(savedPage, true);
								}
								setHasInitialized(true);
								setShowConflictDialog(false);
							}}
						>
							Use Local
						</Button>
						<Button
							onClick={() => {
								const target = applyServerProgress();
								if (target) {
									setCurrentPage(target);
									setVisibleCount(target);
									if (target > 1) {
										setIsAutoScrolling(true);
										initialJumpDone.current = false;
									}
								}
								setHasInitialized(true);
								setShowConflictDialog(false);
							}}
						>
							Use Server
						</Button>
					</DialogFooter>
				</DialogContent>
			</Dialog>
			{/* HEADER */}
			<header className="sticky top-0 z-50 border-b border-border bg-background/95 backdrop-blur supports-[backdrop-filter]:bg-background/60 text-xs sm:text-sm">
				<div className="px-2 py-2 sm:px-4 sm:py-4">
					<div className="flex items-center justify-between gap-2 sm:gap-4">
						<div className="flex items-center gap-1 sm:gap-4 flex-1 min-w-0">
							<div className="flex items-center gap-1 shrink-0">
								<Button
									variant="ghost"
									size="sm"
									onClick={() => navigate(`/manga/${mangaId}`)}
									className="gap-2 px-2 sm:px-3"
								>
									<ArrowLeft className="h-4 w-4" />
									<span className="hidden md:inline">Back</span>
								</Button>

								<Button
									variant="ghost"
									size="sm"
									onClick={() => navigate("/")}
									className="gap-2 px-1.5 sm:px-3"
								>
									<Home className="h-4 w-4" />
									<span className="hidden md:inline">Home</span>
								</Button>
							</div>

							<div className="flex items-center gap-1 shrink-0">
								{previousContentId && (
									<Button
										variant="ghost"
										size="sm"
										onClick={goToPreviousChapter}
										className="gap-1 px-1.5"
									>
										<ChevronLeft className="h-4 w-4" />
										<span className="hidden sm:inline">Prev</span>
									</Button>
								)}
								{nextContentId && (
									<Button
										variant="ghost"
										size="sm"
										onClick={goToNextChapter}
										className="gap-1 px-1.5"
									>
										<span className="hidden sm:inline">Next</span>
										<ChevronRight className="h-4 w-4" />
									</Button>
								)}
							</div>

							{/* Title Info - now visible on all screens in the middle */}
							<div className="flex-1 min-w-0 px-1 text-center">
								<h1 className="text-[10px] sm:text-xs font-semibold text-foreground truncate">
									{data.data.mangaTitle}
								</h1>
								<p className="text-[8px] sm:text-[10px] text-muted-foreground truncate">
									Chapter {chapterNumber}
								</p>
							</div>
						</div>

						<div className="flex items-center gap-2 sm:gap-4 shrink-0">
							<span className="text-[10px] sm:text-sm text-muted-foreground whitespace-nowrap">
								{currentPage} / {images.length}
							</span>
							<Button
								variant="outline"
								size="sm"
								onClick={() => setInfiniteScroll((v) => !v)}
								className="h-8 px-2 sm:px-3 text-[10px] sm:text-xs"
							>
								{infiniteScroll ? (
									<span className="">Single</span>
								) : (
									<span className="">Scroll</span>
								)}
								<span className="hidden sm:inline"> Mode</span>
							</Button>
						</div>
					</div>
				</div>
			</header>

			{/* MAIN */}
			<main
				className={`mx-auto max-w-4xl ${infiniteScroll ? "px-0 py-0" : "px-4 py-8"
					}`}
			>
				{/* Removed mobile header from main as it's now in the sticky header */}

				{/* ------------------------------------------------------------------ */}
				{/* MODE 1 --- INFINITE SCROLL MODE                                    */}
				{/* ------------------------------------------------------------------ */}
				{infiniteScroll ? (
					<div className="flex flex-col space-y-0">
						{images.slice(0, visibleCount).map((key, idx) => (
							<div
								key={idx}
								data-page={idx + 1}
								className="w-full m-0 p-0"
								style={{ aspectRatio: "2/3" }}
								onLoadCapture={(e) => {
									const target = e.currentTarget as HTMLElement;
									target.style.aspectRatio = "auto";
								}}
							>
								<img
									src={`${import.meta.env.VITE_OMV_BASE_URL}/${key}`}
									className="w-full h-auto block m-0 p-0 border-none"
									alt={`Page ${idx + 1}`}
									loading="lazy"
								/>
							</div>
						))}

						{/* LOAD MORE SENTINEL */}
						<div ref={loadMoreRef} className="h-40" />

						{/* CHAPTER NAVIGATION (infinite scroll mode) */}
						{(previousContentId || nextContentId) && (
							<div className="flex items-center justify-center gap-3 border-t border-border py-6">
								{previousContentId ? (
									<Button
										onClick={goToPreviousChapter}
										variant="outline"
										className="gap-2 bg-transparent"
									>
										<ChevronLeft className="h-4 w-4" />
										Previous
									</Button>
								) : (
									<div className="flex-1" />
								)}
								{nextContentId ? (
									<Button
										onClick={goToNextChapter}
										variant="outline"
										className="gap-2 bg-transparent"
									>
										Next
										<ChevronRight className="h-4 w-4" />
									</Button>
								) : (
									<div className="flex-1" />
								)}
							</div>
						)}
					</div>
				) : (
					/* ------------------------------------------------------------------ */
					/* MODE 2 --- STANDARD SINGLE-PAGE MODE                               */
					/* ------------------------------------------------------------------ */
					<>
						<div className="relative mx-auto mb-8 overflow-hidden rounded-lg border border-border bg-muted">
							<img
								src={
									import.meta.env.VITE_OMV_BASE_URL +
									"/" +
									images[currentPage - 1] || "/placeholder.svg"
								}
								alt={`Page ${currentPage}`}
								width={1000}
								height={1400}
								className="h-auto w-full"
							/>
						</div>

						{/* NAVIGATION BUTTONS */}
						<div className="space-y-4">
							<div className="flex items-center justify-center gap-4">
								<Button
									onClick={goToPreviousPage}
									disabled={currentPage === 1}
									variant="outline"
									className="gap-2 bg-transparent"
								>
									<ChevronLeft className="h-4 w-4" />
									Previous Page
								</Button>

								<span className="text-sm font-medium text-foreground">
									{currentPage} / {images.length}
								</span>

								<Button
									onClick={goToNextPage}
									disabled={currentPage === images.length}
									variant="outline"
									className="gap-2 bg-transparent"
								>
									Next Page
									<ChevronRight className="h-4 w-4" />
								</Button>
							</div>

							{/* CHAPTER NAVIGATION */}
							{(previousContentId || nextContentId) && (
								<div className="flex items-center justify-center gap-3 border-t border-border pt-4">
									{previousContentId ? (
										<Button
											onClick={goToPreviousChapter}
											variant="outline"
											className="gap-2 bg-transparent"
										>
											<ChevronLeft className="h-4 w-4" />
											Previous
										</Button>
									) : (
										<div className="flex-1" />
									)}
									{nextContentId ? (
										<Button
											onClick={goToNextChapter}
											variant="outline"
											className="gap-2 bg-transparent"
										>
											Next
											<ChevronRight className="h-4 w-4" />
										</Button>
									) : (
										<div className="flex-1" />
									)}
								</div>
							)}
						</div>
					</>
				)}
			</main>
		</div>
	);
};

export default Chapter;
