import { h } from 'preact';
import { useEffect, useCallback } from 'preact/hooks';

import { useGameState } from '../hooks/useGameState';
import { useNavigation, useNewGameWizard } from '../hooks/useNavigation';
import { useModal, useValidationModal, useCompletionModal } from '../hooks/useModal';

import { GameService } from '../services/gameService';
import type { StandardGame, Game, EndlosGame } from '../types/game';

import { Layout } from './ui/Layout';
import GameListScreen from './screens/GameListScreen';
import NewGameScreen from './screens/NewGameScreen';
import GameDetailScreen from './screens/GameDetailScreen';
import Modal from './Modal';
import ValidationModal from './ValidationModal';
import GameCompletionModal from './GameCompletionModal';
import FullscreenToggle from './FullscreenToggle';

/**
 * Main App component for BSC Score
 */
export default function App() {
  // State management hooks
  const gameState = useGameState();
  const navigation = useNavigation();
  const newGameWizard = useNewGameWizard();
  const modal = useModal();
  const validationModal = useValidationModal();
  const completionModal = useCompletionModal();

  // Game lifecycle handlers
  const handleCreateGame = useCallback(async (gameData: any) => {
    try {
      const gameId = await gameState.addGame(gameData);
      newGameWizard.resetWizard();
      navigation.showGameDetail(gameId);
    } catch (error) {
      console.error('Failed to create game:', error);
      validationModal.showValidation('Failed to create game. Please try again.');
    }
  }, [gameState.addGame, newGameWizard.resetWizard, navigation.showGameDetail, validationModal.showValidation]);


  const handleUpdateScore = useCallback(async (player: number, change: number) => {
    if (!navigation.currentGameId) return;
    
    const game = gameState.getGameById(navigation.currentGameId);
    if (!game || game.status === 'completed') return;
    
    try {
      const updatedGame = GameService.updateGameScore(game as StandardGame, player, change);
      
      // Add undo state for standard games
      const gameWithHistory = {
        ...updatedGame,
        undoStack: [...(game.undoStack || []), game],
        updatedAt: new Date().toISOString(),
      };
      
      await gameState.updateGame(navigation.currentGameId, gameWithHistory);
      
      // Check for completion
      if (GameService.isGameCompleted(gameWithHistory)) {
        completionModal.openCompletionModal(gameWithHistory);
      }
    } catch (error) {
      console.error('Failed to update score:', error);
      validationModal.showValidation('Failed to update score. Please try again.');
    }
  }, [navigation.currentGameId, gameState.getGameById, gameState.updateGame, completionModal.openCompletionModal, validationModal.showValidation]);


  const handleUndo = useCallback(async () => {
    if (!navigation.currentGameId) return;
    
    const game = gameState.getGameById(navigation.currentGameId);
    if (!game?.undoStack?.length) return;

    try {
      const lastState = game.undoStack[game.undoStack.length - 1];
      const newUndoStack = game.undoStack.slice(0, -1);

      await gameState.updateGame(navigation.currentGameId, {
        ...lastState,
        undoStack: newUndoStack,
      } as Game);
    } catch (error) {
      console.error('Failed to undo:', error);
      validationModal.showValidation('Failed to undo. Please try again.');
    }
  }, [navigation.currentGameId, gameState.getGameById, gameState.updateGame, validationModal.showValidation]);

  const handleForfeit = async () => {
    if (!navigation.currentGameId) return;
    
    const game = gameState.getGameById(navigation.currentGameId);
    if (!game || !('players' in game)) return;

    try {
      const currentPlayerIndex = game.currentPlayer;
      if (currentPlayerIndex === null) return;

      const winner = game.players.find((_, idx) => idx !== currentPlayerIndex);
      const forfeitedGame = {
        ...game,
        status: 'completed' as const,
        winner: winner?.name,
        forfeitedBy: game.players[currentPlayerIndex].name,
        updatedAt: new Date().toISOString(),
      };
      
      await gameState.updateGame(navigation.currentGameId, forfeitedGame);
      completionModal.openCompletionModal(forfeitedGame);
    } catch (error) {
      console.error('Failed to forfeit game:', error);
      validationModal.showValidation('Failed to forfeit game. Please try again.');
    }
  };

  const handleFinishGame = () => {
    if (!navigation.currentGameId) return;
    
    const game = gameState.getGameById(navigation.currentGameId);
    if (!game) return;
    
    completionModal.openCompletionModal(game);
  };

  const handleConfirmCompletion = async () => {
    if (!navigation.currentGameId) return;
    
    try {
      await gameState.updateGame(navigation.currentGameId, {
        ...gameState.getGameById(navigation.currentGameId)!,
        status: 'completed',
        updatedAt: new Date().toISOString(),
      });
      
      completionModal.closeCompletionModal();
    } catch (error) {
      console.error('Failed to complete game:', error);
      validationModal.showValidation('Failed to complete game. Please try again.');
    }
  };

  const handleRematch = async () => {
    if (!navigation.currentGameId) return;
    
    const completedGame = gameState.getGameById(navigation.currentGameId);
    if (!completedGame) return;

    let gameData;
    if ('players' in completedGame) {
      gameData = {
        player1: completedGame.players[0]?.name || '',
        player2: completedGame.players[1]?.name || '',
        player3: completedGame.players[2]?.name || '',
        gameType: completedGame.gameType,
        raceTo: completedGame.raceTo.toString(),
      };
    } else {
      gameData = {
        player1: completedGame.player1,
        player2: completedGame.player2,
        player3: completedGame.player3 || '',
        gameType: completedGame.gameType,
        raceTo: completedGame.raceTo.toString(),
      };
    }
    
    try {
      const newGameId = await gameState.addGame(gameData);
      completionModal.closeCompletionModal();
      navigation.showGameDetail(newGameId);
    } catch (error) {
      console.error('Failed to create rematch:', error);
      validationModal.showValidation('Failed to create rematch. Please try again.');
    }
  };

  const handleDeleteGame = (gameId: number) => {
    modal.openModal(gameId);
  };

  const handleConfirmDelete = async () => {
    if (modal.modal.gameId) {
      try {
        await gameState.deleteGame(modal.modal.gameId);
        modal.closeModal();
        navigation.showGameList();
      } catch (error) {
        console.error('Failed to delete game:', error);
        validationModal.showValidation('Failed to delete game. Please try again.');
      }
    }
  };

  return (
    <Layout>
      {navigation.screen === 'game-list' && (
        <GameListScreen
          games={gameState.games}
          filter={gameState.filter}
          onFilterChange={gameState.setFilter}
          onShowGameDetail={navigation.showGameDetail}
          onDeleteGame={handleDeleteGame}
              onShowNewGame={() => {
                newGameWizard.startWizard();
                navigation.showNewGame();
              }}
        />
      )}

      {navigation.screen === 'new-game' && (
        <NewGameScreen
          step={newGameWizard.newGameStep}
          data={newGameWizard.newGameData}
          playerHistory={gameState.getPlayerNameHistory()}
          onStepChange={newGameWizard.nextStep}
          onDataChange={newGameWizard.updateGameData}
          onCreateGame={handleCreateGame}
          onCancel={() => {
            newGameWizard.resetWizard();
            navigation.showGameList();
          }}
          onShowValidation={validationModal.showValidation}
        />
      )}

      {navigation.screen === 'game-detail' && navigation.currentGameId && (
        <GameDetailScreen
          game={gameState.getGameById(navigation.currentGameId)}
          onUpdateScore={handleUpdateScore}
          onFinishGame={handleFinishGame}
          onUpdateGame={async (game: EndlosGame) => {
            try {
              await gameState.updateGame(navigation.currentGameId!, game);
            } catch (error) {
              console.error('Failed to update game:', error);
              validationModal.showValidation('Failed to update game. Please try again.');
            }
          }}
          onUndo={handleUndo}
          onForfeit={handleForfeit}
          onBack={navigation.showGameList}
        />
      )}

      <Modal
        open={modal.modal.open}
        title="Spiel löschen"
        message="Möchten Sie das Spiel wirklich löschen?"
        onCancel={modal.closeModal}
        onConfirm={handleConfirmDelete}
      />

      <ValidationModal
        open={validationModal.validation.open}
        message={validationModal.validation.message}
        onClose={validationModal.closeValidation}
      />

      <GameCompletionModal
        open={completionModal.completionModal.open}
        game={completionModal.completionModal.game}
        onConfirm={handleConfirmCompletion}
        onClose={completionModal.closeCompletionModal}
        onRematch={handleRematch}
      />

      <FullscreenToggle />
    </Layout>
  );
}