package errors

import (
	"net/http"

	grpccodes "google.golang.org/grpc/codes"
)

type ErrorCode int32

const SUCCESS = 0

const (
	PanicError          ErrorCode = -1
	UnrecognizedError   ErrorCode = -2
	K8SClientError      ErrorCode = -3
	AWSClientError      ErrorCode = -4
	InternalServerError ErrorCode = -5
	ResourceNotFound    ErrorCode = -6
	ResourceConflict    ErrorCode = -7
	ResourceIsUsed      ErrorCode = -8
	ResourceNotReady    ErrorCode = -9

	// define common error
	IOReadFileError    ErrorCode = 1001
	B64DecodeError     ErrorCode = 1002
	ParameterInvalid   ErrorCode = 1003
	MarshalError       ErrorCode = 1004
	UnmarshalError     ErrorCode = 1005
	UnsupportedRegion  ErrorCode = 1006
	EmptyEnvError      ErrorCode = 1007
	ConvertError       ErrorCode = 1008
	ParamParseError    ErrorCode = 1009
	AbsenceOfConfig    ErrorCode = 1010
	UnsupportedBizType ErrorCode = 1011
	ConfigInvalid      ErrorCode = 1012

	// define vpc error
	VPCConflict ErrorCode = 2001

	// define privatelink error
	ConnectionNotFound ErrorCode = 3001
)

type ErrorCodeExplanation struct {
	explanation string
	httpCode    int
	grpcCode    grpccodes.Code
}

func (t ErrorCode) GetHttpCode() int {
	if item, ok := explanationContainer[t]; ok {
		return item.httpCode
	}
	return http.StatusInternalServerError
}

func (t ErrorCode) GetGrpcCode() grpccodes.Code {
	if item, ok := explanationContainer[t]; ok {
		return item.grpcCode
	}
	return grpccodes.Unknown
}

func (t ErrorCode) Equal(code int32) bool {
	return code == int32(t)
}

func (t ErrorCode) Explain() string {
	if item, ok := explanationContainer[t]; ok {
		return item.explanation
	}
	return explanationContainer[UnrecognizedError].explanation
}

var explanationContainer = map[ErrorCode]ErrorCodeExplanation{
	PanicError:          {"panic", 500, grpccodes.Internal},
	UnrecognizedError:   {"unrecognized error", 500, grpccodes.Unknown},
	K8SClientError:      {"k8s client error", 500, grpccodes.Internal},
	AWSClientError:      {"aws client error", 500, grpccodes.Internal},
	InternalServerError: {"regionserver internal error", 500, grpccodes.Internal},
	ResourceNotFound:    {"resource not found", 404, grpccodes.NotFound},
	ResourceConflict:    {"resource conflict", 409, grpccodes.AlreadyExists},
	ResourceIsUsed:      {"resource is used", 409, grpccodes.FailedPrecondition},
	ResourceNotReady:    {"resource not ready", 404, grpccodes.NotFound},

	ParameterInvalid:   {"parameter is invalid", 400, grpccodes.InvalidArgument},
	MarshalError:       {"marshal error", 500, grpccodes.Internal},
	UnmarshalError:     {"unmarshal error", 500, grpccodes.Internal},
	UnsupportedRegion:  {"vendor or region is not supported", 400, grpccodes.FailedPrecondition},
	IOReadFileError:    {"io read file error", 500, grpccodes.Internal},
	B64DecodeError:     {"base64 decode error", 500, grpccodes.Internal},
	EmptyEnvError:      {"empty env error", 400, grpccodes.FailedPrecondition},
	ConvertError:       {"convert error", 400, grpccodes.InvalidArgument},
	ParamParseError:    {"parameter parse error", 400, grpccodes.InvalidArgument},
	AbsenceOfConfig:    {"absence of config", 500, grpccodes.Internal},
	UnsupportedBizType: {"biz_type is not supported", 400, grpccodes.FailedPrecondition},
	ConfigInvalid:      {"config is invalid", 500, grpccodes.Internal},

	ConnectionNotFound: {"connection not found", 400, grpccodes.InvalidArgument},
}
