# FlightMonitor/controller/raw_data_logger.py
"""
Manages the creation and writing of raw data logs and summary reports.
This class is designed to be reusable for live, historical, and playback modes.
"""
import os
import json
from datetime import datetime, timezone
from typing import Optional, Dict, Any, TextIO

from flightmonitor.utils.logger import get_logger

module_logger = get_logger(__name__)


class RawDataLogger:
    """
    Handles file operations for a single data logging session.
    It creates and writes to a raw data file and a corresponding summary report.
    """

    def __init__(self):
        """Initializes the RawDataLogger."""
        self._raw_log_file: Optional[TextIO] = None
        self._report_file: Optional[TextIO] = None
        self._is_active: bool = False
        self.raw_log_filepath: Optional[str] = None
        self.report_filepath: Optional[str] = None
        module_logger.debug("RawDataLogger instance created.")

    @property
    def is_active(self) -> bool:
        """Returns True if a logging session is currently active."""
        return self._is_active

    def start_logging_session(
        self, target_directory: str, bounding_box: Dict[str, float]
    ) -> bool:
        """
        Starts a new logging session. Creates files and writes the report header.

        Args:
            target_directory (str): The directory where log files will be saved.
            bounding_box (Dict[str, float]): The bounding box for the session.

        Returns:
            bool: True if the session started successfully, False otherwise.
        """
        if self._is_active:
            module_logger.warning(
                "start_logging_session called while a session is already active. Please stop the current session first."
            )
            return False

        # --- MODIFICA CHIAVE ---
        # Risolve il percorso in un percorso assoluto per evitare ambiguità.
        # Questo garantisce che la cartella venga creata nel posto giusto.
        resolved_directory = os.path.abspath(target_directory)
        module_logger.info(f"Resolved logging directory to absolute path: {resolved_directory}")
        # --- FINE MODIFICA ---

        try:
            os.makedirs(resolved_directory, exist_ok=True)
        except OSError as e:
            module_logger.error(
                f"Failed to create target directory '{resolved_directory}': {e}"
            )
            return False

        now_utc = datetime.now(timezone.utc)
        timestamp_str = now_utc.strftime("%Y%m%d-%H%M%S")
        base_filename = f"atc-{timestamp_str}"

        self.raw_log_filepath = os.path.join(resolved_directory, f"{base_filename}.txt")
        self.report_filepath = os.path.join(
            resolved_directory, f"{base_filename}_report.txt"
        )

        try:
            # Open both files before setting the active state
            self._raw_log_file = open(self.raw_log_filepath, "w", encoding="utf-8")
            self._report_file = open(self.report_filepath, "w", encoding="utf-8")

            self._write_report_header(now_utc, bounding_box)
            self._is_active = True
            module_logger.info(f"Raw logging session started. File: {self.raw_log_filepath}")
            return True
        except IOError as e:
            module_logger.error(f"Failed to open log files for writing: {e}")
            self.stop_logging_session()  # Ensure cleanup if one file fails
            return False

    def _write_report_header(self, start_time: datetime, bbox: Dict[str, float]):
        """Writes the header information to the report file."""
        if not self._report_file:
            return

        self._report_file.write("--- Flight Monitor Session Report ---\n")
        self._report_file.write(f"Session Start (UTC): {start_time.strftime('%Y-%m-%d %H:%M:%S')}\n")
        self._report_file.write(f"Bounding Box:\n")
        self._report_file.write(f"  Lat Min: {bbox.get('lat_min')}\n")
        self._report_file.write(f"  Lon Min: {bbox.get('lon_min')}\n")
        self._report_file.write(f"  Lat Max: {bbox.get('lat_max')}\n")
        self._report_file.write(f"  Lon Max: {bbox.get('lon_max')}\n")
        self._report_file.write("\n--- Data Points ---\n")
        self._report_file.write(f"{'Timestamp (UTC)':<25} | {'Aircraft Count'}\n")
        self._report_file.write(f"{'-'*25} | {'-'*15}\n")

    def log_raw_data(self, raw_json_string: str):
        """
        Writes the raw JSON data string to the log file.

        Args:
            raw_json_string (str): The raw JSON string received from the provider.
        """
        if not self._is_active or not self._raw_log_file:
            # module_logger.warning("Attempted to log raw data, but no active session.")
            return

        try:
            # We assume the input is already a JSON string.
            # We add a newline to separate the JSON objects in the file.
            self._raw_log_file.write(raw_json_string + "\n")
        except IOError as e:
            module_logger.error(f"IOError while writing to raw log file: {e}")
            self.stop_logging_session() # Stop session on write error

    def log_summary_data(self, timestamp: float, aircraft_count: int):
        """
        Writes a summary line to the report file.

        Args:
            timestamp (float): The epoch timestamp of the data fetch.
            aircraft_count (int): The number of aircraft found in that fetch.
        """
        if not self._is_active or not self._report_file:
            # module_logger.warning("Attempted to log summary data, but no active session.")
            return

        try:
            dt_object = datetime.fromtimestamp(timestamp, timezone.utc)
            time_str = dt_object.strftime("%Y-%m-%d %H:%M:%S")
            self._report_file.write(f"{time_str:<25} | {aircraft_count}\n")
        except (IOError, ValueError) as e:
            module_logger.error(f"Error while writing to report file: {e}")
            self.stop_logging_session() # Stop session on write error

    def stop_logging_session(self):
        """
        Closes the log and report files and deactivates the session.
        """
        if not self._is_active:
            return

        module_logger.info("Raw logging session stopping.")
        self._is_active = False

        if self._raw_log_file:
            try:
                self._raw_log_file.close()
            except IOError as e:
                module_logger.error(f"Error closing raw log file: {e}")
            self._raw_log_file = None

        if self._report_file:
            try:
                self._report_file.write(f"\nSession End (UTC):   {datetime.now(timezone.utc).strftime('%Y-%m-%d %H:%M:%S')}\n")
                self._report_file.write("--- End of Report ---\n")
                self._report_file.close()
            except IOError as e:
                module_logger.error(f"Error closing report file: {e}")
            self._report_file = None
            
        self.raw_log_filepath = None
        self.report_filepath = None