package task

import (
	"reflect"

	"github.com/astaxie/beego/context"
)

const (
	HTTPCODE_500 = 500
	ERRCODE_FAIL = 10001

	ERRMSG_UNKNOWN = "系统错误"
)

type Response struct {
	Code int    `json:"code" description:"返回码"`
	Msg  string `json:"msg" description:"错误消息" default:""`
}

type Recoverer interface {
	Recover(v interface{})
}

// 异常时恢复代码
type PanicRecover struct {
	Ctx   *context.Context
	LogID string
}

type GeneralError struct {
	ErrCode int    `json:"err_code" description:"服务器具体错误码"`
	ErrMsg  string `json:"err_msg" description:"服务器错误描述"`
}

func (pr *PanicRecover) Recover(v interface{}) {
	generalError := GetGeneralError(v)
	if generalError == nil {
		generalError = &GeneralError{
			ErrCode: ERRCODE_FAIL,
			ErrMsg:  ERRMSG_UNKNOWN,
		}
	}
	pr.Ctx.Output.JSON(Response{
		Code: generalError.ErrCode,
		Msg:  generalError.ErrMsg,
	}, false, false)
}

func GetGeneralError(val interface{}) *GeneralError {
	generalError := &GeneralError{}
	v := reflect.ValueOf(val)
	if v.Kind() == reflect.Ptr {
		v = v.Elem()
	}

	flag := false
	if v.Kind() == reflect.Struct {
		numField := v.NumField()
		for i := 0; i < numField; i++ {
			if v.Type().Field(i).Name == "ErrCode" && v.Type().Field(i).Type.Kind() == reflect.Int {
				generalError.ErrCode = int(v.Field(i).Int())
				flag = true
			}
			if v.Type().Field(i).Name == "ErrMsg" && v.Type().Field(i).Type.Kind() == reflect.String {
				generalError.ErrMsg = v.Field(i).String()
			}
		}
	}

	if flag {
		return generalError
	}

	return nil
}
