package com.wecloud.imserver.client.model.dto;

import com.fasterxml.jackson.annotation.JsonIgnore;

import java.io.Serializable;

/**
 * @Author wenzhida
 * @Date 2022/1/27 16:11
 * @Description rpc接口外层Result
 */
public class Result<T> implements Serializable {

    private static final long serialVersionUID = -8466892006788842306L;

    /**
     * 成功
     */
    private static final Integer SUCCESS_STATUS = 0;

    /**
     * 业务异常,必填字段为空，年龄为负数等
     */
    private static final Integer BUSINESS_ERROR_STATUS = -1;

    /**
     * 服务异常，数据库连接超时，空指针等
     */
    private static final Integer SERVICE_ERROR_STATUS = -2;

    /**
     * 请求参数非法
     */
    private static final Integer PARAM_ERROR_STATUS = -3;


    /**
     * 服务状态码，为integer类型， 0 为成功，-1为业务校验错误（手机号格式不对，会员不存在等），-2为服务不可用异常（sql语句异常,空指针等）。-3为请求参数非法<br/>
     */
    private Integer status = SUCCESS_STATUS;
    /**
     * 描述信息。用于返回业务校验错误信息和服务不可用异常信息，不可用于设置日志堆栈信息。举例：业务信息： msg = "手机号格式不对" ，服务不可用异常信息：msg="数据库连接池中没有空闲连接".
     */
    private String msg;

    /**
     * 业务语义状态码，用于业务语义路由，通常和msg搭配使用。当status为-1时，用该code指明具体业务校验错误
     */
    private String code;

    /**
     * 业务正常返回的消息体,每个服务使用专用data对象，不可复用。属性命名规则同数据库命名。支持数据结构包装，例如：List<data>，Set<data>。
     */
    private T data;

    /**
     * 异常堆栈信息
     */
    private String trace;

    public Result() {
    }

    public Result(Integer status, String msg, String code, T data, String trace) {
        this.status = status;
        this.msg = msg;
        this.code = code;
        this.data = data;
        this.trace = trace;
    }

    public Result(Integer status, String msg, String code, T data) {
        this(status, msg, code, data, null);
    }

    public Result(Integer status, String msg, String code) {
        this(status, msg, code, null, null);
    }

    /**
     * 请求是否成功，判断status值是否为{@link #SUCCESS_STATUS}
     *
     * @return
     */
    @JsonIgnore
    public boolean isSuccess() {
        return SUCCESS_STATUS.equals(getStatus());
    }


    /**
     * 得到服务异常 Result.msg字段值为"服务器繁忙，请稍候重试！"
     */
    public static <T> Result<T> getServiceError() {
        return getServiceError("服务器繁忙，请稍候重试！", null);
    }

    /**
     * 得到服务异常Result.
     *
     * @param message 用于设置Result.msg字段
     */
    public static <T> Result<T> getServiceError(String message) {
        return getServiceError(message, null);
    }

    /**
     * 得到服务异常Result.
     *
     * @param message 用于设置Result.msg字段
     * @param trace   用于设置Result.trace字段
     */
    public static <T> Result<T> getServiceError(String message, String trace) {
        Result<T> result = new Result<>(SERVICE_ERROR_STATUS, message, null, null, trace);
        return result;
    }


    /**
     * 得到正常结果.
     *
     * @param re 正常结果
     */
    public static <T> Result<T> getSuccessResult(T re) {
        Result<T> result = new Result<>(SUCCESS_STATUS, null, null, re);
        return result;
    }

    /**
     * 得到业务异常Result.
     *
     * @param msg  用于设置Result.msg字段
     * @param code 用于设置Result.code字段
     */
    public static <T> Result<T> getBusinessException(String msg, String code) {
        Result<T> result = new Result<>(BUSINESS_ERROR_STATUS, msg, code, null);
        return result;
    }

    /**
     * 得到业务异常Result.
     *
     * @param code 用于设置Result.code字段
     */
    public static <T> Result<T> getBusinessException(String code) {
        return getBusinessException(null, code);
    }

    /**
     * 得到请求参数非法异常Result.
     *
     * @param code 用于设置Result.code字段
     */
    public static <T> Result<T> getParamException(String code) {
        return getParamException(code, null);
    }

    /**
     * 得到请求参数非法异常Result.
     *
     * @param code 用于设置Result.code字段
     */
    public static <T> Result<T> getParamException(String code, String msg) {
        return new Result<>(PARAM_ERROR_STATUS, msg, code);
    }

    public int getStatus() {
        return status;
    }

    public String getMsg() {
        return msg;
    }

    public T getData() {
        return data;
    }

    public String getCode() {
        return code;
    }

    public String getTrace() {
        return trace;
    }


    @Override
    public String toString() {
        final StringBuilder sb = new StringBuilder("Result{");
        sb.append("status=").append(status);
        sb.append(", msg='").append(msg).append('\'');
        sb.append(", code='").append(code).append('\'');
        sb.append(", data=").append(data);
        sb.append('}');
        return sb.toString();
    }
}
