package com.bohuikeji.frame.module.admin.entity.back;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.bohuikeji.frame.module.admin.base.EntityBase;
import com.bohuikeji.frame.module.admin.base.InterfaceBase;
import com.bohuikeji.frame.module.admin.exception.MethodException;
import com.bohuikeji.frame.module.admin.exception.WebVerifiedException;
import com.bohuikeji.frame.module.admin.utils.NumberUtils;
import com.bohuikeji.frame.module.admin.utils.StringUtils;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.slf4j.helpers.MessageFormatter;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.validation.BindException;

import java.sql.SQLException;
import java.util.List;

/**
 * 接口返回处理
 * @author 10552
 */
@Slf4j
@ApiModel(value="全局接口返回实体",description="返回实体——所有接口统一的返回格式")
public class APIEntity<T> extends InterfaceBase {
    /**
     * 时间戳
     */
    @ApiModelProperty(value="【时间戳】失败返回此字段，成功不返回",name="timestamp",example="1530513668508")
    private Long timestamp;
    /**
     * 状态码
     */
    @ApiModelProperty(value="【状态码】200代表成功,其他皆为异常",name="status",example="200")
    private int status=200;
    /**
     * 描述信息
     */
    @ApiModelProperty(value="【处理结果描述】成功返回成功描述(如：成功)，失败返回失败信息(如：账号或密码错误)。",name="message",example="成功")
    private String message="请求成功";
    /**
     * 请求path
     */
    @ApiModelProperty(value="【请求路径】失败返回此字段，成功不返回。",name="path",example="/notice/tbNtoice/1")
    private String path;
    /**
     * 返回有效data
     */
    @ApiModelProperty(value="【处理结果】，成功返回此字段(如:查询结果数据)，失败不返回。",name="body",example="{}")
    private T body;
    /**
     * 接口签名
     */
    @ApiModelProperty(value="【接口签名】只有在询问模式下生效。",name="sign",example="sign")
    private String sign;

    private APIEntity(){
    }
    private APIEntity(T data){
        this.body=data;
    }
    private APIEntity(Integer status, String message){
        this.status=status;
        this.message=message;
    }
    private APIEntity(int status, String message, String path){
        this.timestamp=System.currentTimeMillis();
        this.status=status;
        this.message=message;
        this.path=path;
    }

    /*//成功
    public static APIEntity success(EntityBase data){
        return new APIEntity(data);
    }*/
    public static <T> APIEntity<T> success(List<EntityBase> dataList){
        return new APIEntity(dataList);
    }
    public static <E> APIEntity<E> success(E data){
        return new APIEntity<E>(data);
    }
    public static <T> APIEntity<T> success(){
        return new APIEntity();
    }
    //失败
    public static <T> APIEntity <T> fail(){
        return new APIEntity(400,"系统繁忙！");
    }
    public static <T> APIEntity<T> fail(String msg){
        return new <T> APIEntity<T>(400,msg);
    }
    public static <T> APIEntity <T> fail(String msg,Object... args){
        return new <T> APIEntity <T>(400, MessageFormatter.arrayFormat(msg,args).getMessage());
    }
    public static <T> APIEntity <T> fail(String msg,int status){
        return new APIEntity(status,msg);
    }


    //异常封装
    public static APIEntity exception(String msg,String path){
        return new APIEntity(500,msg,path);
    }
    public static APIEntity exception(String msg){
        return new APIEntity(500,msg,null);
    }

    //询问式封装
    public static APIEntity ask(String msg,Object... args){
        return new APIEntity(300,StringUtils.formatStr(msg,args),null).setSign(NumberUtils.getPwd());
    }

    /**
     * 检查是否成功
     * @return
     */
    public boolean checkSuccess(){
        if(status!=200){
            return false;
        }
        return true;
    }

    /**
     * 获取异常code
     * @param e
     * @return
     */
    public static APIEntity exception(Exception e){
        APIEntity apiEntity=new APIEntity();
        if(StringUtils.isBlank(e.getMessage())){
            apiEntity.setMessage("系统繁忙，请稍后再试！");
        }
        else{
            apiEntity.setMessage(e.getMessage());
        }

        if(e instanceof WebVerifiedException){
            log.error("参数校验异常：[{}]",e.getMessage());
            apiEntity.setStatus(505);
            return apiEntity;
        }
        if(e instanceof MethodException){
            log.error("内部方法错误：[{}]",e.getMessage());
            apiEntity.setStatus(506);
            return apiEntity;
        }
        log.error("Controller发生异常：",e);
        if(e instanceof BindException){
            apiEntity.setMessage("参数错误："+e.getMessage());
            apiEntity.setStatus(413);
            return apiEntity;
        }
         if (e instanceof HttpMessageNotReadableException){
            apiEntity.setMessage("参数错误！");
            apiEntity.setStatus(413);
            return apiEntity;
        }
         if (e instanceof NullPointerException) {
            apiEntity.setMessage("服务器内部错误，请联系管理员！异常定位："+e.getMessage());
            apiEntity.setStatus(501);
            return apiEntity;
            //空指针异常
        } if (e instanceof IllegalArgumentException) {
            apiEntity.setStatus(502);
            apiEntity.setMessage("参数类型不匹配："+e.getMessage());
            return apiEntity;
            //参数类型不匹配
        }  if (e instanceof SQLException) {
            apiEntity.setStatus(503);
            return apiEntity;
            //数据库异常
        } //手动抛出异常
        if(e instanceof RuntimeException){
            apiEntity.setStatus(400);
            return apiEntity;
        }else{
            apiEntity.setStatus(500);
            apiEntity.setMessage("未知异常:"+e.getMessage());
            //其他异常
        }
        return apiEntity;
    }
    public Long getTimestamp() {
        return timestamp;
    }

    public APIEntity<T> setTimestamp(Long timestamp) {
        this.timestamp = timestamp;
        return this;
    }

    public int getStatus() {
        return status;
    }

    public APIEntity<T> setStatus(int status) {
        this.status = status;
        return this;
    }

    public String getMessage() {
        return message;
    }

    public APIEntity<T> setMessage(String message) {
        this.message = message;
        return this;
    }

    public String getPath() {
        return path;
    }

    public void setPath(String path) {
        this.path = path;
    }

    public T getBody() {
        return body;
    }

    public void setBody(T body) {
        this.body = body;
    }

    public String getSign() {
        return sign;
    }
    public APIEntity<T> setSign(String sign) {
        this.sign = sign;
        return this;
    }

    /**
     * 获取泛型对象
     * @return
     */
    public T myBody(Class<T> clazz){
        return JSONObject.parseObject(JSON.toJSONString(body),clazz);
    }

    /**
     * 获取泛型集合
     * @return
     */
    public List<T> myListBody(Class<T> clazz){
        return JSONArray.parseArray(JSON.toJSONString(body),clazz);
    }

    /**
     * 获取分页对象
     * @return
     */
    public Page<T> myPage(Class<T> clazz){
        Page<T> page =new Page<T>();
        JSONObject jsonObject=JSONObject.parseObject(JSON.toJSONString(body));
        page.setTotal(jsonObject.getIntValue("total"));
        page.setSize(jsonObject.getIntValue("size"));
        page.setCurrent(jsonObject.getIntValue("current"));
        page.setRecords(jsonObject.getJSONArray("records").toJavaList(clazz));
        return page;
    }

    /**
     * 获取StringBody
     * @return
     */
    public String myStrBody(){ return body.toString();}

    @Override
    public String toString() {
        return "ResultEntity{" +
                "timestamp=" + timestamp +
                ", status=" + status +
                ", message='" + message + '\'' +
                ", path='" + path + '\'' +
                ", body=" + body +
                '}';
    }
}
