"""
Logging Module - Diagnostic and mission logging
"""

import logging
import json
import numpy as np
from typing import Dict, Any, Optional, List
from datetime import datetime
import os
from enum import Enum


class LogLevel(Enum):
    """Log levels"""
    DEBUG = 10
    INFO = 20
    WARNING = 30
    ERROR = 40
    CRITICAL = 50


class MissionLogger:
    """
    Mission logging system for HADEX operations
    
    Logs sensor readings, navigation events, and system status
    """
    
    def __init__(self,
                 mission_name: str,
                 log_level: str = "INFO",
                 log_dir: str = "logs"):
        """
        Initialize mission logger
        
        Args:
            mission_name: Name of the mission
            log_level: Logging level
            log_dir: Directory for log files
        """
        self.mission_name = mission_name
        self.log_level = getattr(logging, log_level.upper())
        self.log_dir = log_dir
        
        # Create log directory
        os.makedirs(log_dir, exist_ok=True)
        
        # Set up logger
        self.logger = logging.getLogger(f"hadex.{mission_name}")
        self.logger.setLevel(self.log_level)
        
        # File handler
        timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
        log_file = f"{log_dir}/{mission_name}_{timestamp}.log"
        fh = logging.FileHandler(log_file)
        fh.setLevel(self.log_level)
        
        # Console handler
        ch = logging.StreamHandler()
        ch.setLevel(self.log_level)
        
        # Formatter
        formatter = logging.Formatter(
            '%(asctime)s - %(name)s - %(levelname)s - %(message)s'
        )
        fh.setFormatter(formatter)
        ch.setFormatter(formatter)
        
        # Add handlers
        self.logger.addHandler(fh)
        self.logger.addHandler(ch)
        
        # JSON log for structured data
        self.json_log = []
        
        # Statistics
        self.log_counts = {
            'DEBUG': 0,
            'INFO': 0,
            'WARNING': 0,
            'ERROR': 0,
            'CRITICAL': 0
        }
        
        self.logger.info(f"Mission logger initialized: {mission_name}")
    
    def debug(self, message: str, data: Optional[Dict] = None):
        """Log debug message"""
        self.logger.debug(message)
        self.log_counts['DEBUG'] += 1
        if data:
            self._log_json('DEBUG', message, data)
    
    def info(self, message: str, data: Optional[Dict] = None):
        """Log info message"""
        self.logger.info(message)
        self.log_counts['INFO'] += 1
        if data:
            self._log_json('INFO', message, data)
    
    def warning(self, message: str, data: Optional[Dict] = None):
        """Log warning message"""
        self.logger.warning(message)
        self.log_counts['WARNING'] += 1
        if data:
            self._log_json('WARNING', message, data)
    
    def error(self, message: str, data: Optional[Dict] = None):
        """Log error message"""
        self.logger.error(message)
        self.log_counts['ERROR'] += 1
        if data:
            self._log_json('ERROR', message, data)
    
    def critical(self, message: str, data: Optional[Dict] = None):
        """Log critical message"""
        self.logger.critical(message)
        self.log_counts['CRITICAL'] += 1
        if data:
            self._log_json('CRITICAL', message, data)
    
    def _log_json(self, level: str, message: str, data: Dict):
        """Log structured data as JSON"""
        entry = {
            'timestamp': datetime.now().isoformat(),
            'level': level,
            'message': message,
            'data': self._serialize_data(data)
        }
        self.json_log.append(entry)
    
    def _serialize_data(self, data: Dict) -> Dict:
        """Serialize data for JSON logging"""
        serialized = {}
        for key, value in data.items():
            if isinstance(value, np.ndarray):
                serialized[key] = value.tolist()
            elif isinstance(value, np.integer):
                serialized[key] = int(value)
            elif isinstance(value, np.floating):
                serialized[key] = float(value)
            elif isinstance(value, (dict, list, str, int, float, bool)):
                serialized[key] = value
            else:
                serialized[key] = str(value)
        return serialized
    
    def log_sensor(self,
                  sensor_type: str,
                  value: float,
                  unit: str,
                  timestamp: Optional[float] = None,
                  quality: float = 1.0):
        """
        Log sensor reading
        
        Args:
            sensor_type: Type of sensor
            value: Sensor value
            unit: Measurement unit
            timestamp: Time of measurement
            quality: Data quality (0-1)
        """
        if timestamp is None:
            timestamp = len(self.json_log)
        
        data = {
            'sensor': sensor_type,
            'value': value,
            'unit': unit,
            'quality': quality
        }
        
        self.info(f"Sensor {sensor_type}: {value} {unit}", data)
    
    def log_navigation(self,
                      event_type: str,
                      position: np.ndarray,
                      uncertainty: float,
                      timestamp: Optional[float] = None):
        """
        Log navigation event
        
        Args:
            event_type: Type of navigation event
            position: Vehicle position [x, y, z]
            uncertainty: Position uncertainty (m)
            timestamp: Event timestamp
        """
        if timestamp is None:
            timestamp = len(self.json_log)
        
        data = {
            'event': event_type,
            'position_x': float(position[0]),
            'position_y': float(position[1]),
            'position_z': float(position[2]),
            'uncertainty_m': uncertainty,
            'timestamp': timestamp
        }
        
        self.info(f"Navigation: {event_type} at ({position[0]:.1f}, "
                 f"{position[1]:.1f}, {position[2]:.1f})", data)
    
    def log_alert(self,
                 level: str,
                 message: str,
                 severity: int = 3,
                 affected_vehicles: Optional[List[int]] = None):
        """
        Log alert event
        
        Args:
            level: Alert level (WATCH, WARNING, CRITICAL)
            message: Alert message
            severity: Severity (1-5)
            affected_vehicles: List of affected vehicle IDs
        """
        data = {
            'alert_level': level,
            'severity': severity,
            'affected_vehicles': affected_vehicles or []
        }
        
        if level == "CRITICAL":
            self.critical(message, data)
        elif level == "WARNING":
            self.error(message, data)
        elif level == "WATCH":
            self.warning(message, data)
        else:
            self.info(message, data)
    
    def log_mission_phase(self, phase: str, status: str):
        """Log mission phase change"""
        data = {
            'phase': phase,
            'status': status
        }
        self.info(f"Mission phase: {phase} - {status}", data)
    
    def get_statistics(self) -> Dict:
        """Get logging statistics"""
        return {
            'mission_name': self.mission_name,
            'log_counts': self.log_counts.copy(),
            'total_entries': sum(self.log_counts.values()),
            'json_entries': len(self.json_log)
        }
    
    def export(self,
              format: str = "json",
              destination: Optional[str] = None) -> str:
        """
        Export logs to file
        
        Args:
            format: Export format ('json' or 'text')
            destination: Output file path
            
        Returns:
            Exported data as string
        """
        if destination is None:
            timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
            destination = f"{self.log_dir}/{self.mission_name}_export_{timestamp}.{format}"
        
        if format == "json":
            data = {
                'mission': self.mission_name,
                'logs': self.json_log,
                'statistics': self.get_statistics()
            }
            output = json.dumps(data, indent=2)
        else:
            # Text format
            lines = []
            lines.append(f"MISSION LOG: {self.mission_name}")
            lines.append("=" * 60)
            for entry in self.json_log:
                lines.append(f"[{entry['level']}] {entry['timestamp']}: {entry['message']}")
                if entry.get('data'):
                    lines.append(f"  Data: {entry['data']}")
            output = "\n".join(lines)
        
        with open(destination, 'w') as f:
            f.write(output)
        
        return output
    
    def __repr__(self) -> str:
        stats = self.get_statistics()
        return (f"MissionLogger(mission={self.mission_name}, "
                f"entries={stats['total_entries']})")
