import type { SolverStep } from '@wordle/shared';

const VOWELS = new Set(['a','e','i','o','u']);
const VOWEL_STARTS = ['adieu','audio','raise','arose','irate'];

function getFeedback(target: string, guess: string): string {
  const tu = target.toLowerCase(), gu = guess.toLowerCase();
  const counts: Record<string, number> = {};
  for (const ch of tu) counts[ch] = (counts[ch] ?? 0) + 1;
  const r: string[] = Array(5).fill('x');
  for (let i = 0; i < 5; i++) { if (gu[i] === tu[i]) { r[i] = 'g'; counts[gu[i]]--; } }
  for (let i = 0; i < 5; i++) { if (r[i] === 'g') continue; if ((counts[gu[i]] ?? 0) > 0) { r[i] = 'y'; counts[gu[i]]--; } }
  return r.join('');
}

function matchesFeedback(c: string, g: string, fb: string): boolean { return getFeedback(c, g) === fb; }

export function solveVowelFirst(target: string, allWords: string[], maxAttempts = 6): { attempts: number; steps: SolverStep[] } {
  let candidates = [...allWords];
  const knownVowels = new Set<string>();
  const steps: SolverStep[] = [];

  for (let attempt = 1; attempt <= maxAttempts; attempt++) {
    let bestGuess: string;
    if (attempt === 1) {
      bestGuess = VOWEL_STARTS.find((w) => allWords.includes(w)) ?? 'arise';
    } else if (attempt <= 3 && knownVowels.size < 5) {
      const pool = candidates.length > 0 ? candidates : allWords;
      bestGuess = pool[0]; let best = -1;
      for (const w of pool) {
        const newV = [...w].filter((c) => VOWELS.has(c) && !knownVowels.has(c)).length;
        const s = newV * 3 + new Set(w.split('')).size;
        if (s > best) { best = s; bestGuess = w; }
      }
    } else {
      bestGuess = candidates[0];
    }

    const fb = getFeedback(target, bestGuess);
    steps.push({ guess: bestGuess, colors: fb.split('') });
    if (fb === 'ggggg') return { attempts: attempt, steps };

    for (let i = 0; i < 5; i++) { if ((fb[i] === 'g' || fb[i] === 'y') && VOWELS.has(bestGuess[i])) knownVowels.add(bestGuess[i]); }
    candidates = candidates.filter((c) => matchesFeedback(c, bestGuess, fb));
    if (candidates.length === 0) return { attempts: maxAttempts + 1, steps };
  }

  return { attempts: maxAttempts + 1, steps };
}
