"use client";

import { useQuery } from "@tanstack/react-query";
import { useSetAtom } from "jotai";
import { XIcon } from "lucide-react";
import type { FC } from "react";
import { useEffect, useMemo, useRef } from "react";
import { openEditorPanelAtom } from "@/atoms/editor/editor-panel.atom";
import { MarkdownViewer } from "@/components/markdown-viewer";
import { Button } from "@/components/ui/button";
import { Spinner } from "@/components/ui/spinner";
import { documentsApiService } from "@/lib/apis/documents-api.service";

const DEFAULT_CHUNK_WINDOW = 5;

interface CitationPanelContentProps {
	chunkId: number;
	onClose?: () => void;
	showHeader?: boolean;
}

/**
 * Right-panel citation viewer. Shows the cited chunk surrounded by
 * adjacent chunks (±N chunks via the API's `chunk_window` parameter),
 * with the cited one visually highlighted and auto-scrolled into view.
 * The user can jump to the full document via the editor panel.
 */
export const CitationPanelContent: FC<CitationPanelContentProps> = ({
	chunkId,
	onClose,
	showHeader = true,
}) => {
	const openEditorPanel = useSetAtom(openEditorPanelAtom);

	const chunkWindow = DEFAULT_CHUNK_WINDOW;

	const { data, isLoading, error } = useQuery({
		queryKey: ["citation-panel", chunkId, chunkWindow] as const,
		queryFn: () =>
			documentsApiService.getDocumentByChunk({
				chunk_id: chunkId,
				chunk_window: chunkWindow,
			}),
		staleTime: 5 * 60 * 1000,
	});

	const cited = useMemo(() => data?.chunks.find((c) => c.id === chunkId) ?? null, [data, chunkId]);

	const totalChunks = data?.total_chunks ?? data?.chunks.length ?? 0;
	const startIndex = data?.chunk_start_index ?? 0;
	const hasMoreAbove = startIndex > 0;
	const hasMoreBelow = data ? startIndex + data.chunks.length < totalChunks : false;

	// Scroll the cited chunk into view inside the panel's scroll container
	// (not the page). We anchor the scroll to the panel's scroll element
	// so opening the citation doesn't yank the chat scroll on the left.
	const scrollContainerRef = useRef<HTMLDivElement | null>(null);
	const citedRef = useRef<HTMLDivElement | null>(null);
	useEffect(() => {
		if (!cited) return;
		const id = requestAnimationFrame(() => {
			const container = scrollContainerRef.current;
			const target = citedRef.current;
			if (!container || !target) return;
			const containerRect = container.getBoundingClientRect();
			const targetRect = target.getBoundingClientRect();
			const offset = targetRect.top - containerRect.top + container.scrollTop;
			container.scrollTo({
				top: Math.max(0, offset - 16),
				behavior: "smooth",
			});
		});
		return () => cancelAnimationFrame(id);
	}, [cited]);

	const handleOpenFullDocument = () => {
		if (!data) return;
		openEditorPanel({
			documentId: data.id,
			searchSpaceId: data.search_space_id,
			title: data.title,
		});
	};

	return (
		<>
			<div className="shrink-0">
				{showHeader && (
					<div className="shrink-0 flex h-12 items-center justify-between px-3 border-b">
						<h2 className="select-none text-lg font-semibold">Citation</h2>
						<div className="flex items-center gap-1 shrink-0">
							{onClose && (
								<Button
									variant="ghost"
									size="icon"
									onClick={onClose}
									className="h-8 w-8 rounded-full shrink-0 text-muted-foreground hover:text-accent-foreground"
								>
									<XIcon className="h-4 w-4" />
									<span className="sr-only">Close citation panel</span>
								</Button>
							)}
						</div>
					</div>
				)}
				<div className="grid h-10 grid-cols-[minmax(0,1fr)_auto] items-center gap-3 border-b px-4">
					<div className="min-w-0 flex flex-1 items-center gap-2">
						<p className="truncate text-sm text-muted-foreground">
							{data?.title ?? (isLoading ? "Loading…" : `Chunk #${chunkId}`)}
						</p>
					</div>
					<div className="flex items-center gap-3 shrink-0 text-[11px] text-muted-foreground">
						{totalChunks > 0 && <span>{totalChunks} chunks</span>}
						{!isLoading && !error && data && (
							<Button
								variant="default"
								size="sm"
								className="h-6 px-1.5 text-[11px]"
								onClick={handleOpenFullDocument}
							>
								Open
							</Button>
						)}
					</div>
				</div>
			</div>

			<div ref={scrollContainerRef} className="flex-1 overflow-y-auto px-5 py-4">
				{isLoading && (
					<div className="flex min-h-full items-center justify-center text-muted-foreground">
						<Spinner size="md" />
					</div>
				)}

				{error && (
					<p className="py-8 text-sm text-destructive">
						{error instanceof Error ? error.message : "Failed to load citation"}
					</p>
				)}

				{!isLoading && !error && data && (
					<>
						{hasMoreAbove && (
							<p className="mb-3 text-center text-[11px] text-muted-foreground">
								… {startIndex} earlier chunk{startIndex === 1 ? "" : "s"} not shown
							</p>
						)}
						<div className="space-y-3">
							{data.chunks.map((chunk) => {
								const isCited = chunk.id === chunkId;
								return (
									<div
										key={chunk.id}
										ref={isCited ? citedRef : null}
										data-cited={isCited || undefined}
										className={
											isCited
												? "rounded-md border-2 border-primary bg-accent px-4 py-3 shadow-sm"
												: "rounded-md bg-accent px-4 py-3 opacity-70 transition-opacity hover:opacity-100"
										}
									>
										<div className="mb-1.5 flex items-center justify-between">
											<span
												className={
													isCited
														? "text-[11px] text-muted-foreground"
														: "text-[11px] font-medium text-muted-foreground"
												}
											>
												Chunk #{chunk.id}
											</span>
											{isCited && (
												<span className="text-[11px] font-semibold text-primary">Cited chunk</span>
											)}
										</div>
										<div className="text-sm">
											<MarkdownViewer content={chunk.content} enableCitations />
										</div>
									</div>
								);
							})}
						</div>
						{hasMoreBelow && (
							<p className="mt-3 text-center text-[11px] text-muted-foreground">
								… {totalChunks - (startIndex + data.chunks.length)} later chunk
								{totalChunks - (startIndex + data.chunks.length) === 1 ? "" : "s"} not shown
							</p>
						)}
					</>
				)}
			</div>
		</>
	);
};
