import { Router, Request, Response } from 'express';
import type { WordBank, GuessResponse, CachedResult } from '@wordle/shared';
import { isValidGuess, getTargetWord } from '../validate.js';
import { computeFeedback } from '../feedback.js';
import { computeReplays } from '@wordle/shared';
import { runSolverInWorker } from '../solver-pool.js';

export function createGuessRouter(wordBank: WordBank, cache: Map<number, CachedResult>): Router {
  const router = Router();

  router.post('/', (req: Request, res: Response) => {
    const { wordId, guess, tryNo } = req.body ?? {};

    // Validate request shape
    if (typeof wordId !== 'number' || typeof guess !== 'string' || typeof tryNo !== 'number') {
      res.status(400).json({ error: 'Invalid request: wordId (number), guess (string), and tryNo (number) required' });
      return;
    }

    if (guess.length !== 5) {
      res.status(400).json({ error: 'Guess must be exactly 5 letters' });
      return;
    }

    // Validate the guess is a real word
    if (!isValidGuess(wordBank, guess)) {
      const response: GuessResponse = { valid: false };
      res.json(response);
      return;
    }

    // Look up target word
    const target = getTargetWord(wordBank, wordId);
    if (!target) {
      res.status(404).json({ error: `Word ${wordId} not found` });
      return;
    }

    // Compute feedback
    const colors = computeFeedback(target.word, guess);
    const correct = colors.every((c) => c === 'g');
    const isLastAttempt = tryNo >= 6;

    const response: GuessResponse = {
      valid: true,
      colors,
      correct,
    };

    // Reveal word on loss (last attempt, not correct)
    if (isLastAttempt && !correct) {
      response.word = target.word;
    }

    // Compute difficulty and replays on final guess (win or loss)
    if (correct || isLastAttempt) {
      let result = cache.get(wordId);

      if (!result) {
        // Cache miss — compute with 3 fast solvers for immediate response
        result = computeReplays(target.word, wordBank.guessable);
        cache.set(wordId, result);

        // Fire background computation with all 4 solvers (including entropy)
        // in a worker thread so the ~14s entropy run never blocks the API.
        const targetWord = target.word;
        const guessable = wordBank.guessable;
        runSolverInWorker({ target: targetWord, allWords: guessable, mode: 'full' })
          .then((full) => { cache.set(wordId, full); })
          .catch((err) => { console.error('Solver worker failed:', err); });
      }

      response.difficulty = result.difficulty;
      response.replays = result.replays;
    }

    res.json(response);
  });

  return router;
}
