import { useEffect, useState } from "react";
import { loadSlideModule } from "../lib/slideRegistry";
import { SlideErrorBoundary } from "./SlideErrorBoundary";
import { FallbackSlide } from "../slides/FallbackSlide";
import type {
  GlitchSlide,
  Slide,
  SlideComponentModule,
  SlideRegistry,
  SlideRuntimeProps
} from "../types/lecture";

export interface LoadedGlitchSlideProps {
  lectureId: string;
  slide: Slide;
  glitchSlide: GlitchSlide;
  slideRegistry: SlideRegistry;
  paused: boolean;
  onMediaLoadingChange?: (isLoading: boolean) => void;
}

export function LoadedGlitchSlide({
  lectureId,
  slide,
  glitchSlide,
  slideRegistry,
  paused,
  onMediaLoadingChange
}: LoadedGlitchSlideProps) {
  const [LoadedComponent, setLoadedComponent] =
    useState<SlideComponentModule["default"] | null>(null);
  const [loadError, setLoadError] = useState<string | null>(null);

  useEffect(() => {
    let cancelled = false;
    setLoadError(null);
    setLoadedComponent(null);

    loadSlideModule(slideRegistry, glitchSlide.componentKey)
      .then((module) => {
        if (!cancelled) {
          setLoadError(null);
          setLoadedComponent(() => module.default);
        }
      })
      .catch((caughtError: unknown) => {
        if (!cancelled) {
          setLoadedComponent(null);
          setLoadError(
            caughtError instanceof Error
              ? caughtError.message
              : "Failed to load slide component."
          );
        }
      });

    return () => {
      cancelled = true;
    };
  }, [glitchSlide.componentKey, slideRegistry]);

  const runtimeProps: SlideRuntimeProps = {
    lectureId,
    slideId: slide.id,
    glitchSlideId: glitchSlide.id,
    displayMode: slide.displayMode,
    props: glitchSlide.props,
    latexString: glitchSlide.latexString,
    paused,
    onMediaLoadingChange
  };

  return (
    <SlideErrorBoundary fallback={<FallbackSlide reason={loadError} />}>
      {LoadedComponent ? (
        <LoadedComponent {...runtimeProps} />
      ) : loadError ? (
        <FallbackSlide reason={loadError} />
      ) : (
        <FallbackSlide reason="Loading candidate module..." />
      )}
    </SlideErrorBoundary>
  );
}
