import { useState, useEffect } from 'react'; import { Navigation } from '@/components/Navigation'; import { ResultsDashboard } from '@/components/ResultsDashboard'; import { Button } from '@/components/ui/button'; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select'; import { Card } from '@/components/ui/card'; import { TeamData, CompetitorData, MatchFixture, SimulationResult } from '@/types'; import { runMonteCarloSimulation } from '@/lib/simulation'; import { Trophy, TrendingDown, Home, Youtube, RefreshCw } from 'lucide-react'; import { toast } from 'sonner'; import { brasileirao2025Data } from '@/data/standings'; import santosverseLogo from '@/assets/santosverse-logo.png'; import { supabase } from '@/integrations/supabase/client'; const Index = () => { const [selectedTeam, setSelectedTeam] = useState(''); const [currentPoints, setCurrentPoints] = useState(0); const [currentRound, setCurrentRound] = useState(29); const [results, setResults] = useState(null); const [isSimulating, setIsSimulating] = useState(false); const [standingsData, setStandingsData] = useState(brasileirao2025Data); const [isLoadingData, setIsLoadingData] = useState(false); useEffect(() => { fetchStandingsData(); }, []); const fetchStandingsData = async () => { setIsLoadingData(true); try { console.log('Buscando dados do Brasileirão...'); const { data, error } = await supabase.functions.invoke('fetch-brasileirao'); // Se houver erro HTTP, tentar acessar os dados da resposta if (error) { console.error('Erro ao buscar dados:', error); // Verificar se é um erro de fallback (API retornou dados incompletos) // Neste caso, usar dados locais sem mostrar erro if (data && data.useFallback) { console.log('API retornou dados incompletos, usando dados locais'); toast.info('Usando dados locais atualizados', { description: '📊 Tabela completa do Brasileirão com 20 times', duration: 3000, }); setStandingsData(brasileirao2025Data); setIsLoadingData(false); return; } throw error; } // Verificar se há erro de API key if (data && data.error) { console.error('Erro da API:', data); // Se for erro de API incompleta, usar fallback if (data.useFallback || data.error === 'API_UNAVAILABLE') { console.log('API indisponível ou incompleta, usando dados locais'); toast.info('Usando dados locais atualizados', { description: '📊 Tabela completa do Brasileirão com 20 times', duration: 3000, }); setStandingsData(brasileirao2025Data); return; } if (data.error === 'API_KEY_NOT_CONFIGURED') { toast.error('API não configurada', { description: '📝 Para dados ao vivo, configure uma chave API gratuita em api-football.com', duration: 6000, }); } else if (data.error === 'INVALID_API_KEY') { toast.error('Chave API inválida', { description: '🔑 Verifique sua chave API ou obtenha uma nova em api-football.com', duration: 6000, }); } else { toast.error('Erro na API', { description: data.message || 'Usando dados locais', duration: 4000, }); } // Usar dados locais como fallback setStandingsData(brasileirao2025Data); return; } if (data && data.teams) { console.log('Dados recebidos:', data); setStandingsData(data); setCurrentRound(data.round || 29); toast.success('✅ Dados atualizados!', { description: `Rodada ${data.round} • ${data.teams.length} times` }); } } catch (error) { console.error('Erro ao buscar dados da API:', error); toast.info('Usando dados locais atualizados', { description: '📊 Tabela completa do Brasileirão com 20 times', duration: 3000, }); setStandingsData(brasileirao2025Data); } finally { setIsLoadingData(false); } }; const handleSimulation = () => { if (!selectedTeam) { toast.error('Selecione um time para analisar'); return; } setIsSimulating(true); toast.info('Iniciando simulação de Monte Carlo...', { description: 'Processando 1 milhão de cenários' }); setTimeout(() => { try { const teamInfo = standingsData.teams.find((t: any) => t.name === selectedTeam); if (!teamInfo) return; // Prepare team data using user-provided values const teamData: TeamData = { name: teamInfo.name, points: currentPoints, gamesPlayed: currentRound, wins: teamInfo.wins, draws: teamInfo.draws, losses: teamInfo.losses, goalDifference: teamInfo.goalDifference, position: teamInfo.position }; // Prepare competitors (teams around relegation zone - positions 12-20) const competitors: CompetitorData[] = standingsData.teams .filter((t: any) => t.position >= 12 && t.name !== selectedTeam) .map((t: any) => ({ name: t.name, points: t.points, gamesPlayed: t.gamesPlayed, position: t.position })); // Generate realistic fixtures for remaining games const remainingGames = 38 - currentRound; const fixtures: MatchFixture[] = []; for (let i = 0; i < remainingGames; i++) { const homeAway = Math.random() > 0.5 ? 'C' : 'F'; const opponentPool = standingsData.teams.filter((t: any) => t.name !== selectedTeam); const opponent = opponentPool[Math.floor(Math.random() * opponentPool.length)]; fixtures.push({ matchNumber: i + 1, homeAway: homeAway as 'C' | 'F', opponent: opponent.name, opponentPosition: opponent.position }); } const result = runMonteCarloSimulation({ targetTeam: teamData, competitors, fixtures }); setResults(result); setIsSimulating(false); toast.success('Simulação concluída!', { description: `Probabilidade: ${result.relegationProbability.toFixed(2)}%` }); setTimeout(() => { document.getElementById('results')?.scrollIntoView({ behavior: 'smooth', block: 'start' }); }, 100); } catch (error) { console.error('Erro na simulação:', error); toast.error('Erro ao executar simulação'); setIsSimulating(false); } }, 1500); }; return (
{/* Hero Section */}
Santosverse

SANTOSVERSE

Análise Estatística Avançada - Simulação de Monte Carlo

Brasileirão Série A 2025 • Modelo Preditivo com 1 milhão de iterações

{/* Main Content */}

Configuração da Análise

setCurrentPoints(parseInt(e.target.value) || 0)} className="w-full h-10 px-3 rounded-md bg-input border border-primary/30 text-foreground focus:outline-none focus:ring-2 focus:ring-primary" placeholder="Ex: 38" />
setCurrentRound(parseInt(e.target.value) || 29)} className="w-full h-10 px-3 rounded-md bg-input border border-primary/30 text-foreground focus:outline-none focus:ring-2 focus:ring-primary" placeholder="Ex: 29" />
{/* Resultados */} {results && selectedTeam && (

Resultados da Análise

)}
{/* Footer */}
); }; export default Index;