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 IsErrUserNotFound(err error) bool {
	code, _ := DecodeErr(err)
	return code == ErrUserNotFound.Code
}

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."}

	// coin errors
	ErrCoinNotFound = &Errno{Code: 20101, Message: "The coin was not found."}
	ErrCountCoin    = &Errno{Code: 20102, Message: "The coins statistic error."}
	ErrAddCoin      = &Errno{Code: 20101, Message: "The coin add error."}
	ErrUpdateCoin   = &Errno{Code: 20102, Message: "The coin update error."}
	ErrDeleteCoin   = &Errno{Code: 20102, Message: "The coin delete error."}
	ErrExistCoin    = &Errno{Code: 20103, Message: "The coin already exists."}
	ErrNotExistCoin = &Errno{Code: 20104, Message: "The coin not exists."}
	ErrAuthCoin     = &Errno{Code: 20105, Message: "The coin auth error."}

	// recommend coin errors
	ErrRecommendCoinNotFound = &Errno{Code: 20101, Message: "The recommend coin was not found."}
	ErrCountRecommendCoin    = &Errno{Code: 20102, Message: "The recommend coins statistic error."}
	ErrAddRecommendCoin      = &Errno{Code: 20103, Message: "The recommend coin add error."}
	ErrUpdateRecommendCoin   = &Errno{Code: 20104, Message: "The recommend coin update error."}
	ErrDeleteRecommendCoin   = &Errno{Code: 20105, Message: "The recommend coin delete error."}
	ErrExistRecommendCoin    = &Errno{Code: 20106, Message: "The recommend coin already exists."}

	// wallet errors
	ErrWalletNotFound = &Errno{Code: 20101, Message: "The wallet was not found."}
	ErrCountWallet    = &Errno{Code: 20102, Message: "The wallets statistic error."}
	ErrAddWallet      = &Errno{Code: 20103, Message: "The wallet add error."}
	ErrUpdateWallet   = &Errno{Code: 20104, Message: "The wallet update error."}
	ErrDeleteWallet   = &Errno{Code: 20105, Message: "The wallet delete error."}

	// chain errors
	ErrChainNotFound = &Errno{Code: 20101, Message: "The chain was not found."}
	ErrCountChain    = &Errno{Code: 20102, Message: "The chain statistic error."}
	ErrAddChain      = &Errno{Code: 20103, Message: "The chain add error."}
	ErrUpdateChain   = &Errno{Code: 20104, Message: "The chain update error."}
	ErrDeleteChain   = &Errno{Code: 20105, Message: "The chain delete error."}
	ErrExistChain    = &Errno{Code: 20106, Message: "The chain already exists."}

	// supported currency errors
	ErrSupportedCurrencyNotFound = &Errno{Code: 20101, Message: "The supported currency was not found."}
	ErrCountSupportedCurrency    = &Errno{Code: 20102, Message: "The supported currency statistic error."}
	ErrAddSupportedCurrency      = &Errno{Code: 20103, Message: "The supported currency add error."}
	ErrUpdateSupportedCurrency   = &Errno{Code: 20104, Message: "The supported currency update error."}
	ErrDeleteSupportedCurrency   = &Errno{Code: 20105, Message: "The supported currency delete error."}
	ErrExistSupportedCurrency    = &Errno{Code: 20106, Message: "The supported currency already exists."}

	// recommend category errors
	ErrRecommendCategoryNotFound = &Errno{Code: 20101, Message: "The recommend category was not found."}
	ErrCountRecommendCategory    = &Errno{Code: 20102, Message: "The recommend category statistic error."}
	ErrAddRecommendCategory      = &Errno{Code: 20103, Message: "The recommend category add error."}
	ErrUpdateRecommendCategory   = &Errno{Code: 20104, Message: "The recommend category update error."}
	ErrDeleteRecommendCategory   = &Errno{Code: 20105, Message: "The recommend category delete error."}
	ErrExistRecommendCategory    = &Errno{Code: 20106, Message: "The recommend category already exists."}

	// wallet supported chain errors
	ErrSupportedChainNotFound = &Errno{Code: 20101, Message: "The wallet supported chain was not found."}
	ErrCountSupportedChain    = &Errno{Code: 20102, Message: "The wallet supported chain statistic error."}
	ErrAddSupportedChain      = &Errno{Code: 20103, Message: "The wallet supported chain add error."}
	ErrDeleteSupportedChain   = &Errno{Code: 20104, Message: "The wallet supported chain delete error."}
	ErrExistSupportedChain    = &Errno{Code: 20105, Message: "The wallet supported chain already exists."}

	// user errors
	ErrUserNotFound       = &Errno{Code: 20101, Message: "The user was not found."}
	ErrCountUsers         = &Errno{Code: 20102, Message: "The users statistic error."}
	ErrAddUser            = &Errno{Code: 20103, Message: "The user add error."}
	ErrUpdateUser         = &Errno{Code: 20104, Message: "The user update error."}
	ErrDeleteUser         = &Errno{Code: 20105, Message: "The user delete error."}
	ErrExistUser          = &Errno{Code: 20106, Message: "The user already exists."}
	ErrDeleteSelf         = &Errno{Code: 20105, Message: "The user can not delete yourself."}
	ErrUpdateSelf         = &Errno{Code: 20105, Message: "The user can not modify yourself."}
	ErrPasswordIncorrect  = &Errno{Code: 20107, Message: "The password was incorrect."}
	ErrUserAuthIncorrect  = &Errno{Code: 40001, Message: "The user auth was incorrect."}
	ErrUserTokenIncorrect = &Errno{Code: 40001, Message: "The user token was incorrect."}

	// operation log errors
	ErrCountOperationLog = &Errno{Code: 20102, Message: "The operation log statistic error."}
	ErrAddOperationLog   = &Errno{Code: 20101, Message: "The operation log add error."}

	// news errors
	ErrNewsNotFound = &Errno{Code: 20101, Message: "The news was not found."}
	ErrCountNews    = &Errno{Code: 20102, Message: "The news statistic error."}
	ErrAddNews      = &Errno{Code: 20103, Message: "The news add error."}
	ErrUpdateNews   = &Errno{Code: 20104, Message: "The news update error."}
	ErrDeleteNews   = &Errno{Code: 20105, Message: "The news delete error."}
	ErrExistNews    = &Errno{Code: 20106, Message: "The news already exists."}

	// article errors
	ErrArticleNotFound = &Errno{Code: 20101, Message: "The article was not found."}
	ErrCountArticle    = &Errno{Code: 20102, Message: "The article statistic error."}
	ErrAddArticle      = &Errno{Code: 20103, Message: "The article add error."}
	ErrUpdateArticle   = &Errno{Code: 20104, Message: "The article update error."}
	ErrDeleteArticle   = &Errno{Code: 20105, Message: "The article delete error."}
	ErrExistArticle    = &Errno{Code: 20106, Message: "The article already exists."}

	// live category errors
	ErrLiveCategoryNotFound = &Errno{Code: 20101, Message: "The live category was not found."}
	ErrCountLiveCategory    = &Errno{Code: 20102, Message: "The live category statistic error."}
	ErrAddLiveCategory      = &Errno{Code: 20103, Message: "The live category add error."}
	ErrUpdateLiveCategory   = &Errno{Code: 20104, Message: "The live category update error."}
	ErrDeleteLiveCategory   = &Errno{Code: 20105, Message: "The live category delete error."}
	ErrExistLiveCategory    = &Errno{Code: 20106, Message: "The live category already exists."}

	// live info errors
	ErrLiveInfoNotFound = &Errno{Code: 20101, Message: "The live info was not found."}
	ErrCountLiveInfo    = &Errno{Code: 20102, Message: "The live info statistic error."}
	ErrAddLiveInfo      = &Errno{Code: 20103, Message: "The live info add error."}
	ErrUpdateLiveInfo   = &Errno{Code: 20104, Message: "The live info update error."}
	ErrDeleteLiveInfo   = &Errno{Code: 20105, Message: "The live info delete error."}
	ErrExistLiveInfo    = &Errno{Code: 20106, Message: "The live info already exists."}
	ErrPrice            = &Errno{Code: 20107, Message: "The live info price err."}

	// live charge errors
	ErrLiveChargeNotFound = &Errno{Code: 20101, Message: "The live charge was not found."}
	ErrCountLiveCharge    = &Errno{Code: 20102, Message: "The live charge statistic error."}
	ErrAddLiveCharge      = &Errno{Code: 20103, Message: "The live charge add error."}
	ErrUpdateLiveCharge   = &Errno{Code: 20104, Message: "The live charge update error."}
	ErrDeleteLiveCharge   = &Errno{Code: 20105, Message: "The live charge delete error."}
	ErrExistLiveCharge    = &Errno{Code: 20106, Message: "The live charge already exists."}

	// live title record errors
	ErrLiveTitleRecordNotFound = &Errno{Code: 20101, Message: "The live title record was not found."}
	ErrCountLiveTitleRecord    = &Errno{Code: 20102, Message: "The live title record statistic error."}
	ErrAddLiveTitleRecord      = &Errno{Code: 20103, Message: "The live title record add error."}
	ErrUpdateLiveTitleRecord   = &Errno{Code: 20104, Message: "The live title record update error."}
	ErrDeleteLiveTitleRecord   = &Errno{Code: 20105, Message: "The live title record delete error."}
	ErrExistLiveTitleRecord    = &Errno{Code: 20106, Message: "The live title record already exists."}

	// live banner errors
	ErrLiveBannerNotFound = &Errno{Code: 20101, Message: "The live banner was not found."}
	ErrCountLiveBanner    = &Errno{Code: 20102, Message: "The live banners statistic error."}
	ErrAddLiveBanner      = &Errno{Code: 20103, Message: "The live banner add error."}
	ErrUpdateLiveBanner   = &Errno{Code: 20104, Message: "The live banner update error."}
	ErrDeleteLiveBanner   = &Errno{Code: 20105, Message: "The live banner delete error."}

	// app errors
	ErrClientAppNotFound = &Errno{Code: 20101, Message: "The client app was not found."}
	ErrCountClientApp    = &Errno{Code: 20102, Message: "The client apps statistic error."}
	ErrAddClientApp      = &Errno{Code: 20103, Message: "The client app add error."}
	ErrUpdateClientApp   = &Errno{Code: 20104, Message: "The client app update error."}
	ErrDeleteClientApp   = &Errno{Code: 20105, Message: "The client app delete error."}
)
