import os
import base64

from contextlib import contextmanager

_TRACING_ENABLED = os.getenv(
    "ENABLE_TRACING",
    "false"
).lower() == "true"

tracer = None

if _TRACING_ENABLED:

    try:

        from opentelemetry import trace

        from opentelemetry.sdk.trace import (
            TracerProvider
        )

        from opentelemetry.sdk.resources import (
            Resource
        )

        from opentelemetry.sdk.trace.export import (
            BatchSpanProcessor
        )

        from opentelemetry.exporter.otlp.proto.http.trace_exporter import (
            OTLPSpanExporter
        )

        endpoint = os.getenv(
            "OTEL_EXPORTER_OTLP_ENDPOINT",
            "http://localhost:8087/api/public/otel/v1/traces"
        )

        # -----------------------------------
        # LANGFUSE AUTH
        # -----------------------------------

        public_key = os.getenv(
            "LANGFUSE_PUBLIC_KEY"
        )

        secret_key = os.getenv(
            "LANGFUSE_SECRET_KEY"
        )

        headers = {}

        if public_key and secret_key:

            auth = base64.b64encode(
                f"{public_key}:{secret_key}".encode()
            ).decode()

            headers["Authorization"] = (
                f"Basic {auth}"
            )

        # -----------------------------------
        # RESOURCE
        # -----------------------------------

        resource = Resource.create({
            "service.name":
                "nemo_guardrails_governed_project"
        })

        provider = TracerProvider(
            resource=resource
        )

        exporter = OTLPSpanExporter(
            endpoint=endpoint,
            headers=headers,
            timeout=5
        )

        span_processor = BatchSpanProcessor(
            exporter
        )

        provider.add_span_processor(
            span_processor
        )

        if not isinstance(
                trace.get_tracer_provider(),
                TracerProvider
        ):
            trace.set_tracer_provider(provider)

        tracer = trace.get_tracer(__name__)

        print(
            f"[Tracing Enabled] endpoint={endpoint}"
        )

    except Exception as e:

        print(
            f"[Tracing Disabled] Error: {e}"
        )

        tracer = None


@contextmanager
def span(name: str, **attrs):

    if tracer is None:
        yield None
        return

    try:

        with tracer.start_as_current_span(name) as sp:

            for k, v in attrs.items():

                if isinstance(
                        v,
                        (str, int, float, bool)
                ):
                    sp.set_attribute(k, v)

                else:
                    sp.set_attribute(k, str(v))

            yield sp

    except Exception as e:

        print(
            f"[Tracing Error] Span '{name}' failed: {e}"
        )

        yield None
