/**
 * ReadingPage — full-screen EPUB reading view powered by react-reader (epub.js).
 */

import { lazy, Suspense, useCallback, useEffect, useState } from "react";
import { useLocation, useNavigate, useParams } from "react-router-dom";
import { useTranslation } from "react-i18n-lite";
import { EpubView, EpubViewStyle } from "react-reader";
import { booksApi } from "../api/books";
import { useEpubHighlights } from "../hooks/useEpubHighlights";
import { useEpubReader } from "../hooks/useEpubReader";
import { useEpubSelection } from "../hooks/useEpubSelection";
import { useReadingSettings } from "../hooks/useReadingSettings";
import type { EBookDetail } from "../types/book";
import type { EpubTocItem } from "../components/reader/TableOfContents";
import { SelectionPopover } from "../components/reader/SelectionPopover";
import { BookMarkersPanel } from "../components/reader/BookMarkersPanel";
import { ResumeReadingButton } from "../components/reader/ResumeReadingButton";
import type { MarkerEntry } from "@/types";
import "../reader.css";

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

type LocationState = { epubLocation?: string } | null;

export default function ReadingPage() {
  const { t } = useTranslation();
  const { id } = useParams<{ id: string }>();
  const navigate = useNavigate();
  const routerLocation = useLocation();
  const bookId = Number(id);
  const initialEpubLocation = (routerLocation.state as LocationState)?.epubLocation;

  const [book, setBook] = useState<EBookDetail | null>(null);
  const [bookLoading, setBookLoading] = useState(true);
  const [bookError, setBookError] = useState<string | null>(null);
  const [tocOpen, setTocOpen] = useState(false);
  const [settingsOpen, setSettingsOpen] = useState(false);
  const [markersOpen, setMarkersOpen] = useState(false);
  const [tocItems, setTocItems] = useState<EpubTocItem[]>([]);
  const [renditionVersion, setRenditionVersion] = useState(0);

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

  const {
    epubUrl,
    location,
    chapterTitle,
    progress,
    isLoading: epubLoading,
    error: epubError,
    handleLocationChanged,
    handleGetRendition,
    navigateToHref,
    beginBookmarkPeek,
    resumeReadingAnchor,
    isBookmarkPeekActive,
    readingAnchor,
    goToNextPage,
    goToPrevPage,
    applySettings,
    epubOptions,
    renditionRef,
  } = useEpubReader(bookId, settings.margin_width, initialEpubLocation);

  const { pendingSelection, clearSelection } = useEpubSelection(
    renditionRef,
    chapterTitle,
    renditionVersion,
  );

  useEpubHighlights(bookId, renditionRef, renditionVersion);

  useEffect(() => {
    if (!bookId || Number.isNaN(bookId)) return;
    setBookLoading(true);
    setBookError(null);
    booksApi
      .getEBook(bookId)
      .then((data) => {
        if (data.format !== "epub") {
          setBookError(t("reader.epubOnly"));
          setBook(null);
          return;
        }
        setBook(data);
      })
      .catch(() => setBookError(t("reader.loadBookFailed")))
      .finally(() => setBookLoading(false));
  }, [bookId, t]);

  useEffect(() => {
    applySettings(settings);
  }, [settings, applySettings]);

  useEffect(() => {
    const root = document.documentElement;
    if (settings.orientation_lock !== "auto") {
      root.style.setProperty(
        "--reader-orientation",
        settings.orientation_lock === "portrait" ? "portrait" : "landscape",
      );
    } else {
      root.style.removeProperty("--reader-orientation");
    }
  }, [settings.orientation_lock]);

  const handleTocChanged = useCallback((toc: EpubTocItem[]) => {
    setTocItems(toc);
  }, []);

  const handleTocNavigate = useCallback(
    (href: string) => {
      navigateToHref(href);
    },
    [navigateToHref],
  );

  const onGetRendition = useCallback(
    (rendition: Parameters<typeof handleGetRendition>[0]) => {
      handleGetRendition(rendition);
      setRenditionVersion((v) => v + 1);
    },
    [handleGetRendition],
  );

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

  const isLoading = bookLoading || epubLoading;
  const error = bookError ?? epubError;

  if (isLoading) {
    return (
      <div className="reader-loading">
        <div className="spinner" />
        <p>{t("reader.loading")}</p>
      </div>
    );
  }

  if (error || !epubUrl) {
    return (
      <div className="reader-loading">
        <p className="reader-error">{error ?? t("reader.unableToOpen")}</p>
        <button type="button" className="back-button" onClick={() => navigate("/")}>
          {t("reader.backToLibrary")}
        </button>
      </div>
    );
  }

  return (
    <Suspense
      fallback={
        <div className="reader-loading">
          <div className="spinner" />
        </div>
      }
    >
      <div className="reader-container" data-theme={settings.theme}>
        <ReaderToolbar
          bookTitle={book?.title ?? t("reader.reading")}
          chapterTitle={chapterTitle || t("reader.reading")}
          progress={progress}
          onBack={() => navigate("/")}
          onToggleToc={() => setTocOpen((v) => !v)}
          onToggleSettings={() => setSettingsOpen((v) => !v)}
          onToggleMarkers={() => setMarkersOpen((v) => !v)}
        />

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

        <BookMarkersPanel
          ebookId={bookId}
          isOpen={markersOpen}
          onClose={() => setMarkersOpen(false)}
          onGoToPassage={handleGoToMarker}
        />

        <ReadingSettingsPanel
          settings={settings}
          isOpen={settingsOpen}
          onClose={() => setSettingsOpen(false)}
          onUpdate={updateSettings}
          onFlush={flushSettings}
        />

        {pendingSelection && (
          <SelectionPopover
            ebookId={bookId}
            selection={pendingSelection}
            onClose={clearSelection}
            onSaved={clearSelection}
          />
        )}

        <main className="reader-epub-container">
          <EpubView
            url={epubUrl}
            location={location}
            locationChanged={handleLocationChanged}
            tocChanged={handleTocChanged}
            getRendition={(rendition) =>
              onGetRendition(rendition as unknown as Parameters<typeof handleGetRendition>[0])
            }
            epubInitOptions={{ openAs: "epub" }}
            epubOptions={epubOptions}
            epubViewStyles={EpubViewStyle}
            loadingView={
              <div className="reader-loading">
                <div className="spinner" />
              </div>
            }
          />
          <button
            type="button"
            className="reader-page-nav reader-page-nav--prev"
            onClick={goToPrevPage}
            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}
            aria-label={t("reader.nextPage")}
          >
            ›
          </button>
        </main>
      </div>
    </Suspense>
  );
}
