"""OpenTelemetry tracing setup with auto-instrumentation."""

from opentelemetry import trace
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import BatchSpanProcessor
from opentelemetry.exporter.otlp.proto.grpc.trace_exporter import OTLPSpanExporter
from opentelemetry.instrumentation.fastapi import FastAPIInstrumentor
from opentelemetry.instrumentation.sqlalchemy import SQLAlchemyInstrumentor
from opentelemetry.sdk.resources import Resource, SERVICE_NAME

from settings import settings


_initialized = False


def init_tracing(app, engine=None):
    """Initialize OpenTelemetry tracing.

    Call this in your FastAPI lifespan function.

    Args:
        app: FastAPI application instance
        engine: SQLAlchemy async engine (optional)
    """
    global _initialized

    if _initialized:
        return

    if not settings.metrics_enabled:
        return

    resource = Resource(attributes={SERVICE_NAME: settings.otel_service_name})

    provider = TracerProvider(resource=resource)
    processor = BatchSpanProcessor(
        OTLPSpanExporter(endpoint=settings.otel_exporter_otlp_endpoint, insecure=True)
    )
    provider.add_span_processor(processor)
    trace.set_tracer_provider(provider)

    # Auto-instrument FastAPI
    FastAPIInstrumentor.instrument_app(app)

    # Auto-instrument SQLAlchemy if engine provided
    if engine:
        SQLAlchemyInstrumentor().instrument(engine=engine.sync_engine)

    _initialized = True


def shutdown_tracing():
    """Shutdown tracing and flush pending spans."""
    provider = trace.get_tracer_provider()
    if hasattr(provider, "shutdown"):
        provider.shutdown()


def get_tracer(name: str):
    """Get a tracer for creating custom spans.

    Example:
        tracer = get_tracer(__name__)

        async def process_order(order_id: str):
            with tracer.start_as_current_span("process_order") as span:
                span.set_attribute("order.id", order_id)
                # ... business logic
    """
    return trace.get_tracer(name)
