import { Alpine } from "../alpine";
import { getReaderMetadata } from "../api";
import "./comic/panel-editor";
import { createReaderContext, type ReaderContext } from "./core/reader-context";
import { getState, setState } from "./core/reader-state";
import { createNavigationAPI } from "./core/reader-navigation";
import { readerEvents } from "./core/reader-events";

interface UniversalReader {
  type: "ebook";
  cif: any;
  currentSpineIndex: number;
}

interface PDFReader {
  type: "pdf";
  doc: any;
  currentPage: number;
}

interface ComicReader {
  type: "comic";
  images: Blob[];
  currentPage: number;
}

interface MangaReader {
  type: "manga";
  images: Blob[];
  currentPage: number;
  readingDirection: "rtl" | "vertical";
}

type CurrentReader = UniversalReader | PDFReader | ComicReader | MangaReader;

let currentReader: CurrentReader | null = null;
let readerMetadata: ReaderMetadata | null = null;

// ============================================================
// Feature Registry
// ============================================================

type FeatureInit = (context: ReaderContext) => void | Promise<void>;

const featureModules: FeatureInit[] = [
  // Core features
  (ctx) => import("./features/gestures").then((m) => m.init(ctx)),
  (ctx) => import("./features/keyboard-shortcuts").then((m) => m.init(ctx)),
  (ctx) => import("./features/panel-dock-system").then((m) => m.init(ctx)),
  (ctx) => import("./features/navigator-panel").then((m) => m.init(ctx)),
  (ctx) => import("./features/offline-manager").then((m) => m.init(ctx)),
  (ctx) => import("./features/reading-speed-tracker").then((m) => m.init(ctx)),
  (ctx) => import("./features/progress-indicator").then((m) => m.init(ctx)),

  // Comic features
  (ctx) => import("./comic/background-color").then((m) => m.init?.(ctx)),
  (ctx) => import("./comic/chapter-markers").then((m) => m.init?.(ctx)),
  (ctx) => import("./comic/page-cache").then((m) => m.init?.(ctx)),

  // PDF features
  (ctx) => import("./pdf/pdf-navigation").then((m) => m.init?.(ctx)),
  (ctx) => import("./pdf/pdf-text-selection").then((m) => m.init?.(ctx)),
  (ctx) => import("./pdf/annotation-layer").then((m) => m.init?.(ctx)),

  // Ebook features
  (ctx) => import("./ebook/copy-handler").then((m) => m.init?.(ctx)),
  (ctx) => import("./ebook/font-loader").then((m) => m.init?.(ctx)),

  // Manga features
  (ctx) => import("./manga/reading-direction").then((m) => m.init?.(ctx)),
  (ctx) => import("./manga/vertical-scroll-mode").then((m) => m.init?.(ctx)),
];

async function initializeFeatures(context: ReaderContext): Promise<void> {
  const results = await Promise.allSettled(
    featureModules.map((getInit) => getInit(context)),
  );

  results.forEach((result, index) => {
    if (result.status === "rejected") {
      console.warn(`Feature ${index} failed to initialize:`, result.reason);
    }
  });
}

// ============================================================
// Reader Initialization
// ============================================================

async function initializeReader(): Promise<void> {
  const mediaItemId = document.body.dataset.mediaItemId;
  console.log("Initializing reader for:", mediaItemId);
  if (!mediaItemId) {
    console.error("No mediaItemId on body");
    return;
  }

  try {
    readerMetadata = await getReaderMetadata(mediaItemId);
    console.log("Got metadata:", readerMetadata);
    console.log("Library type:", readerMetadata.library_type_name);
    console.log("Mime type:", readerMetadata.mime_type);
    switch (readerMetadata.format_group) {
      case "reflowable":
        if (
          readerMetadata.mime_type === "application/epub+zip" ||
          readerMetadata.file_path.endsWith(".epub")
        ) {
          currentReader = await initializeEbookReader(readerMetadata);
        }
        break;
      case "fixed_layout":
        currentReader = await initializePDFReader(readerMetadata);
        break;
      case "comic_archive":
        // Check manga_type or library_type_name
        if (
          readerMetadata.manga_type === "yes" ||
          readerMetadata.manga_type === "yes_and_right_to_left" ||
          readerMetadata.library_type_name === "manga"
        ) {
          currentReader = await initializeMangaReader(readerMetadata);
        } else {
          currentReader = await initializeComicReader(readerMetadata);
        }
        break;
    }

    if (!currentReader) return;

    setState({ currentReader, readerMetadata });

    const context = createReaderContext(
      getState,
      setState,
      createNavigationAPI(),
      () =>
        (context.render = () => {
          // Delegates to navigation module
        }),
    );

    await initializeFeatures(context);
    readerEvents.emit("readerReady", currentReader);
  } catch (error) {
    console.error("Render initialization failed:", error);
  }
}

async function initializeEbookReader(metadata: any): Promise<UniversalReader> {
  const { parseEbook, requiresServerParsing } =
    await import("./core/parser-manager");

  const needsServer = requiresServerParsing(
    metadata.mime_type,
    getFileExtension(metadata.file_path),
  );

  let ebookFile: Blob;

  if (needsServer) {
    const response = await fetch(`/readers/${metadata.media_item_id}/parse`, {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify({
        mime_type: metadata.mime_type,
        file_path: metadata.file_path,
      }),
    });

    if (!response.ok) {
      throw new Error(`Server parsing failed: ${response.statusText}`);
    }

    ebookFile = await response.blob();
  } else {
    const response = await fetch(metadata.file_path);
    ebookFile = await response.blob();
  }

  const cif = await parseEbook(
    ebookFile,
    metadata.mime_type,
    getFileExtension(metadata.file_path),
  );

  return {
    type: "ebook",
    cif,
    currentSpineIndex: 0,
  };
}

async function initializePDFReader(metadata: any): Promise<PDFReader> {
  const { initializePDFReader } = await import("./pdf/pdfjs-wrapper");
  return initializePDFReader(metadata);
}

async function initializeComicReader(metadata: any): Promise<ComicReader> {
  const { initializeComicReader } = await import("./comic/image-parser");
  return initializeComicReader(metadata);
}

async function initializeMangaReader(metadata: any): Promise<MangaReader> {
  const { initializeMangaReader } = await import("./comic/image-parser");
  return initializeMangaReader(metadata);
}

function getFileExtension(filepath: string): string {
  const match = filepath.match(/\.([^.]+)$/);
  return match ? `.${match[1]}` : "";
}

// ============================================================
// Alpine.js Integration
// ============================================================

Alpine.data("readerShell", () => ({
  initReader() {
    initializeReader();
  },

  get currentPage() {
    const state = getState();
    if (!state.currentReader) return 0;

    if (state.currentReader.type === "ebook") {
      return state.currentReader.currentSpineIndex + 1;
    }
    return state.currentReader.currentPage;
  },

  get totalPages() {
    const state = getState();
    if (!state.currentReader || !state.readerMetadata) return 0;

    if (state.currentReader.type === "ebook") {
      return state.currentReader.cif.spine.length;
    } else if (state.currentReader.type === "pdf") {
      return state.readerMetadata.total_pages || 0;
    } else {
      return (state.currentReader as any).images.length;
    }
  },
}));
