"""
Split Flow Details Panel - Top/Bottom layout for flow and sub-flow details
"""

from textual.widget import Widget
from textual.containers import Vertical
from textual.widgets import Static
from textual.reactive import reactive
from rich.text import Text
from rich.panel import Panel
from rich.console import RenderableType, Group
from rich.table import Table
from typing import TYPE_CHECKING, Optional, Dict

if TYPE_CHECKING:
    from ....models import FlowStats, FrameTypeStats


class FlowMainDetailsPanel(Vertical):
    """Top panel showing main flow details"""
    
    DEFAULT_CSS = """
    FlowMainDetailsPanel {
        height: 1fr;
        padding: 1;
    }
    
    FlowMainDetailsPanel Static {
        margin-bottom: 0;
    }
    """
    
    def __init__(self, **kwargs):
        super().__init__(**kwargs)
        self.current_flow = None
    
    def compose(self):
        """Create the main flow details layout"""
        yield Static("Main Flow Details", classes="panel-header")
        yield Static(
            "Select a flow to view details",
            id="main-details-content"
        )
    
    def update_flow(self, flow: Optional['FlowStats']) -> None:
        """Update panel with main flow details"""
        flow_info = f"{flow.src_ip}:{flow.src_port}" if flow else "None"
        try:
            debug_panel = self.app.query_one("#debug-panel")
            debug_panel.add_debug_message(f"MAIN_PANEL: Update called - {flow_info}")
        except:
            pass
        
        self.current_flow = flow
        content_widget = self.query_one("#main-details-content", Static)
        
        if not flow:
            content_widget.update("Select a flow to view details")
            return
        
        details = self._create_main_flow_details(flow)
        
        # Debug what content we're actually setting
        try:
            debug_panel = self.app.query_one("#debug-panel")
            debug_panel.add_debug_message(f"CONTENT: Setting panel content for {flow.src_ip}:{flow.src_port}")
        except:
            pass
            
        content_widget.update(details)
    
    def _create_main_flow_details(self, flow: 'FlowStats') -> RenderableType:
        """Create main flow details display"""
        sections = []
        
        # Flow identification
        id_table = Table(show_header=False, box=None, padding=0)
        id_table.add_column(style="dim", width=12)
        id_table.add_column()
        
        id_table.add_row("Source:", f"{flow.src_ip}:{flow.src_port}")
        id_table.add_row("Destination:", f"{flow.dst_ip}:{flow.dst_port}")
        id_table.add_row("Protocol:", flow.transport_protocol)
        id_table.add_row("Packets:", f"{flow.frame_count:,}")
        id_table.add_row("Volume:", self._format_bytes(flow.total_bytes))
        
        sections.append(Text("Flow Information", style="bold blue"))
        sections.append(id_table)
        
        # Enhanced analysis
        if flow.enhanced_analysis.decoder_type != "Standard":
            enhanced_table = Table(show_header=False, box=None, padding=0)
            enhanced_table.add_column(style="dim", width=12)
            enhanced_table.add_column()
            
            enhanced_table.add_row("Decoder:", flow.enhanced_analysis.decoder_type)
            enhanced_table.add_row("Quality:", f"{flow.enhanced_analysis.avg_frame_quality:.1f}%")
            enhanced_table.add_row("Fields:", str(flow.enhanced_analysis.field_count))
            
            if flow.enhanced_analysis.frame_types:
                types_str = ", ".join(list(flow.enhanced_analysis.frame_types)[:3])
                if len(flow.enhanced_analysis.frame_types) > 3:
                    types_str += f" +{len(flow.enhanced_analysis.frame_types) - 3}"
                enhanced_table.add_row("Types:", types_str)
            
            sections.append(Text("Enhanced Analysis", style="bold green"))
            sections.append(enhanced_table)
        
        # Timing analysis - only show if no enhanced sub-flows exist
        # Match the same logic as _should_show_subrows in flow_table_v2.py
        has_enhanced_subflows = self._has_enhanced_subflows(flow)
        
        # Debug output
        try:
            debug_panel = self.app.query_one("#debug-panel")
            debug_panel.add_debug_message(f"TIMING_LOGIC: {flow.src_ip}:{flow.src_port} - types={len(flow.frame_types)}, decoder={flow.enhanced_analysis.decoder_type}, has_enhanced_subflows={has_enhanced_subflows}")
        except:
            pass
        
        if not has_enhanced_subflows:
            try:
                debug_panel = self.app.query_one("#debug-panel")
                debug_panel.add_debug_message(f"BRANCH: Taking FULL timing branch for {flow.src_ip}:{flow.src_port}")
            except:
                pass
                
            timing_table = Table(show_header=False, box=None, padding=0)
            timing_table.add_column(style="dim", width=12)
            timing_table.add_column()
            
            timing_table.add_row("Duration:", f"{flow.duration:.2f}s")
            timing_table.add_row("Avg ΔT:", f"{flow.avg_inter_arrival * 1000:.1f}ms")
            timing_table.add_row("Std σ:", f"{flow.std_inter_arrival * 1000:.1f}ms")
            timing_table.add_row("Outliers:", f"{len(flow.outlier_frames)}")
            timing_table.add_row("Jitter:", f"{flow.jitter * 1000:.2f}ms")
            timing_table.add_row("First Seen:", self._format_timestamp(flow.first_seen))
            timing_table.add_row("Last Seen:", self._format_timestamp(flow.last_seen))
            
            sections.append(Text("Timing Analysis", style="bold cyan"))
            sections.append(timing_table)
        else:
            try:
                debug_panel = self.app.query_one("#debug-panel")
                debug_panel.add_debug_message(f"BRANCH: Taking BASIC timeline branch for {flow.src_ip}:{flow.src_port}")
            except:
                pass
                
            # Just show duration and timestamps for flows with sub-flows
            basic_timing_table = Table(show_header=False, box=None, padding=0)
            basic_timing_table.add_column(style="dim", width=12)
            basic_timing_table.add_column()
            
            basic_timing_table.add_row("Duration:", f"{flow.duration:.2f}s")
            basic_timing_table.add_row("First Seen:", self._format_timestamp(flow.first_seen))
            basic_timing_table.add_row("Last Seen:", self._format_timestamp(flow.last_seen))
            
            sections.append(Text("Flow Timeline", style="bold cyan"))
            sections.append(basic_timing_table)
        
        return Group(*sections)
    
    def _has_enhanced_subflows(self, flow: 'FlowStats') -> bool:
        """Check if flow has enhanced frame types that warrant sub-rows"""
        enhanced_protocols = {'CHAPTER10', 'CH10', 'PTP', 'IENA'}
        
        for frame_type in flow.frame_types.keys():
            # Check if this frame type belongs to an enhanced protocol
            if any(enhanced_proto in frame_type for enhanced_proto in enhanced_protocols):
                return True
            elif frame_type.startswith(('CH10-', 'PTP-', 'IENA-')):
                return True
        
        return False
    
    def _format_bytes(self, bytes_count: int) -> str:
        """Format byte count with units"""
        if bytes_count >= 1_000_000_000:
            return f"{bytes_count / 1_000_000_000:.2f} GB"
        elif bytes_count >= 1_000_000:
            return f"{bytes_count / 1_000_000:.2f} MB"
        elif bytes_count >= 1_000:
            return f"{bytes_count / 1_000:.2f} KB"
        else:
            return f"{bytes_count} B"
    
    def _format_timestamp(self, timestamp: float) -> str:
        """Format timestamp for display"""
        import datetime
        dt = datetime.datetime.fromtimestamp(timestamp)
        return dt.strftime("%H:%M:%S.%f")[:-3]


class SubFlowDetailsPanel(Vertical):
    """Bottom panel showing sub-flow details or summary"""
    
    DEFAULT_CSS = """
    SubFlowDetailsPanel {
        height: 1fr;
        padding: 1;
    }
    
    SubFlowDetailsPanel Static {
        margin-bottom: 0;
    }
    """
    
    def __init__(self, **kwargs):
        super().__init__(**kwargs)
        self.current_flow = None
        self.selected_subflow = None
    
    def compose(self):
        """Create the sub-flow details layout"""
        yield Static("Sub-Flow Details", classes="panel-header")
        yield Static(
            "No sub-flow selected",
            id="sub-details-content"
        )
    
    def update_flow(self, flow: Optional['FlowStats'], subflow_type: Optional[str] = None) -> None:
        """Update panel with sub-flow details or summary"""
        self.current_flow = flow
        self.selected_subflow = subflow_type
        content_widget = self.query_one("#sub-details-content", Static)
        
        if not flow:
            content_widget.update("No sub-flow selected")
            return
        
        if subflow_type and subflow_type in flow.frame_types:
            # Show specific sub-flow details
            details = self._create_subflow_details(flow, flow.frame_types[subflow_type])
        else:
            # Show summary of all sub-flows
            details = self._create_subflow_summary(flow)
        
        content_widget.update(details)
    
    def _create_subflow_details(self, flow: 'FlowStats', subflow: 'FrameTypeStats') -> RenderableType:
        """Create specific sub-flow details"""
        sections = []
        
        # Sub-flow identification
        id_table = Table(show_header=False, box=None, padding=0)
        id_table.add_column(style="dim", width=12)
        id_table.add_column()
        
        id_table.add_row("Frame Type:", subflow.frame_type)
        id_table.add_row("Packets:", f"{subflow.count:,}")
        id_table.add_row("Volume:", self._format_bytes(subflow.total_bytes))
        
        percentage = (subflow.count / flow.frame_count * 100) if flow.frame_count > 0 else 0
        id_table.add_row("% of Flow:", f"{percentage:.1f}%")
        
        sections.append(Text("Sub-Flow Information", style="bold yellow"))
        sections.append(id_table)
        
        # Sub-flow timing
        timing_table = Table(show_header=False, box=None, padding=0)
        timing_table.add_column(style="dim", width=12)
        timing_table.add_column()
        
        timing_table.add_row("Avg ΔT:", f"{subflow.avg_inter_arrival * 1000:.1f}ms" if subflow.avg_inter_arrival > 0 else "N/A")
        timing_table.add_row("Std σ:", f"{subflow.std_inter_arrival * 1000:.1f}ms" if subflow.std_inter_arrival > 0 else "N/A")
        timing_table.add_row("Outliers:", f"{len(subflow.outlier_frames)}")
        
        sections.append(Text("Sub-Flow Timing", style="bold cyan"))
        sections.append(timing_table)
        
        # Enhanced outlier details if any
        if subflow.outlier_frames:
            outlier_table = Table(show_header=True, box=None)
            outlier_table.add_column("Frame#", justify="right")
            outlier_table.add_column("Prev Frame#", justify="right")
            outlier_table.add_column("ΔT(ms)", justify="right")
            outlier_table.add_column("σ Dev", justify="right")
            
            # Use enhanced details if available, fallback to legacy details
            outlier_data = []
            if hasattr(subflow, 'enhanced_outlier_details') and subflow.enhanced_outlier_details:
                for frame_num, prev_frame_num, delta_t in subflow.enhanced_outlier_details[:5]:
                    # Calculate sigma deviation
                    sigma_dev = "N/A"
                    if subflow.std_inter_arrival > 0 and subflow.avg_inter_arrival > 0:
                        deviation = (delta_t - subflow.avg_inter_arrival) / subflow.std_inter_arrival
                        sigma_dev = f"{deviation:.1f}σ"
                    
                    outlier_data.append((frame_num, prev_frame_num, delta_t, sigma_dev))
            elif subflow.outlier_details:
                for frame_num, delta_t in subflow.outlier_details[:5]:
                    # Calculate sigma deviation
                    sigma_dev = "N/A"
                    if subflow.std_inter_arrival > 0 and subflow.avg_inter_arrival > 0:
                        deviation = (delta_t - subflow.avg_inter_arrival) / subflow.std_inter_arrival
                        sigma_dev = f"{deviation:.1f}σ"
                    
                    outlier_data.append((frame_num, "N/A", delta_t, sigma_dev))
            
            for frame_num, prev_frame_num, delta_t, sigma_dev in outlier_data:
                outlier_table.add_row(
                    str(frame_num),
                    str(prev_frame_num) if prev_frame_num != "N/A" else "N/A",
                    f"{delta_t * 1000:.1f}",
                    sigma_dev
                )
            
            total_outliers = len(subflow.enhanced_outlier_details) if hasattr(subflow, 'enhanced_outlier_details') else len(subflow.outlier_details)
            if total_outliers > 5:
                outlier_table.add_row("...", "...", f"+{total_outliers - 5}", "more")
            
            sections.append(Text("Outlier Details", style="bold red"))
            sections.append(outlier_table)
        
        return Group(*sections)
    
    def _create_subflow_summary(self, flow: 'FlowStats') -> RenderableType:
        """Create summary of all sub-flows for enhanced flows"""
        # For enhanced flows, show ALL frame types, not just enhanced ones
        if flow.enhanced_analysis.decoder_type != "Standard":
            frame_types_to_show = flow.frame_types
            title = "Sub-Flow Summary (All Frame Types)"
        else:
            # For standard flows, only show enhanced frame types if any
            frame_types_to_show = self._get_enhanced_frame_types(flow)
            title = "Enhanced Sub-Flow Summary"
        
        if not frame_types_to_show:
            return Text("No sub-flows available", style="dim")
        
        sections = []
        sections.append(Text(title, style="bold yellow"))
        
        # Frame type breakdown table for enhanced protocols only
        frame_table = Table(show_header=True, box=None)
        frame_table.add_column("Frame Type", style="blue")
        frame_table.add_column("Count", justify="right")
        frame_table.add_column("%", justify="right", style="dim")
        frame_table.add_column("ΔT(ms)", justify="right", style="cyan")
        frame_table.add_column("σ(ms)", justify="right", style="cyan")
        frame_table.add_column("Out", justify="right", style="red")
        
        total = flow.frame_count
        for frame_type, stats in sorted(
            frame_types_to_show.items(), 
            key=lambda x: x[1].count, 
            reverse=True
        ):
            percentage = (stats.count / total * 100) if total > 0 else 0
            
            # Use same logic as grid rows for consistency
            delta_t = ""
            if stats.avg_inter_arrival > 0:
                dt_ms = stats.avg_inter_arrival * 1000
                delta_t = f"{dt_ms:.1f}" if dt_ms < 1000 else f"{dt_ms/1000:.1f}s"
            elif len(stats.inter_arrival_times) >= 2:
                # Fallback calculation if stored avg is zero
                import statistics
                avg_arrival = statistics.mean(stats.inter_arrival_times)
                if avg_arrival > 0:
                    dt_ms = avg_arrival * 1000
                    delta_t = f"{dt_ms:.1f}" if dt_ms < 1000 else f"{dt_ms/1000:.1f}s"
            
            sigma = ""
            if stats.std_inter_arrival > 0:
                sig_ms = stats.std_inter_arrival * 1000
                sigma = f"{sig_ms:.1f}" if sig_ms < 1000 else f"{sig_ms/1000:.1f}s"
            elif len(stats.inter_arrival_times) >= 2:
                # Fallback calculation if stored std is zero
                import statistics
                std_arrival = statistics.stdev(stats.inter_arrival_times)
                if std_arrival > 0:
                    sig_ms = std_arrival * 1000
                    sigma = f"{sig_ms:.1f}" if sig_ms < 1000 else f"{sig_ms/1000:.1f}s"
            
            outliers = str(len(stats.outlier_frames))
            
            frame_table.add_row(
                frame_type,  # Show full frame type name
                f"{stats.count:,}",
                f"{percentage:.1f}%",
                delta_t if delta_t else "N/A",
                sigma if sigma else "N/A", 
                outliers
            )
        
        sections.append(frame_table)
        return Group(*sections)
    
    def _get_enhanced_frame_types(self, flow: 'FlowStats') -> Dict[str, 'FrameTypeStats']:
        """Get only frame types that belong to enhanced protocols"""
        enhanced_protocols = {'CHAPTER10', 'CH10', 'PTP', 'IENA'}
        enhanced_frame_types = {}
        
        for frame_type, stats in flow.frame_types.items():
            # Check if this frame type belongs to an enhanced protocol
            if any(enhanced_proto in frame_type for enhanced_proto in enhanced_protocols):
                enhanced_frame_types[frame_type] = stats
            elif frame_type.startswith(('CH10-', 'PTP-', 'IENA-')):
                enhanced_frame_types[frame_type] = stats
            elif frame_type in ('TMATS', 'TMATS-Data'):  # TMATS is part of Chapter 10
                enhanced_frame_types[frame_type] = stats
        
        return enhanced_frame_types
    
    def _format_bytes(self, bytes_count: int) -> str:
        """Format byte count with units"""
        if bytes_count >= 1_000_000_000:
            return f"{bytes_count / 1_000_000_000:.2f} GB"
        elif bytes_count >= 1_000_000:
            return f"{bytes_count / 1_000_000:.2f} MB"
        elif bytes_count >= 1_000:
            return f"{bytes_count / 1_000:.2f} KB"
        else:
            return f"{bytes_count} B"


class SplitFlowDetailsPanel(Vertical):
    """Combined panel with top/bottom split for flow and sub-flow details"""
    
    DEFAULT_CSS = """
    SplitFlowDetailsPanel {
        height: 1fr;
        padding: 0;
    }
    
    SplitFlowDetailsPanel > FlowMainDetailsPanel {
        height: 3fr;
    }
    
    SplitFlowDetailsPanel > SubFlowDetailsPanel {
        height: 2fr; 
    }
    """
    
    def __init__(self, **kwargs):
        super().__init__(**kwargs)
        self.current_flow = None
    
    def compose(self):
        """Create the split layout"""
        yield FlowMainDetailsPanel(id="main-flow-details")
        yield SubFlowDetailsPanel(id="sub-flow-details")
    
    def update_flow(self, flow: Optional['FlowStats'], subflow_type: Optional[str] = None) -> None:
        """Update both panels with flow data"""
        self.current_flow = flow
        
        # Update main flow details
        main_panel = self.query_one("#main-flow-details", FlowMainDetailsPanel)
        main_panel.update_flow(flow)
        
        # Update sub-flow details  
        sub_panel = self.query_one("#sub-flow-details", SubFlowDetailsPanel)
        sub_panel.update_flow(flow, subflow_type)