#!/usr/bin/env python
'''
@file __init__.py

@brief Initialize the logging setting and switch the log file.

Copyright (C) Atmosic 2024
'''
from __future__ import annotations
import sys
import logging, logging.config
from datetime import datetime
from pathlib import Path
from typing import List
import os
from shutil import copytree

from .handler.async_file_handler import AsyncFileHandler
from .color_format import ColorFormatter


root_log_folder = Path("logs")
base_log_folder = root_log_folder / "tool"
fail_log_folder = root_log_folder / "tool_fail"
def start_new_session(title=None):
    """Start a new logging session with optional title"""
    timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
    folder_name = f"{timestamp}_{title}"
    session_folder = base_log_folder / folder_name

    async_file_handlers: List[AsyncFileHandler] = []
    for handler in logging.root.handlers:
        if not isinstance(handler, AsyncFileHandler):
            continue
        async_file_handlers.append(handler)

    if len(async_file_handlers) == 1:
        h = async_file_handlers[0]
        tool_log_filepath = session_folder / "tool_detail.log"
        if Path(h.baseFilename).parent.absolute() == base_log_folder.absolute():
            h.move_file(tool_log_filepath)
        else:
            h.switch_file(tool_log_filepath)
    elif len(async_file_handlers) > 1:
        for h in async_file_handlers:
            h.switch_folder(session_folder)

def start_retry_session(retry_lable: str):
    """Start a retry logging session in the same folder with retry label"""

    for handler in logging.root.handlers:
        if not isinstance(handler, AsyncFileHandler):
            continue
        base_log_folder = Path(handler.baseFilename).parent
        new_filename = base_log_folder / f"{retry_lable}.log"
        handler.switch_file(new_filename)

def set_console_log_level(level):
    """Set console handler log level"""
    for handler in logging.root.handlers:
        if not isinstance(handler, logging.StreamHandler):
            continue
        if handler.stream != sys.stdout:
            continue
        handler.setLevel(level)

def get_logging_config():
    """
    Generate logging dictConfig that matches AtmosicLogger behavior.
    
    Returns:
        dict: Configuration dict for logging.config.dictConfig()
    """
    # Calculate paths (matching AtmosicLogger logic)
    base_log_folder = Path("logs/tool")
    timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
    pid = os.getpid()
    
    # Importing log (temporary, before session starts)
    importing_log = base_log_folder / f"importing_{timestamp}_PID{pid}.log"
    
    # Ensure directories exist
    base_log_folder.mkdir(parents=True, exist_ok=True)
    
    return {
        "version": 1,
        "disable_existing_loggers": False,
        
        # Custom formatter classes
        "formatters": {
            "color_console": {
                "()": ColorFormatter,
            },
            "detailed": {
                "format": "%(asctime)s - %(levelname)s - %(filename)s:%(lineno)d - %(message)s"
            },
            "raw": {
                "format": "%(message)s"
            }
        },
        
        # Custom handler classes
        "handlers": {
            "console": {
                "class": "logging.StreamHandler",
                "level": "INFO",
                "formatter": "color_console",
                "stream": "ext://sys.stdout"
            },
            "tool_detail_file": {
                "()": AsyncFileHandler,
                "filename": str(importing_log),
                "mode": "a",
                "encoding": "utf-8",
                "delay": True,
                "level": "DEBUG",
                "formatter": "detailed"
            },
        },

        "loggers" :{
            "uart": {
                "level": "DEBUG",
                "handlers": [],
                "propagate": False
            },
            "packet": {
                "level": "DEBUG",
                "handlers": [],
                "propagate": False
            }
        },
        
        # Root logger (for new per-module loggers)
        "root": {
            "level": "DEBUG",
            "handlers": ["console", "tool_detail_file"]
        }
    }

def setup_config():
    config = get_logging_config()
    logging.config.dictConfig(config)


def close_all_handler():
    for handler in logging.root.handlers:
        handler.flush()
        handler.close()

    logger_dict = logging.Logger.manager.loggerDict
    for _, logger_obj in logger_dict.items():
        if not isinstance(logger_obj, logging.Logger):
            continue
        for handler in logger_obj.handlers:
            handler.flush()
            handler.close()

def copy_fail_logs(handler: AsyncFileHandler, error_code: int):
    base_folder = Path(handler.baseFilename).parent.name
    error_code_folder = fail_log_folder / str(error_code) / base_folder
    log_folder = handler.get_log_folder()
    
    error_code_folder.mkdir(parents=True, exist_ok=True)
    copytree(log_folder, error_code_folder, dirs_exist_ok=True)

def copy_fail_log_to_fail_folder(error_code: int):
    print(f"Copy fail log to fail folder {error_code}")
    for handler in logging.root.handlers:
        if not isinstance(handler, AsyncFileHandler):
            continue
        copy_fail_logs(handler, error_code)

    logger_dict = logging.Logger.manager.loggerDict
    for _, logger_obj in logger_dict.items():
        if not isinstance(logger_obj, logging.Logger):
            continue
        for handler in logger_obj.handlers:
            if not isinstance(handler, AsyncFileHandler):
                continue
            copy_fail_logs(handler, error_code)