"""
Data Recording and Replay module for ARTOS integration.

Provides Record & Replay functionality for deterministic test execution.
"""
import json
import logging
from datetime import datetime
from pathlib import Path
from typing import Any, Dict, List, Optional
from dataclasses import dataclass, asdict

logger = logging.getLogger("BusMonitor.Recorder")


@dataclass
class RecordedEvent:
    """
    Represents a single event in a recorded sequence.
    
    Attributes:
        timestamp: System time when event occurred (float, seconds since epoch)
        event_type: Type of event (e.g., 'msg_received', 'msg_sent', 'command')
        data: Event-specific payload (message content, command parameters, etc.)
        label: Optional label for easy reference (e.g., message label "msg_a2")
        hw_timestamp: Optional hardware timestamp from the source (if available)
    """
    timestamp: float
    event_type: str
    data: Dict[str, Any]
    label: Optional[str] = None
    hw_timestamp: Optional[float] = None


class DataRecorder:
    """
    Records sequences of 1553 bus events with precise timing information.
    
    This enables:
    - Recording live test sessions
    - Replaying tests for regression testing
    - Deterministic validation in ARTOS Collector
    """

    def __init__(self):
        self.recording: bool = False
        self.events: List[RecordedEvent] = []
        self.session_start_time: Optional[float] = None

    def start_recording(self) -> None:
        """Begin recording a new sequence."""
        self.recording = True
        self.events = []
        self.session_start_time = datetime.now().timestamp()
        logger.info("Started recording session")

    def stop_recording(self) -> None:
        """Stop the current recording session."""
        self.recording = False
        logger.info(f"Stopped recording. Captured {len(self.events)} events")

    def record_event(
        self,
        event_type: str,
        data: Dict[str, Any],
        label: Optional[str] = None,
        hw_timestamp: Optional[float] = None
    ) -> None:
        """
        Record a single event if recording is active.
        
        Args:
            event_type: Category of event (e.g., 'msg_received', 'msg_sent')
            data: Event payload (should be JSON-serializable)
            label: Optional label for filtering/searching
            hw_timestamp: Optional hardware timestamp from source
        """
        if not self.recording:
            return

        event = RecordedEvent(
            timestamp=datetime.now().timestamp(),
            event_type=event_type,
            data=data,
            label=label,
            hw_timestamp=hw_timestamp
        )
        self.events.append(event)

    def save_to_file(self, filepath: Path) -> None:
        """
        Save recorded sequence to JSON file.
        
        Args:
            filepath: Path where to save the recording
        """
        output = {
            "session_start_time": self.session_start_time,
            "event_count": len(self.events),
            "events": [asdict(event) for event in self.events]
        }

        with open(filepath, 'w') as f:
            json.dump(output, f, indent=2)

        logger.info(f"Saved {len(self.events)} events to {filepath}")

    def load_from_file(self, filepath: Path) -> None:
        """
        Load a recorded sequence from JSON file.
        
        Args:
            filepath: Path to the recording file
        """
        with open(filepath, 'r') as f:
            data = json.load(f)

        self.session_start_time = data['session_start_time']
        self.events = [RecordedEvent(**event) for event in data['events']]

        logger.info(f"Loaded {len(self.events)} events from {filepath}")

    def get_events_by_label(self, label: str) -> List[RecordedEvent]:
        """
        Retrieve all events with a specific label.
        
        Args:
            label: Label to filter by
            
        Returns:
            List of matching events
        """
        return [e for e in self.events if e.label == label]

    def get_events_by_type(self, event_type: str) -> List[RecordedEvent]:
        """
        Retrieve all events of a specific type.
        
        Args:
            event_type: Type to filter by
            
        Returns:
            List of matching events
        """
        return [e for e in self.events if e.event_type == event_type]

    def get_time_window(
        self, 
        start_time: float, 
        end_time: float
    ) -> List[RecordedEvent]:
        """
        Retrieve events within a specific time window.
        
        Args:
            start_time: Window start (seconds since epoch)
            end_time: Window end (seconds since epoch)
            
        Returns:
            List of events within the time window
        """
        return [
            e for e in self.events 
            if start_time <= e.timestamp <= end_time
        ]
