package workflow

import (
	"context"
	"encoding/hex"
	"encoding/json"

	"github.com/tidbcloud/fastflow/pkg/entity/run"
	"github.com/tidbcloud/tiinf/monitor/tilog"
	"go.opentelemetry.io/otel"
	"go.opentelemetry.io/otel/trace"
	"go.uber.org/zap"

	"github.com/tidbcloud/tidb-management-service/utilities/grpc/metadata"
)

var tracer = otel.Tracer("Domain.Workflow")

func GetTraceId(ctx context.Context) string {
	spanCtx := trace.SpanContextFromContext(ctx)
	if spanCtx.HasTraceID() {
		return spanCtx.TraceID().String()
	}
	return "" // test trace id
}

func GenerateContext(ctx run.ExecuteContext) (context.Context, trace.Span) {
	spanName, _ := ctx.GetVar(KeySpanName)
	traceId, _ := ctx.GetVar(KeyTraceId)
	if spanName == "" {
		spanName = "Unknown"
	}

	cctx, span := tracer.Start(ctx.Context(), spanName)
	if traceId != "" {
		traceIdHex, err := hex.DecodeString(traceId)
		if err != nil {
			tilog.Error(cctx, "decode traceId failed", zap.Error(err))
		} else {
			cctx = trace.ContextWithSpanContext(cctx, span.SpanContext().WithTraceID(trace.TraceID(traceIdHex)))
		}
	}

	// request metadata
	requestMetaJson, _ := ctx.GetVar(KeyRequestMeta)
	if requestMetaJson != "" {
		var requestMeta metadata.RequestMeta
		err := json.Unmarshal([]byte(requestMetaJson), &requestMeta)
		if err != nil {
			tilog.Error(
				cctx,
				"failed to unmarshal request meta ",
				zap.String("request meta", requestMetaJson),
				zap.Error(err),
			)
		} else {
			cctx = metadata.AppendToOutgoingMeta(cctx, &requestMeta)
		}
	}

	return cctx, span
}
