package thyyxxk.webserver.service.medicalinsurance;

import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpEntity;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
import thyyxxk.webserver.config.exception.BizException;
import thyyxxk.webserver.constants.sidicts.SiFunction;
import thyyxxk.webserver.dao.his.medicalinsurance.SiZyDao;
import thyyxxk.webserver.utils.DateUtil;
import thyyxxk.webserver.utils.SiUtil;
import thyyxxk.webserver.utils.StringUtil;
import thyyxxk.webserver.utils.TokenUtil;

/**
 * @description: 医保交易执行
 * @author: DingJie
 * @create: 2021-05-28 15:57:26
 **/
@Slf4j
@Service
public class ExecService {
    private static final String RESULT_CODE = "infcode";
    private static final String OUTPUT = "output";
    private static final String MAC_ADDR = "FE-FC-FE-35-35-DE";
    private static final String IP_ADDR = "218.104.151.243";
    @Value("${si-api-url}")
    private String siApiUrl;
    private final SiZyDao dao;
    private volatile String signNo;

    @Autowired
    public ExecService(SiZyDao dao) {
        this.dao = dao;
    }

    private synchronized String getSignNo() {
        if (StringUtil.isBlank(signNo)) {
            signIn();
        }
        return signNo;
    }

    public synchronized void signIn() {
        JSONObject input = makeSignHeader(SiFunction.SIGN_IN);
        JSONObject signIn = new JSONObject();
        signIn.put("opter_no", "99999");
        signIn.put("mac", MAC_ADDR);
        signIn.put("ip", IP_ADDR);
        input.getJSONObject("input").put("signIn", signIn);
        JSONObject result = executeTrade(input, SiFunction.SIGN_IN);
        log.info("医保签到：\n参数：{}，\n结果：{}", input, result);
        if (null != result && result.getInteger(RESULT_CODE) == 0) {
            try {
                JSONObject output = result.getJSONObject(OUTPUT);
                signNo = output.getJSONObject("signinoutb").getString("sign_no");
                log.info("签到成功，签到号：{}", signNo);
            } catch (Exception e) {
                throw new BizException();
            }
        }
    }

    public void signOut() {
        if (StringUtil.notBlank(signNo)) {
            JSONObject input = makeSignHeader(SiFunction.SIGN_OUT);
            JSONObject signOut = new JSONObject();
            signOut.put("sign_no", signNo);
            signOut.put("opter_no", "99999");
            input.getJSONObject("input").put("signOut", signOut);
            JSONObject result = executeTrade(input, SiFunction.SIGN_OUT);
            log.info("医保签退：\n参数：{}，\n结果：{}", input, result);
            if (null != result && result.getIntValue(RESULT_CODE) == 0) {
                signNo = null;
            }
        }
    }

    private JSONObject makeSignHeader(SiFunction function) {
        JSONObject header = makePublicHeader("");
        header.put("infno", function.getCode());
        header.put("opter", "99999");
        header.put("opter_name", "全院");
        return header;
    }

    public JSONObject makeTradeHeader(SiFunction function) {
        String staffId = TokenUtil.getTokenUserId();
        String staffName = dao.selectStaffName(staffId);
        JSONObject header = makePublicHeader(SiUtil.INSTITUTION_AREA);
        header.put("infno", function.getCode());
        header.put("opter", staffId);
        header.put("opter_name", staffName);
        header.replace("sign_no", getSignNo());
        return header;
    }

    public JSONObject makeTradeHeaderWithInsureArea(SiFunction function, String insureArea) {
        String staffId = TokenUtil.getTokenUserId();
        String staffName = dao.selectStaffName(staffId);
        JSONObject header = makePublicHeader(insureArea);
        header.put("infno", function.getCode());
        header.put("opter", staffId);
        header.put("opter_name", staffName);
        header.replace("sign_no", getSignNo());
        return header;
    }

    public JSONObject makePublicHeader(String insureArea) {
        if (null == insureArea) {
            insureArea = "";
        }
        JSONObject header = new JSONObject();
        JSONObject input = new JSONObject();
        header.put("msgid", SiUtil.makeMsgId());
        header.put("mdtrtarea_admvs", SiUtil.getInstitutionArea(insureArea));
        header.put("insuplc_admdvs", insureArea);
        header.put("recer_sys_code", "医院");
        header.put("dev_no", "");
        header.put("dev_safe_info", "");
        header.put("cainfo", "");
        header.put("signtype", "");
        header.put("infver", SiUtil.API_VERSION);
        header.put("opter_type", "1");
        header.put("inf_time", DateUtil.now());
        header.put("fixmedins_code", SiUtil.INSTITUTION_ID);
        header.put("fixmedins_name", SiUtil.INSTITUTION_NAME);
        header.put("sign_no", "");
        header.put("input", input);
        return header;
    }

    public JSONObject executeTrade(JSONObject input, SiFunction function) {
        RestTemplate template = new RestTemplate();
        try {
            String result = template.postForObject(siApiUrl,
                    new HttpEntity<>(input, SiUtil.getHttpHeaders(function)), String.class);
            return JSONObject.parseObject(result);
        } catch (Exception e) {
            e.printStackTrace();
            log.error("医保网络出错", e);
            JSONObject object = new JSONObject();
            object.put("infcode", -1);
            if (e.getMessage().contains("Connection timed out")) {
                object.put("err_msg", "医保中心网络故障，连接超时。");
            } else {
                object.put("err_msg", e.getMessage());
            }
            return object;
        }
    }
}
