#!/usr/bin/env python3
"""
Real-time Dashboard Integration Module for Phase 3
WebSocket-based real-time dashboard and visualization system

Author: Pezhman Hajipour  
Version: 3.0.0
"""

import asyncio
import json
import logging
from collections import defaultdict
from datetime import datetime, timedelta
from typing import Dict, List, Optional, Any, Callable
from dataclasses import dataclass, asdict
import uuid
from fastapi import FastAPI, WebSocket, WebSocketDisconnect, BackgroundTasks
from fastapi.responses import HTMLResponse
from fastapi.staticfiles import StaticFiles
import uvicorn

from ..core_types import WhaleBotConfig, EnhancedTrade, WhaleTier
from ..tracking import AdvancedWhaleBot, RealTimeAlert, CrossChainMonitor
from ..intelligence import ModelEnsemble

logger = logging.getLogger(__name__)

@dataclass
class DashboardData:
    """Real-time dashboard data structure"""
    timestamp: str
    whales_detected: int
    total_volume_24h: float
    active_alerts: int
    market_regime: str
    sentiment_score: float
    ml_predictions: List[Dict[str, Any]]
    cross_chain_activity: List[Dict[str, Any]]
    performance_metrics: Dict[str, float]

@dataclass
class DashboardWidget:
    """Dashboard widget configuration"""
    widget_id: str
    widget_type: str  # 'chart', 'metric', 'table', 'alert'
    title: str
    data_source: str
    update_interval: int  # seconds
    position: Dict[str, int]  # x, y, width, height
    config: Dict[str, Any]

class DashboardWebSocket:
    """WebSocket connection manager for dashboard"""
    
    def __init__(self):
        self.active_connections: Dict[str, WebSocket] = {}
        self.subscribers: Dict[str, List[str]] = defaultdict(list)  # topic -> [connection_ids]
        
    async def connect(self, websocket: WebSocket, client_id: str):
        """Accept new WebSocket connection"""
        await websocket.accept()
        self.active_connections[client_id] = websocket
        logger.info(f"Dashboard client {client_id} connected")
    
    def disconnect(self, client_id: str):
        """Remove WebSocket connection"""
        if client_id in self.active_connections:
            del self.active_connections[client_id]
        logger.info(f"Dashboard client {client_id} disconnected")
    
    async def send_message(self, client_id: str, message: Dict[str, Any]):
        """Send message to specific client"""
        if client_id in self.active_connections:
            try:
                await self.active_connections[client_id].send_text(json.dumps(message))
            except Exception as e:
                logger.error(f"Error sending message to {client_id}: {e}")
                self.disconnect(client_id)
    
    async def broadcast_message(self, message: Dict[str, Any], topic: str = None):
        """Broadcast message to all connected clients or specific topic"""
        if topic:
            # Send to subscribers of specific topic
            for client_id in self.subscribers.get(topic, []):
                await self.send_message(client_id, message)
        else:
            # Send to all clients
            for client_id in list(self.active_connections.keys()):
                await self.send_message(client_id, message)
    
    def subscribe_to_topic(self, client_id: str, topic: str):
        """Subscribe client to specific topic"""
        self.subscribers[topic].append(client_id)
    
    def unsubscribe_from_topic(self, client_id: str, topic: str):
        """Unsubscribe client from specific topic"""
        if topic in self.subscribers and client_id in self.subscribers[topic]:
            self.subscribers[topic].remove(client_id)

class DashboardDataProcessor:
    """Processes and formats data for dashboard display"""
    
    def __init__(self, whale_bot: AdvancedWhaleBot):
        self.whale_bot = whale_bot
        self.data_cache: Dict[str, Any] = {}
        self.last_update = datetime.now()
        
    async def process_whale_data(self, trade: EnhancedTrade) -> Dict[str, Any]:
        """Process whale trade data for dashboard"""
        try:
            # Get comprehensive analysis
            analysis = await self.whale_bot.comprehensive_whale_analysis(trade)
            
            processed_data = {
                'whale_detection': {
                    'id': str(uuid.uuid4()),
                    'timestamp': trade.timestamp.isoformat(),
                    'address': trade.address,
                    'asset': trade.coin,
                    'size_usd': trade.size_usd,
                    'whale_tier': trade.whale_tier.value,
                    'side': trade.side,
                    'price_impact_estimate': analysis.get('phase3_analysis', {}).get('price_impact_estimate', 0),
                    'ml_prediction': analysis.get('phase3_analysis', {}).get('ml_prediction'),
                    'confidence': analysis.get('phase3_analysis', {}).get('ml_confidence', 0),
                    'cross_chain_activity': analysis.get('phase3_analysis', {}).get('cross_chain_involvement', 0)
                },
                'market_impact': {
                    'immediate_impact': self._calculate_immediate_impact(trade),
                    'correlation_effect': analysis.get('phase2_analysis', {}).get('correlation_strength', 0),
                    'sentiment_impact': analysis.get('phase2_analysis', {}).get('sentiment_score', 0)
                },
                'recommendations': analysis.get('recommendations', []),
                'alert_info': analysis.get('alert_info', {})
            }
            
            return processed_data
            
        except Exception as e:
            logger.error(f"Error processing whale data: {e}")
            return {}
    
    def _calculate_immediate_impact(self, trade: EnhancedTrade) -> float:
        """Calculate immediate market impact estimate"""
        # Simple impact calculation based on trade size and tier
        tier_multipliers = {
            WhaleTier.MINNOW: 0.001,
            WhaleTier.DOLPHIN: 0.005,
            WhaleTier.WHALE: 0.015,
            WhaleTier.MEGA_WHALE: 0.035,
            WhaleTier.GIANT_WHALE: 0.075
        }
        
        multiplier = tier_multipliers.get(trade.whale_tier, 0.001)
        impact = trade.size_usd * multiplier / 1000000  # Convert to percentage
        
        return min(0.1, max(-0.1, impact))  # Cap between -10% and +10%
    
    async def process_market_overview(self) -> Dict[str, Any]:
        """Process market overview data for dashboard"""
        try:
            # Get system status
            system_status = await self.whale_bot.get_system_status()
            
            overview_data = {
                'timestamp': datetime.now().isoformat(),
                'whales_detected_today': system_status['performance_metrics']['whales_detected_today'],
                'total_volume_24h': self._calculate_total_volume_24h(),
                'active_alerts': system_status['phase3_features']['active_alerts']['total_active'],
                'market_regime': self._get_current_market_regime(),
                'sentiment_score': self._get_current_sentiment(),
                'ml_accuracy': system_status['performance_metrics']['accuracy_score'],
                'cross_chain_whales': system_status['phase3_features']['cross_chain_whales_tracked'],
                'coordination_score': self._get_coordination_score(),
                'risk_level': self._get_current_risk_level()
            }
            
            return overview_data
            
        except Exception as e:
            logger.error(f"Error processing market overview: {e}")
            return {}
    
    def _calculate_total_volume_24h(self) -> float:
        """Calculate total whale volume in last 24 hours"""
        # Simulate calculation
        import random
        return random.uniform(100_000_000, 500_000_000)
    
    def _get_current_market_regime(self) -> str:
        """Get current market regime"""
        # Simulate regime detection
        import random
        regimes = ['BULL_MARKET', 'BEAR_MARKET', 'SIDEWAYS', 'HIGH_VOLATILITY']
        return random.choice(regimes)
    
    def _get_current_sentiment(self) -> float:
        """Get current market sentiment score (-1 to 1)"""
        # Simulate sentiment calculation
        import random
        return random.uniform(-0.8, 0.8)
    
    def _get_coordination_score(self) -> float:
        """Get current cross-chain coordination score"""
        # Simulate coordination score
        import random
        return random.uniform(0.3, 0.9)
    
    def _get_current_risk_level(self) -> str:
        """Get current overall risk level"""
        # Simulate risk assessment
        import random
        risk_levels = ['LOW', 'MEDIUM', 'HIGH', 'EXTREME']
        return random.choices(risk_levels, weights=[0.3, 0.4, 0.2, 0.1])[0]

class RealTimeDashboard:
    """Main real-time dashboard system"""
    
    def __init__(self, whale_bot: AdvancedWhaleBot, port: int = 8080):
        self.whale_bot = whale_bot
        self.port = port
        self.app = FastAPI(title="Whale Bot Real-Time Dashboard", version="3.0.0")
        self.websocket_manager = DashboardWebSocket()
        self.data_processor = DashboardDataProcessor(whale_bot)
        self.dashboard_running = False
        
        # Dashboard widgets configuration
        self.widgets = self._initialize_widgets()
        
        # Background tasks
        self.background_tasks = []
        
        self._setup_routes()
    
    def _initialize_widgets(self) -> List[DashboardWidget]:
        """Initialize dashboard widgets"""
        return [
            DashboardWidget(
                widget_id="whale_feed",
                widget_type="table",
                title="Real-Time Whale Detections",
                data_source="whale_detections",
                update_interval=5,
                position={"x": 0, "y": 0, "width": 8, "height": 6},
                config={
                    "columns": ["Time", "Asset", "Size", "Tier", "Impact", "ML Prediction"],
                    "max_rows": 20,
                    "highlight_large_trades": True
                }
            ),
            DashboardWidget(
                widget_id="market_overview",
                widget_type="metric",
                title="Market Overview",
                data_source="market_overview", 
                update_interval=10,
                position={"x": 8, "y": 0, "width": 4, "height": 3},
                config={
                    "metrics": ["whales_detected_today", "total_volume_24h", "active_alerts", "sentiment_score"]
                }
            ),
            DashboardWidget(
                widget_id="ml_predictions",
                widget_type="chart",
                title="ML Predictions Timeline",
                data_source="ml_predictions",
                update_interval=15,
                position={"x": 0, "y": 6, "width": 6, "height": 4},
                config={
                    "chart_type": "line",
                    "time_window": "4h",
                    "show_confidence": True
                }
            ),
            DashboardWidget(
                widget_id="cross_chain_activity",
                widget_type="network",
                title="Cross-Chain Activity Map",
                data_source="cross_chain_data",
                update_interval=20,
                position={"x": 6, "y": 6, "width": 6, "height": 4},
                config={
                    "show_coordination": True,
                    "color_by_volume": True
                }
            ),
            DashboardWidget(
                widget_id="alerts_panel",
                widget_type="alert",
                title="Active Alerts",
                data_source="active_alerts",
                update_interval=2,
                position={"x": 0, "y": 10, "width": 12, "height": 3},
                config={
                    "max_alerts": 10,
                    "show_sound": True,
                    "group_by_priority": True
                }
            )
        ]
    
    def _setup_routes(self):
        """Setup FastAPI routes"""
        
        @self.app.get("/")
        async def get_dashboard():
            return HTMLResponse(self._generate_dashboard_html())
        
        @self.app.get("/api/widgets")
        async def get_widgets():
            return {"widgets": [asdict(widget) for widget in self.widgets]}
        
        @self.app.get("/api/market-overview")
        async def get_market_overview():
            data = await self.data_processor.process_market_overview()
            return data
        
        @self.app.websocket("/ws/{client_id}")
        async def websocket_endpoint(websocket: WebSocket, client_id: str):
            await self.websocket_manager.connect(websocket, client_id)
            try:
                while True:
                    # Receive messages from client
                    data = await websocket.receive_text()
                    message = json.loads(data)
                    
                    if message.get("type") == "subscribe":
                        topic = message.get("topic")
                        self.websocket_manager.subscribe_to_topic(client_id, topic)
                        await self.websocket_manager.send_message(client_id, {
                            "type": "subscription_confirmed",
                            "topic": topic
                        })
                    
            except WebSocketDisconnect:
                self.websocket_manager.disconnect(client_id)
    
    def _generate_dashboard_html(self) -> str:
        """Generate HTML for dashboard"""
        return """
        <!DOCTYPE html>
        <html lang="en">
        <head>
            <meta charset="UTF-8">
            <meta name="viewport" content="width=device-width, initial-scale=1.0">
            <title>Whale Bot Real-Time Dashboard</title>
            <style>
                * { margin: 0; padding: 0; box-sizing: border-box; }
                body { 
                    font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
                    background: linear-gradient(135deg, #1e3c72 0%, #2a5298 100%);
                    color: white;
                    overflow-x: hidden;
                }
                .header {
                    background: rgba(0,0,0,0.2);
                    padding: 20px;
                    text-align: center;
                    backdrop-filter: blur(10px);
                }
                .dashboard-grid {
                    display: grid;
                    grid-template-columns: repeat(12, 1fr);
                    gap: 20px;
                    padding: 20px;
                    min-height: 100vh;
                }
                .widget {
                    background: rgba(255,255,255,0.1);
                    border-radius: 15px;
                    padding: 20px;
                    backdrop-filter: blur(10px);
                    border: 1px solid rgba(255,255,255,0.2);
                    box-shadow: 0 8px 32px rgba(0,0,0,0.1);
                }
                .whale-table {
                    width: 100%;
                    border-collapse: collapse;
                    max-height: 400px;
                    overflow-y: auto;
                }
                .whale-table th, .whale-table td {
                    padding: 10px;
                    text-align: left;
                    border-bottom: 1px solid rgba(255,255,255,0.1);
                }
                .metric-card {
                    text-align: center;
                    padding: 15px;
                }
                .metric-value {
                    font-size: 2em;
                    font-weight: bold;
                    margin: 10px 0;
                }
                .alert-item {
                    background: rgba(255,0,0,0.1);
                    border-left: 4px solid #ff4757;
                    padding: 10px;
                    margin: 5px 0;
                    border-radius: 5px;
                }
                .status-indicator {
                    display: inline-block;
                    width: 10px;
                    height: 10px;
                    border-radius: 50%;
                    margin-right: 10px;
                }
                .status-live { background: #2ed573; }
                .status-warning { background: #ffa502; }
                .status-error { background: #ff4757; }
                .chart-container {
                    height: 300px;
                    position: relative;
                }
                @keyframes pulse {
                    0% { opacity: 1; }
                    50% { opacity: 0.5; }
                    100% { opacity: 1; }
                }
                .live-indicator {
                    animation: pulse 2s infinite;
                }
            </style>
        </head>
        <body>
            <div class="header">
                <h1>🐋 Whale Bot Real-Time Dashboard</h1>
                <div class="status-indicator status-live"></div>
                <span>Live Monitoring System</span>
                <div id="connection-status">Connecting...</div>
            </div>
            
            <div class="dashboard-grid">
                <!-- Whale Feed Widget -->
                <div class="widget" style="grid-column: 1 / 9; grid-row: 1 / 7;">
                    <h2>🔍 Real-Time Whale Detections</h2>
                    <table class="whale-table" id="whale-table">
                        <thead>
                            <tr>
                                <th>Time</th>
                                <th>Asset</th>
                                <th>Size (USD)</th>
                                <th>Tier</th>
                                <th>Price Impact</th>
                                <th>ML Prediction</th>
                            </tr>
                        </thead>
                        <tbody id="whale-table-body">
                            <!-- Dynamic content -->
                        </tbody>
                    </table>
                </div>
                
                <!-- Market Overview Widget -->
                <div class="widget" style="grid-column: 9 / 13; grid-row: 1 / 4;">
                    <h2>📊 Market Overview</h2>
                    <div class="metric-card">
                        <div>Whales Today</div>
                        <div class="metric-value" id="whales-today">0</div>
                    </div>
                    <div class="metric-card">
                        <div>Volume 24h</div>
                        <div class="metric-value" id="volume-24h">$0</div>
                    </div>
                    <div class="metric-card">
                        <div>Active Alerts</div>
                        <div class="metric-value" id="active-alerts">0</div>
                    </div>
                    <div class="metric-card">
                        <div>Sentiment</div>
                        <div class="metric-value" id="sentiment-score">0.00</div>
                    </div>
                </div>
                
                <!-- ML Predictions Chart -->
                <div class="widget" style="grid-column: 1 / 7; grid-row: 7 / 11;">
                    <h2>🤖 ML Predictions Timeline</h2>
                    <div class="chart-container">
                        <canvas id="ml-chart"></canvas>
                    </div>
                </div>
                
                <!-- Cross-Chain Activity -->
                <div class="widget" style="grid-column: 7 / 13; grid-row: 7 / 11;">
                    <h2>🔗 Cross-Chain Activity</h2>
                    <div id="cross-chain-network">
                        <!-- Network visualization -->
                    </div>
                </div>
                
                <!-- Alerts Panel -->
                <div class="widget" style="grid-column: 1 / 13; grid-row: 11 / 14;">
                    <h2>🚨 Active Alerts</h2>
                    <div id="alerts-container">
                        <!-- Dynamic alerts -->
                    </div>
                </div>
            </div>
            
            <script>
                const ws = new WebSocket(`ws://${window.location.host}/ws/${Date.now()}`);
                const clientId = Date.now();
                
                ws.onopen = function() {
                    document.getElementById('connection-status').textContent = 'Connected';
                    document.getElementById('connection-status').className = 'status-indicator status-live';
                    
                    // Subscribe to data streams
                    ws.send(JSON.stringify({type: 'subscribe', topic: 'whale_detections'}));
                    ws.send(JSON.stringify({type: 'subscribe', topic: 'market_overview'}));
                    ws.send(JSON.stringify({type: 'subscribe', topic: 'active_alerts'}));
                    ws.send(JSON.stringify({type: 'subscribe', topic: 'ml_predictions'}));
                };
                
                ws.onmessage = function(event) {
                    const data = JSON.parse(event.data);
                    handleWebSocketMessage(data);
                };
                
                ws.onclose = function() {
                    document.getElementById('connection-status').textContent = 'Disconnected';
                    document.getElementById('connection-status').className = 'status-indicator status-error';
                };
                
                function handleWebSocketMessage(data) {
                    switch(data.type) {
                        case 'whale_detection':
                            addWhaleDetection(data.payload);
                            break;
                        case 'market_overview':
                            updateMarketOverview(data.payload);
                            break;
                        case 'alert':
                            addAlert(data.payload);
                            break;
                        case 'ml_prediction':
                            updateMLChart(data.payload);
                            break;
                    }
                }
                
                function addWhaleDetection(detection) {
                    const tbody = document.getElementById('whale-table-body');
                    const row = tbody.insertRow(0);
                    row.innerHTML = `
                        <td>${new Date(detection.timestamp).toLocaleTimeString()}</td>
                        <td>${detection.asset}</td>
                        <td>$${(detection.size_usd / 1000000).toFixed(2)}M</td>
                        <td>${detection.whale_tier}</td>
                        <td>${(detection.price_impact_estimate * 100).toFixed(2)}%</td>
                        <td>${detection.ml_prediction || 'N/A'}</td>
                    `;
                    
                    // Keep only last 20 rows
                    while (tbody.rows.length > 20) {
                        tbody.deleteRow(-1);
                    }
                }
                
                function updateMarketOverview(data) {
                    document.getElementById('whales-today').textContent = data.whales_detected_today;
                    document.getElementById('volume-24h').textContent = `$${(data.total_volume_24h / 1000000).toFixed(0)}M`;
                    document.getElementById('active-alerts').textContent = data.active_alerts;
                    document.getElementById('sentiment-score').textContent = data.sentiment_score.toFixed(2);
                }
                
                function addAlert(alert) {
                    const container = document.getElementById('alerts-container');
                    const alertDiv = document.createElement('div');
                    alertDiv.className = 'alert-item';
                    alertDiv.innerHTML = `
                        <strong>${alert.title}</strong><br>
                        ${alert.description}<br>
                        <small>${new Date(alert.timestamp).toLocaleTimeString()}</small>
                    `;
                    container.insertBefore(alertDiv, container.firstChild);
                    
                    // Keep only last 10 alerts
                    while (container.children.length > 10) {
                        container.removeChild(container.lastChild);
                    }
                }
                
                function updateMLChart(data) {
                    // Update ML predictions chart
                    console.log('ML Prediction update:', data);
                }
                
                // Periodic data refresh
                setInterval(async () => {
                    try {
                        const response = await fetch('/api/market-overview');
                        const data = await response.json();
                        updateMarketOverview(data);
                    } catch (e) {
                        console.error('Failed to refresh market data:', e);
                    }
                }, 10000);
            </script>
        </body>
        </html>
        """
    
    async def start_dashboard(self):
        """Start the real-time dashboard"""
        if self.dashboard_running:
            logger.warning("Dashboard is already running")
            return
        
        self.dashboard_running = True
        
        # Start background data feeds
        self.background_tasks.append(asyncio.create_task(self._data_feeder_loop()))
        self.background_tasks.append(asyncio.create_task(self._alerts_feeder_loop()))
        
        logger.info(f"Starting dashboard on port {self.port}")
        
        # Start FastAPI server
        config = uvicorn.Config(
            self.app,
            host="0.0.0.0",
            port=self.port,
            log_level="info"
        )
        server = uvicorn.Server(config)
        await server.serve()
    
    async def stop_dashboard(self):
        """Stop the real-time dashboard"""
        self.dashboard_running = False
        
        # Cancel background tasks
        for task in self.background_tasks:
            task.cancel()
        
        self.background_tasks.clear()
        logger.info("Dashboard stopped")
    
    async def _data_feeder_loop(self):
        """Background task to feed real-time data to dashboard"""
        while self.dashboard_running:
            try:
                # Process market overview
                market_data = await self.data_processor.process_market_overview()
                await self.websocket_manager.broadcast_message({
                    "type": "market_overview",
                    "payload": market_data
                }, "market_overview")
                
                await asyncio.sleep(10)  # Update every 10 seconds
                
            except Exception as e:
                logger.error(f"Error in data feeder loop: {e}")
                await asyncio.sleep(30)
    
    async def _alerts_feeder_loop(self):
        """Background task to feed alerts to dashboard"""
        while self.dashboard_running:
            try:
                # Get system status for alerts
                system_status = await self.whale_bot.get_system_status()
                active_alerts = system_status['phase3_features']['active_alerts']
                
                await self.websocket_manager.broadcast_message({
                    "type": "alerts_update",
                    "payload": active_alerts
                }, "active_alerts")
                
                await asyncio.sleep(5)  # Update every 5 seconds
                
            except Exception as e:
                logger.error(f"Error in alerts feeder loop: {e}")
                await asyncio.sleep(15)

    async def broadcast_whale_detection(self, trade: EnhancedTrade):
        """Broadcast new whale detection to dashboard"""
        try:
            whale_data = await self.data_processor.process_whale_data(trade)
            await self.websocket_manager.broadcast_message({
                "type": "whale_detection",
                "payload": whale_data['whale_detection']
            }, "whale_detections")
        except Exception as e:
            logger.error(f"Error broadcasting whale detection: {e}")
    
    async def broadcast_alert(self, alert: RealTimeAlert):
        """Broadcast new alert to dashboard"""
        try:
            alert_data = asdict(alert)
            await self.websocket_manager.broadcast_message({
                "type": "alert",
                "payload": alert_data
            }, "active_alerts")
        except Exception as e:
            logger.error(f"Error broadcasting alert: {e}")


class DashboardIntegration:
    """
    High-level dashboard integration system
    Provides unified interface for dashboard operations
    """
    
    def __init__(self, config: Optional[WhaleBotConfig] = None):
        """
        Initialize dashboard integration
        
        Args:
            config: Optional configuration for dashboard
        """
        self.config = config or WhaleBotConfig()
        self.dashboard = RealTimeDashboard(self.config)
        self._logger = logging.getLogger(__name__)
        logger.info("DashboardIntegration initialized")
    
    async def start_dashboard(self, host: str = "localhost", port: int = 8080):
        """Start the dashboard server"""
        self._logger.info(f"Starting dashboard on {host}:{port}")
        await self.dashboard.start_server(host, port)
    
    async def stop_dashboard(self):
        """Stop the dashboard server"""
        self._logger.info("Stopping dashboard")
        await self.dashboard.stop_server()
    
    def get_dashboard_status(self) -> Dict[str, Any]:
        """Get dashboard status"""
        return {
            "status": "running" if self.dashboard.is_running else "stopped",
            "active_connections": len(self.dashboard.websocket_manager.connections),
            "config": self.config.__dict__
        }
    
    async def send_custom_data(self, data_type: str, data: Dict[str, Any]):
        """Send custom data to dashboard"""
        try:
            await self.dashboard.websocket_manager.broadcast_message({
                "type": data_type,
                "payload": data
            })
        except Exception as e:
            self._logger.error(f"Error sending custom data: {e}")
