""" Enhanced API Endpoints Additional API routes for: - Enhanced predictions with caching - Real-time data streaming - User notifications - Advanced statistics - Match recommendations """ from flask import Blueprint, jsonify, request from datetime import datetime, timedelta from typing import Dict, List, Optional # Import our new modules from src.cache_system import ( cache_prediction, cache_fixtures, prediction_cache, get_cache_stats, invalidate_prediction_cache ) from src.realtime_updates import ( event_emitter, live_tracker, odds_tracker, alert_manager, get_event_stream, emit_prediction ) from src.notification_service import ( notification_service, get_user_notifications, get_unread_count, notify_sure_win ) # Create blueprint enhanced_api = Blueprint('enhanced_api', __name__, url_prefix='/api/v4') # ============================================================ # Enhanced Prediction Endpoints # ============================================================ @enhanced_api.route('/predict/enhanced') def enhanced_prediction(): """Enhanced prediction with caching and full analysis""" home = request.args.get('home') away = request.args.get('away') league = request.args.get('league', 'bundesliga') if not home or not away: return jsonify({'success': False, 'error': 'Missing home or away team'}) # Check cache first cache_key = f"pred_{home}_{away}_{league}" cached = prediction_cache.get(cache_key) if cached: cached['from_cache'] = True cached['cache_age'] = 'recent' return jsonify({'success': True, 'prediction': cached}) # Generate prediction try: from src.enhanced_predictor_v2 import enhanced_predict_with_goals from src.advanced_features import get_team_form, get_h2h_stats # Get prediction prediction = enhanced_predict_with_goals(home, away, league) # Enrich with additional data home_form = get_team_form(home) away_form = get_team_form(away) h2h = get_h2h_stats(home, away) result = { 'match': { 'home': home, 'away': away, 'league': league }, 'prediction': prediction, 'form': { 'home': home_form, 'away': away_form }, 'h2h': h2h, 'timestamp': datetime.now().isoformat(), 'from_cache': False } # Cache the result prediction_cache.set(cache_key, result, ttl=300) # Emit event for real-time subscribers emit_prediction(result) # Check for sure win if prediction.get('confidence', 0) >= 0.91: alert_manager.send_sure_win_alert(result) return jsonify({'success': True, 'prediction': result}) except Exception as e: return jsonify({'success': False, 'error': str(e)}) @enhanced_api.route('/predict/batch', methods=['POST']) def batch_predictions(): """Get predictions for multiple matches at once""" data = request.get_json() or {} matches = data.get('matches', []) if not matches: return jsonify({'success': False, 'error': 'No matches provided'}) results = [] for match in matches[:20]: # Limit to 20 matches home = match.get('home') away = match.get('away') league = match.get('league', 'bundesliga') if home and away: cache_key = f"pred_{home}_{away}_{league}" cached = prediction_cache.get(cache_key) if cached: results.append({'match': match, 'prediction': cached, 'cached': True}) else: try: from src.enhanced_predictor_v2 import enhanced_predict pred = enhanced_predict(home, away, league) prediction_cache.set(cache_key, pred, ttl=300) results.append({'match': match, 'prediction': pred, 'cached': False}) except Exception as e: results.append({'match': match, 'error': str(e)}) return jsonify({ 'success': True, 'predictions': results, 'count': len(results) }) # ============================================================ # Real-time Data Endpoints # ============================================================ @enhanced_api.route('/realtime/stream') def realtime_stream(): """Get real-time event stream status""" return jsonify({ 'success': True, 'stream': get_event_stream() }) @enhanced_api.route('/realtime/events') def get_events(): """Get recent events""" event_type = request.args.get('type') limit = int(request.args.get('limit', 50)) events = event_emitter.get_history(event_type, limit) return jsonify({ 'success': True, 'events': events, 'count': len(events) }) @enhanced_api.route('/realtime/live-matches') def get_live_matches(): """Get currently tracked live matches""" return jsonify({ 'success': True, 'matches': live_tracker.get_live_matches(), 'count': len(live_tracker.live_matches) }) @enhanced_api.route('/realtime/alerts') def get_alerts(): """Get recent alerts""" limit = int(request.args.get('limit', 20)) return jsonify({ 'success': True, 'alerts': alert_manager.get_active_alerts(limit) }) # ============================================================ # Notification Endpoints # ============================================================ @enhanced_api.route('/notifications') def user_notifications(): """Get user notifications""" user_id = request.args.get('user_id', 'default') return jsonify({ 'success': True, 'notifications': get_user_notifications(user_id), 'unread_count': get_unread_count(user_id) }) @enhanced_api.route('/notifications/mark-read', methods=['POST']) def mark_notification_read(): """Mark notification as read""" data = request.get_json() or {} user_id = data.get('user_id', 'default') notification_id = data.get('notification_id') if notification_id: success = notification_service.in_app.mark_read(user_id, notification_id) return jsonify({'success': success}) return jsonify({'success': False, 'error': 'Missing notification_id'}) @enhanced_api.route('/notifications/subscribe', methods=['POST']) def subscribe_notifications(): """Subscribe to push notifications""" data = request.get_json() or {} subscription = data.get('subscription') if subscription: success = notification_service.push.subscribe(subscription) return jsonify({'success': success}) return jsonify({'success': False, 'error': 'Missing subscription data'}) # ============================================================ # Cache Management Endpoints # ============================================================ @enhanced_api.route('/cache/stats') def cache_stats(): """Get cache statistics""" return jsonify({ 'success': True, 'stats': get_cache_stats() }) @enhanced_api.route('/cache/clear', methods=['POST']) def clear_cache(): """Clear prediction cache""" cleared = prediction_cache.clear() return jsonify({ 'success': True, 'cleared': cleared }) @enhanced_api.route('/cache/invalidate', methods=['POST']) def invalidate_cache(): """Invalidate specific cache entries""" data = request.get_json() or {} home = data.get('home') away = data.get('away') league = data.get('league') invalidate_prediction_cache(home, away, league) return jsonify({'success': True}) # ============================================================ # Advanced Statistics Endpoints # ============================================================ @enhanced_api.route('/stats/accuracy') def accuracy_stats(): """Get detailed accuracy statistics""" try: from src.accuracy_monitor import get_accuracy_stats, get_recent_predictions stats = get_accuracy_stats() recent = get_recent_predictions(limit=20) return jsonify({ 'success': True, 'stats': stats, 'recent': recent }) except Exception as e: return jsonify({'success': False, 'error': str(e)}) @enhanced_api.route('/stats/leagues') def league_stats(): """Get per-league statistics""" try: from src.success_tracker import get_success_analytics analytics = get_success_analytics() return jsonify({ 'success': True, 'analytics': analytics }) except Exception as e: return jsonify({'success': False, 'error': str(e)}) @enhanced_api.route('/stats/performance') def performance_stats(): """Get overall performance metrics""" try: from src.accuracy_monitor import get_accuracy_stats stats = get_accuracy_stats() cache = get_cache_stats() return jsonify({ 'success': True, 'accuracy': stats, 'cache_performance': cache, 'uptime': '99.9%', 'api_version': 'v4', 'timestamp': datetime.now().isoformat() }) except Exception as e: return jsonify({'success': False, 'error': str(e)}) # ============================================================ # Match Recommendations # ============================================================ @enhanced_api.route('/recommendations') def get_recommendations(): """Get personalized match recommendations""" user_id = request.args.get('user_id', 'default') strategy = request.args.get('strategy', 'balanced') limit = int(request.args.get('limit', 10)) try: from src.data.free_data_sources import UnifiedFreeDataProvider from src.enhanced_predictor_v2 import enhanced_predict provider = UnifiedFreeDataProvider() fixtures = provider.get_unified_fixtures('bundesliga') recommendations = [] for fixture in fixtures[:limit]: home = fixture.get('home_team', {}).get('name') or fixture.get('home_team') away = fixture.get('away_team', {}).get('name') or fixture.get('away_team') if home and away: try: pred = enhanced_predict(home, away, 'bundesliga') # Calculate recommendation score confidence = pred.get('confidence', 0.5) if strategy == 'safe': score = confidence * 100 elif strategy == 'value': edge = pred.get('edge', 0) score = edge * 10 + confidence * 50 else: # balanced score = confidence * 70 + 30 recommendations.append({ 'match': f"{home} vs {away}", 'home': home, 'away': away, 'prediction': pred.get('predicted_outcome', 'N/A'), 'confidence': round(confidence * 100, 1), 'score': round(score, 1), 'reason': 'High confidence' if confidence > 0.7 else 'Good value' }) except: pass # Sort by score recommendations.sort(key=lambda x: x['score'], reverse=True) return jsonify({ 'success': True, 'strategy': strategy, 'recommendations': recommendations[:limit] }) except Exception as e: return jsonify({'success': False, 'error': str(e)}) @enhanced_api.route('/recommendations/sure-wins') def sure_wins_endpoint(): """Get sure win recommendations""" try: from src.confidence_sections import get_sure_wins sure_wins = get_sure_wins(min_confidence=0.91) return jsonify({ 'success': True, 'sure_wins': sure_wins, 'count': len(sure_wins) }) except Exception as e: return jsonify({'success': False, 'error': str(e)}) # ============================================================ # Health & API Info # ============================================================ @enhanced_api.route('/health') def api_health(): """Enhanced API health check""" return jsonify({ 'success': True, 'status': 'healthy', 'version': 'v4', 'features': [ 'enhanced_predictions', 'caching', 'realtime_events', 'notifications', 'batch_predictions', 'recommendations', 'performance_stats' ], 'cache': get_cache_stats(), 'timestamp': datetime.now().isoformat() }) @enhanced_api.route('/info') def api_info(): """Get API information""" return jsonify({ 'success': True, 'api': { 'name': 'FootyPredict Pro Enhanced API', 'version': 'v4.0.0', 'base_url': '/api/v4', 'endpoints': { 'predictions': '/predict/enhanced', 'batch': '/predict/batch', 'realtime': '/realtime/stream', 'notifications': '/notifications', 'stats': '/stats/performance', 'recommendations': '/recommendations' } }, 'rate_limits': { 'predictions': '100/minute', 'batch': '10/minute', 'general': '1000/hour' } }) def register_enhanced_api(app): """Register the enhanced API blueprint""" app.register_blueprint(enhanced_api) print("✅ Enhanced API v4 registered at /api/v4")