/**
 * @fileoverview Context isolado para progresso de fases do jogo.
 *
 * Gerencia: fase atual, fases completadas, persistência em localStorage e migração de dados.
 *
 * GameStateProvider compõe este provider internamente via Proxy Pattern,
 * garantindo zero breaking changes: useGameState() continua expondo todos
 * os campos de progresso no mesmo objeto de contexto.
 *
 * @module contexts.GameProgressContext
 */

import {
  createContext,
  useCallback,
  useContext,
  useEffect,
  useRef,
  useState,
} from "react";
import PropTypes from "prop-types";
import { getUnlockedPhases } from "../utils/phaseUtils";

const GameProgressContext = createContext(null);

/**
 * Provider que gerencia progresso de fases: fase atual, fases completadas
 * e persistência bidirecional em localStorage (incluindo migração de chave legada).
 *
 * @component
 * @param {Object}          props
 * @param {React.ReactNode} props.children
 * @param {Object}          props.gameConfig         - Configuração do jogo
 * @param {string}          props.gameConfig.gameId  - ID único do jogo
 * @param {Array}           props.gameConfig.fases   - Array de fases
 */
export function GameProgressProvider({ children, gameConfig }) {
  const [currentPhase, setCurrentPhase] = useState(1);
  const [completedPhases, setCompletedPhases] = useState([]);

  const storageKey = `${gameConfig.gameId}-completed-phases`;
  const legacyStorageKey = `${gameConfig.gameId}-fases-concluidas`;
  const initialized = useRef(false);

  // Carrega progresso salvo na montagem; aplica debug mode se necessário.
  useEffect(() => {
    // Try both window.location.search and hash-based query params (for HashRouter)
    let urlParams = new URLSearchParams(window.location.search);
    let debugKey = Array.from(urlParams.keys()).find(
      (k) => k.toLowerCase() === "debug",
    );

    // If not found in search, try hash (for HashRouter with ?debug=true after hash)
    if (!debugKey && window.location.hash.includes('?')) {
      const hashSearch = window.location.hash.split('?')[1];
      urlParams = new URLSearchParams(hashSearch);
      debugKey = Array.from(urlParams.keys()).find(
        (k) => k.toLowerCase() === "debug",
      );
    }

    const isDebug = urlParams.get(debugKey)?.toLowerCase() === "true";

    if (isDebug) {
      const todas = Array.from(
        { length: gameConfig.fases.length },
        (_, i) => i + 1,
      );
      setCompletedPhases(todas);
      localStorage.setItem(storageKey, JSON.stringify(todas));
      setCurrentPhase(gameConfig.fases.length);
      return;
    }

    if (initialized.current) return;

    let fasesSalvas = null;

    try {
      const saved = localStorage.getItem(storageKey);
      if (saved) {
        fasesSalvas = JSON.parse(saved);
      } else {
        // Migração de chave legada
        const legacySaved = localStorage.getItem(legacyStorageKey);
        if (legacySaved) {
          fasesSalvas = JSON.parse(legacySaved);
          localStorage.setItem(storageKey, JSON.stringify(fasesSalvas));
          console.info("[Migration] Data synced to new key", {
            gameId: gameConfig.gameId,
            migratedItems: fasesSalvas.length,
            timestamp: new Date().toISOString(),
          });
        }
      }
    } catch (error) {
      console.error(
        "[Migration Error] Failed to restore phases from storage",
        error,
      );
      fasesSalvas = null;
    }

    if (fasesSalvas && fasesSalvas.length > 0) {
      setCompletedPhases(fasesSalvas);
      const unlockedPhases = getUnlockedPhases(
        fasesSalvas,
        gameConfig.fases.length,
      );
      setCurrentPhase(Math.max(...unlockedPhases));
    }

    initialized.current = true;
  }, [storageKey, legacyStorageKey, gameConfig.gameId, gameConfig.fases.length]);

  // Persiste fases completadas sempre que mudam (após inicialização).
  useEffect(() => {
    if (!initialized.current) return;
    try {
      localStorage.setItem(storageKey, JSON.stringify(completedPhases));
    } catch (error) {
      console.error("[Storage Error] Failed to save completed phases", error);
    }
  }, [completedPhases, storageKey]);

  /** Navega para uma fase específica (apenas progresso; execução fica em GameStateContext). */
  const changePhase = useCallback((numeroFase) => {
    setCurrentPhase(numeroFase);
  }, []);

  /** Remove todo o progresso e volta para a fase 1. */
  const resetProgress = useCallback(() => {
    setCompletedPhases([]);
    setCurrentPhase(1);
    localStorage.removeItem(storageKey);
  }, [storageKey]);

  return (
    <GameProgressContext.Provider
      value={{
        currentPhase,
        setCurrentPhase,
        completedPhases,
        setCompletedPhases,
        changePhase,
        resetProgress,
      }}
    >
      {children}
    </GameProgressContext.Provider>
  );
}

GameProgressProvider.propTypes = {
  children: PropTypes.node.isRequired,
  gameConfig: PropTypes.shape({
    gameId: PropTypes.string.isRequired,
    fases: PropTypes.array.isRequired,
  }).isRequired,
};

/**
 * Consome GameProgressContext diretamente.
 * Consumidores que só precisam de dados de progresso podem migrar para este hook
 * ao longo do tempo, sem depender do GameStateContext completo.
 *
 * @hook
 * @returns {{ currentPhase, setCurrentPhase, completedPhases, setCompletedPhases, changePhase, resetProgress }}
 */
export function useGameProgress() {
  const context = useContext(GameProgressContext);
  if (!context) {
    throw new Error(
      "useGameProgress deve ser usado dentro de GameProgressProvider",
    );
  }
  return context;
}
