import time
import signal
import sys
import threading
from datetime import datetime
from gps_handler import GPSHandler
from rtc_handler import RTCHandler
from signal_controller import SignalController
from logger import main_log, log_session_info
from config import TRANSMIT_TIME, PAUSE_TIME, FREQUENCY_HZ, DUTY_MODE, DEFAULT_LATITUDE, DEFAULT_LONGITUDE

# Global references for cleanup
signals = None
gps = None
rtc = None

def signal_handler(sig, frame):
    """Handle Ctrl+C gracefully"""
    timestamp = datetime.now().strftime("%H:%M:%S")
    print(f"\n[{timestamp}] [MAIN] Interrupt received, shutting down...")
    cleanup_and_exit()

def cleanup_and_exit():
    """Comprehensive cleanup before exit"""
    global signals
    if signals:
        signals.cleanup()
    else:
        # Fallback emergency cleanup
        from signal_controller import emergency_cleanup
        emergency_cleanup()
    
    timestamp = datetime.now().strftime("%H:%M:%S")
    print(f"[{timestamp}] [MAIN] Cleanup complete")
    sys.exit(0)

def get_current_time_source():
    """Determine and return the current time source and time"""
    global gps, rtc
    
    if gps and gps.has_good_signal() and gps.last_gps_time:
        return "GPS", gps.last_gps_time
    elif rtc and rtc.rtc_available:
        return "RTC", rtc.get_utc_time()
    else:
        return "SYSTEM", datetime.utcnow()

if __name__ == "__main__":
    try:
        # Set up signal handler for Ctrl+C
        signal.signal(signal.SIGINT, signal_handler)
        
        # Initialize RTC handler first
        rtc = RTCHandler()
        
        # Display and log RTC time at startup
        if rtc.rtc_available:
            rtc_time = rtc.read_rtc_time()
            if rtc_time:
                timestamp = datetime.now().strftime("%H:%M:%S")
                print(f"[{timestamp}] [RTC] Current RTC time: {rtc_time.strftime('%Y-%m-%d %H:%M:%S UTC')}")
                main_log(f"RTC startup time: {rtc_time.strftime('%Y-%m-%d %H:%M:%S UTC')}")
            else:
                timestamp = datetime.now().strftime("%H:%M:%S")
                print(f"[{timestamp}] [RTC] Warning: Could not read RTC time")
                main_log("Warning: Could not read RTC time at startup")
        else:
            timestamp = datetime.now().strftime("%H:%M:%S")
            print(f"[{timestamp}] [RTC] RTC not available")
            main_log("RTC not available at startup")
        
        # Initialize GPS handler with RTC reference
        gps = GPSHandler(rtc_handler=rtc)
        gps.connect()
        gps.start_reading()

        # Wait for GPS position with timeout
        timestamp = datetime.now().strftime("%H:%M:%S")
        print(f"[{timestamp}] [MAIN] Waiting for GPS position (60 second timeout)...")
        
        gps_timeout = time.time() + 60  # 1 minute timeout
        gps_available = False
        
        while gps.last_latlon is None and time.time() < gps_timeout:
            time.sleep(1)
        
        if gps.last_latlon is not None:
            gps_available = True
            timestamp = datetime.now().strftime("%H:%M:%S")
            print(f"[{timestamp}] [MAIN] GPS position acquired successfully")
        else:
            # GPS timeout - check if we can use RTC
            timestamp = datetime.now().strftime("%H:%M:%S")
            print(f"[{timestamp}] [MAIN] GPS timeout after 60 seconds")
            main_log("GPS position timeout after 60 seconds")
            
            if rtc.rtc_available:
                rtc_time = rtc.read_rtc_time()
                if rtc_time and rtc_time.year > 2020:  # Sanity check - time should be reasonable
                    timestamp = datetime.now().strftime("%H:%M:%S")
                    print(f"[{timestamp}] [MAIN] Using RTC time for operation: {rtc_time.strftime('%Y-%m-%d %H:%M:%S UTC')}")
                    main_log(f"Proceeding with RTC time only: {rtc_time.strftime('%Y-%m-%d %H:%M:%S UTC')}")
                    
                    # Set a default position from configuration
                    gps.last_latlon = (DEFAULT_LATITUDE, DEFAULT_LONGITUDE)
                    timestamp = datetime.now().strftime("%H:%M:%S")
                    print(f"[{timestamp}] [MAIN] Using default position: Lat {DEFAULT_LATITUDE:.6f}, Lon {DEFAULT_LONGITUDE:.6f}")
                    main_log(f"Using default position: Lat {DEFAULT_LATITUDE:.6f}, Lon {DEFAULT_LONGITUDE:.6f}")
                else:
                    timestamp = datetime.now().strftime("%H:%M:%S")
                    print(f"[{timestamp}] [MAIN] ERROR: RTC time invalid ({rtc_time}), cannot proceed without GPS")
                    main_log(f"ERROR: RTC time invalid ({rtc_time}), cannot proceed")
                    sys.exit(1)
            else:
                timestamp = datetime.now().strftime("%H:%M:%S")
                print(f"[{timestamp}] [MAIN] ERROR: No GPS position and no RTC available, cannot proceed")
                main_log("ERROR: No GPS position and no RTC available")
                sys.exit(1)

        # Wait for minute synchronization
        if gps_available and gps.has_good_signal():
            gps.wait_for_next_minute()
        elif rtc.rtc_available:
            timestamp = datetime.now().strftime("%H:%M:%S")
            print(f"[{timestamp}] [MAIN] Using RTC for minute synchronization")
            main_log("Using RTC for minute synchronization (no GPS available)")
            rtc.wait_for_next_minute_rtc()
        else:
            timestamp = datetime.now().strftime("%H:%M:%S")
            print(f"[{timestamp}] [MAIN] WARNING: No precision timing available, proceeding immediately")
            main_log("WARNING: No precision timing available")

        # Log session configuration with time source info
        time_source, current_time = get_current_time_source()
        lat, lon = gps.last_latlon
        
        log_session_info(
            gps_time=current_time.strftime("%Y-%m-%d %H:%M:%S UTC"),
            latitude=lat, 
            longitude=lon, 
            frequency=FREQUENCY_HZ, 
            transmit_time=TRANSMIT_TIME, 
            pause_time=PAUSE_TIME
        )
        
        # Log additional session info about duty mode and time source
        main_log(f"Duty mode: {DUTY_MODE}")
        main_log(f"Time source: {time_source}")
        if rtc.rtc_available:
            main_log("RTC (DS3231) available as backup timing source")
        else:
            main_log("Warning: No RTC available - system time will be used as fallback")

        # Initialize signal controller
        signals = SignalController()

        while True:
            # Check and log time source changes
            time_source, current_time = get_current_time_source()
            
            # Get and display current position for this transmission
            gps.get_position_for_transmission()
            
            main_log(f"Starting transmission (Time source: {time_source})")
            signals.transmit(TRANSMIT_TIME)

            main_log("Pausing")
            time.sleep(PAUSE_TIME)
            
    except KeyboardInterrupt:
        print("\n[MAIN] KeyboardInterrupt caught")
        cleanup_and_exit()
    except Exception as e:
        print(f"\n[MAIN] Unexpected error: {e}")
        cleanup_and_exit()
    finally:
        # Final safety net
        if signals:
            signals.cleanup()
        else:
            from signal_controller import emergency_cleanup
            emergency_cleanup()