# log_manager.py with queuing
import importlib
import json
import logging
import queue
from datetime import datetime, timezone
from logging.handlers import QueueHandler, QueueListener
from typing import Any

from common.iconfig import IBaseConfig

# from fenselogger.core.iconfig import IBaseConfig
# from fenselogger.core.iconfig import IBaseConfig

# from fformatter import FFormatter


class FFormatter(logging.Formatter):
    """'
    Custom Fense Log Formatting Class
    """

    def format(self, record):
        # log_record = LogRecord()
        log_record = {
            # "timestamp": datetime.fromtimestamp(
            #     record.created, tz=timezone.utc
            # ).isoformat(sep=" ", timespec="seconds"),
            "timestamp": datetime.now(timezone.utc).strftime("%Y-%m-%d"),
            "level": record.levelname,
            "module": record.module,
            "message": record.message,
        }

        extra = getattr(record, "extra", None)
        if extra:
            rec = extra.__dict__
            for k, v in rec.items():
                log_record[k] = v

        return json.dumps(log_record)


class ExtraLog:
    """
        Helper class to add additional fields to log.
        Note: send this object in the "extra" object\n

    Usage:\n
        one = ExtraLog()\n
        one.tenant_id = "tenA1123r"\n
        one.correlation_id = 11\n
        one.customer_name = "ABC Inc"\n
        one.provider_name = "Fortuna Cysec"\n
        logger.info("Discovery Scanning Started", extra={"extra": one})
    """

    def __init__(self):
        self.tenant_id: str
        """
        Tenant Id is mandatory value
        """
        self.correlation_id: str = None
        self.process_name: str = None
        self.sub_process_name: str = None
        self.status: str = None
        self.execution_time_ms: str = None
        self.key_data: dict = {}

    def addKeyData(self, key: str, value: str):
        """
        Add additional Key data to log
        """
        self.key_data[key] = value
        return self

    def toDict(self) -> Any:
        return self.__dict__


class LogManager:
    def __init__(self, config_provider: IBaseConfig, queue_size=1000):
        self.config_provider = config_provider
        self.logger = logging.getLogger("FenseLogger")
        self.logger.setLevel(logging.DEBUG)

        # Central queue for async logging
        self.log_queue = queue.Queue(maxsize=queue_size)

        # QueueHandler replaces direct handlers in logger
        self.queue_handler = QueueHandler(self.log_queue)
        self.logger.addHandler(self.queue_handler)

        # Background listener thread
        self.listener = None
        self._setup_listeners()

    def _setup_listeners(self):
        config = self.config_provider.load()
        formatter = FFormatter()

        handlers = []
        for target_name, target_cfg in config.get("targets", {}).items():
            if not target_cfg.get("enabled", False):
                continue

            # conn_module = f"src.fenselogger.loggers.{target_name}.connection"
            conn_module = f"fenselogger.loggers.{target_name}.connection"
            conn_class = f"F{
                (
                    ''.join([p.capitalize() for p in target_name.split('_')])
                    + 'Connection'
                )
            }"

            # handler_module = f"src.fenselogger.loggers.{target_name}.handler"
            handler_module = f"fenselogger.loggers.{target_name}.handler"
            handler_class = f"F{
                (''.join([p.capitalize() for p in target_name.split('_')]) + 'Handler')
            }"

            try:
                conn_mod = importlib.import_module(conn_module)
                conn_obj = getattr(conn_mod, conn_class)(
                    **target_cfg.get("options", {})
                )

                handler_mod = importlib.import_module(handler_module)
                handler_cls = getattr(handler_mod, handler_class)

                handler = handler_cls(conn_obj, **target_cfg.get("handlers", {}))

                handler.setFormatter(formatter)
                handlers.append(handler)

            except Exception as e:
                raise RuntimeError(f"Failed to load {target_name}: {e}")

        # Create background listener thread
        self.listener = QueueListener(
            self.log_queue, *handlers, respect_handler_level=True
        )
        self.listener.start()

    def get_logger(self):
        """
        Get the Logger to Start Logging
        """
        return self.logger

    def stop(self):
        """
        Stop the Queue Listener
        """
        if self.listener:
            self.listener.stop()
