'use client';

import { useState, useEffect } from 'react';
import { getTodayISOString } from './dateUtils';
import { loadPlayerState, savePlayerState, getGenreKey } from './playerStorage';

export interface GameState {
    date: string;
    guesses: string[]; // Array of song titles or IDs guessed
    isSolved: boolean;
    isFailed: boolean;
    lastPlayed: number; // Timestamp
    score: number;
    replayCount: number;
    skipCount: number;
    scoreBreakdown: Array<{ value: number; reason: string }>;
    yearGuessed: boolean;
}

export interface Statistics {
    solvedIn1: number;
    solvedIn2: number;
    solvedIn3: number;
    solvedIn4: number;
    solvedIn5: number;
    solvedIn6: number;
    solvedIn7: number;
    failed: number;
}

const INITIAL_SCORE = 90;

export function useGameState(
    genre: string | null = null,
    maxAttempts: number = 7,
    isSpecial: boolean = false
) {
    const [gameState, setGameState] = useState<GameState | null>(null);
    const [statistics, setStatistics] = useState<Statistics | null>(null);
    
    // Get genre key for backend storage
    // For specials, genre contains the special name
    const genreKey = getGenreKey(isSpecial ? null : genre, isSpecial, isSpecial ? genre || undefined : undefined);

    const createNewState = (date: string): GameState => ({
        date,
        guesses: [],
        isSolved: false,
        isFailed: false,
        lastPlayed: Date.now(),
        score: INITIAL_SCORE,
        replayCount: 0,
        skipCount: 0,
        scoreBreakdown: [{ value: INITIAL_SCORE, reason: 'Start value' }],
        yearGuessed: false
    });

    const createNewStatistics = (): Statistics => ({
        solvedIn1: 0,
        solvedIn2: 0,
        solvedIn3: 0,
        solvedIn4: 0,
        solvedIn5: 0,
        solvedIn6: 0,
        solvedIn7: 0,
        failed: 0,
    });

    useEffect(() => {
        const today = getTodayISOString();
        
        // Always recompute genreKey to ensure it's current
        const currentGenreKey = getGenreKey(isSpecial ? null : genre, isSpecial, isSpecial ? genre || undefined : undefined);
        
        // Try to load from backend first
        const loadFromBackend = async () => {
            try {
                const backendState = await loadPlayerState(currentGenreKey);
                
                if (backendState) {
                    const { gameState: loadedState, statistics: loadedStats } = backendState;
                    
                    // Check if the loaded state is for today
                    if (loadedState.date === today) {
                        setGameState(loadedState);
                        setStatistics(loadedStats);
                        return; // Successfully loaded from backend
                    } else {
                        // State is for a different day - create new state
                        const newState = createNewState(today);
                        setGameState(newState);
                        setStatistics(loadedStats); // Keep statistics across days
                        // Save new state to backend
                        await savePlayerState(currentGenreKey, newState, loadedStats);
                        return;
                    }
                } else {
                    // No backend state found - create new state
                    // This is the normal case for first-time players or new genre
                    const newState = createNewState(today);
                    setGameState(newState);
                    const newStats = createNewStatistics();
                    setStatistics(newStats);
                    // Save to backend for cross-domain sync
                    await savePlayerState(currentGenreKey, newState, newStats);
                    return;
                }
            } catch (error) {
                console.error('[gameState] Failed to load from backend:', error);
                
                // On error, create new state and try to save to backend
                // This handles network errors gracefully
                const newState = createNewState(today);
                setGameState(newState);
                const newStats = createNewStatistics();
                setStatistics(newStats);
                // Try to save to backend (may fail, but we try)
                try {
                    await savePlayerState(currentGenreKey, newState, newStats);
                } catch (saveError) {
                    console.error('[gameState] Failed to save new state to backend:', saveError);
                }
            }
        };
        
        loadFromBackend();
    }, [genre, isSpecial]); // Re-run when genre or isSpecial changes

    const saveState = async (newState: GameState) => {
        setGameState(newState);
        
        // Save to backend only
        if (statistics) {
            try {
                // Always use the current genreKey (recompute it in case genre/isSpecial changed)
                const currentGenreKey = getGenreKey(isSpecial ? null : genre, isSpecial, isSpecial ? genre || undefined : undefined);
                await savePlayerState(currentGenreKey, newState, statistics);
            } catch (error) {
                console.error('[gameState] Failed to save to backend:', error);
                // No fallback - backend is required for cross-domain sync
            }
        }
    };

    const updateStatistics = async (attempts: number, solved: boolean) => {
        if (!statistics) return;

        const newStats = { ...statistics };

        if (solved) {
            switch (attempts) {
                case 1: newStats.solvedIn1++; break;
                case 2: newStats.solvedIn2++; break;
                case 3: newStats.solvedIn3++; break;
                case 4: newStats.solvedIn4++; break;
                case 5: newStats.solvedIn5++; break;
                case 6: newStats.solvedIn6++; break;
                case 7: newStats.solvedIn7++; break;
                default:
                    break;
            }
        } else {
            newStats.failed++;
        }

        setStatistics(newStats);
        
        // Save to backend only
        if (gameState) {
            try {
                // Always use the current genreKey (recompute it in case genre/isSpecial changed)
                const currentGenreKey = getGenreKey(isSpecial ? null : genre, isSpecial, isSpecial ? genre || undefined : undefined);
                await savePlayerState(currentGenreKey, gameState, newStats);
            } catch (error) {
                console.error('[gameState] Failed to save statistics to backend:', error);
                // No fallback - backend is required for cross-domain sync
            }
        }
    };

    const addGuess = (guess: string, correct: boolean) => {
        if (!gameState) return;
        // Prevent adding guesses if already solved or failed
        if (gameState.isSolved || gameState.isFailed) return;

        const newGuesses = [...gameState.guesses, guess];
        const isSolved = correct;
        const isFailed = !correct && newGuesses.length >= maxAttempts;

        let newScore = gameState.score;
        const newBreakdown = [...gameState.scoreBreakdown];

        if (correct) {
            newScore += 20;
            newBreakdown.push({ value: 20, reason: 'Correct Answer' });
        } else {
            if (guess === 'SKIPPED') {
                newScore -= 5;
                newBreakdown.push({ value: -5, reason: 'Skip' });
            } else {
                newScore -= 3;
                newBreakdown.push({ value: -3, reason: 'Wrong guess' });
                // Additional penalty for track extension (unlock steps)
                newScore -= 5;
                newBreakdown.push({ value: -5, reason: 'Track extension' });
            }
        }

        // If failed, reset score to 0
        if (isFailed) {
            if (newScore > 0) {
                newBreakdown.push({ value: -newScore, reason: 'Game Over' });
                newScore = 0;
            }
        }

        // Ensure score doesn't go below 0
        newScore = Math.max(0, newScore);

        const newState = {
            ...gameState,
            guesses: newGuesses,
            isSolved,
            isFailed,
            lastPlayed: Date.now(),
            score: newScore,
            scoreBreakdown: newBreakdown,
            // Update skip count if skipped
            skipCount: guess === 'SKIPPED' ? gameState.skipCount + 1 : gameState.skipCount
        };

        saveState(newState);

        // Update statistics when game ends
        if (isSolved || isFailed) {
            updateStatistics(newGuesses.length, isSolved);
        }
    };

    const giveUp = () => {
        if (!gameState || gameState.isSolved || gameState.isFailed) return;

        let newScore = 0;
        const newBreakdown = [...gameState.scoreBreakdown];

        if (gameState.score > 0) {
            newBreakdown.push({ value: -gameState.score, reason: 'Gave Up' });
        }

        const newState = {
            ...gameState,
            isFailed: true,
            score: 0,
            scoreBreakdown: newBreakdown,
            lastPlayed: Date.now()
        };
        saveState(newState);
        updateStatistics(gameState.guesses.length, false);
    };

    const addReplay = () => {
        if (!gameState || gameState.isSolved || gameState.isFailed) return;

        let newScore = gameState.score - 1;
        // Ensure score doesn't go below 0
        newScore = Math.max(0, newScore);

        const newBreakdown = [...gameState.scoreBreakdown, { value: -1, reason: 'Replay snippet' }];

        const newState = {
            ...gameState,
            replayCount: gameState.replayCount + 1,
            score: newScore,
            scoreBreakdown: newBreakdown
        };
        saveState(newState);
    };

    const addYearBonus = (correct: boolean) => {
        if (!gameState) return;

        let newScore = gameState.score;
        const newBreakdown = [...gameState.scoreBreakdown];

        if (correct) {
            newScore += 10;
            newBreakdown.push({ value: 10, reason: 'Bonus: Correct Year' });
        } else {
            newBreakdown.push({ value: 0, reason: 'Bonus: Wrong Year' });
        }

        const newState = {
            ...gameState,
            score: newScore,
            scoreBreakdown: newBreakdown,
            yearGuessed: true
        };
        saveState(newState);
    };

    const skipYearBonus = () => {
        if (!gameState) return;

        const newBreakdown = [...gameState.scoreBreakdown, { value: 0, reason: 'Bonus: Skipped' }];

        const newState = {
            ...gameState,
            scoreBreakdown: newBreakdown,
            yearGuessed: true
        };
        saveState(newState);
    };

    return { gameState, statistics, addGuess, giveUp, addReplay, addYearBonus, skipYearBonus };
}
