package errno

import "fmt"

type Errno struct {
	Code    int
	Message string
}

func (err Errno) Error() string {
	return err.Message
}

// Err represents an error
type Err struct {
	Code    int
	Message string
	Err     error
}

func New(errno *Errno, err error) *Err {
	return &Err{Code: errno.Code, Message: errno.Message, Err: err}
}

func (err *Err) Add(message string) error {
	err.Message += " " + message
	return err
}

func (err *Err) Addf(format string, args ...interface{}) error {
	err.Message += " " + fmt.Sprintf(format, args...)
	return err
}

func (err *Err) Error() string {
	return fmt.Sprintf("Err - code: %d, message: %s, error: %s", err.Code, err.Message, err.Err)
}

func DecodeErr(err error) (int, string) {
	if err == nil {
		return OK.Code, OK.Message
	}

	switch typed := err.(type) {
	case *Err:
		return typed.Code, typed.Message
	case *Errno:
		return typed.Code, typed.Message
	default:
	}

	return InternalServerError.Code, err.Error()
}

var (
	// Common errors
	OK                  = &Errno{Code: 0, Message: "OK"}
	InternalServerError = &Errno{Code: 10001, Message: "Internal server error"}
	ErrBind             = &Errno{Code: 10002, Message: "Error occurred while binding the request body to the struct."}

	ErrValidation = &Errno{Code: 20001, Message: "Validation failed."}
	ErrDatabase   = &Errno{Code: 20002, Message: "Database error."}
	ErrTs         = &Errno{Code: 20003, Message: "Ts error."}
	ErrSn         = &Errno{Code: 20004, Message: "Sn error."}
	ErrAk         = &Errno{Code: 20005, Message: "Ak error."}

	PermissionDenied = &Errno{Code: 403, Message: "Permission Denied"}

	// bank errors
	ErrBankNotFound       = &Errno{Code: 20101, Message: "银行账号绑定未找到."}
	ErrAddBank           = &Errno{Code: 20102, Message: "银行账号绑定失败."}
	ErrUpdateBank         = &Errno{Code: 20103, Message: "银行账号更新失败."}
	ErrDeleteBank         = &Errno{Code: 20104, Message: "银行账号删除失败."}
)
