import { useCallback, useEffect, useState } from "react";
import {
  fetchPresentationById,
  getPlayerModeFromLocation,
  getPresentationIdFromLocation,
  getTargetSlideIdFromLocation
} from "./lib/presentationApi";
import {
  GlitchPlayer,
  createSessionId,
  defaultSlideRegistry
} from "./player";
import { mockVoteApi } from "./lib/voteApi";
import type { VoteRequest } from "./types/events";
import type { PresentationDefinition } from "./types/lecture";

export default function App() {
  const [presentationId] = useState(() => getPresentationIdFromLocation());
  const [playerMode] = useState(() => getPlayerModeFromLocation());
  const [targetSlideId] = useState(() => getTargetSlideIdFromLocation());
  const [presentation, setPresentation] = useState<PresentationDefinition | null>(
    null
  );
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState<string | null>(null);
  const [sessionId] = useState(() => createSessionId());

  const handleVoteCommit = useCallback(
    async (vote: VoteRequest) => {
      if (!presentation) {
        return;
      }

      await mockVoteApi(presentation.id, vote);
    },
    [presentation]
  );

  useEffect(() => {
    let cancelled = false;

    fetchPresentationById(presentationId)
      .then((loadedPresentation) => {
        if (cancelled) {
          return;
        }

        setPresentation(loadedPresentation);
      })
      .catch((caughtError: unknown) => {
        if (cancelled) {
          return;
        }

        setError(
          caughtError instanceof Error
            ? caughtError.message
            : "Could not load presentation fixture."
        );
      })
      .finally(() => {
        if (!cancelled) {
          setLoading(false);
        }
      });

    return () => {
      cancelled = true;
    };
  }, [presentationId]);

  if (loading) {
    return (
      <main className="app-shell app-shell--player-only">
        <section className="app-panel app-panel--fallback">
          <p className="eyebrow">Loading</p>
          <h1>Glitch Presentation Layer POC</h1>
          <p>
            Fetching presentation <strong>{presentationId}</strong> from the mock
            API and warming the player shell.
          </p>
        </section>
      </main>
    );
  }

  if (error || !presentation) {
    return (
      <main className="app-shell app-shell--player-only">
        <section className="app-panel app-panel--fallback">
          <p className="eyebrow">Load failure</p>
          <h1>Glitch Presentation Layer POC</h1>
          <p>{error ?? "Presentation data is unavailable."}</p>
        </section>
      </main>
    );
  }

  return (
    <main className="app-shell app-shell--player-only">
      <section className="app-panel app-panel--player-only">
        <GlitchPlayer
          presentation={presentation}
          slideRegistry={defaultSlideRegistry}
          mode={playerMode}
          targetSlideId={targetSlideId}
          initialSessionId={sessionId}
          onVoteCommit={handleVoteCommit}
        />
      </section>
    </main>
  );
}
