import logging
import os

from . import fastapi
from e80_sdk.internal.httpx_async import async_client
from contextlib import asynccontextmanager
from opentelemetry.trace import set_tracer_provider
from opentelemetry.metrics import set_meter_provider
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import BatchSpanProcessor
from opentelemetry.sdk.metrics import MeterProvider
from opentelemetry.sdk.metrics.export import PeriodicExportingMetricReader
from opentelemetry.sdk.resources import SERVICE_NAME, Resource
from opentelemetry.sdk._logs import LoggerProvider, LoggingHandler
from opentelemetry.sdk._logs.export import BatchLogRecordProcessor
from opentelemetry.exporter.otlp.proto.http.trace_exporter import OTLPSpanExporter
from opentelemetry.exporter.otlp.proto.http.metric_exporter import OTLPMetricExporter
from opentelemetry.exporter.otlp.proto.http._log_exporter import OTLPLogExporter
from opentelemetry.instrumentation.fastapi import FastAPIInstrumentor

from opentelemetry._logs import set_logger_provider


otel_collector_url = os.environ.get("8080_OTEL_COLLECTOR_URL")

if otel_collector_url is not None:
    project_slug = os.environ["8080_PROJECT_SLUG"]

    resource = Resource.create(attributes={SERVICE_NAME: project_slug})
    tracer_provider = TracerProvider(resource=resource)
    tracer_provider.add_span_processor(
        BatchSpanProcessor(OTLPSpanExporter(endpoint=f"{otel_collector_url}/v1/traces"))
    )
    set_tracer_provider(tracer_provider)

    meter_provider = MeterProvider(
        resource=resource,
        metric_readers=[
            PeriodicExportingMetricReader(
                OTLPMetricExporter(endpoint=f"{otel_collector_url}/v1/metrics")
            )
        ]
        if otel_collector_url
        else [],
    )
    set_meter_provider(meter_provider)

    log_exporter = OTLPLogExporter(endpoint=f"{otel_collector_url}/v1/logs")
    logger_provider = LoggerProvider(resource=resource)
    logger_provider.add_log_record_processor(BatchLogRecordProcessor(log_exporter))
    handler = LoggingHandler(level=logging.INFO, logger_provider=logger_provider)

    # Make sure to add logging for OpenTelemetry
    # and logging handler.
    set_logger_provider(logger_provider)

    stream_handler = logging.StreamHandler()
    logging.basicConfig(
        level=logging.INFO,
        format="%(asctime)s - %(levelname)s - %(message)s",
        handlers=[handler, stream_handler],
    )


logger = logging.getLogger(__name__)

_EIGHTY80_HEALTH_CHECK_PATH = "/.8080/health"


def eighty80_app() -> fastapi.FastAPI:
    eighty80_app = fastapi.FastAPI()
    FastAPIInstrumentor.instrument_app(
        eighty80_app,
        excluded_urls=_EIGHTY80_HEALTH_CHECK_PATH,
    )

    eighty80_app.get(_EIGHTY80_HEALTH_CHECK_PATH)(_eighty80_health_check)

    return eighty80_app


async def _eighty80_health_check():
    return {"status": "ok"}


@asynccontextmanager
async def lifespan(app: fastapi.FastAPI):
    yield
    await async_client.aclose()
