"""Project-facing wrapper around the RapidKit vendor logging runtime."""

from __future__ import annotations

import importlib.util
import os
import sys
from functools import lru_cache
from pathlib import Path
from types import ModuleType
from typing import Any, Dict

_VENDOR_MODULE = "{{ rapidkit_vendor_module }}"
_VENDOR_VERSION = "{{ rapidkit_vendor_version }}"
_VENDOR_RELATIVE_PATH = "{{ rapidkit_vendor_relative_path }}"
_VENDOR_ROOT_ENV = "RAPIDKIT_VENDOR_ROOT"
_CACHE_PREFIX = "rapidkit_vendor_"
_REQUEST_CONTEXT_ENABLED = {{ 'True' if logging_request_context_enabled | default(true) else 'False' }}


def _project_root() -> Path:
    return Path(__file__).resolve().parents[5]


def _vendor_root() -> Path:
    override = os.getenv(_VENDOR_ROOT_ENV)
    if override:
        return Path(override).expanduser().resolve()
    return _project_root() / ".rapidkit" / "vendor"


def _vendor_base_dir() -> Path:
    root = _vendor_root()
    module_dir = root / _VENDOR_MODULE
    preferred = module_dir / _VENDOR_VERSION if _VENDOR_VERSION else None
    if preferred and preferred.exists():
        return preferred
    candidates = sorted(
        (p for p in module_dir.glob("*") if p.is_dir()),
        reverse=True,
    )
    if candidates:
        return candidates[0]
    raise RuntimeError(
        "RapidKit vendor payload for '{module}' not found under {root}. "
        "Re-run `rapidkit modules install {module}`.".format(
            module=_VENDOR_MODULE, root=root
        )
    )


def _vendor_file() -> Path:
    return _vendor_base_dir() / _VENDOR_RELATIVE_PATH


@lru_cache(maxsize=1)
def _load_vendor_module() -> ModuleType:
    vendor_path = _vendor_file()
    if not vendor_path.exists():
        raise RuntimeError(
            "RapidKit vendor logging file missing at {path}. "
            "Re-run `rapidkit modules install {module}`.".format(
                path=vendor_path,
                module=_VENDOR_MODULE,
            )
        )

    module_name = _CACHE_PREFIX + _VENDOR_MODULE.replace("/", "_") + "_logging"

    spec = importlib.util.spec_from_file_location(module_name, vendor_path)
    if spec is None or spec.loader is None:
        raise RuntimeError(f"Unable to load vendor logging module from {vendor_path}")

    module = importlib.util.module_from_spec(spec)
    sys.modules.setdefault(module_name, module)
    spec.loader.exec_module(module)
    return module


def _resolve_export(name: str):
    vendor = _load_vendor_module()
    try:
        return getattr(vendor, name)
    except AttributeError as exc:  # pragma: no cover - defensive against drift
        raise RuntimeError(f"Vendor module missing attribute '{name}'") from exc


def refresh_vendor_module() -> None:
    """Clear vendor import caches (useful after module upgrades)."""

    _load_vendor_module.cache_clear()


# Exported APIs delegated to vendor implementation
get_logger = _resolve_export("get_logger")
LoggingConfig = _resolve_export("LoggingConfig")
OTelBridgeHandler = _resolve_export("OTelBridgeHandler")
MetricsBridgeHandler = _resolve_export("MetricsBridgeHandler")
NoiseFilter = _resolve_export("NoiseFilter")
RedactionFilter = _resolve_export("RedactionFilter")
ContextEnricher = _resolve_export("ContextEnricher")
JsonFormatter = _resolve_export("JsonFormatter")
ColoredFormatter = _resolve_export("ColoredFormatter")
create_stream_handler = _resolve_export("create_stream_handler")
create_file_handler = _resolve_export("create_file_handler")
create_syslog_handler = _resolve_export("create_syslog_handler")
create_queue_handler = _resolve_export("create_queue_handler")
setup_queue_listeners = _resolve_export("setup_queue_listeners")
shutdown_queue = _resolve_export("shutdown_queue")


if _REQUEST_CONTEXT_ENABLED:
    set_request_context = _resolve_export("set_request_context")
    RequestContextMiddleware = _resolve_export("RequestContextMiddleware")
else:  # pragma: no cover - defensive stub when overrides disable middleware

    def set_request_context(*args: Any, **kwargs: Any) -> None:
        raise RuntimeError(
            "Request context propagation disabled via generator overrides."
        )

    class RequestContextMiddleware:  # type: ignore[too-many-ancestors]
        def __init__(self, *args: Any, **kwargs: Any) -> None:  # noqa: D401
            raise RuntimeError(
                "Request context middleware disabled via generator overrides."
            )


def get_logging_metadata() -> Dict[str, Any]:
    """Return vendor metadata for observability dashboards."""

    vendor = _load_vendor_module()
    return {
        "module": _VENDOR_MODULE,
        "version": _VENDOR_VERSION,
        "available": sorted(getattr(vendor, "__all__", [])),
    }


try:  # Optional override contracts (used by enterprise deployments)
    from core.services.override_contracts import apply_module_overrides
except ImportError:  # pragma: no cover - override system optional
    apply_module_overrides = None

if apply_module_overrides is not None:  # pragma: no branch - tiny guard
    apply_module_overrides(sys.modules[__name__], "logging")


__all__ = [
    "get_logger",
    "set_request_context",
    "RequestContextMiddleware",
    "LoggingConfig",
    "OTelBridgeHandler",
    "MetricsBridgeHandler",
    "NoiseFilter",
    "RedactionFilter",
    "ContextEnricher",
    "JsonFormatter",
    "ColoredFormatter",
    "create_stream_handler",
    "create_file_handler",
    "create_syslog_handler",
    "create_queue_handler",
    "setup_queue_listeners",
    "shutdown_queue",
    "get_logging_metadata",
    "refresh_vendor_module",
]
