/**
 * PdfReadingView — full-screen PDF reading powered by PDF.js.
 */

import { lazy, useCallback, useEffect, useMemo, useState } from "react";
import { useNavigate } from "react-router-dom";
import { useTranslation } from "react-i18n-lite";
import { useAnnotations } from "@/context/AnnotationsContext";
import { useBookmarkRailLayout } from "../../hooks/useBookmarkRailLayout";
import { usePdfReader } from "../../hooks/usePdfReader";
import { useReadingSettings } from "../../hooks/useReadingSettings";
import { useReaderOrientationCss } from "../../hooks/useReaderOrientationCss";
import { ReaderErrorScreen } from "./ReaderErrorScreen";
import { ReaderLoadingScreen } from "./ReaderLoadingScreen";
import { ReaderSuspenseShell } from "./ReaderSuspenseShell";
import { useToast } from "../../hooks/useToast";
import { booksApi } from "../../api/books";
import type { EBookDetail } from "../../types/book";
import type { EpubTocItem } from "./TableOfContents";
import { parsePageHref, serializePdfAnchor } from "../../utils/pdfAnchor";
import { fallbackPdfPageToc } from "../../utils/pdfToc";
import { BookMarkersPanel } from "./BookMarkersPanel";
import { BookmarkReaderRail } from "./BookmarkReaderRail";
import { ResumeReadingButton } from "./ResumeReadingButton";
import { PdfLimitationsNotice } from "./PdfLimitationsNotice";
import { PdfViewer } from "./PdfViewer";
import type { MarkerEntry } from "@/types";

const ReaderToolbar = lazy(() => import("./ReaderToolbar"));
const TableOfContents = lazy(() => import("./TableOfContents"));
const ReadingSettingsPanel = lazy(() => import("./ReadingSettingsPanel"));

interface PdfReadingViewProps {
  book: EBookDetail;
  bookId: number;
  initialAnchor?: string;
}

export function PdfReadingView({ book, bookId, initialAnchor }: PdfReadingViewProps) {
  const { t } = useTranslation();
  const navigate = useNavigate();
  const { showToast } = useToast();
  const { markers, addMarker, loadBookmarks } = useAnnotations();

  const [tocOpen, setTocOpen] = useState(false);
  const [settingsOpen, setSettingsOpen] = useState(false);
  const [markersOpen, setMarkersOpen] = useState(false);
  const [tocItems, setTocItems] = useState<EpubTocItem[]>([]);

  const { settings, updateSettings, flushSettings } = useReadingSettings();

  const {
    pdfDocument,
    currentPage,
    pageCount,
    scale,
    setScale,
    chapterTitle,
    progress,
    isLoading,
    error,
    isBookmarkPeekActive,
    readingAnchor,
    goToPage,
    goToNextPage,
    goToPrevPage,
    beginBookmarkPeek,
    resumeReadingAnchor,
    goToAnchor,
  } = usePdfReader(bookId, book.page_count, initialAnchor);

  const bookMarkers = useMemo(
    () => markers.filter((m) => m.ebook_id === bookId),
    [markers, bookId],
  );

  const railItems = useBookmarkRailLayout(bookMarkers);

  useEffect(() => {
    if (!bookId || Number.isNaN(bookId)) return;
    void loadBookmarks(bookId);
  }, [bookId, loadBookmarks]);

  useEffect(() => {
    void booksApi
      .getToc(bookId)
      .then((res) => {
        const items = res.chapters.map((ch) => ({
          label: ch.title,
          href: ch.href || `pdf:page:${ch.index + 1}`,
        }));
        setTocItems(
          items.length > 0
            ? items
            : fallbackPdfPageToc(pageCount, (p) => t("reader.pdfPageLabel", { page: String(p) })),
        );
      })
      .catch(() =>
        setTocItems(fallbackPdfPageToc(pageCount, (p) => t("reader.pdfPageLabel", { page: String(p) }))),
      );
  }, [bookId, pageCount, t]);

  useReaderOrientationCss(settings.orientation_lock);

  const handleTocNavigate = useCallback(
    (href: string) => {
      const page = parsePageHref(href);
      if (page) goToPage(page);
      else goToAnchor(href);
    },
    [goToAnchor, goToPage],
  );

  const handleGoToMarker = useCallback(
    (marker: MarkerEntry) => {
      beginBookmarkPeek(marker.epub_cfi);
      setMarkersOpen(false);
    },
    [beginBookmarkPeek],
  );

  const handleBookmarkPage = useCallback(() => {
    const anchor = serializePdfAnchor(currentPage);
    const exists = bookMarkers.some((m) => m.epub_cfi === anchor);
    if (exists) {
      showToast({ message: t("reader.pageAlreadyBookmarked"), variant: "warning" });
      return;
    }
    void addMarker({
      ebook: bookId,
      epub_cfi: anchor,
      chapter_index: currentPage - 1,
      chapter_title: t("reader.pdfPageLabel", { page: String(currentPage) }),
      location_text: "",
      content: "",
    })
      .then(() => {
        showToast({ message: t("reader.pageBookmarked"), variant: "success" });
      })
      .catch(() => {
        showToast({ message: t("annotations.saveFailed"), variant: "error" });
      });
  }, [addMarker, bookId, bookMarkers, currentPage, showToast, t]);

  const progressForToolbar = useMemo(() => {
    if (!progress) return progress;
    const pct = pageCount > 0 ? Math.round((currentPage / pageCount) * 100) : 0;
    return {
      ...progress,
      percentage: pct,
      current_position: pct,
      current_chapter: currentPage,
    };
  }, [progress, currentPage, pageCount]);

  const isCurrentPageBookmarked = useMemo(() => {
    const anchor = serializePdfAnchor(currentPage);
    return bookMarkers.some((m) => m.epub_cfi === anchor);
  }, [bookMarkers, currentPage]);

  if (isLoading) {
    return <ReaderLoadingScreen />;
  }

  if (error || !pdfDocument) {
    const message =
      error === "PDF_PASSWORD" ? t("reader.pdfPassword") : (error ?? t("reader.unableToOpen"));
    return <ReaderErrorScreen message={message} onBack={() => navigate("/")} />;
  }

  return (
    <ReaderSuspenseShell theme={settings.theme}>
        <ReaderToolbar
          bookTitle={book.title}
          chapterTitle={chapterTitle || t("reader.reading")}
          progress={progressForToolbar}
          onBack={() => navigate("/")}
          onToggleToc={() => setTocOpen((v) => !v)}
          onToggleSettings={() => setSettingsOpen((v) => !v)}
          onToggleMarkers={() => setMarkersOpen((v) => !v)}
          onBookmarkPage={handleBookmarkPage}
          isCurrentPageBookmarked={isCurrentPageBookmarked}
        />

        <PdfLimitationsNotice bookId={bookId} />

        <TableOfContents
          items={tocItems}
          isOpen={tocOpen}
          onClose={() => setTocOpen(false)}
          onNavigate={handleTocNavigate}
        />

        <BookMarkersPanel
          ebookId={bookId}
          isOpen={markersOpen}
          onClose={() => setMarkersOpen(false)}
          onGoToPassage={handleGoToMarker}
          emptyHintKey="annotations.pdfPageBookmarkHint"
        />

        <ReadingSettingsPanel
          format="pdf"
          settings={settings}
          pdfScale={scale}
          onPdfScaleChange={setScale}
          isOpen={settingsOpen}
          onClose={() => setSettingsOpen(false)}
          onUpdate={updateSettings}
          onFlush={flushSettings}
        />

        <main className="reader-pdf-container">
          <div className="reader-pdf-scroll">
            <PdfViewer
              document={pdfDocument}
              pageNumber={currentPage}
              scale={scale}
            />
          </div>
          <BookmarkReaderRail
            items={railItems}
            onGoToBookmark={beginBookmarkPeek}
          />
          <button
            type="button"
            className="reader-page-nav reader-page-nav--prev"
            onClick={goToPrevPage}
            disabled={currentPage <= 1}
            aria-label={t("reader.prevPage")}
          >
            ‹
          </button>
          <ResumeReadingButton
            visible={isBookmarkPeekActive && readingAnchor != null}
            onResume={resumeReadingAnchor}
          />
          <button
            type="button"
            className="reader-page-nav reader-page-nav--next"
            onClick={goToNextPage}
            disabled={currentPage >= pageCount}
            aria-label={t("reader.nextPage")}
          >
            ›
          </button>
        </main>
    </ReaderSuspenseShell>
  );
}
