package consts

import (
	"context"
	"errors"
	"strings"

	"go.opentelemetry.io/otel/trace"
)

const (
	uiRequestKey        = "/api"
	uiVersionKey        = "/v2023"
	nextGenUiVersionKey = "/v2025/cloud"

	ProjectIdKey = "projectId"
	OrgIdKey     = "orgId"
	ClusterIdKey = "clusterId"
	TidbIdKey    = "tidbId"

	// grpc error
	Fallback = `{"code": 59900104, "message": "failed to marshal error message"}`

	Domain    = "tidbapi.com"
	DomainKey = "domain.tidbapi.com"

	// for rabc
	RBACOrgIdKey          = "org_id"
	RBACProjectIdKey      = "project_id"
	RBACClusterIdKey      = "cluster_id"
	RBACShadowPoolIdKey   = "shadow_pool_id"
	RBACTidbIdKey         = "tidb_id"
	RBACResourcePoolIdKey = "resource_pool_id"
)

var (
	// error msg
	ErrNoRoute           = errors.New("invalid path")
	ErrUnauthenticated   = errors.New("access denied. Please login or provide valid credentials")
	ErrResourceNotFound  = errors.New("resource not found")
	ErrPermissionDenied  = errors.New("API key or the user does not have permission to access the resource")
	ErrImpersonateDenied = errors.New("impersonated user is read-only user")
	ErrInternal          = errors.New("internal Server Error")
	ErrInvalidOrgId      = errors.New("invalid Organization ID")
)

func IsUIRequest(path string) bool {
	return strings.Contains(path, uiRequestKey)
}

// /serverless/v1beta1/regions -> /serverless/regions
// /dedicated/v1beta1/regions -> /dedicated/regions
// /serverless/api/v1beta1/clusters -> /serverless/clusters
// /dedicated/api/v1beta1/clusters -> /dedicated/clusters
// /api/v2023/clusterManagement/v1beta1/clusters -> /clusterManagement/clusters
// /api/v2023/serverless/v1beta1/clusters -> /serverless/clusters
// /api/v2023/dedicated/v1beta1/clusters -> /dedicated/clusters
func RelativePath(requestPath string) string {
	requestPath = strings.ReplaceAll(requestPath, uiRequestKey, "")        // remove /api
	requestPath = strings.ReplaceAll(requestPath, uiVersionKey, "")        // remove /v2023
	requestPath = strings.ReplaceAll(requestPath, nextGenUiVersionKey, "") // remove /v2025/cloud

	if !strings.HasPrefix(requestPath, "/") {
		requestPath = "/" + requestPath
	}

	// slipt the path by "/"
	// /serverless/v1beta1/regions -> ["", "serverless", "v1beta1", "regions"]
	// /v1beta2/tidbs/10411292523848492340/publicConnectionSetting -> ["", "v1beta2", "tidbs", "10411292523848492340", "publicConnectionSetting"]
	paths := strings.Split(requestPath, "/")

	// ["", "v1beta2", "tidbs", "10411292523848492340", "publicConnectionSetting"]
	if strings.HasPrefix(requestPath, "/v") {
		return strings.Join(append(paths[0:1], paths[2:]...), "/") // remove the version part
	}

	if len(paths) < 3 { //  ["", "serverless", "v1beta1"]
		return requestPath
	}

	return strings.Join(append(paths[0:2], paths[3:]...), "/")
}

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

const (
	// XAuthUser for rbac middleware
	XAuthUser = "X-Auth-User"
)
