from __future__ import annotations

import logging
import threading
from typing import Any, Dict, Optional

from .otlp_endpoints import signal_endpoint

LOGGER = logging.getLogger(__name__)

_handler = None
_provider = None
_target_logger: Optional[logging.Logger] = None
_lock = threading.Lock()


def attach_otel_log_handler(
    *,
    otlp_endpoint: str,
    otlp_protocol: str,
    headers: Optional[Dict[str, str]] = None,
    resource_attributes: Optional[Dict[str, Any]] = None,
    logger: Optional[logging.Logger] = None,
) -> Optional[LoggingHandler]:
    """Attach a native OTEL logging handler without altering existing handlers."""
    global _handler, _provider, _target_logger

    with _lock:
        if _handler is not None:
            return _handler

    try:
        from opentelemetry._logs import set_logger_provider
        from opentelemetry.sdk._logs import LoggerProvider, LoggingHandler
        from opentelemetry.sdk._logs.export import BatchLogRecordProcessor
        from opentelemetry.sdk.resources import Resource

        if otlp_protocol == "grpc":
            from opentelemetry.exporter.otlp.proto.grpc._log_exporter import (
                OTLPLogExporter,
            )

            exporter = OTLPLogExporter(endpoint=otlp_endpoint, headers=headers)
        else:
            from opentelemetry.exporter.otlp.proto.http._log_exporter import (
                OTLPLogExporter,
            )

            log_endpoint = signal_endpoint(otlp_endpoint, "logs")
            base_headers = dict(headers or {})
            base_headers.setdefault("stream-name", "highlighter_logs")
            exporter = OTLPLogExporter(endpoint=log_endpoint, headers=base_headers)

        resource = Resource(attributes=resource_attributes or {})
        provider = LoggerProvider(resource=resource)
        provider.add_log_record_processor(BatchLogRecordProcessor(exporter))
        set_logger_provider(provider)

        handler = LoggingHandler(level=logging.NOTSET, logger_provider=provider)
        target = logger or logging.getLogger()
        target.addHandler(handler)

        with _lock:
            if _handler is not None:
                target.removeHandler(handler)
                return _handler
            _provider = provider
            _handler = handler
            _target_logger = target
            return _handler
    except Exception as exc:
        LOGGER.warning("Failed to attach OTEL log handler: %s", exc)
        return None


def close_otel_log_handler() -> None:
    """Flush and detach the OTEL logging handler if it exists."""
    global _handler, _provider, _target_logger
    with _lock:
        handler = _handler
        provider = _provider
        target = _target_logger
        _handler = None
        _provider = None
        _target_logger = None
    if handler and target:
        try:
            target.removeHandler(handler)
        except Exception:
            LOGGER.debug("Failed to remove OTEL log handler")
    if provider:
        try:
            provider.shutdown()
        except Exception:
            LOGGER.debug("Failed to shutdown OTEL logger provider")
