package middleware

import (
	"github.com/gin-gonic/gin"
	"base-gin/utils/base"
	"net/http"

	"github.com/opentracing/opentracing-go"
	"github.com/opentracing/opentracing-go/ext"
)

func Tracer() gin.HandlerFunc {
	return func(ctx *gin.Context) {
		span := base.TracerStartSpan(getSpanContextFromRequest(ctx.Request), "HTTP_"+ctx.Request.URL.Path, getSpanTagsByHttpServer(ctx.Request))
		defer span.Finish()
		ctx.Set(base.TraceContextKey, span)
		ctx.Set("requestId", base.GetRequestIdFromTrace(ctx))

		ctx.Next()

		render, exist := ctx.Get("render")
		retCode := 0
		if exist {
			retCode = render.(base.TRenderJson).ReturnCode
		}
		span.SetTag("retCode", retCode)
		span.SetTag(string(ext.HTTPStatusCode), ctx.Writer.Status())
	}
}

func TracerBeforeRun(ctx *gin.Context) {
	ctx.Set("requestId", base.GetRequestIdFromTrace(ctx))
}

func TracerAfterRun(ctx *gin.Context) {
	retCode := 0
	if ctx.Err().Error != nil {
		retCode = -1
	}

	tempSpan, exist := ctx.Get(base.TraceContextKey)
	if exist {
		span := tempSpan.(opentracing.Span)
		span.SetTag("retCode", retCode)
		span.Finish()
	}
}

func getSpanContextFromRequest(req *http.Request) (spanContext opentracing.SpanContext) {
	if req.Header != nil {
		spanContext, _ = opentracing.GlobalTracer().Extract(opentracing.HTTPHeaders, opentracing.HTTPHeadersCarrier(req.Header))
	}
	return spanContext
}

func getSpanTagsByHttpServer(req *http.Request) map[string]interface{} {
	return map[string]interface{}{
		ext.SpanKindRPCServer.Key: ext.SpanKindRPCServer.Value,
		string(ext.HTTPMethod):    req.Method,
		string(ext.HTTPUrl):       req.URL.Path,
	}
}