import logging
from logging import Logger
from typing import Optional

from config.settings import (
    LOG_LEVEL,
    LOG_DIR,
    LOG_TO_FILE,
    LOG_TO_STDOUT,
)
from config.constants import DEFAULT_LOG_LEVEL


# Log Format
LOG_FORMAT = (
    "%(asctime)s | %(levelname)s | %(name)s | %(message)s"
)
DATE_FORMAT = "%Y-%m-%d %H:%M:%S"


# Internal State
_CONFIGURED = False


# Configuration
def configure_logging(force: bool = False) -> None:
    """
    Configures global logging behavior.
    """
    global _CONFIGURED

    if _CONFIGURED and not force:
        return

    root = logging.getLogger()
    root.setLevel(LOG_LEVEL or DEFAULT_LOG_LEVEL)

    # Clear existing handlers to avoid duplicates
    root.handlers.clear()

    formatter = logging.Formatter(
        fmt=LOG_FORMAT,
        datefmt=DATE_FORMAT,
    )

    if LOG_TO_STDOUT:
        stream_handler = logging.StreamHandler()
        stream_handler.setFormatter(formatter)
        root.addHandler(stream_handler)

    if LOG_TO_FILE:
        log_file = LOG_DIR / "ocf.log"
        file_handler = logging.FileHandler(log_file)
        file_handler.setFormatter(formatter)
        root.addHandler(file_handler)

    _CONFIGURED = True


# Logger Factory
def get_logger(
    name: str,
    *,
    ticker: Optional[str] = None,
) -> Logger:
    """
    Get a configured logger with optional contextual enrichment.
    """
    if not _CONFIGURED:
        configure_logging()

    logger = logging.getLogger(name)

    if ticker:
        return _ContextualLoggerAdapter(logger, {"ticker": ticker})

    return logger


# Contextual Adapter
class _ContextualLoggerAdapter(logging.LoggerAdapter):
    """
    Lightweight logger adapter to inject contextual fields (e.g. ticker) into log messages.
    """

    def process(self, msg, kwargs):
        context = " ".join(
            f"{k}={v}" for k, v in self.extra.items()
        )
        return f"[{context}] {msg}", kwargs