package dapi

import (
	"bytes"
	"encoding/json"
	"epur-pay/pkg/config"
	"epur-pay/pkg/logger"
	"errors"
	"github.com/go-sql-driver/mysql"
	"gorm.io/gorm"
	"net/http"
)

var (
	//成功
	Success = 200
	//服务错误
	ServerError = 500
	//资源不存在
	NotFound = 404
	//参数错误
	InvalidParams = 965
	//请求错误
	PublicError = 999
	//Token失效
	TokenInvalid = 600
)

type RequestLimit struct {
	Page int `json:"page"` //页数
	Size int `json:"size"` //条数
}

// 返回公共结构体
type ResponseCommon struct {
	Code  int         `json:"code"`            //返回Code 200 成功 其他是失败
	Msg   interface{} `json:"message"`         //返回信息
	Count int64       `json:"count,omitempty"` // 条数
}

// 返回结构体 带Data
type Response struct {
	*ResponseCommon
	Data interface{} `json:"data"` //返回的数据
}

func (a *ApiBase) DbErrRecordNotFound(err error, msg string) {
	if err == gorm.ErrRecordNotFound {
		panic(msg)
	} else if err != nil {
		panic(err.Error())
	}
}

func (a *ApiBase) DbErrSkipRecordNotFound(err error) {
	if err != nil && err != gorm.ErrRecordNotFound {
		panic(err.Error())
	}
}

func (a *ApiBase) DbErrRecordNotFoundBool(err error) bool {
	if err == gorm.ErrRecordNotFound {
		return false
	} else if err != nil {
		return false
	}
	return true
}

func (a *ApiBase) DbErrUniqueIndexConflict(err error, msg string) error {
	if err != nil {
		if err.(*mysql.MySQLError).Number == 1062 {
			return a.ReturnErrorResponse(PublicError, msg)
		} else {
			return a.ReturnErrorResponse(ServerError, a.Translate("sys_error"))
		}
	} else {
		return nil
	}
}

func (a *ApiBase) DbErrSkipRecordNotFoundBool(err error) bool {
	if err != nil && err != gorm.ErrRecordNotFound {
		return false
	}
	return true
}

func (a *ApiBase) JSONMarshal(t interface{}) ([]byte, error) {
	buffer := &bytes.Buffer{}
	encoder := json.NewEncoder(buffer)
	encoder.SetEscapeHTML(false)
	err := encoder.Encode(t)
	return buffer.Bytes(), err
}

func (a *ApiBase) response() {

	var response []byte

	if a.IsCustomResponse {
		return
	}

	if a.Error == nil {
		if a.CustomResponse != nil {
			response, _ = a.JSONMarshal(&a.CustomResponse)
		} else if a.Response != nil {
			response, _ = a.JSONMarshal(&a.Response)
		} else {
			_ = a.ReturnErrorResponse(500, a.Error.Error())
			response, _ = a.JSONMarshal(&a.Response)
		}
	} else {
		if a.CustomResponse != nil {
			response, _ = a.JSONMarshal(&a.CustomResponse)
		} else if a.Response != nil {
			response, _ = a.JSONMarshal(&a.Response)
		} else {
			_ = a.ReturnErrorResponse(500, a.Error.Error())
			response, _ = a.JSONMarshal(&a.Response)
		}
	}

	r := string(response)
	if config.Cf.Common.RunMode == "debug" {
		logger.AccessLogger.Infof("%s 返回数据 -> %s", a.C.FullPath(), r)
	}
	a.C.String(http.StatusOK, r)
}

func (a *ApiBase) NewResponseCommon(code int, msg string) *ResponseCommon {
	return &ResponseCommon{
		Code: code,
		Msg:  msg,
	}
}

func (a *ApiBase) NewSuccessResponseCommon() *ResponseCommon {
	return a.NewResponseCommon(Success, a.Translate("success"))
}

func (a *ApiBase) NewResponse(code int, msg string, data ...interface{}) *Response {
	return &Response{
		ResponseCommon: a.NewResponseCommon(code, msg),
		Data:           dataHandler(data...),
	}
}

func (a *ApiBase) NewSuccessResponse(data ...interface{}) *Response {
	return &Response{
		ResponseCommon: a.NewSuccessResponseCommon(),
		Data:           dataHandler(data...),
	}
}

func (a *ApiBase) ReturnSuccessResponse(data ...interface{}) error {
	a.Response = a.NewSuccessResponse(data)
	return nil
}

func (a *ApiBase) ReturnErrorResponse(code int, msg string, data ...interface{}) error {
	a.Response = a.NewResponse(code, msg, data)
	a.Error = errors.New(msg)
	return a.Error
}

func (a *ApiBase) ReturnPublicErrorResponse(msg string, data ...interface{}) error {

	if len(msg) <= 0 {
		//logger.AccessLogger.Errorln("系统错误!")
		//msg = cache.Global.GetLang(a.Lang, "sys_error")
	}
	return a.ReturnErrorResponse(PublicError, msg, data...)
}

func (a *ApiBase) ReturnSuccessCustomResponse(data interface{}) error {
	a.CustomResponse = &data
	return nil
}

func dataHandler(data ...interface{}) interface{} {
	if len(data) == 1 {
		return data[0]
	} else {
		return data
	}
}