"use client"; import { useState, useEffect } from "react"; import { Stockfish, StockfishEvaluation } from "@/lib/stockfish"; import { OpeningMetadata, lookupOpening } from "@/lib/openings"; import { getGenAIModel } from "@/lib/gemini"; import { Loader2, X, Brain, Trophy, AlertTriangle } from "lucide-react"; interface GameAnalysisModalProps { fen: string; stockfish: Stockfish | null; apiKey: string | null; language: 'en' | 'de' | 'fr' | 'it'; onClose: () => void; } export function GameAnalysisModal({ fen, stockfish, apiKey, language, onClose }: GameAnalysisModalProps) { const [evaluation, setEvaluation] = useState(null); const [opening, setOpening] = useState(null); const [summary, setSummary] = useState(""); const [isLoading, setIsLoading] = useState(true); useEffect(() => { const analyze = async () => { setIsLoading(true); try { // 1. Stockfish Evaluation let evalResult: StockfishEvaluation | null = null; if (stockfish) { evalResult = await stockfish.evaluate(fen, 15); // Quick depth setEvaluation(evalResult); } // 2. Opening Lookup const openingData = lookupOpening(fen); setOpening(openingData); // 3. LLM Summary if (apiKey && evalResult) { const model = getGenAIModel(apiKey, "gemini-2.5-flash"); const evalInPawns = (evalResult.score / 100).toFixed(2); const prompt = ` You are a Chess Grandmaster Analyst. Analyze this position for the user. DATA: - FEN: ${fen} - Evaluation: ${evalInPawns} pawns (${evalResult.score} centipawns) Note: Positive = White advantage, Negative = Black advantage 100 centipawns = 1 pawn - Mate in: ${evalResult.mate ?? "N/A"} - Best Move: ${evalResult.bestMove} - Opening: ${openingData ? `${openingData.name} (${openingData.eco})` : "Unknown/Midgame"} INSTRUCTIONS: 1. Summarize who is winning and why (based on score). Use the pawn value (e.g., "White is up 2.5 pawns" not "250 centipawns"). 2. Identify the key strategic factors (space, piece activity, king safety). 3. Mention the opening if relevant. 4. Keep it concise (max 3-4 sentences). 5. Respond in ${language.toUpperCase()}. OUTPUT FORMAT: Plain text paragraph. `; const result = await model.generateContent(prompt); setSummary(result.response.text()); } else if (!apiKey) { setSummary("Please provide an API Key to get an AI summary."); } } catch (e) { console.error("Analysis failed:", e); setSummary("Failed to generate analysis."); } finally { setIsLoading(false); } }; analyze(); }, [fen, stockfish, apiKey, language]); return (
{/* Header */}

Game Analysis

{/* Content */}
{isLoading ? (

Analyzing position...

) : ( <> {/* Evaluation Score */}

Evaluation

0 ? "text-green-600" : (evaluation?.score || 0) < 0 ? "text-red-600" : "text-gray-600" }`}> {evaluation?.mate ? `Mate in ${evaluation.mate}` : `${(evaluation?.score || 0) > 0 ? "+" : ""}${(evaluation?.score || 0) / 100}`}

Best Move

{evaluation?.bestMove}

{/* Opening Info */} {opening && (

Opening Identified

{opening.name} ({opening.eco})

)} {/* AI Summary */}

Coach's Summary

{summary}
)}
); }