"""
Cascade Visualization - Command Center

The nerve center. Where causation is tracked forwards and backwards through time.
This is not a report - this is a command center in a state of readiness.
"""

import json
from typing import Optional
from pathlib import Path
from datetime import datetime

from cascade.core.graph import CausationGraph


def to_html(graph: CausationGraph, title: str = "CASCADE // COMMAND") -> str:
    """Export causation graph to command center HTML interface."""
    
    # Extract data
    events = []
    for event_id, event in graph._events.items():
        events.append({
            "id": event.event_id,
            "timestamp": event.timestamp,
            "component": event.component,
            "type": event.event_type,
            "data": event.data,
        })
    
    links = []
    for link_id, link in graph._links.items():
        links.append({
            "source": link.from_event,
            "target": link.to_event,
            "type": link.causation_type,
            "strength": link.strength,
        })
    
    events.sort(key=lambda e: e["timestamp"])
    
    html = f'''<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>{title}</title>
    <style>
        @import url('https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;500;600;700&family=Inter:wght@400;500;600;700;800;900&display=swap');
        
        :root {{
            --bg-void: #000000;
            --bg-primary: #0a0a0a;
            --bg-panel: #0f0f0f;
            --bg-elevated: #141414;
            --text-bright: #ffffff;
            --text-primary: #e0e0e0;
            --text-secondary: #707070;
            --text-muted: #404040;
            --accent-active: #00ff88;
            --accent-warning: #ff6b00;
            --accent-critical: #ff0040;
            --accent-info: #00a8ff;
            --accent-temporal: #8b5cf6;
            --border-subtle: #1a1a1a;
            --border-active: #2a2a2a;
        }}
        
        * {{ margin: 0; padding: 0; box-sizing: border-box; }}
        
        body {{
            font-family: 'JetBrains Mono', monospace;
            background: var(--bg-void);
            color: var(--text-primary);
            min-height: 100vh;
            overflow: hidden;
        }}
        
        /* === COMMAND HEADER === */
        .command-header {{
            display: grid;
            grid-template-columns: 1fr auto 1fr;
            align-items: center;
            padding: 0 24px;
            height: 64px;
            background: var(--bg-primary);
            border-bottom: 1px solid var(--border-subtle);
        }}
        
        .system-id {{
            display: flex;
            align-items: center;
            gap: 16px;
        }}
        
        .logo {{
            font-family: 'Inter', sans-serif;
            font-weight: 900;
            font-size: 24px;
            letter-spacing: -1px;
            color: var(--text-bright);
        }}
        
        .status-badge {{
            display: flex;
            align-items: center;
            gap: 8px;
            padding: 6px 12px;
            background: rgba(0, 255, 136, 0.1);
            border: 1px solid var(--accent-active);
            font-size: 10px;
            font-weight: 600;
            letter-spacing: 2px;
            color: var(--accent-active);
            text-transform: uppercase;
        }}
        
        .status-dot {{
            width: 6px;
            height: 6px;
            background: var(--accent-active);
            border-radius: 50%;
            animation: pulse 2s ease-in-out infinite;
        }}
        
        @keyframes pulse {{
            0%, 100% {{ opacity: 1; box-shadow: 0 0 0 0 rgba(0, 255, 136, 0.4); }}
            50% {{ opacity: 0.8; box-shadow: 0 0 0 8px rgba(0, 255, 136, 0); }}
        }}
        
        .center-display {{
            text-align: center;
        }}
        
        .mission-clock {{
            font-size: 32px;
            font-weight: 600;
            color: var(--text-bright);
            font-variant-numeric: tabular-nums;
        }}
        
        .mission-date {{
            font-size: 11px;
            color: var(--text-secondary);
            letter-spacing: 1px;
        }}
        
        .metrics-bar {{
            display: flex;
            justify-content: flex-end;
            gap: 24px;
        }}
        
        .metric {{
            text-align: right;
        }}
        
        .metric-value {{
            font-size: 20px;
            font-weight: 700;
            color: var(--text-bright);
        }}
        
        .metric-label {{
            font-size: 9px;
            color: var(--text-muted);
            letter-spacing: 1.5px;
            text-transform: uppercase;
        }}
        
        /* === MAIN GRID === */
        .command-grid {{
            display: grid;
            grid-template-columns: 300px 1fr 340px;
            grid-template-rows: 1fr;
            height: calc(100vh - 64px);
            gap: 1px;
            background: var(--border-subtle);
        }}
        
        .panel {{
            background: var(--bg-panel);
            display: flex;
            flex-direction: column;
        }}
        
        .panel-header {{
            padding: 16px 20px;
            border-bottom: 1px solid var(--border-subtle);
            display: flex;
            justify-content: space-between;
            align-items: center;
        }}
        
        .panel-title {{
            font-size: 10px;
            font-weight: 700;
            letter-spacing: 2px;
            color: var(--text-secondary);
            text-transform: uppercase;
        }}
        
        .panel-indicator {{
            width: 8px;
            height: 8px;
            background: var(--accent-active);
            animation: pulse 2s ease-in-out infinite;
        }}
        
        .panel-content {{
            flex: 1;
            overflow-y: auto;
            padding: 0;
        }}
        
        /* === EVENT QUEUE === */
        .event-queue-item {{
            display: grid;
            grid-template-columns: 80px 1fr;
            gap: 12px;
            padding: 12px 20px;
            border-bottom: 1px solid var(--border-subtle);
            cursor: pointer;
            transition: background 0.1s;
        }}
        
        .event-queue-item:hover {{
            background: var(--bg-elevated);
        }}
        
        .event-queue-item.selected {{
            background: var(--bg-elevated);
            border-left: 2px solid var(--accent-info);
        }}
        
        .event-queue-item.critical {{
            border-left: 2px solid var(--accent-critical);
        }}
        
        .event-queue-item.warning {{
            border-left: 2px solid var(--accent-warning);
        }}
        
        .event-time {{
            font-size: 11px;
            color: var(--accent-info);
            font-variant-numeric: tabular-nums;
        }}
        
        .event-info {{
            min-width: 0;
        }}
        
        .event-type {{
            font-size: 12px;
            font-weight: 600;
            color: var(--text-primary);
            white-space: nowrap;
            overflow: hidden;
            text-overflow: ellipsis;
        }}
        
        .event-component {{
            font-size: 10px;
            color: var(--text-muted);
            text-transform: uppercase;
            letter-spacing: 0.5px;
        }}
        
        /* === TEMPORAL CANVAS === */
        .temporal-canvas {{
            background: var(--bg-void);
            position: relative;
        }}
        
        .temporal-header {{
            position: absolute;
            top: 0;
            left: 0;
            right: 0;
            padding: 20px 24px;
            display: flex;
            justify-content: space-between;
            align-items: flex-start;
            z-index: 10;
            background: linear-gradient(to bottom, var(--bg-void) 0%, transparent 100%);
        }}
        
        /* Motto is the primary anchor */
        .footer {
            position: fixed;
            bottom: 0;
            left: 0;
            right: 0;
            padding: 16px 24px;
            background: var(--bg-primary);
            border-top: 1px solid var(--border-subtle);
            display: flex;
            justify-content: center;
            align-items: center;
            z-index: 100;
        }
        
        .motto {
            font-size: 11px;
            font-style: italic;
            color: var(--text-muted);
            letter-spacing: 1px;
        }
        
        .temporal-title {{
            font-family: 'Inter', sans-serif;
            font-size: 11px;
            font-weight: 700;
            letter-spacing: 3px;
            color: var(--text-muted);
            text-transform: uppercase;
        }}
        
        .direction-indicators {{
            display: flex;
            gap: 16px;
        }}
        
        .direction {{
            display: flex;
            align-items: center;
            gap: 6px;
            font-size: 10px;
            letter-spacing: 1px;
        }}
        
        .direction.backward {{
            color: var(--accent-critical);
        }}
        
        .direction.forward {{
            color: var(--accent-active);
        }}
        
        .direction-arrow {{
            font-size: 14px;
        }}
        
        .timeline-flow {{
            position: absolute;
            top: 60px;
            bottom: 80px;
            left: 50%;
            width: 2px;
            background: linear-gradient(to bottom,
                var(--accent-critical) 0%,
                var(--accent-temporal) 30%,
                var(--accent-temporal) 70%,
                var(--accent-active) 100%
            );
            transform: translateX(-50%);
        }}
        
        .timeline-flow::before {{
            content: '';
            position: absolute;
            top: 0;
            left: 50%;
            transform: translateX(-50%);
            width: 8px;
            height: 8px;
            background: var(--accent-critical);
            clip-path: polygon(50% 0%, 0% 100%, 100% 100%);
        }}
        
        .timeline-flow::after {{
            content: '';
            position: absolute;
            bottom: 0;
            left: 50%;
            transform: translateX(-50%);
            width: 8px;
            height: 8px;
            background: var(--accent-active);
            clip-path: polygon(0% 0%, 100% 0%, 50% 100%);
        }}
        
        .event-nodes {{
            position: absolute;
            top: 80px;
            bottom: 100px;
            left: 0;
            right: 0;
            overflow-y: auto;
            padding: 20px 24px;
        }}
        
        .node {{
            display: flex;
            align-items: flex-start;
            margin-bottom: 16px;
            position: relative;
        }}
        
        .node-marker {{
            width: 40px;
            display: flex;
            justify-content: center;
            padding-top: 4px;
        }}
        
        .node-dot {{
            width: 10px;
            height: 10px;
            background: var(--text-muted);
            border: 2px solid var(--bg-void);
        }}
        
        .node.critical .node-dot {{
            background: var(--accent-critical);
            box-shadow: 0 0 12px var(--accent-critical);
        }}
        
        .node.warning .node-dot {{
            background: var(--accent-warning);
        }}
        
        .node-content {{
            flex: 1;
            padding: 12px 16px;
            background: var(--bg-panel);
            border: 1px solid var(--border-subtle);
            cursor: pointer;
            transition: all 0.15s;
        }}
        
        .node-content:hover {{
            border-color: var(--border-active);
        }}
        
        .node.selected .node-content {{
            border-color: var(--accent-info);
            box-shadow: 0 0 0 1px var(--accent-info);
        }}
        
        .node-header {{
            display: flex;
            justify-content: space-between;
            margin-bottom: 8px;
        }}
        
        .node-type {{
            font-weight: 600;
            font-size: 13px;
            color: var(--text-bright);
        }}
        
        .node-timestamp {{
            font-size: 10px;
            color: var(--accent-info);
            font-variant-numeric: tabular-nums;
        }}
        
        .node-data {{
            font-size: 11px;
            color: var(--text-secondary);
        }}
        
        .node-data-item {{
            display: flex;
            gap: 8px;
            padding: 2px 0;
        }}
        
        .node-data-key {{
            color: var(--text-muted);
        }}
        
        /* Removed temporal footer - motto is standalone */
        
        /* === ANALYSIS PANEL === */
        .analysis-section {{
            padding: 16px 20px;
            border-bottom: 1px solid var(--border-subtle);
        }}
        
        .analysis-label {{
            font-size: 9px;
            font-weight: 600;
            letter-spacing: 1.5px;
            color: var(--text-muted);
            text-transform: uppercase;
            margin-bottom: 8px;
        }}
        
        .analysis-value {{
            font-size: 13px;
            color: var(--text-primary);
        }}
        
        .causation-chain {{
            margin-top: 8px;
        }}
        
        .chain-link {{
            display: flex;
            align-items: center;
            gap: 8px;
            padding: 8px 12px;
            background: var(--bg-elevated);
            margin-bottom: 4px;
            font-size: 11px;
        }}
        
        .chain-arrow {{
            color: var(--accent-critical);
            font-size: 14px;
        }}
        
        .chain-arrow.effect {{
            color: var(--accent-active);
        }}
        
        .prediction-box {{
            background: var(--bg-elevated);
            border: 1px solid var(--accent-warning);
            padding: 12px;
            margin-top: 8px;
        }}
        
        .prediction-header {{
            display: flex;
            align-items: center;
            gap: 8px;
            font-size: 10px;
            font-weight: 600;
            letter-spacing: 1px;
            color: var(--accent-warning);
            text-transform: uppercase;
            margin-bottom: 8px;
        }}
        
        .prediction-item {{
            font-size: 11px;
            color: var(--text-secondary);
            padding: 4px 0;
        }}
        
        .empty-analysis {{
            padding: 40px 20px;
            text-align: center;
            color: var(--text-muted);
            font-size: 11px;
        }}
        
        .command-grid {{
            padding-bottom: 60px;
        }}
        
        /* === SCANLINE EFFECT === */
        .scanline {{
            position: fixed;
            top: 0;
            left: 0;
            right: 0;
            height: 2px;
            background: linear-gradient(90deg, 
                transparent 0%, 
                var(--accent-active) 50%, 
                transparent 100%
            );
            opacity: 0.3;
            animation: scan 4s linear infinite;
            pointer-events: none;
        }}
        
        @keyframes scan {{
            0% {{ top: 0; opacity: 0; }}
            10% {{ opacity: 0.3; }}
            90% {{ opacity: 0.3; }}
            100% {{ top: 100vh; opacity: 0; }}
        }}
    </style>
</head>
<body>
    <div class="scanline"></div>
    
    <header class="command-header">
        <div class="system-id">
            <div class="logo">CASCADE</div>
            <div class="status-badge">
                <div class="status-dot"></div>
                <span>TRACKING ACTIVE</span>
            </div>
        </div>
        
        <div class="center-display">
            <div class="mission-clock" id="clock">--:--:--</div>
            <div class="mission-date" id="date">INITIALIZING</div>
        </div>
        
        <div class="metrics-bar">
            <div class="metric">
                <div class="metric-value">{len(events)}</div>
                <div class="metric-label">Events Captured</div>
            </div>
            <div class="metric">
                <div class="metric-value">{len(links)}</div>
                <div class="metric-label">Causations Mapped</div>
            </div>
            <div class="metric">
                <div class="metric-value">{len(set(e["component"] for e in events))}</div>
                <div class="metric-label">Components</div>
            </div>
        </div>
    </header>
    
    <main class="command-grid">
        <div class="panel">
            <div class="panel-header">
                <span class="panel-title">Event Queue</span>
                <div class="panel-indicator"></div>
            </div>
            <div class="panel-content" id="event-queue"></div>
        </div>
        
        <div class="temporal-canvas">
            <div class="temporal-header">
                <div class="temporal-title">Temporal Sequence</div>
                <div class="direction-indicators">
                    <div class="direction backward">
                        <span class="direction-arrow">↑</span>
                        <span>TRACE BACK</span>
                    </div>
                    <div class="direction forward">
                        <span class="direction-arrow">↓</span>
                        <span>PREDICT</span>
                    </div>
                </div>
            </div>
            <div class="timeline-flow"></div>
            <div class="event-nodes" id="nodes"></div>
        </div>
        
        <div class="panel">
            <div class="panel-header">
                <span class="panel-title">Causation Analysis</span>
                <div class="panel-indicator"></div>
            </div>
            <div class="panel-content" id="analysis">
                <div class="empty-analysis">
                    SELECT EVENT TO ANALYZE<br>
                    CAUSATION CHAIN
                </div>
            </div>
        </div>
    </main>
    
    <footer class="footer">
        <div class="motto">"even still, i grow, and yet, I grow still"</div>
    </footer>
    
    <script>
        const events = {json.dumps(events, default=str)};
        const links = {json.dumps(links, default=str)};
        
        const eventMap = new Map();
        events.forEach(e => eventMap.set(e.id, e));
        
        const causesMap = new Map();
        const effectsMap = new Map();
        
        links.forEach(link => {{
            if (!effectsMap.has(link.source)) effectsMap.set(link.source, []);
            if (!causesMap.has(link.target)) causesMap.set(link.target, []);
            effectsMap.get(link.source).push({{ event: eventMap.get(link.target), link }});
            causesMap.get(link.target).push({{ event: eventMap.get(link.source), link }});
        }});
        
        let selectedId = null;
        
        // Clock
        function updateClock() {{
            const now = new Date();
            document.getElementById('clock').textContent = 
                now.toLocaleTimeString('en-US', {{ hour12: false }});
            document.getElementById('date').textContent = 
                now.toLocaleDateString('en-US', {{ 
                    weekday: 'short', 
                    year: 'numeric', 
                    month: 'short', 
                    day: 'numeric' 
                }}).toUpperCase();
        }}
        setInterval(updateClock, 1000);
        updateClock();
        
        function formatTime(ts) {{
            const d = new Date(ts * 1000);
            return d.toLocaleTimeString('en-US', {{ hour12: false }}) + 
                   '.' + String(d.getMilliseconds()).padStart(3, '0');
        }}
        
        function getClass(type) {{
            if (['error', 'anomaly', 'crash', 'failure'].some(k => type.includes(k))) return 'critical';
            if (['warning', 'warn', 'spike'].some(k => type.includes(k))) return 'warning';
            return '';
        }}
        
        function select(id) {{
            selectedId = id;
            document.querySelectorAll('.event-queue-item, .node').forEach(el => 
                el.classList.remove('selected'));
            document.querySelectorAll(`[data-id="${{id}}"]`).forEach(el => 
                el.classList.add('selected'));
            renderAnalysis(id);
        }}
        
        function renderQueue() {{
            document.getElementById('event-queue').innerHTML = events.map(e => `
                <div class="event-queue-item ${{getClass(e.type)}}" data-id="${{e.id}}" onclick="select('${{e.id}}')">
                    <div class="event-time">${{formatTime(e.timestamp)}}</div>
                    <div class="event-info">
                        <div class="event-type">${{e.type}}</div>
                        <div class="event-component">${{e.component}}</div>
                    </div>
                </div>
            `).join('');
        }}
        
        function renderNodes() {{
            if (events.length === 0) {{
                document.getElementById('nodes').innerHTML = 
                    '<div class="empty-analysis" style="padding-top:100px">AWAITING EVENTS<br>SYSTEM READY</div>';
                return;
            }}
            
            document.getElementById('nodes').innerHTML = events.map(e => `
                <div class="node ${{getClass(e.type)}}" data-id="${{e.id}}" onclick="select('${{e.id}}')">
                    <div class="node-marker"><div class="node-dot"></div></div>
                    <div class="node-content">
                        <div class="node-header">
                            <span class="node-type">${{e.type}}</span>
                            <span class="node-timestamp">${{formatTime(e.timestamp)}}</span>
                        </div>
                        <div class="node-data">
                            ${{Object.entries(e.data).slice(0,3).map(([k,v]) => 
                                `<div class="node-data-item"><span class="node-data-key">${{k}}:</span>${{JSON.stringify(v)}}</div>`
                            ).join('')}}
                        </div>
                    </div>
                </div>
            `).join('');
        }}
        
        function renderAnalysis(id) {{
            const e = eventMap.get(id);
            if (!e) return;
            
            const causes = causesMap.get(id) || [];
            const effects = effectsMap.get(id) || [];
            
            let html = `
                <div class="analysis-section">
                    <div class="analysis-label">Event</div>
                    <div class="analysis-value" style="font-weight:600;font-size:15px">${{e.type}}</div>
                </div>
                <div class="analysis-section">
                    <div class="analysis-label">Component</div>
                    <div class="analysis-value">${{e.component}}</div>
                </div>
                <div class="analysis-section">
                    <div class="analysis-label">Timestamp</div>
                    <div class="analysis-value" style="color:var(--accent-info)">${{formatTime(e.timestamp)}}</div>
                </div>
                <div class="analysis-section">
                    <div class="analysis-label">Data</div>
                    <div class="analysis-value">
                        ${{Object.entries(e.data).map(([k,v]) => 
                            `<div class="node-data-item"><span class="node-data-key">${{k}}:</span>${{JSON.stringify(v)}}</div>`
                        ).join('')}}
                    </div>
                </div>
            `;
            
            if (causes.length > 0) {{
                html += `
                    <div class="analysis-section">
                        <div class="analysis-label">← Caused By</div>
                        <div class="causation-chain">
                            ${{causes.map(c => c.event ? `
                                <div class="chain-link">
                                    <span class="chain-arrow">←</span>
                                    <span>${{c.event.type}}</span>
                                </div>
                            ` : '').join('')}}
                        </div>
                    </div>
                `;
            }}
            
            if (effects.length > 0) {{
                html += `
                    <div class="analysis-section">
                        <div class="analysis-label">→ Caused</div>
                        <div class="causation-chain">
                            ${{effects.map(ef => ef.event ? `
                                <div class="chain-link">
                                    <span class="chain-arrow effect">→</span>
                                    <span>${{ef.event.type}}</span>
                                </div>
                            ` : '').join('')}}
                        </div>
                    </div>
                `;
            }}
            
            // Prediction placeholder
            html += `
                <div class="analysis-section">
                    <div class="prediction-box">
                        <div class="prediction-header">
                            <span>⚡</span> Predicted Cascade
                        </div>
                        <div class="prediction-item">Analyzing patterns...</div>
                        <div class="prediction-item" style="color:var(--text-muted)">Insufficient data for prediction</div>
                    </div>
                </div>
            `;
            
            document.getElementById('analysis').innerHTML = html;
        }}
        
        renderQueue();
        renderNodes();
        if (events.length > 0) select(events[0].id);
    </script>
</body>
</html>'''
    
    return html


def save_html(graph: CausationGraph, path: str = "cascade_command.html", open_browser: bool = False) -> Path:
    """Save causation graph to command center HTML."""
    html = to_html(graph)
    output_path = Path(path)
    with open(output_path, 'w', encoding='utf-8') as f:
        f.write(html)
    if open_browser:
        import webbrowser
        webbrowser.open(f'file://{output_path.absolute()}')
    return output_path
