package bizerr

import (
	"net/http"

	"github.com/tidbcloud/pkgv2/svcid"
	"google.golang.org/grpc/codes"
)

// TODO: refactor this file to make bizerr.ErrCode, grpc.Code, http.Code, grpcstatus.reason and errMsg consistent !!!!
// FIXME: refactor this file to make bizerr.ErrCode, grpc.Code, http.Code, grpcstatus.reason and errMsg consistent !!!!

// mgmt
var (
	// TiDB Mgmt service's internal error codes
	GeneralInternalErrorCode              = newInternalErrCode(svcid.TiDBManagementService, 1, "INTERNAL")
	GrayscaleUpgradeDataNotInTargetSystem = ErrCode(61600000)

	// TiDB Mgmt service's business error codes
	ErrCodeRegionalAPI                          = newBusinessErrCode(svcid.TiDBManagementService, 100, "ErrCodeRegionalAPI")
	ErrCodeConfigCenterAPI                      = newBusinessErrCode(svcid.TiDBManagementService, 101, "ErrCodeConfigCenter")
	ErrCodePhysicalClusterNotReady              = newBusinessErrCode(svcid.TiDBManagementService, 102, "ErrCodePhysicalClusterNotReady")
	ErrCodePrivateLinkIPAddressTypePrecondition = newBusinessErrCode(
		svcid.TiDBManagementService,
		103,
		"ErrCodePrivateLinkIPAddressTypePrecondition",
	)
	ErrCodeNotAllow3LayerArch = newBusinessErrCode(svcid.TiDBManagementService, 403, "ErrNotAllow3LayerArch")
)

// dedicated
var (
	ErrCodeDuplicateDisplayName = newBusinessErrCode(
		svcid.Core,
		1,
		"ErrCodeInvalidDuplicateDisplayName",
	)
	ErrCodeNoPocPoints                = newBusinessErrCode(svcid.Core, 3, "ErrCodeNoPocPoints")
	ErrCodeClusterQuotaExceed         = newBusinessErrCode(svcid.Core, 6, "ErrCodeClusterQuotaExceed")
	ErrCodeDuplicatedCIDR             = newBusinessErrCode(svcid.Core, 17, "ErrCodeDuplicatedCIDR")
	ErrCodeStorageScaleCoolDown       = newBusinessErrCode(svcid.Core, 18, "ErrCodeStorageScaleCoolDown")
	ErrCodeScaleUpLocalDisk           = newBusinessErrCode(svcid.Core, 20, "ErrCodeScaleUpLocalDisk")
	ErrCodeInvalidNodeSize            = newBusinessErrCode(svcid.Core, 21, "ErrCodeInvalidNodeSize")
	ErrCodeInvalidStorageSize         = newBusinessErrCode(svcid.Core, 22, "ErrCodeInvalidStorageSize")
	ErrCodeInvalidNodeQuantity        = newBusinessErrCode(svcid.Core, 23, "ErrCodeInvalidNodeQuantity")
	ErrCodeInvalidClusterModification = newBusinessErrCode(
		svcid.Core,
		24,
		"ErrCodeInvalidClusterModification",
	)
	ErrCodeInvalidClusterCombination = newBusinessErrCode(
		svcid.Core,
		25,
		"ErrCodeInvalidClusterCombination",
	)
	ErrCodeScaleComputeNonEksGkeCluster = newBusinessErrCode(
		svcid.Core,
		30,
		"ErrCodeScaleComputeNonEksGkeCluster",
	)
	ErrCodePrivateLinkServiceNotAllowed = newBusinessErrCode(
		svcid.Core,
		31,
		"ErrCodePrivateLinkServiceNotAllowed",
	)
	ErrCodeClusterProxy                 = newInternalErrCode(svcid.Core, 33, "ErrCodeSvcClusterProxy")
	ErrCodeVPCPeeringCreatePrerequisite = newBusinessErrCode(
		svcid.Core,
		34,
		"ErrCodeVPCPeeringCreatePrerequisite",
	)
	ErrCodeVPCPeeringConflictWithCurrentPeeringCidr = newBusinessErrCode(
		svcid.Core,
		36,
		"ErrCodeVPCPeeringConflictWithCurrentPeeringCidr",
	)
	ErrCodeVPCPeeringConflictWithRegionCidr = newBusinessErrCode(
		svcid.Core,
		37,
		"ErrCodeVPCPeeringConflictWithRegionCidr",
	)
	ErrCodeTokenBasedAuthRequired = newBusinessErrCode(
		svcid.Core,
		39,
		"ErrCodeTokenBasedAuthRequired",
	)
	ErrCodeUnexpectedClusterStatus = newBusinessErrCode(
		svcid.Core,
		40,
		"ErrCodeUnexpectedClusterStatus",
	)
	ErrCodeTooManyTrafficFilters = newBusinessErrCode(svcid.Core, 42, "ErrCodeTooManyTrafficFilters")
	ErrCodeWithoutPaymentMethods = newBusinessErrCode(svcid.Core, 44, "ErrCodeWithoutPaymentMethods")
	ErrCodeSvcAccount            = newInternalErrCode(svcid.Core, 34, "ErrCodeSvcAccount")

	// Reserved 51 to 59 for bff CheckModificationRisks api
	ErrCodePdScale = newBusinessErrCode(svcid.Core, 51, "ErrCodePdScaleWarning")

	ErrCodePublicInboundRulesFailed      = newBusinessErrCode(svcid.Core, 60, "ErrCodePublicInboundRulesFailed")
	ErrCodePublicEndpointRunningTask     = newBusinessErrCode(svcid.Core, 61, "ErrCodePublicEndpointRunningTask")
	ErrCodePublicEndpointClusterNotReady = newBusinessErrCode(svcid.Core, 62, "ErrCodePublicEndpointClusterNotReady")
)

// serverless
var (
	ErrCodeInvalidSpendLimitValue = newBusinessErrCode(
		svcid.ServerlessService,
		1,
		"ErrCodeInvalidSpendLimitValue",
	)
	ErrCodeLessThanMinSpendLimitValue = newBusinessErrCode(
		svcid.ServerlessService,
		2,
		"ErrCodeLessThanMinSpendLimitValue",
	)
	ErrCodeNoPaymentMethods          = newBusinessErrCode(svcid.ServerlessService, 3, "ErrCodeNoPaymentMethods")
	ErrCodeNoFreeCreditAndSpendLimit = newBusinessErrCode(
		svcid.ServerlessService,
		4,
		"ErrCodeNoFreeCreditAndSpendLimit",
	)
	ErrCodeServerlessReachMaxFreeNum = newBusinessErrCode(
		svcid.ServerlessService,
		5,
		"ErrCodeServerlessReachMaxFreeNum",
	)
	ErrCodeGreaterThanMaxSpendLimitValue = newBusinessErrCode(
		svcid.ServerlessService,
		6,
		"ErrCodeGreaterThanMaxSpendLimitValue",
	)
	ErrCodeSpendLimitsSetting = newBusinessErrCode(
		svcid.ServerlessService,
		45,
		"ErrCodeSpendLimitsSettingFailed",
	)
)

// Shared error messages.
const (
	// mgmt
	ErrMsgResourceNoPermission = "Does not have permission to access the resources in belonged project."
	ErrMsgDupDisplayName       = "Duplicate displayName. The cluster display name must be unique in a project."
	ErrMsg3rdPartyAccount      = "cloud provider %s is not allowed for third party account"
)

var (
	ErrCode2HttpStatus = map[ErrCode]int{
		ErrCodeOK: 200,

		ErrCodeParams:          400,
		ErrCodeAuth:            401,
		ErrCodePermission:      403,
		ErrCodeRecordNotFound:  404,
		ErrCodeRecordExist:     409,
		ErrCodeTooManyRequests: 429,
		ErrCodeUnknown:         500,

		ErrCodeTimeout: 504,
		ErrCodePrivateLinkIPAddressTypePrecondition: http.StatusPreconditionFailed,

		BusinessErrCodeStart: 400,
	}

	BizErrCode2HttpStatus = map[ErrCode]int{
		ErrCodeOK: http.StatusOK,

		ErrCodeParams:           http.StatusBadRequest,
		ErrCodeAuth:             http.StatusUnauthorized,
		ErrCodePermission:       http.StatusForbidden,
		ErrCodeUnderMaintenance: http.StatusForbidden,
		ErrCodeIPBlocked:        http.StatusForbidden,
		ErrCodeRecordNotFound:   http.StatusNotFound,
		ErrCodeRecordExist:      http.StatusConflict,
		ErrCodeTooManyRequests:  http.StatusTooManyRequests,
		ErrCodeUnknown:          http.StatusInternalServerError,
		ErrCodeTimeout:          http.StatusGatewayTimeout,

		// mgmt biz error codes
		ErrCodeDuplicateDisplayName:                 http.StatusBadRequest,
		ErrCodeRegionalAPI:                          http.StatusInternalServerError,
		ErrCodePhysicalClusterNotReady:              http.StatusBadRequest,
		ErrCodePrivateLinkIPAddressTypePrecondition: http.StatusPreconditionFailed,

		// Serverless biz error codes
		ErrCodeInvalidSpendLimitValue:        http.StatusBadRequest,
		ErrCodeLessThanMinSpendLimitValue:    http.StatusBadRequest,
		ErrCodeNoPaymentMethods:              http.StatusPaymentRequired,
		ErrCodeNoFreeCreditAndSpendLimit:     http.StatusPaymentRequired,
		ErrCodeServerlessReachMaxFreeNum:     http.StatusBadRequest,
		ErrCodeGreaterThanMaxSpendLimitValue: http.StatusBadRequest,
		ErrCodeSpendLimitsSetting:            http.StatusInternalServerError,

		// Core biz error codes
		ErrCodeClusterProxy:                 http.StatusInternalServerError,
		ErrCodeVPCPeeringCreatePrerequisite: http.StatusInternalServerError,
		ErrCodeWithoutPaymentMethods:        http.StatusPaymentRequired,

		// Dedicated biz error codes
		ErrCodeNoPocPoints:                              http.StatusPaymentRequired,
		ErrCodeClusterQuotaExceed:                       http.StatusBadRequest,
		ErrCodeStorageScaleCoolDown:                     http.StatusBadRequest,
		ErrCodeScaleUpLocalDisk:                         http.StatusBadRequest,
		ErrCodeInvalidStorageSize:                       http.StatusBadRequest,
		ErrCodeInvalidNodeSize:                          http.StatusBadRequest,
		ErrCodeInvalidNodeQuantity:                      http.StatusBadRequest,
		ErrCodeInvalidClusterModification:               http.StatusBadRequest,
		ErrCodeInvalidClusterCombination:                http.StatusBadRequest,
		ErrCodeScaleComputeNonEksGkeCluster:             http.StatusBadRequest,
		ErrCodeDuplicatedCIDR:                           http.StatusBadRequest,
		ErrCodePrivateLinkServiceNotAllowed:             http.StatusBadRequest,
		ErrCodeVPCPeeringConflictWithCurrentPeeringCidr: http.StatusBadRequest,
		ErrCodeVPCPeeringConflictWithRegionCidr:         http.StatusBadRequest,
		ErrCodeUnexpectedClusterStatus:                  http.StatusBadRequest,
		ErrCodeTooManyTrafficFilters:                    http.StatusBadRequest,
		ErrCodeWithoutPaymentMethods:                    http.StatusPaymentRequired,
		ErrCodeTokenBasedAuthRequired:                   http.StatusForbidden,
		ErrCodeSvcAccount:                               http.StatusForbidden,
		ErrCodePublicInboundRulesFailed:                 http.StatusBadRequest,
		ErrCodePublicEndpointClusterNotReady:            http.StatusBadRequest,
		ErrCodePublicEndpointRunningTask:                http.StatusBadRequest,
	}

	GrpcErrCode2BizErrCode = map[codes.Code]ErrCode{
		codes.OK:                 ErrCodeOK,
		codes.Canceled:           ErrCodeTimeout,
		codes.Unknown:            ErrCodeUnknown,
		codes.InvalidArgument:    ErrCodeParams,
		codes.DeadlineExceeded:   ErrCodeTimeout,
		codes.NotFound:           ErrCodeRecordNotFound,
		codes.AlreadyExists:      ErrCodeRecordExist,
		codes.PermissionDenied:   ErrCodePermission,
		codes.ResourceExhausted:  ErrCodeTooManyRequests,
		codes.FailedPrecondition: ErrCodeGRPC,
		codes.Aborted:            ErrCodeGRPC,
		codes.OutOfRange:         ErrCodeParams,
		codes.Unimplemented:      ErrCodeGRPC,
		codes.Internal:           ErrCodeUnknown,
		codes.Unavailable:        ErrCodeUnknown,
		codes.DataLoss:           ErrCodeUnknown,
		codes.Unauthenticated:    ErrCodeAuth,
	}

	HttpStatus2BizErrCode = map[int]ErrCode{
		http.StatusBadRequest:          ErrCodeParams,
		http.StatusUnauthorized:        ErrCodeAuth,
		http.StatusForbidden:           ErrCodePermission,
		http.StatusNotFound:            ErrCodeRecordNotFound,
		http.StatusConflict:            ErrCodeRecordExist,
		http.StatusTooManyRequests:     ErrCodeTooManyRequests,
		http.StatusInternalServerError: ErrCodeUnknown,
	}
)
