import json
import logging
import sys
from datetime import datetime, timezone
from typing import Optional

TRAINING_LOGGER_NAME = "training"
TRAINING_COMPONENT = "training"
HEALTH_PATHS = ("/health", "/healthz", "/ready", "/readyz")


class JsonFormatter(logging.Formatter):
    """JSON-форматтер для парсинга в Yandex Cloud Logging (json_payload)."""

    def format(self, record: logging.LogRecord) -> str:
        payload = {
            "timestamp": datetime.now(timezone.utc).isoformat(),
            "level": record.levelname,
            "logger": record.name,
            "message": record.getMessage(),
        }
        component: Optional[str] = getattr(record, "component", None)
        if component:
            payload["component"] = component
            payload["message"] = f"[{component}] {payload['message']}"
        if record.exc_info:
            payload["exception"] = self.formatException(record.exc_info)
        return json.dumps(payload, ensure_ascii=False)


class ComponentFilter(logging.Filter):
    """Добавляет поле component в LogRecord для фильтрации в Cloud Logging."""

    def __init__(self, component: str) -> None:
        super().__init__()
        self.component = component

    def filter(self, record: logging.LogRecord) -> bool:
        record.component = self.component
        return True


class HealthCheckAccessFilter(logging.Filter):
    """Отсекает access-логи проб health/ready."""

    def filter(self, record: logging.LogRecord) -> bool:
        message = record.getMessage()
        return not any(path in message for path in HEALTH_PATHS)


def setup_logging(level: int = logging.INFO) -> None:
    """
    Настраивает корневое JSON-логирование и фильтр uvicorn.access для /health.

    Фильтры обучения в Yandex Cloud Logging:
    - json_payload.component = "training"
    - message: "[training]"
    """
    root = logging.getLogger()
    if getattr(root, "_size_model_logging_configured", False):
        ensure_access_filter()
        return
    root.handlers.clear()
    root.setLevel(level)
    handler = logging.StreamHandler(sys.stdout)
    handler.setFormatter(JsonFormatter())
    root.addHandler(handler)
    training_logger = logging.getLogger(TRAINING_LOGGER_NAME)
    training_logger.setLevel(level)
    training_logger.addFilter(ComponentFilter(TRAINING_COMPONENT))
    training_logger.propagate = True
    for name in ("uvicorn", "uvicorn.error", "uvicorn.access"):
        uv_logger = logging.getLogger(name)
        uv_logger.handlers.clear()
        uv_logger.propagate = True
    ensure_access_filter()
    root._size_model_logging_configured = True


def ensure_access_filter() -> None:
    access_logger = logging.getLogger("uvicorn.access")
    if not any(isinstance(f, HealthCheckAccessFilter) for f in access_logger.filters):
        access_logger.addFilter(HealthCheckAccessFilter())


def get_training_logger() -> logging.Logger:
    """Возвращает логгер обучения с component=training для Cloud Logging."""
    return logging.getLogger(TRAINING_LOGGER_NAME)
