import { useCallback, useEffect, useState } from "react";
import {
  applySliceEvent,
  createGameSliceSession,
  getGameSliceSessionIdFromUrl,
  loadGameSliceSession,
  resetGameSliceSession,
  saveGameSliceSession,
  withGameSliceSession,
} from "./gameSliceState";
import type { GameSliceSession, SliceEvent } from "./types";

export function useGameSliceSession(options: { createIfMissing?: boolean } = {}) {
  const { createIfMissing = false } = options;
  const [session, setSession] = useState<GameSliceSession | null>(null);
  const [missingRequestedSession, setMissingRequestedSession] = useState<string | null>(null);

  useEffect(() => {
    const id = getGameSliceSessionIdFromUrl();
    const loaded = id ? loadGameSliceSession(id) : null;
    if (loaded) {
      setSession(loaded);
      return;
    }
    if (id) setMissingRequestedSession(id);
    if (!id && createIfMissing) {
      const created = createGameSliceSession();
      saveGameSliceSession(created);
      window.history.replaceState(null, "", withGameSliceSession(`${window.location.pathname}${window.location.search}`, created.id));
      setSession(created);
    }
  }, [createIfMissing]);

  const persist = useCallback((updater: GameSliceSession | ((session: GameSliceSession) => GameSliceSession)) => {
    setSession((prev) => {
      if (!prev) return prev;
      const next = typeof updater === "function" ? updater(prev) : updater;
      saveGameSliceSession(next);
      return next;
    });
  }, []);

  const emit = useCallback((event: SliceEvent) => {
    setSession((prev) => {
      if (!prev) return prev;
      const next = applySliceEvent(prev, event);
      saveGameSliceSession(next);
      return next;
    });
  }, []);

  const reset = useCallback(() => {
    const id = session?.id ?? getGameSliceSessionIdFromUrl() ?? undefined;
    const next = id ? resetGameSliceSession(id) : createGameSliceSession();
    if (!id) saveGameSliceSession(next);
    window.history.replaceState(null, "", withGameSliceSession(window.location.pathname, next.id));
    setMissingRequestedSession(null);
    setSession(next);
    return next;
  }, [session?.id]);

  return { session, setSession: persist, emit, reset, missingRequestedSession };
}
