package com.nbport.zgwl.common;

import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonView;
import com.nbport.zgwl.exception.ServiceErrorCodeRange;
import com.nbport.zgwl.exception.ServiceException;
import io.swagger.v3.oas.annotations.media.Schema;

import java.io.Serial;
import java.io.Serializable;
import java.util.Objects;

public class R<T> implements Serializable {

    @Serial
    private static final long serialVersionUID = 1L;

    @Schema(description = "响应状态码", example = "0000")
    @JsonView(Views.Public.class)
    private String code;

    @Schema(description = "响应数据")
    @JsonView(Views.Public.class)
    private T result;

    @Schema(description = "响应消息", example = "操作成功")
    @JsonView(Views.Public.class)
    private String message;

    public static <T> R<T> error(R<?> result) {
        return error(result.getCode(), result.getMessage());
    }

    public static <T> R<T> error(String code, String message) {
        if (Objects.equals(GlobalErrorCodeConstants.SUCCESS.getCode(), code)) {
            throw new ServiceException(ServiceErrorCodeRange.DEFAULT, "code 必须是错误的！");
        }
        R<T> result = new R<>();
        result.code = code;
        result.message = message;
        return result;
    }

    public static <T> R<T> error(ErrorCode errorCode) {
        return error(errorCode.getCode(), errorCode.getMsg());
    }

    public static <T> R<T> success(T data) {
        R<T> result = new R<>();
        result.code = GlobalErrorCodeConstants.SUCCESS.getCode();
        result.result = data;
        result.message = "";
        return result;
    }

    public static <T> R<T> success(String message) {
        R<T> result = new R<>();
        result.code = GlobalErrorCodeConstants.SUCCESS.getCode();
        result.result = null;
        result.message = message;
        return result;
    }

    public static <T> R<T> success(String code, String message) {
        R<T> result = new R<>();
        result.code = code;
        result.result = null;
        result.message = message;
        return result;
    }

    public static <T> R<T> error(String message) {
        R<T> result = new R<>();
        result.code = GlobalErrorCodeConstants.ERROR.getCode();
        result.result = null;
        result.message = message;
        return result;
    }

    public static <T> R<T> success() {
        R<T> result = new R<>();
        result.code = GlobalErrorCodeConstants.SUCCESS.getCode();
        result.result = null;
        result.message = "";
        return result;
    }

    public static <T> R<T> data(String message, T data) {
        R<T> result = new R<>();
        result.code = GlobalErrorCodeConstants.SUCCESS.getCode();
        result.result = data;
        result.message = message;
        return result;
    }

    public static <T> R<T> data(T data) {
        R<T> result = new R<>();
        result.code = GlobalErrorCodeConstants.SUCCESS.getCode();
        result.result = data;
        result.message = null;
        return result;
    }

    public static boolean isSuccess(String code) {
        return Objects.equals(code, GlobalErrorCodeConstants.SUCCESS.getCode());
    }

    @JsonIgnore
    public boolean isSuccess() {
        return isSuccess(code);
    }

    @JsonIgnore
    public boolean isError() {
        return !isSuccess();
    }

    public void checkError() throws ServiceException {
        if (isSuccess()) {
            return;
        }
        throw new ServiceException(code, message);
    }

    @JsonIgnore
    public T getCheckedData() {
        checkError();
        return result;
    }

    public static <T> R<T> error(ServiceException serviceException) {
        return error(serviceException.getCode(), serviceException.getMessage());
    }

    public String getCode() {
        return code;
    }

    public void setCode(String code) {
        this.code = code;
    }

    public T getResult() {
        return result;
    }

    public void setResult(T result) {
        this.result = result;
    }

    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }
}
