# FlightMonitor/controller/historical_data_processor.py
"""
Manages the processing of historical flight data from the adapter's output queue.
It updates the GUI's virtual clock and dispatches flight states to the map.
"""
from queue import Queue, Empty as QueueEmpty
from typing import Optional, TYPE_CHECKING

from flightmonitor.utils.logger import get_logger
from flightmonitor.data.opensky_live_adapter import AdapterMessage, MSG_TYPE_FLIGHT_DATA, MSG_TYPE_ADAPTER_STATUS, STATUS_STOPPED

if TYPE_CHECKING:
    from flightmonitor.controller.app_controller import AppController

module_logger = get_logger(__name__)

# Intervallo con cui il processore controlla la coda dei dati storici
GUI_QUEUE_CHECK_INTERVAL_MS = 100

class HistoricalDataProcessor:
    """
    Processes historical flight data snapshots from a queue, updating the GUI
    (virtual clock, map) for each snapshot.
    """

    def __init__(self, app_controller: "AppController", data_queue: Queue[AdapterMessage]):
        """
        Initializes the HistoricalDataProcessor.

        Args:
            app_controller: The main AppController instance.
            data_queue: The queue from which to read historical data snapshots.
        """
        self.app_controller = app_controller
        self.data_queue = data_queue
        self._gui_after_id: Optional[str] = None
        module_logger.debug("HistoricalDataProcessor initialized.")

    def start_processing(self):
        """Starts the periodic processing of the historical data queue."""
        main_window = self.app_controller.main_window
        if not (main_window and main_window.root and main_window.root.winfo_exists()):
            module_logger.error("HistoricalDataProcessor: Cannot start queue processing, MainWindow or root is missing.")
            return

        if self._gui_after_id:
            try:
                main_window.root.after_cancel(self._gui_after_id)
            except Exception: pass

        module_logger.info("HistoricalDataProcessor: Starting historical data queue processing loop.")
        self._gui_after_id = main_window.root.after(GUI_QUEUE_CHECK_INTERVAL_MS, self._process_queue_cycle)

    def stop_processing(self):
        """Stops the periodic processing loop."""
        main_window = self.app_controller.main_window
        if self._gui_after_id and main_window and main_window.root.winfo_exists():
            try:
                main_window.root.after_cancel(self._gui_after_id)
                module_logger.info("HistoricalDataProcessor: Stopped queue processing loop.")
            except Exception: pass
            finally:
                self._gui_after_id = None
        
        # Svuota la coda da eventuali messaggi residui per evitare elaborazioni fantasma
        if self.data_queue:
            while not self.data_queue.empty():
                try:
                    self.data_queue.get_nowait()
                except QueueEmpty:
                    break

    def _process_queue_cycle(self):
        """
        The core processing cycle that runs on the GUI thread.
        It retrieves a data snapshot, updates the clock, and updates the map.
        """
        main_window = self.app_controller.main_window
        data_storage = self.app_controller.data_storage

        if not (main_window and main_window.root and main_window.root.winfo_exists()):
            self._gui_after_id = None
            return

        try:
            # Estraiamo un solo messaggio (snapshot) alla volta per creare l'effetto di avanzamento
            message = self.data_queue.get_nowait()
            
            message_type = message.get("type")
            
            if message_type == MSG_TYPE_FLIGHT_DATA:
                snapshot_timestamp = message.get("timestamp")
                flight_states = message.get("payload", [])

                # Aggiorna sempre l'orologio virtuale per mostrare il progresso
                if snapshot_timestamp and hasattr(main_window, "function_notebook_panel") and main_window.function_notebook_panel.historical_panel:
                    main_window.function_notebook_panel.historical_panel.update_virtual_clock(snapshot_timestamp)

                # --- INIZIO MODIFICA ---
                # Controlla se sono stati trovati aerei in questo snapshot
                if flight_states:
                    # Se ci sono dati, salvali e aggiorna la mappa
                    if data_storage:
                        for state in flight_states:
                            flight_id = data_storage.add_or_update_flight_daily(
                                icao24=state.icao24, callsign=state.callsign,
                                origin_country=state.origin_country, detection_timestamp=state.timestamp
                            )
                            if flight_id:
                                data_storage.add_position_daily(flight_id, state)
                    
                    if main_window.map_manager_instance:
                        main_window.map_manager_instance.update_flights_on_map(flight_states)
                else:
                    # Se non ci sono dati, aggiorna solo il messaggio di stato per dare feedback
                    if main_window and hasattr(main_window, 'update_semaphore_and_status'):
                        from ..utils.gui_utils import GUI_STATUS_FETCHING
                        from datetime import datetime
                        
                        dt_object = datetime.fromtimestamp(snapshot_timestamp)
                        time_str = dt_object.strftime("%H:%M:%S")
                        
                        main_window.update_semaphore_and_status(
                            GUI_STATUS_FETCHING,
                            f"No flights found at {time_str}. Continuing scan..."
                        )
                # --- FINE MODIFICA ---
            
            elif message_type == MSG_TYPE_ADAPTER_STATUS:
                if message.get("status_code") == STATUS_STOPPED:
                    module_logger.info("Historical adapter finished. Stopping historical download from processor.")
                    self.app_controller.stop_historical_download(finished_normally=True)

            self.data_queue.task_done()

        except QueueEmpty:
            # La coda è vuota, è normale. Aspettiamo il prossimo ciclo.
            pass
        except Exception as e:
            module_logger.error(f"Error in HistoricalDataProcessor cycle: {e}", exc_info=True)
            self.app_controller.stop_historical_download(from_error=True)

        # Ripianifica il prossimo controllo se il download è ancora attivo
        if self.app_controller.is_historical_download_active:
            self._gui_after_id = main_window.root.after(GUI_QUEUE_CHECK_INTERVAL_MS, self._process_queue_cycle)
        else:
            self._gui_after_id = None