/*
 * Copyright The OpenTelemetry Authors
 * SPDX-License-Identifier: Apache-2.0
 */

package io.opentelemetry.javaagent.instrumentation.armeria.v1_3;

import com.linecorp.armeria.common.HttpRequest;
import com.linecorp.armeria.common.HttpResponse;
import com.linecorp.armeria.server.HttpService;
import com.linecorp.armeria.server.ServiceRequestContext;
import com.linecorp.armeria.server.SimpleDecoratingHttpService;
import io.opentelemetry.api.trace.Span;
import io.opentelemetry.api.trace.StatusCode;
import io.opentelemetry.context.Context;
import io.opentelemetry.instrumentation.api.instrumenter.ErrorCauseExtractor;
import io.opentelemetry.instrumentation.api.instrumenter.http.HttpRouteHolder;
import io.opentelemetry.instrumentation.api.instrumenter.http.HttpRouteSource;

class ServerDecorator extends SimpleDecoratingHttpService {

  ServerDecorator(HttpService delegate) {
    super(delegate);
  }

  @Override
  public HttpResponse serve(ServiceRequestContext ctx, HttpRequest req) throws Exception {
    String matchedRoute = ctx.config().route().patternString();
    if (matchedRoute == null || matchedRoute.isEmpty()) {
      matchedRoute = "/";
    } else if (!matchedRoute.startsWith("/")) {
      matchedRoute = "/" + matchedRoute;
    }

    Context otelContext = Context.current();

    HttpRouteHolder.updateHttpRoute(
        otelContext, HttpRouteSource.SERVLET, (context, name) -> name, matchedRoute);

    try {
      return unwrap().serve(ctx, req);
    } catch (Throwable throwable) {
      Span span = Span.fromContext(otelContext);
      span.setStatus(StatusCode.ERROR);
      span.recordException(ErrorCauseExtractor.getDefault().extract(throwable));

      throw throwable;
    }
  }
}
