package com.sdtool.common.entity.base;

import com.sdtool.common.entity.site.ERPTokenUser;
import com.dySweetFishPlugin.tool.crypto.EncryptUtil;
import com.sweetfish.convert.json.JsonConvert;
import com.sweetfish.source.PageFlipper;
import com.sweetfish.util.AnyValue;
import com.sweetfish.util.Comment;
import org.apache.commons.lang3.StringUtils;

import java.util.HashMap;
import java.util.Map;

public class InvokeCallParams extends BaseEntity {

    private String businessMethod;

    private String timeStamp;

    /**
     * json字符串
     * 这里针对业务类的数据直接用json字符串，是当前各平台的通用做法，之前验签如果双发使用了不同的序列化工具，导致有的null的字段没有带上，序列化之后的结果会不同，验签就出现问题
     * 现在直接统一Params即可
     */
    private String params;

    /**
     * 附加字符串，params不够用的情况下，增加附件参数
     */
    @Comment("附加参数")
    private AnyValue attach;

    /**
     * 分页对象，这里还是把分页信息从params里面拆分出来，减少脚本中转换的次数
     */
    private PageFlipper page;

    /**
     * 客户编号，由我们提供
     */
    private String clientCode;

    private String openId;

    /**
     * 签名key来源
     * 0 产品中心的ERPClient
     * 1 ConfigValue里面的CallSignKey的值
     */
    private int signFrom;

    /**
     * md5串，字符串由
     * <ul>clientCode=xxx&params=xxx&timestamp=xxx</ul>
     * 组成,所有参数均使用此格式，避免扩展麻烦，至于具体的业务，则由params的json字符串定义即可
     */
    private String digest;

    private String token;

    private String forceOperatorWait; // "ASYNC","SYNC","AWAIT"

    //下面的字段由服务端赋值

    private ERPTokenUser currentUser;

    private String dataSourceId;

    private long supplierCode;

    private String callClientIP;

    private final Map<String, JsonConvert> jsonConvertMap = new HashMap<>();

    public InvokeCallParams() {
    }


    private InvokeCallParams(Builder builder) {
        setBusinessMethod(builder.businessMethod);
        setTimeStamp(builder.timeStamp);
        setParams(builder.params);
        setAttach(builder.attach);
        setPage(builder.page);
        setClientCode(builder.clientCode);
        setSignFrom(builder.signFrom);
        setDigest(builder.digest);
        setToken(builder.token);
        setForceOperatorWait(builder.forceOperatorWait);
        setCurrentUser(builder.currentUser);
        setDataSourceId(builder.dataSourceId);
        setSupplierCode(builder.supplierCode);
        setCallClientIP(builder.callClientIP);
    }

    public static Builder newBuilder() {
        return new Builder();
    }

    public boolean verifySign(String key) {
        String params = "businessMethod=" + this.businessMethod + "&clientCode=" + this.clientCode + "&params=" + this.params + "&timestamp=" + this.timeStamp + "&key=" + key;
        String newDigest = EncryptUtil.md5Digest(params);
        return StringUtils.equals(newDigest.toUpperCase(), digest);
    }

    public InvokeCallParams generateSign(String key) {
        String params = "businessMethod=" + this.businessMethod + "&clientCode=" + this.clientCode + "&params=" + this.params + "&timestamp=" + this.timeStamp + "&key=" + key;
        this.digest = EncryptUtil.md5Digest(params);
        return this;
    }

    public InvokeCallParams addConvert(String name, JsonConvert jsonConvert) {
        this.jsonConvertMap.put(name, jsonConvert);
        return this;
    }

    public JsonConvert getConvert(String name){
        return this.jsonConvertMap.get(name);
    }

    public String getBusinessMethod() {
        return businessMethod;
    }

    public void setBusinessMethod(String businessMethod) {
        this.businessMethod = businessMethod;
    }

    public String getTimeStamp() {
        return timeStamp;
    }

    public void setTimeStamp(String timeStamp) {
        this.timeStamp = timeStamp;
    }

    public String getParams() {
        return params;
    }

    public void setParams(String params) {
        this.params = params;
    }

    public ERPTokenUser getCurrentUser() {
        return currentUser;
    }

    public void setCurrentUser(ERPTokenUser currentUser) {
        this.currentUser = currentUser;
    }

    public String getDataSourceId() {
        return dataSourceId;
    }

    public void setDataSourceId(String dataSourceId) {
        this.dataSourceId = dataSourceId;
    }

    public long getSupplierCode() {
        return supplierCode;
    }

    public void setSupplierCode(long supplierCode) {
        this.supplierCode = supplierCode;
    }

    public Map<String, JsonConvert> getJsonConvertMap() {
        return jsonConvertMap;
    }

    public String getClientCode() {
        return clientCode;
    }

    public void setClientCode(String clientCode) {
        this.clientCode = clientCode;
    }

    public String getDigest() {
        return digest;
    }

    public void setDigest(String digest) {
        this.digest = digest;
    }

    public PageFlipper getPage() {
        return page;
    }

    public void setPage(PageFlipper page) {
        this.page = page;
    }

    public String getToken() {
        return token;
    }

    public void setToken(String token) {
        this.token = token;
    }

    public AnyValue getAttach() {
        return attach;
    }

    public void setAttach(AnyValue attach) {
        this.attach = attach;
    }

    public String getCallClientIP() {
        return callClientIP;
    }

    public void setCallClientIP(String callClientIP) {
        this.callClientIP = callClientIP;
    }

    public String getForceOperatorWait() {
        return forceOperatorWait;
    }

    public void setForceOperatorWait(String forceOperatorWait) {
        this.forceOperatorWait = forceOperatorWait;
    }

    public int getSignFrom() {
        return signFrom;
    }

    public void setSignFrom(int signFrom) {
        this.signFrom = signFrom;
    }

    public String getOpenId() {
        return openId;
    }

    public void setOpenId(String openId) {
        this.openId = openId;
    }

    public static final class Builder {
        private String businessMethod;
        private String timeStamp;
        private String params;
        private AnyValue attach;
        private PageFlipper page;
        private String clientCode;
        private int signFrom;
        private String digest;
        private String token;
        private ERPTokenUser currentUser;
        private String dataSourceId;
        private long supplierCode;
        private String callClientIP;
        private String forceOperatorWait;

        private Builder() {
        }

        public Builder businessMethod(String val) {
            businessMethod = val;
            return this;
        }

        public Builder timeStamp(String val) {
            timeStamp = val;
            return this;
        }

        public Builder params(String val) {
            params = val;
            return this;
        }

        public Builder attach(AnyValue val) {
            attach = val;
            return this;
        }

        public Builder page(PageFlipper val) {
            page = val;
            return this;
        }

        public Builder clientCode(String val) {
            clientCode = val;
            return this;
        }

        public Builder signFrom(int val) {
            signFrom = val;
            return this;
        }

        public Builder digest(String val) {
            digest = val;
            return this;
        }

        public Builder token(String val) {
            token = val;
            return this;
        }

        public Builder currentUser(ERPTokenUser val) {
            currentUser = val;
            return this;
        }

        public Builder dataSourceId(String val) {
            dataSourceId = val;
            return this;
        }

        public Builder supplierCode(long val) {
            supplierCode = val;
            return this;
        }

        public Builder callClientIP(String val) {
            callClientIP = val;
            return this;
        }

        public Builder forceOperatorWait(String val) {
            forceOperatorWait = val;
            return this;
        }

        public InvokeCallParams build() {
            return new InvokeCallParams(this);
        }
    }
}
