import logging
import os
import random
import shutil
import sys  # <-- import sys for excepthook
import time
from pathlib import Path

# Setup logging
from utils.constants import LOG_FOLDER
from utils.signal_utils import signal_manager

Path(LOG_FOLDER).mkdir(parents=True, exist_ok=True)

# Add a random number to the filename to avoid conflicts (no while loop)
rand_num = random.randint(1000, 9999)
file_path = f"{LOG_FOLDER}/log_{time.strftime('%Y-%m-%d_%H-%M-%S', time.localtime())}_{rand_num}.log"
LOG_FILE_PATH = file_path


def setup_logger(name: str = "logger", log_file_path: str = LOG_FILE_PATH) -> logging.Logger:
    logger = logging.getLogger(name)
    # Only configure if not already configured
    if not logger.handlers:
        logger.setLevel(logging.DEBUG)

        # Console handler and logging format
        console_handler = logging.StreamHandler()
        console_handler.setLevel(logging.INFO)
        console_formatter = logging.Formatter("%(message)s")  # Simple format for console
        console_handler.setFormatter(console_formatter)

        # File handler and logging format
        file_handler = logging.FileHandler(log_file_path)
        file_handler.setLevel(logging.DEBUG)
        file_formatter = logging.Formatter("%(asctime)s - %(levelname)s - %(message)s")
        file_handler.setFormatter(file_formatter)

        logger.addHandler(console_handler)
        logger.addHandler(file_handler)
        print(f"LOGGER INITIALIZED. Saving logs to: {log_file_path}")
    return logger


def save_log_file_path(save_dir: str) -> None:
    with open(os.path.join(save_dir, "log_files.txt"), "a+") as f:
        f.write(f"'{LOG_FILE_PATH}'\n")


def save_log_file(save_dir: str, log_filename: str = "log.txt") -> None:
    shutil.copy(LOG_FILE_PATH, os.path.join(save_dir, log_filename))


def cleanup_logs(log_dir: str = LOG_FOLDER) -> None:
    """
    Deletes all log files in the specified log directory that are empty or contain only whitespace.
    """
    log_directory = Path(log_dir)
    for log_file in log_directory.glob("*.log"):
        if log_file.is_file():
            # If the file is completely empty (0 bytes), delete it immediately.
            if log_file.stat().st_size == 0:
                # logger.info(f"Deleting empty log file: {log_file.name}")
                log_file.unlink()
                continue

            # Otherwise, read the file contents.
            try:
                with log_file.open("r", encoding="utf-8") as f:
                    content = f.read()
            except UnicodeDecodeError:
                # Fallback in case of decoding issues
                with log_file.open("r", encoding="latin-1") as f:
                    content = f.read()

            # Delete the file if it contains only whitespace.
            if content.strip() == "":
                # logger.info(f"Deleting whitespace-only log file: {log_file.name}")
                log_file.unlink()


# Create a default logger when module is imported
signal_manager.add_cleanup_function(cleanup_logs)
logger = setup_logger()


def handle_uncaught_exception(exc_type, exc_value, exc_traceback):
    """
    This function logs all uncaught exceptions other than KeyboardInterrupt.
    By setting sys.excepthook, any uncaught exceptions in the script
    importing this logger will be logged.
    """
    # Do not log KeyboardInterrupt as an error.
    if issubclass(exc_type, KeyboardInterrupt):
        sys.__excepthook__(exc_type, exc_value, exc_traceback)
        return
    logger.error("Uncaught exception", exc_info=(exc_type, exc_value, exc_traceback))


# Set the custom exception handler to log unhandled exceptions.
sys.excepthook = handle_uncaught_exception
