import React, { useState, useMemo } from 'react'; import { TrendingUp, Award, Grid3X3, DollarSign, Target, Filter } from 'lucide-react'; import { LotomaniaGame, LotomaniaResult } from '../types'; import { LotomaniaAlgorithm } from '../utils/lotomaniaAlgorithm'; interface DetailedGameAnalysisProps { allGames: LotomaniaGame[]; algorithm: LotomaniaAlgorithm; currentResult: LotomaniaResult; analyzeGameResult: (numbers: number[], result: LotomaniaResult) => any; } interface DetailedGameResult { game: LotomaniaGame; numbers: number[]; matchedNumbers: number[]; nonMatchedNumbers: number[]; drawnButNotPlayed: number[]; points: number; prizeValue: number; prizeDescription: string; netProfit: number; isWinning: boolean; } export const DetailedGameAnalysis: React.FC = ({ allGames, algorithm, currentResult, analyzeGameResult }) => { const [filterType, setFilterType] = useState<'all' | 'vertical' | 'horizontal'>('all'); const [filterPoints, setFilterPoints] = useState<'all' | '15+' | '16+' | '17+' | '18+' | '19+' | '20'>('all'); const [currentPage, setCurrentPage] = useState(1); const [showGrid, setShowGrid] = useState(true); const GAMES_PER_PAGE = 5; // Análise detalhada de todos os jogos const detailedResults = useMemo(() => { console.log('🔄 Analisando todos os jogos detalhadamente...'); const results: DetailedGameResult[] = allGames.map(game => { const gameNumbers = algorithm.getNumbersFromGame(game); const analysis = analyzeGameResult(gameNumbers, currentResult); // Separar números const matchedNumbers = gameNumbers.filter(num => currentResult.numeros.includes(num)); const nonMatchedNumbers = gameNumbers.filter(num => !currentResult.numeros.includes(num)); const drawnButNotPlayed = currentResult.numeros.filter(num => !gameNumbers.includes(num)); // Buscar prêmio oficial let prizeValue = 0; let prizeDescription = 'Sem prêmio'; const premio = currentResult.premiacoes?.find(p => p.acertos === analysis.points); if (premio && analysis.points >= 15) { prizeValue = premio.valorPremio; prizeDescription = premio.descricao; } else if (analysis.points === 0) { const premioZero = currentResult.premiacoes?.find(p => p.acertos === 0); if (premioZero) { prizeValue = premioZero.valorPremio; prizeDescription = premioZero.descricao; } } const netProfit = prizeValue - 3.00; // Custo do jogo return { game, numbers: gameNumbers, matchedNumbers, nonMatchedNumbers, drawnButNotPlayed, points: analysis.points, prizeValue, prizeDescription, netProfit, isWinning: prizeValue > 0 }; }); console.log(`✅ Análise detalhada concluída: ${results.length} jogos processados`); return results; }, [allGames, algorithm, currentResult, analyzeGameResult]); // Filtrar resultados const filteredResults = useMemo(() => { let filtered = detailedResults; // Filtro por tipo if (filterType !== 'all') { filtered = filtered.filter(r => r.game.type === filterType); } // Filtro por pontos if (filterPoints === '20') { filtered = filtered.filter(r => r.points === 20 || r.points === 0); } else if (filterPoints !== 'all') { const minPoints = parseInt(filterPoints.replace('+', '')); filtered = filtered.filter(r => r.points >= minPoints); } return filtered; }, [detailedResults, filterType, filterPoints]); // Paginação const totalPages = Math.ceil(filteredResults.length / GAMES_PER_PAGE); const paginatedResults = filteredResults.slice( (currentPage - 1) * GAMES_PER_PAGE, currentPage * GAMES_PER_PAGE ); // Estatísticas resumidas const statistics = useMemo(() => { const totalGames = filteredResults.length; const winningGames = filteredResults.filter(r => r.isWinning).length; const totalCost = totalGames * 3.00; const totalPrizes = filteredResults.reduce((sum, r) => sum + r.prizeValue, 0); const netResult = totalPrizes - totalCost; // Distribuição por pontos const pointsDistribution = filteredResults.reduce((acc, r) => { acc[r.points] = (acc[r.points] || 0) + 1; return acc; }, {} as Record); // Distribuição por prêmios const prizeDistribution = filteredResults .filter(r => r.isWinning) .reduce((acc, r) => { if (!acc[r.points]) { acc[r.points] = { count: 0, totalValue: 0 }; } acc[r.points].count++; acc[r.points].totalValue += r.prizeValue; return acc; }, {} as Record); return { totalGames, winningGames, totalCost, totalPrizes, netResult, winRate: (winningGames / totalGames) * 100, pointsDistribution, prizeDistribution }; }, [filteredResults]); // Renderizar grid de um jogo const renderGameGrid = (result: DetailedGameResult) => { if (!showGrid) return null; return (
Grid de Marcação - Jogo #{result.game.id}
{/* Headers */}
{[1, 2, 3, 4, 5, 6, 7, 8, 9, 10].map(col => (
C{col}
))}
{/* Grid 10x10 */} {[1, 2, 3, 4, 5, 6, 7, 8, 9, 10].map(row => (
L{row}
{[1, 2, 3, 4, 5, 6, 7, 8, 9, 10].map(col => { const number = (row - 1) * 10 + (col - 1); // 0-99 const isMarked = result.numbers.includes(number); const isHit = result.matchedNumbers.includes(number); const wasDrawn = currentResult.numeros.includes(number); let cellClass = ''; let icon = ''; if (isMarked && isHit) { cellClass = 'bg-green-600 text-white border-green-700'; // Marcado e acertou icon = '✓'; } else if (isMarked && !isHit) { cellClass = 'bg-blue-600 text-white border-blue-700'; // Marcado mas não acertou } else if (!isMarked && wasDrawn) { cellClass = 'bg-yellow-400 text-black border-yellow-500'; // Não marcado mas saiu icon = '★'; } else { cellClass = 'bg-gray-100 text-gray-600 border-gray-300'; // Normal } return (
{number === 0 ? '00' : number.toString().padStart(2, '0')} {icon && ( {icon} )}
); })}
))} {/* Legenda */}
Marcado + Acertou ({result.matchedNumbers.length})
Marcado + Não acertou ({result.numbers.length - result.matchedNumbers.length})
Não marcado + Saiu ({result.drawnButNotPlayed.length})
Normal
); }; return (
{/* Header */}

Análise Detalhada Jogo por Jogo

Resultado individual de cada jogo contra o concurso {currentResult.concurso}

{/* Estatísticas Resumidas */}
Total de Jogos

{statistics.totalGames}

{filterType === 'all' ? 'Todos os tipos' : filterType}

Jogos Premiados

{statistics.winningGames}

{statistics.winRate.toFixed(1)}% de aproveitamento

Total de Prêmios

R$ {statistics.totalPrizes.toLocaleString('pt-BR', { maximumFractionDigits: 0 })}

Custo: R$ {statistics.totalCost.toLocaleString('pt-BR', { maximumFractionDigits: 0 })}

= 0 ? 'border-green-500 bg-green-50' : 'border-red-500 bg-red-50' }`}> = 0 ? 'text-green-600' : 'text-red-600'}`}> Resultado Líquido

= 0 ? 'text-green-800' : 'text-red-800'}`}> {statistics.netResult >= 0 ? '+' : ''}R$ {statistics.netResult.toLocaleString('pt-BR', { maximumFractionDigits: 0 })}

= 0 ? 'text-green-600' : 'text-red-600'}`}> {statistics.netResult >= 0 ? 'Lucro' : 'Prejuízo'}

{/* Filtros e Controles */}
Filtros:
{filteredResults.length} jogo(s) encontrado(s)
{/* Lista Detalhada de Jogos */}
{paginatedResults.map((result, index) => (
{/* Header do Jogo */}
Jogo #{result.game.id}
📍 Fase {result.game.phase}, Ciclo {result.game.cycle}
🎯 {result.game.type === 'vertical' ? 'Vertical (Colunas)' : 'Horizontal (Linhas)'}
{result.game.type === 'vertical' ? (
🔹 Colunas: {result.game.markedColumns.join(', ')}
) : (
🔸 Linhas: {result.game.markedRows?.join(', ')}
)}
{result.points} pts
{result.isWinning ? `+R$ ${result.prizeValue.toLocaleString('pt-BR', { minimumFractionDigits: 2 })}` : `-R$ 3,00` }
= 0 ? 'text-green-600' : 'text-red-600' }`}> Líquido: {result.netProfit >= 0 ? '+' : ''}R$ {result.netProfit.toLocaleString('pt-BR', { minimumFractionDigits: 2 })}
{result.isWinning ? `🏆 ${result.prizeDescription}` : '❌ Não premiado'}
{/* Grid Visual */} {renderGameGrid(result)} {/* Resumo de Números */}
Números Acertados ({result.matchedNumbers.length})
{result.matchedNumbers.length > 0 ? result.matchedNumbers.map(num => ( {num === 0 ? '00' : num.toString().padStart(2, '0')} )) : ( Nenhum acerto )}
⭐ Números Sorteados Não Jogados ({result.drawnButNotPlayed.length})
{result.drawnButNotPlayed.map(num => ( {num === 0 ? '00' : num.toString().padStart(2, '0')} ))}
Resultado Financeiro
Custo do jogo: -R$ 3,00
Prêmio obtido: +R$ {result.prizeValue.toLocaleString('pt-BR', { minimumFractionDigits: 2 })}
Saldo: = 0 ? 'text-green-600' : 'text-red-600' }`}> {result.netProfit >= 0 ? '+' : ''}R$ {result.netProfit.toLocaleString('pt-BR', { minimumFractionDigits: 2 })}
))}
{/* Paginação */} {totalPages > 1 && (
{Array.from({ length: Math.min(5, totalPages) }, (_, i) => { const page = currentPage <= 3 ? i + 1 : currentPage - 2 + i; if (page > totalPages) return null; return ( ); })}
Página {currentPage} de {totalPages}
)} {/* Resumo de Distribuição por Pontos */}

Distribuição de Resultados

{Object.entries(statistics.pointsDistribution) .sort(([a], [b]) => parseInt(b) - parseInt(a)) .map(([points, count]) => { const prizeInfo = statistics.prizeDistribution[parseInt(points)]; const isWinning = prizeInfo && prizeInfo.count > 0; return (
{points}
pontos
{count} jogos
{isWinning && (
R$ {prizeInfo.totalValue.toLocaleString('pt-BR', { maximumFractionDigits: 0 })}
)}
); })}
); }; export default DetailedGameAnalysis;