package thyyxxk.webserver.service.medicalinsurance;

import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import thyyxxk.webserver.config.envionment.SystemConfig;
import thyyxxk.webserver.config.exception.BizException;
import thyyxxk.webserver.config.exception.ExceptionEnum;
import thyyxxk.webserver.constants.sidicts.SiFunction;
import thyyxxk.webserver.dao.his.medicalinsurance.*;
import thyyxxk.webserver.entity.ResultVo;
import thyyxxk.webserver.entity.login.UserInfo;
import thyyxxk.webserver.entity.medicalinsurance.log.SiLog;
import thyyxxk.webserver.entity.medicalinsurance.psnrcd.*;
import thyyxxk.webserver.service.hutoolcache.UserCache;
import thyyxxk.webserver.utils.ResultVoUtil;
import thyyxxk.webserver.utils.TokenUtil;

import java.util.List;

/**
 * @description: 人员备案服务
 * @author: DingJie
 * @create: 2021/7/1615:13
 */
@Slf4j
@Service
public class SiPsnRcdService {
    private static final String RESULT_CODE = "infcode";
    private static final String ERROR_MESSAGE = "err_msg";
    private static final String OUTPUT = "output";
    private final ExecService exec;
    private final SlwSpcChrRcdDao slwSpcChrRcdDao;
    private final TransHospRcdDao trsHspRcdDao;
    private final PsnAsgnmtRcdDao psnAsgRcdDao;
    private final PsnAccidentRcdDao psnAccdntDao;
    private final BirthRcdDao birthRcdDao;
    private final SiLogDao logDao;
    private final UserCache userCache;
    private final SystemConfig sysCfg;

    @Autowired
    public SiPsnRcdService(ExecService exec, SlwSpcChrRcdDao dao, TransHospRcdDao trsHspRcdDao, PsnAsgnmtRcdDao psnAsgRcdDao, PsnAccidentRcdDao psnAccdntDao, BirthRcdDao birthRcdDao, SiLogDao logDao, UserCache userCache, SystemConfig sysCfg) {
        this.exec = exec;
        this.slwSpcChrRcdDao = dao;
        this.trsHspRcdDao = trsHspRcdDao;
        this.psnAsgRcdDao = psnAsgRcdDao;
        this.psnAccdntDao = psnAccdntDao;
        this.birthRcdDao = birthRcdDao;
        this.logDao = logDao;
        this.userCache = userCache;
        this.sysCfg = sysCfg;
    }

    public ResultVo<String> transferHospitalRecord(TransHospRcd trsHspRcd) {
        JSONObject input = exec.makeTradeHeaderWithInsureArea(SiFunction.TRANSFER_HOSPITAL_RECORD, trsHspRcd.getInsuOptins());
        String ref = JSONObject.toJSONStringWithDateFormat(trsHspRcd, "yyyy-MM-dd");
        input.getJSONObject("input").put("refmedin", JSONObject.parseObject(ref));
        JSONObject result = exec.executeTrade(input, SiFunction.TRANSFER_HOSPITAL_RECORD);
        if (null == result) {
            return ResultVoUtil.fail(ExceptionEnum.NETWORK_ERROR);
        }
        Integer infcode = result.getInteger(RESULT_CODE);
        logDao.insert(new SiLog(input, result, null, null, null, infcode, trsHspRcd.getPsnNo()));
        if (null == infcode) {
            return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, "医保中心报错：" + result.getString("message"));
        }
        if (infcode == 0) {
            JSONObject output = result.getJSONObject(OUTPUT);
            String trtDclaDetlSn = output.getJSONObject("result").getString("trt_dcla_detl_sn");
            trsHspRcd.setTrtDclaDetlSn(trtDclaDetlSn);
            trsHspRcdDao.insert(trsHspRcd);
            return ResultVoUtil.success("备案成功，备案明细流水号为：" + trtDclaDetlSn);
        }
        return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, result.getString(ERROR_MESSAGE));
    }

    public ResultVo<List<TransHospRcd>> getAllTrsHospRcdByPsnNo(String psnNo) {
        QueryWrapper<TransHospRcd> wrapper = new QueryWrapper<>();
        wrapper.eq("psn_no", psnNo);
        List<TransHospRcd> list = trsHspRcdDao.selectList(wrapper);
        if (null == list || list.isEmpty()) {
            return ResultVoUtil.fail(ExceptionEnum.NULL_POINTER, "没有找到此患者在本院的转院备案记录！");
        }
        return ResultVoUtil.success(list);
    }

    public ResultVo<String> revokeTransferHospitalRecord(RvkPsnRcd rvkPsnRcd) {
        JSONObject input = exec.makeTradeHeader(SiFunction.REVOKE_TRANSFER_HOSPITAL_RECORD);
        String ref = JSONObject.toJSONString(rvkPsnRcd);
        input.getJSONObject("input").put("data", JSONObject.parseObject(ref));
        JSONObject result = exec.executeTrade(input, SiFunction.REVOKE_TRANSFER_HOSPITAL_RECORD);
        if (null == result) {
            return ResultVoUtil.fail(ExceptionEnum.NETWORK_ERROR);
        }
        Integer infcode = result.getInteger(RESULT_CODE);
        logDao.insert(new SiLog(input, result, null, null, null, infcode, rvkPsnRcd.getPsnNo()));
        if (null == infcode) {
            return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, "医保中心报错：" + result.getString("message"));
        }
        if (infcode == 0) {
            trsHspRcdDao.deleteById(rvkPsnRcd.getId());
            return ResultVoUtil.success("转院备案撤销成功。");
        }
        return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, result.getString(ERROR_MESSAGE));
    }

    public ResultVo<String> specialChronicDiseasesRecord(SlwSpcDiseRcd slwSpcDiseRcd) {
        UserInfo userInfo = userCache.get(slwSpcDiseRcd.getDiagDrCodg());
        if (StrUtil.isBlank(userInfo.getYbCode())) {
            throw new BizException(ExceptionEnum.USER_NOT_EXIST, "诊断医生没有医保赋码！");
        }
        slwSpcDiseRcd.setIdeFixmedinsNo(sysCfg.getInstitutionId());
        slwSpcDiseRcd.setIdeFixmedinsName(sysCfg.getInstitutionName());
        JSONObject input = exec.makeTradeHeaderWithInsureArea(SiFunction.SPECIAL_CHRONIC_DISEASES_RECORD, slwSpcDiseRcd.getInsuOptins());
        String ref = JSONObject.toJSONStringWithDateFormat(slwSpcDiseRcd, "yyyy-MM-dd");
        input.getJSONObject("input").put("data", JSONObject.parseObject(ref));
        JSONObject result = exec.executeTrade(input, SiFunction.SPECIAL_CHRONIC_DISEASES_RECORD);
        if (null == result) {
            return ResultVoUtil.fail(ExceptionEnum.NETWORK_ERROR);
        }
        Integer infcode = result.getInteger(RESULT_CODE);
        logDao.insert(new SiLog(input, result, null, null, null, infcode, slwSpcDiseRcd.getPsnNo()));
        if (null == infcode) {
            return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, "医保中心报错：" + result.getString("message"));
        }
        if (infcode == 0) {
            JSONObject output = result.getJSONObject(OUTPUT);
            String trtDclaDetlSn = output.getJSONObject("result").getString("trt_dcla_detl_sn");
            slwSpcDiseRcd.setTrtDclaDetlSn(trtDclaDetlSn);
            slwSpcChrRcdDao.insert(slwSpcDiseRcd);
            return ResultVoUtil.success("备案成功，备案明细流水号为：" + trtDclaDetlSn);
        }
        return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, result.getString(ERROR_MESSAGE));
    }

    public ResultVo<List<SlwSpcDiseRcd>> getAllSpcChrRcdsByPsnNo(String psnNo) {
        QueryWrapper<SlwSpcDiseRcd> wrapper = new QueryWrapper<>();
        wrapper.eq("psn_no", psnNo);
        List<SlwSpcDiseRcd> list = slwSpcChrRcdDao.selectList(wrapper);
        if (null == list || list.isEmpty()) {
            return ResultVoUtil.fail(ExceptionEnum.NULL_POINTER, "没有找到此患者在本院的备案记录！");
        }
        return ResultVoUtil.success(list);
    }

    public ResultVo<String> revokeSpecialChronicDiseasesRecord(RvkPsnRcd rvkPsnRcd) {
        JSONObject input = exec.makeTradeHeader(SiFunction.REVOKE_SPECIAL_CHRONIC_DISEASES_RECORD);
        String ref = JSONObject.toJSONString(rvkPsnRcd);
        input.getJSONObject("input").put("data", JSONObject.parseObject(ref));
        JSONObject result = exec.executeTrade(input, SiFunction.REVOKE_SPECIAL_CHRONIC_DISEASES_RECORD);
        if (null == result) {
            return ResultVoUtil.fail(ExceptionEnum.NETWORK_ERROR);
        }
        Integer infcode = result.getInteger(RESULT_CODE);
        logDao.insert(new SiLog(input, result, null, null, null, infcode, rvkPsnRcd.getPsnNo()));
        if (null == infcode) {
            return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, "医保中心报错：" + result.getString("message"));
        }
        if (infcode == 0) {
            slwSpcChrRcdDao.deleteById(rvkPsnRcd.getId());
            return ResultVoUtil.success("人员慢特病备案撤销成功。");
        }
        return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, result.getString(ERROR_MESSAGE));
    }

    public ResultVo<String> personnelAssignmentRecord(PsnAsgnmtRcd psnAgnRcd) {
        psnAgnRcd.setFixmedinsCode(sysCfg.getInstitutionId());
        psnAgnRcd.setFixmedinsName(sysCfg.getInstitutionName());
        JSONObject input = exec.makeTradeHeader(SiFunction.PERSONNEL_ASSIGNMENT_RECORD);
        String ref = JSONObject.toJSONStringWithDateFormat(psnAgnRcd, "yyyy-MM-dd");
        input.getJSONObject("input").put("data", JSONObject.parseObject(ref));
        JSONObject result = exec.executeTrade(input, SiFunction.PERSONNEL_ASSIGNMENT_RECORD);
        if (null == result) {
            return ResultVoUtil.fail(ExceptionEnum.NETWORK_ERROR);
        }
        Integer infcode = result.getInteger(RESULT_CODE);
        logDao.insert(new SiLog(input, result, null, null, null, infcode, psnAgnRcd.getPsnNo()));
        if (null == infcode) {
            return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, "医保中心报错：" + result.getString("message"));
        }
        if (infcode == 0) {
            JSONObject output = result.getJSONObject(OUTPUT);
            String trtDclaDetlSn = output.getJSONObject("result").getString("trt_dcla_detl_sn");
            psnAgnRcd.setTrtDclaDetlSn(trtDclaDetlSn);
            psnAsgRcdDao.insert(psnAgnRcd);
            return ResultVoUtil.success("备案成功，备案明细流水号为：" + trtDclaDetlSn);
        }
        return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, result.getString(ERROR_MESSAGE));
    }

    public ResultVo<List<PsnAsgnmtRcd>> getAllPsnAsgnmtRcdByPsnNo(String psnNo) {
        QueryWrapper<PsnAsgnmtRcd> wrapper = new QueryWrapper<>();
        wrapper.eq("psn_no", psnNo);
        List<PsnAsgnmtRcd> list = psnAsgRcdDao.selectList(wrapper);
        if (null == list || list.isEmpty()) {
            return ResultVoUtil.fail(ExceptionEnum.NULL_POINTER, "没有找到此患者在本院的备案记录！");
        }
        return ResultVoUtil.success(list);
    }

    public ResultVo<String> revokePersonnelAssignmentRecord(RvkPsnRcd rvkPsnRcd) {
        JSONObject input = exec.makeTradeHeader(SiFunction.REVOKE_PERSONNEL_ASSIGNMENT_RECORD);
        String ref = JSONObject.toJSONString(rvkPsnRcd);
        input.getJSONObject("input").put("data", JSONObject.parseObject(ref));
        JSONObject result = exec.executeTrade(input, SiFunction.REVOKE_PERSONNEL_ASSIGNMENT_RECORD);
        if (null == result) {
            return ResultVoUtil.fail(ExceptionEnum.NETWORK_ERROR);
        }
        Integer infcode = result.getInteger(RESULT_CODE);
        logDao.insert(new SiLog(input, result, null, null, null, infcode, rvkPsnRcd.getPsnNo()));
        if (null == infcode) {
            return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, "医保中心报错：" + result.getString("message"));
        }
        if (infcode == 0) {
            psnAsgRcdDao.deleteById(rvkPsnRcd.getId());
            return ResultVoUtil.success("人员定点备案撤销成功。");
        }
        return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, result.getString(ERROR_MESSAGE));
    }

    public ResultVo<String> personnelAccidentRecord(PsnAccdntRcd psnAccdntRcd) {
        /*psnAccdntRcd.setFixmedinsCode(sysCfg.getInstitutionId());
        psnAccdntRcd.setFixmedinsName(sysCfg.getInstitutionName());*/
        JSONObject input = exec.makeTradeHeader(SiFunction.PERSONNEL_ACCIDENT_RECORD);
        String ref = JSONObject.toJSONStringWithDateFormat(psnAccdntRcd, "yyyy-MM-dd");
        input.getJSONObject("input").put("data", JSONObject.parseObject(ref));
        JSONObject result = exec.executeTrade(input, SiFunction.PERSONNEL_ACCIDENT_RECORD);
        if (null == result) {
            return ResultVoUtil.fail(ExceptionEnum.NETWORK_ERROR);
        }
        Integer infcode = result.getInteger(RESULT_CODE);
        logDao.insert(new SiLog(input, result, null, null, null, infcode, psnAccdntRcd.getPsnNo()));
        if (null == infcode) {
            return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, "医保中心报错：" + result.getString("message"));
        }
        if (infcode == 0) {
            JSONObject output = result.getJSONObject(OUTPUT);
            String trtDclaDetlSn = output.getString("trtDclaDetlSn");
            psnAccdntRcd.setTrtDclaDetlSn(trtDclaDetlSn);
            psnAccdntDao.insert(psnAccdntRcd);
            return ResultVoUtil.success("人员意外伤害备案成功，备案明细流水号为：" + trtDclaDetlSn);
        }
        return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, result.getString(ERROR_MESSAGE));
    }

    public ResultVo<String> revokePersonnelAccidentRecord(RvkPsnRcd rvkPsnRcd) {
        JSONObject input = exec.makeTradeHeader(SiFunction.REVOKE_PERSONNEL_ACCIDENT_RECORD);
        String ref = JSONObject.toJSONString(rvkPsnRcd);
        input.getJSONObject("input").put("data", JSONObject.parseObject(ref));
        JSONObject result = exec.executeTrade(input, SiFunction.REVOKE_PERSONNEL_ACCIDENT_RECORD);
        if (null == result) {
            return ResultVoUtil.fail(ExceptionEnum.NETWORK_ERROR);
        }
        Integer infcode = result.getInteger(RESULT_CODE);
        logDao.insert(new SiLog(input, result, null, null, null, infcode, rvkPsnRcd.getPsnNo()));
        if (null == infcode) {
            return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, "医保中心报错：" + result.getString("message"));
        }
        if (infcode == 0) {
            QueryWrapper<PsnAsgnmtRcd> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("trt_dcla_detl_sn", rvkPsnRcd.getTrtDclaDetlSn());
            psnAsgRcdDao.delete(queryWrapper);
            return ResultVoUtil.success("人员意外伤害备案撤销成功。");
        }
        return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, result.getString(ERROR_MESSAGE));
    }

    public ResultVo<String> birthRecord(BirthRcd birthRcd) {
        JSONObject input = exec.makeTradeHeader(SiFunction.BIRTH_RECORD);
        String ref = JSONObject.toJSONStringWithDateFormat(birthRcd, "yyyy-MM-dd");
        input.getJSONObject("input").put("data", JSONObject.parseObject(ref));
        JSONObject result = exec.executeTrade(input, SiFunction.BIRTH_RECORD);
        if (null == result) {
            return ResultVoUtil.fail(ExceptionEnum.NETWORK_ERROR);
        }
        Integer infcode = result.getInteger(RESULT_CODE);
        logDao.insert(new SiLog(input, result, null, null, null, infcode, birthRcd.getPsnNo()));
        if (null == infcode) {
            return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, "医保中心报错：" + result.getString("message"));
        }
        if (infcode == 0) {
            JSONObject output = result.getJSONObject(OUTPUT);
            String trtDclaDetlSn = output.getString("trt_dcla_detl_sn");
            if(StringUtils.isBlank(trtDclaDetlSn)) {
                trtDclaDetlSn = output.getJSONObject("result").getString("trtDclaDetlSn");
            }
            birthRcd.setTrtDclaDetlSn(trtDclaDetlSn);
            birthRcdDao.insert(birthRcd);
            return ResultVoUtil.success("生育待遇备案登记成功，备案明细流水号为：" + trtDclaDetlSn);
        }
        return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, result.getString(ERROR_MESSAGE));
    }

    public ResultVo<String> revokeBirthRecord(RvkPsnRcd rvkPsnRcd) {
        JSONObject input = exec.makeTradeHeader(SiFunction.REVOKE_BIRTH_RECORD);
        String ref = JSONObject.toJSONString(rvkPsnRcd);
        input.getJSONObject("input").put("data", JSONObject.parseObject(ref));
        JSONObject result = exec.executeTrade(input, SiFunction.REVOKE_BIRTH_RECORD);
        if (null == result) {
            return ResultVoUtil.fail(ExceptionEnum.NETWORK_ERROR);
        }
        Integer infcode = result.getInteger(RESULT_CODE);
        logDao.insert(new SiLog(input, result, null, null, null, infcode, rvkPsnRcd.getPsnNo()));
        if (null == infcode) {
            return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, "医保中心报错：" + result.getString("message"));
        }
        if (infcode == 0) {
            psnAsgRcdDao.deleteById(rvkPsnRcd.getId());
            return ResultVoUtil.success("生育待遇备案登记撤销成功。");
        }
        return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, result.getString(ERROR_MESSAGE));
    }

    public ResultVo<List<SlwSpcDiseRcd>> selectAllSpcSlwRcds(String begntime, String endtime) {
        begntime = begntime + " 00:00:00.000";
        endtime = endtime + " 23:59:59.999";
        QueryWrapper<SlwSpcDiseRcd> wrapper = new QueryWrapper<>();
        wrapper.apply("create_datetime>='" + begntime + "'");
        wrapper.apply("create_datetime<='" + endtime + "'");
        return ResultVoUtil.success(slwSpcChrRcdDao.selectList(wrapper));
    }
}
