import { useState, useCallback } from 'react';
import type { GuessEntry, GuessResponse, SolverReplay } from '@wordle/shared';
import { getMessages, getApiBase } from '../messages/index.js';

interface UseGameReturn {
  guesses: GuessEntry[];
  gameStatus: 'playing' | 'won' | 'lost';
  message: string | null;
  lastDifficulty: number | null;
  revealedWord: string | null;
  replays: SolverReplay[] | null;
  submitGuess: (wordId: number, guess: string) => Promise<boolean>;
  dismissMessage: () => void;
  resetForNewGame: () => void;
}

export function useGame(initialGuesses: GuessEntry[]): UseGameReturn {
  const [guesses, setGuesses] = useState<GuessEntry[]>(initialGuesses);
  const [message, setMessage] = useState<string | null>(null);
  const [lastDifficulty, setLastDifficulty] = useState<number | null>(null);
  const [revealedWord, setRevealedWord] = useState<string | null>(null);
  const [replays, setReplays] = useState<SolverReplay[] | null>(null);

  const gameStatus = deriveStatus(guesses);
  const dismissMessage = useCallback(() => setMessage(null), []);

  const resetForNewGame = useCallback(() => {
    setGuesses([]);
    setMessage(null);
    setLastDifficulty(null);
    setRevealedWord(null);
    setReplays(null);
  }, []);

  const submitGuess = useCallback(async (wordId: number, guess: string) => {
    const tryNo = guesses.length + 1;
    const lowerGuess = guess.toLowerCase();

    const res = await fetch(`${getApiBase()}/guess`, {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ wordId, guess: lowerGuess, tryNo }),
    });

    if (!res.ok) {
      const body = await res.json().catch(() => ({}));
      setMessage((body as { error?: string }).error ?? `HTTP ${res.status}`);
      return false;
    }

    const data: GuessResponse = await res.json();

    if (!data.valid) {
      setMessage(getMessages().game.unknownWord);
      return false;
    }

    const entry: GuessEntry = { guess: lowerGuess, colors: data.colors! };
    setGuesses((prev) => [...prev, entry]);

    if (data.difficulty !== undefined) {
      setLastDifficulty(data.difficulty);
    }
    if (data.word) {
      setRevealedWord(data.word);
    }
    if (data.replays) {
      setReplays(data.replays);
    }
    return true;
  }, [guesses.length]);

  return { guesses, gameStatus, message, lastDifficulty, revealedWord, replays, submitGuess, dismissMessage, resetForNewGame };
}

function deriveStatus(guesses: GuessEntry[]): 'playing' | 'won' | 'lost' {
  if (guesses.length === 0) return 'playing';
  const last = guesses[guesses.length - 1];
  if (last.colors.every((c) => c === 'g')) return 'won';
  if (guesses.length >= 6) return 'lost';
  return 'playing';
}
