package consts

import (
	"context"

	"github.com/tidbcloud/devops/pkg/infra/utils/pointer"
)

// Context keys
const (
	// CtxOperatorType is the type of the operator.
	// Value Type: string
	//
	//  - If caller is a User, the value is "user"
	//  - If caller is a APIToken, the value is "api_token"
	//  - If caller is a APIKey, the value is "api_key"
	CtxOperatorType = "OPERATOR_TYPE"
	// CtxOperator is the caller of the request.
	// Value Type: string
	//
	//  - If caller is a User, the value is user email
	//  - If caller is a APIToken, the value is user email
	//  - If caller is a APIKey, the value is api key name
	CtxOperator = "OPERATOR"
	// CtxUserEmail is the user email of the request.
	// Value Type: string
	//
	//  - If caller is a User, the value is user email
	//  - If caller is a APIToken, the value is user email
	//  - If caller is a APIKey, the value is the owner of api key
	CtxUserEmail = "USER_EMAIL"
	// CtxUserProfile is the user info of the request.
	// Value Type: *userapiv1.PrincipalProfile
	//
	//  - If caller is a User/APIToken/APIKey, the value is *userapiv1.PrincipalProfile
	//  - Otherwise, the value is nil
	// Some API will use the user profile info to verify permission.
	CtxUserProfile = "USER_PROFILE"
	// CtxAPIKeyProfile is the api key info of the request.
	// Value Type: *iamv1.APIKey
	//
	//  - If caller is a APIKey, the value is *iamv1.APIKey
	//  - Otherwise, the value is nil
	CtxAPIKeyProfile = "APIKEY_PROFILE"
	// CtxRoleScope is the tenant scope of the caller's bound role, populated
	// after authz. nil means the request was authorized without any tenant
	// restriction (e.g. the auth service did not return a scope).
	// Currently only set for API key callers; user callers may adopt the same
	// mechanism in the future.
	// Value Type: *userapiv1.PrincipalRoleScope
	CtxRoleScope = "ROLE_SCOPE"
	// CtxLarkCardAction is the action info of the lark card callback.
	// Value Type: *larkcard.CardAction
	CtxLarkCardAction = "LARK_CARD_ACTION" // type: *larkcard.CardAction
	// CtxLarkEvent is the event info of the lark event callback.
	// Value Type: *larkevent.EventV2Body
	CtxLarkEvent = "LARK_EVENT" // type:  &larkevent.EventV2Body{}
)

const (
	CtxOperatorTypeUser     = "user"
	CtxOperatorTypeAPIToken = "api_token"
	CtxOperatorTypeAPIKey   = "api_key"
)

// GetOperatorFromCtx return the operator from context
func GetOperatorFromCtx(ctx context.Context, def string) string {
	return pointer.DerefAny(ctx.Value(CtxOperator), def)
}

// GetOperatorTypeFromCtx return the operator type from context
func GetOperatorTypeFromCtx(ctx context.Context) string {
	return pointer.DerefAny(ctx.Value(CtxOperatorType), "unknown")
}

// GetUserEmailFromCtx return the user email from context
func GetUserEmailFromCtx(ctx context.Context, def string) string {
	return pointer.DerefAny(ctx.Value(CtxUserEmail), def)
}

// HTTP Header
const (
	HTTPHeaderAPIKey   = "X-API-KEY"
	HTTPHeaderAPIToken = "X-API-TOKEN" //nolint:gosec
)

// Lark related
const (
	// LarkCardButtonNameKey is the key of the button name in the lark card action.
	LarkCardButtonNameKey = "button_name"
	// LarkApprovalIDKey is the key of approval id in the lark card action.
	LarkApprovalIDKey = "approval_id"

	CardButtonUserApproved = "ApprovalTaskApproved"
	CardButtonUserRejected = "ApprovalTaskRejected"
)

func ConsoleAddr() string {
	addrMap := map[Environment]string{}

	switch GetPartition() {
	case PartitionGlobal:
		addrMap = map[Environment]string{
			EnvironmentDev:     "ops-dev.tidbcloud.com",
			EnvironmentStaging: "ops-staging.tidbcloud.com",
			EnvironmentProd:    "ops.tidbcloud.com",
		}
	case PartitionCN:
		addrMap = map[Environment]string{
			EnvironmentDev:     "dev.ops-portal.cloud.pingkai.cn",
			EnvironmentStaging: "staging.ops-portal.cloud.pingkai.cn",
			EnvironmentProd:    "prod.ops-portal.cloud.pingkai.cn",
		}
	}

	return addrMap[GetEnv()]
}

func ServerAddr() string {
	return ServerAddrOfEnv(GetEnv())
}

func ServerAddrOfEnv(env Environment) string {
	addrMap := map[Environment]string{}

	switch GetPartition() {
	case PartitionGlobal:
		addrMap = map[Environment]string{
			EnvironmentDev:     "dev.devops.pingcap.com",
			EnvironmentStaging: "staging.devops.pingcap.com",
			EnvironmentProd:    "prod.devops.pingcap.com",
		}
	case PartitionCN:
		addrMap = map[Environment]string{
			EnvironmentDev:     "dev.devops.cloud.pingkai.cn",
			EnvironmentStaging: "staging.devops.cloud.pingkai.cn",
			EnvironmentProd:    "prod.devops.cloud.pingkai.cn",
		}
	}

	return addrMap[GetEnv()]
}

// Misc
const (
	AutomatedTestApprovalTemplate = "automated-test"
	AutomatedTestReason           = "automated test"

	// InternalVirtualEmail is the virtual user email
	// * for the approval request created by the system, it is used to skip the notification for the approval request.
	InternalVirtualEmail = "devops-internal@pingcap.com"

	JumpPodAgentPort = 11277
)
