package com.miyzh.service;

import com.alibaba.fastjson.JSONObject;
import com.miyzh.config.ClinicListConfig;
import com.miyzh.entity.*;
import com.miyzh.mapper.prod.InsDSettlementMapper;
import com.miyzh.mapper.write.UploadMapper;
import com.miyzh.utils.CsvUtil;
import com.miyzh.utils.DateUtils;
import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.annotations.XStreamAlias;
import com.thoughtworks.xstream.io.xml.DomDriver;
import com.thoughtworks.xstream.io.xml.XmlFriendlyReplacer;
import com.thoughtworks.xstream.io.xml.XppDriver;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.codehaus.jackson.map.ser.std.ScalarSerializerBase;
import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.websocket.Session;
import java.math.BigDecimal;
import java.util.*;
import java.util.concurrent.*;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;

/**
 * description: UploadService
 * date: 2020/6/18 15:48
 * author: SZQ
 */
@Slf4j
@Service
public class UploadService {

    @Autowired
    private WsClientService wsClientService;
    @Autowired
    private UploadExceptionLogService uploadExceptionLogService;
    @Value("${scheduling.limit}")
    private int limit;
    @Value(value = "${scheduling.startDate}")
    private String startDate;
    @Value(value = "${scheduling.endDate}")
    private String endDate;
    @Value("${ws.webUrl}")
    private String webUrl;

    @Autowired
    private InsDSettlementMapper insDSettlementMapper;

    @Autowired
    private ClinicListConfig clinicListConfig;

    @Autowired
    private UploadMapper uploadMapper;

    @Autowired
    private WebSocketService webSocketService;

    public void uplodaHosByDate() {
        try {
            for(String clinicId : clinicListConfig.getList()) {
                ClcClinicIns clinicIns = insDSettlementMapper.queryClinicIns(clinicId);
                System.out.println(clinicId + "正在查询...");
                List<InsHospitalTotalSettlement> list = insDSettlementMapper.queryAllVisitCodeByClinicIdAndDays(clinicId, startDate, endDate);
                List<String> hospitalPreSettleDataList = new ArrayList<>();
                List<String> hospitalConfirmSettleDataList = new ArrayList<>();
                for(InsHospitalTotalSettlement insHospitalTotalSettlement : list) {
                    if(!StringUtils.isEmpty(insHospitalTotalSettlement.getSettleTransactionId())) {
                        InsDSettlementDetails searchSettlementDetailsList = new InsDSettlementDetails();
                        InsDSettlement searchSettlement = new InsDSettlement();
                        searchSettlement.setClinicId(clinicId);
                        searchSettlement.setSettleTransactionId(insHospitalTotalSettlement.getSettleTransactionId());
                        InsDSettlement targetSettlement = insDSettlementMapper.queryInsDSettlementList(searchSettlement);
                        if(null == targetSettlement) {
                            break;
                        }
                        searchSettlementDetailsList.setClinicId(clinicId);
                        searchSettlementDetailsList.setVisitCode(insHospitalTotalSettlement.getVisitCode());
                        List<InsDSettlementDetails> settlementDetailsList = insDSettlementMapper.queryAllInsDSettlementByVisitCode(searchSettlementDetailsList);
                        InsHospitalSign hospitalSign = insDSettlementMapper.queryInsHospitalSign(insHospitalTotalSettlement.getVisitCode(), insHospitalTotalSettlement.getPatientId(), clinicId);
                        if(null != hospitalSign) {
                            hospitalPreSettleDataList.add(hospitalPreSettleData(targetSettlement,settlementDetailsList,hospitalSign, clinicIns).getUploadInfo());
                        }
                    }
                }
                if(hospitalPreSettleDataList.size() > 0){
                    System.out.println(clinicId + "住院结算开始上传===");
                    insert(hospitalPreSettleDataList);
//                    Thread.sleep(50000);
                    System.out.println(clinicId + "住院结算上传成功");
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public void uplodaCliByDate() {
        try {
            for(String clinicId : clinicListConfig.getList()) {
                ClcClinicIns clinicIns = insDSettlementMapper.queryClinicIns(clinicId);
                System.out.println(clinicId + "正在查询...");
                List<InsClinicSettlement> list = insDSettlementMapper.queryAllVisitCodeByClinicIdCliAndDays(clinicId, startDate, endDate);
                List<String> clinicPreSettleDataList = new ArrayList<>();
                for(InsClinicSettlement insClinicSettlement : list) {
                    if(!StringUtils.isEmpty(insClinicSettlement.getSettleTransactionId())) {
                        InsDSettlementDetails searchSettlementDetailsList = new InsDSettlementDetails();
                        InsDSettlement searchSettlement = new InsDSettlement();
                        searchSettlement.setClinicId(clinicId);
                        searchSettlement.setSettleTransactionId(insClinicSettlement.getSettleTransactionId());
                        InsDSettlement targetSettlement = insDSettlementMapper.queryInsDSettlementList(searchSettlement);
                        if(null == targetSettlement) {
                            break;
                        }
                        searchSettlementDetailsList.setClinicId(clinicId);
                        searchSettlementDetailsList.setPrescriptionId(insClinicSettlement.getPrescriptionId());
                        List<InsDSettlementDetails> settlementDetailsList = insDSettlementMapper.queryAllInsDSettlementByPrescriptionId(searchSettlementDetailsList);
                        clinicPreSettleDataList.add(clinicPreSettleData(targetSettlement,insClinicSettlement,settlementDetailsList, clinicIns).getUploadInfo());
                    }
                }
                if(clinicPreSettleDataList.size() > 0){
                    System.out.println(clinicId + "门诊结算开始上传===");
                insert(clinicPreSettleDataList);
//                    Thread.sleep(50000);
                    System.out.println(clinicId + "门诊结算上传成功");
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    @Transactional
    public void insert(List<String> list) {
        for(String s : list) {
            RequestVo requestVo = toObj(s);
            try{
                int i = uploadMapper.insert(requestVo);
                if(i == 0) {
                    System.out.println(requestVo.getSerialNumber());
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
            try{
                if(null != requestVo.getBillDetailList() && requestVo.getBillDetailList().size() > 0) {
                    uploadMapper.insertDetail(requestVo.getBillDetailList());
                }
            } catch (Exception e) {
                e.printStackTrace();
            }

        }
    }
    @Transactional
    public String upload(UploadExceptionLog uploadExceptionLog) {
        try {
            Document doc = DocumentHelper.parseText(uploadExceptionLog.getUploadInfo());
            if (StringUtils.isBlank(uploadExceptionLog.getTradeCode())) {
                if (StringUtils.isBlank(doc.getRootElement().element("TradeCode").getTextTrim())) {
                    log.error("交易码不能为空");
                    return "交易码不能为空";
                }
                uploadExceptionLog.setTradeCode(doc.getRootElement().element("TradeCode").getTextTrim());
            }
            if (StringUtils.isBlank(uploadExceptionLog.getSerialNumber())) {
                if (StringUtils.isBlank(doc.getRootElement().element("SERIAL_NUMBER").getTextTrim())) {
                    return "业务流水号不能为空";
                }
                uploadExceptionLog.setSerialNumber(doc.getRootElement().element("SERIAL_NUMBER").getTextTrim());
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return runservice(uploadExceptionLog);
    };

    public String searchBySerialNo(String serialNo){
        return uploadExceptionLogService.searchBySerialNo(serialNo);
    }

    public String searchDocBySerialNo(String serialNo){
        return uploadExceptionLogService.searchDocBySerialNo(serialNo);
    }

    public String searchErrBySerialNo(String serialNo){
        return uploadExceptionLogService.searchErrBySerialNo(serialNo);
    }

    public Manage init(){
        return uploadExceptionLogService.init();
    }

    public Manage initY(){
        return uploadExceptionLogService.initY();
    }


    // 两种情况 1:第一次调用 2:第二次调用,第二次调用成功标记删除
    @Transactional
    public String runservice(UploadExceptionLog uploadExceptionLog) {
//        try{
//
//            log.info("开始上传" + new Date().toString() + "==" + uploadExceptionLog.getClinicNo());
//            String methodName = "runservice";
//            String param = uploadExceptionLog.getUploadInfo();
//            String result = wsClientService.callWebSV(webUrl, methodName, param);
//            String resultCode = JSONObject.parseObject(result).get("resultCode").toString();
//            // 第二次请求
//            if (null != uploadExceptionLog.getId() && uploadExceptionLog.getId() > 0) {
//                // 如果有返回证明请求正常,标记删除该记录并记录状态,如果再次失败证明请求参数异常,更新异常信息
//                if (StringUtils.isNotBlank(resultCode)) {
//                    uploadExceptionLog.setIsDel(0);
//                    // 成功
//                    if ("0".equals(resultCode)) {
//                        uploadExceptionLog.setStatus(1);
//                    } else {
//                        uploadExceptionLog.setStatus(3);
//                        uploadExceptionLog.setErrorMsg(JSONObject.parseObject(wsClientService.callWebSV(webUrl, methodName, param))
//                                .get("resultContent").toString());
//                    }
//                    uploadExceptionLogService.update(uploadExceptionLog);
//                }
//            } else {
//                if (StringUtils.isNotBlank(resultCode) && "1".equals(resultCode)) {
//                    uploadExceptionLog.setIsDel(0);
//                    uploadExceptionLog.setStatus(3);
//                    uploadExceptionLog.setErrorMsg(JSONObject.parseObject(wsClientService.callWebSV(webUrl, methodName, param))
//                            .get("resultContent").toString());
//                    uploadExceptionLogService.inster(uploadExceptionLog);
//                }
//            }
//            return resultCode;
//        } catch (Exception e) {
//            e.printStackTrace();
//            uploadExceptionLog.setErrorMsg(e.getCause().getMessage());
//            uploadExceptionLog.setIsDel(1);
//            uploadExceptionLog.setStatus(0);
//            if (null != uploadExceptionLog.getId() && uploadExceptionLog.getId() > 0) {
//                // 修改
//                uploadExceptionLogService.update(uploadExceptionLog);
//            } else {
//                // 新增异常记录
//                uploadExceptionLogService.inster(uploadExceptionLog);
//            }
//            return "2";
//        }

        try{
            log.info("开始上传" + new Date().toString() + "==" + uploadExceptionLog.getClinicNo());
            String xmlParam = uploadExceptionLog.getUploadInfo();
            RequestVo requestVo = toObj(xmlParam);
            int i = uploadMapper.insert(requestVo);
            if(i == 0) {
                System.out.println(requestVo.getSerialNumber());
            }
            if(null != requestVo.getBillDetailList() && requestVo.getBillDetailList().size() > 0) {
                uploadMapper.insertDetail(requestVo.getBillDetailList());
            }

        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }


    public Integer retryUpload() {
        List<UploadExceptionLog> list = uploadExceptionLogService.listUploadExceptionLogLimit(limit);
        log.info("查询异常记录" + new Date().toString());
        if (null != list && list.size() > 0) {
            list.stream().forEach(item -> {
                log.info("开始上传:" + item.getClinicNo() + item.getTradeCode() + ":" + item.getSerialNumber());
                upload(item);
            });
            return list.size();
        }
        return 0;
    }


    public Integer uploadDocStatusYesterday() {
        List<UploadExceptionLog> list = uploadExceptionLogService.listUploadDocStatus();
        log.info("查询确认结算记录" + new Date().toString());
        if (null != list && list.size() > 0) {
            list.stream().forEach(item -> {
                log.info("开始上传:" + item.getTradeCode() + ":" + item.getSerialNumber());
                upload(item);
            });
            return list.size();
        }
        return 0;
    }

    public void updateHosYesterday(){
        try {
            for(String clinicId : clinicListConfig.getList()) {
                ClcClinicIns clinicIns = insDSettlementMapper.queryClinicIns(clinicId);
                System.out.println(clinicId + "正在查询...");
                List<InsHospitalTotalSettlement> list = insDSettlementMapper.queryAllVisitCodeByClinicIdYesterday(clinicId);
                List<String> hospitalPreSettleDataList = new ArrayList<>();
                List<UploadExceptionLog> hospitalConfirmSettleDataList = new ArrayList<>();
                for(InsHospitalTotalSettlement insHospitalTotalSettlement : list) {
                    if(!StringUtils.isEmpty(insHospitalTotalSettlement.getSettleTransactionId())) {
                        InsDSettlementDetails searchSettlementDetailsList = new InsDSettlementDetails();
                        InsDSettlement searchSettlement = new InsDSettlement();
                        searchSettlement.setClinicId(clinicId);
                        searchSettlement.setSettleTransactionId(insHospitalTotalSettlement.getSettleTransactionId());
                        InsDSettlement targetSettlement = insDSettlementMapper.queryInsDSettlementList(searchSettlement);
                        searchSettlementDetailsList.setClinicId(clinicId);
                        searchSettlementDetailsList.setVisitCode(insHospitalTotalSettlement.getVisitCode());
                        List<InsDSettlementDetails> settlementDetailsList = insDSettlementMapper.queryAllInsDSettlementByVisitCode(searchSettlementDetailsList);
                        InsHospitalSign hospitalSign = insDSettlementMapper.queryInsHospitalSign(insHospitalTotalSettlement.getVisitCode(), insHospitalTotalSettlement.getPatientId(), clinicId);
                        if(null != hospitalSign) {
                            hospitalPreSettleDataList.add(hospitalPreSettleData(targetSettlement,settlementDetailsList,hospitalSign, clinicIns).getUploadInfo());
                        }
                    }
                }
                if(hospitalPreSettleDataList.size() > 0){
                    insert(hospitalPreSettleDataList);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    public void updateCliYesterday(){
        try {
            for(String clinicId : clinicListConfig.getList()) {
                    ClcClinicIns clinicIns = insDSettlementMapper.queryClinicIns(clinicId);
                    System.out.println(clinicId + "正在查询...");
                    List<InsClinicSettlement> list = insDSettlementMapper.queryAllVisitCodeByClinicIdCliYesterday(clinicId);
                    List<String> clinicPreSettleDataList = new ArrayList<>();
                    List<UploadExceptionLog> clinicConfirmSettleDataList = new ArrayList<>();
                    for(InsClinicSettlement insClinicSettlement : list) {
                        if(!StringUtils.isEmpty(insClinicSettlement.getSettleTransactionId())) {
                            InsDSettlementDetails searchSettlementDetailsList = new InsDSettlementDetails();
                            InsDSettlement searchSettlement = new InsDSettlement();
                            searchSettlement.setClinicId(clinicId);
                            searchSettlement.setSettleTransactionId(insClinicSettlement.getSettleTransactionId());
                            InsDSettlement targetSettlement = insDSettlementMapper.queryInsDSettlementList(searchSettlement);
                            searchSettlementDetailsList.setClinicId(clinicId);
                            searchSettlementDetailsList.setPrescriptionId(insClinicSettlement.getPrescriptionId());
                            List<InsDSettlementDetails> settlementDetailsList = insDSettlementMapper.queryAllInsDSettlementByPrescriptionId(searchSettlementDetailsList);
                            clinicPreSettleDataList.add(clinicPreSettleData(targetSettlement,insClinicSettlement,settlementDetailsList, clinicIns).getUploadInfo());
                            if("1".equals(insClinicSettlement.getTransforType())) {
                                clinicConfirmSettleDataList.add(clinicConfirmSettleData(clinicIns,insClinicSettlement.getVisitCode(),0));
                            } else if("2".equals(insClinicSettlement.getTransforType())) {
                                clinicConfirmSettleDataList.add(clinicConfirmSettleData(clinicIns,insClinicSettlement.getVisitCode(),2));
                            }
                        }
                    }
                    if(clinicPreSettleDataList.size() > 0){
                        insert(clinicPreSettleDataList);
                    }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

    }


    public UploadExceptionLog hospitalPreSettleData(InsDSettlement settle, List<InsDSettlementDetails> details, InsHospitalSign sign, ClcClinicIns clinicIns) {
        RequestVo req = new RequestVo();
        UploadExceptionLog uploadExceptionLog = new UploadExceptionLog();
        List<BillDetailVo> billDetailList = new ArrayList<>();
        BillDetailVo detail = null;
        req.setTradeCode("uploadPatBillInfo");
        req.setVersion("");
        req.setYljgdm(clinicIns.getInsCode());
        req.setYljgmc(clinicIns.getClinicName());
        req.setYljgxzqh("即墨区");
        req.setAgentIP("");
        req.setAgentMAC("");
        req.setJysj(DateUtils.getCurrent("yyyy-MM-dd HH:mm:ss"));
        req.setSettleTransactionId(settle.getSettleTransactionId());
        req.setDetailInvoiceId("");
        req.setPersonalTotalScore(settle.getPersonalTotalScore().toString());
        req.setInsideLargeAmountPayment(settle.getInsideLargeAmountPayment().toString());
        req.setAllSupplementInsAmount(settle.getAllSupplementInsAmount().toString());
        req.setPremiumsPaymentAmount(settle.getPremiumsPaymentAmount().toString());
        req.setLowerInsPaymentAmountThisYear(settle.getLowerInsPaymentAmountThisYear().toString());
        req.setInsType(insTypeToCode(settle.getInsType()));
        try{
            req.setSerialNumber(settle.getVisitCode().substring(7));
        } catch (Exception e) {
            req.setSerialNumber("00000000");
        }
        req.setHsNumber(sign.getHospitalMedicalRecordNo());
        req.setPatientIdstr(sign.getPatientInsuranceId());
        req.setHsPatientName(sign.getPatientName());
        req.setCbrxzqh("即墨区");
        req.setBenefitTypeCode(settle.getInsType().contains("职")?"1":"2");
        req.setBenefitType(settle.getInsType().contains("职")?"职工":"居民");
        req.setBmiConveredAmount(settle.getTotalScore().subtract(settle.getPersonalCash()));
        req.setAge(DateUtils.getYearByBirthday(DateUtils.getStrDateFormat("yyyy-MM-dd",sign.getPatientBirth())));
        req.setCkc892(DateUtils.getCurrent("yyyy-MM-dd HH:mm:ss"));
        req.setPatientBenefitGroupCode("-1");
        req.setBenefitgroupId(this.userTypeToCode(settle.getInsType()));
        req.setMpName(settle.getInsType());
        req.setGender("女".equals(sign.getPatientSex())?0:1);
        req.setPatientBirth(DateUtils.getStrDateFormat("yyyy-MM-dd",sign.getPatientBirth()));
        req.setMCardNo(sign.getIdCard());
        req.setCardType("1");
        req.setCardNo(sign.getIdCard());
        req.setPayUnit(clinicIns.getClinicName());
        req.setHsStatus("0");
        req.setContact(sign.getPatientPhone());
        req.setDocNumber(details.get(0).getSettleDetailId().substring(7));
        String settleDetailId = details.get(0).getSettleDetailId().substring(7);
        req.setBno(settleDetailId);
        req.setMedicalType(this.settleTypeToCode(settle.getSettlementBizType()));
        req.setMedicalTypeName(this.settleTypeToName(settle.getSettlementBizType()));
        req.setJzwybh(settle.getVisitCode().substring(7));
        req.setBdate(DateUtils.getStrDateFormat("yyyy-MM-dd HH:mm:ss",settle.getSettlementTime()!=null?settle.getSettlementTime():new Date()));
        req.setHospitalId(clinicIns.getInsCode());
        req.setHospitalType("4");
        req.setHospitalLevel("-2");
        req.setDeptCode(sign.getDepartmentId());
        req.setAkf005(sign.getDoctorId());
        req.setDiagnosisIn(sign.getDiagnosis1());
        req.setHsDiagnosisInName(sign.getDiagnosisValue() != null ? sign.getDiagnosisValue() : "居家巡护");
        req.setDiagnosisOut(sign.getDiagnosis1());
        req.setHsDiagnosisOutName(sign.getDiagnosisValue() != null ? sign.getDiagnosisValue() : "居家巡护");
        req.setIcd1(sign.getDiagnosis1());
        req.setIcd2(sign.getDiagnosis2());
        req.setIcd3(sign.getDiagnosis3());
        req.setIcd4("");
        req.setIcd5("");
        req.setIcd6("");
        req.setIcd7("");
        req.setIcd8("");
        req.setIcd9("");
        req.setIcd10("");
        req.setIcd11("");
        req.setIcd12("");
        req.setIcd13("");
        req.setIcd14("");
        req.setIcd15("");
        req.setIcd16("");
        req.setInDate(DateUtils.getStrDateFormat("yyyy-MM-dd",sign.getInHospitalTime()));
        req.setOutDate(DateUtils.getStrDateFormat("yyyy-MM-dd",sign.getOutHospitalTime()));
        req.setSettleDate(DateUtils.getStrDateFormat("yyyy-MM-dd",settle.getSettlementTime()));
        req.setCDate(DateUtils.getStrDateFormat("yyyy-MM-dd",settle.getCreateTime()));
        req.setTotalCost(settle.getTotalScore());
        req.setMtCode("1");
        req.setRefund("0");
        req.setRefundBNo("");
        req.setHName(clinicIns.getClinicName());
        req.setFhid(clinicIns.getInsCode());
        req.setFHName(clinicIns.getClinicName());
        req.setTHName("");
        req.setDPVisit("");
        req.setOHReasonCode("");
        req.setCDBNo("");
        req.setCdicd("");
        req.setIsPregnant("0");
        req.setIsLactation("0");
        req.setHeight("");
        req.setWeight("");
        req.setTinHosp("");
        req.setChargeBNo("");
        req.setDPMpName("");
        req.setDPDist("");
        req.setBed("");
        req.setDoctorName(sign.getDoctorName());
        // 医疗年度
        // 费用总额
        req.setTotalJe(settle.getTotalScore() != null ?settle.getTotalScore().toString() : "");
        // 起付线支付金额
        req.setPayUpLine(settle.getSelfPaymentStartLine() != null ? settle.getSelfPaymentStartLine().toString() : "");
        // 全额统筹
        req.setTotalTCJe(settle.getTotalOrdination() != null ? settle.getTotalOrdination().toString() : "");
        // 部分统筹
        req.setPartTcJe(settle.getPartOrdination() != null ? settle.getPartOrdination().toString() : "");
        // 全额自费
        req.setTotaLSelfAmount(settle.getPersonalTotalScore() != null ? settle.getPersonalTotalScore().toString() : "");
        // 救助范围外全额自费
        req.setSelfPayUpSvr(settle.getOutsideLargeAmountSelfAmount() != null ? settle.getOutsideLargeAmountSelfAmount().toString() : "");
        // 部分自费
        // 账户支付
        req.setAccPayJe(settle.getAccountPayment() != null ? settle.getAccountPayment().toString() : "");
        // 统筹支付
        req.setTcPayJe(settle.getOrdinateTotalScore() != null ? settle.getOrdinateTotalScore().toString() : "");
        // 离休账户支付
        req.setSvtPayJe(settle.getAccountPayment() != null ? settle.getAccountPayment().toString() : "");
        // 公务员补贴
        req.setSvtOffer(settle.getAgentRescueTotalScore() != null ? settle.getAgentRescueTotalScore().toString() : "");
        // 个人现金支付
        req.setGrXjPayJe(settle.getPersonalCash() != null ? settle.getPersonalCash().toString() : "");
        // 特药救助
        req.setSpecDrugSalvPayAmont(settle.getSpecialHelpPayment() != null ? settle.getSpecialHelpPayment().toString() : "");
        // 特材救助
        req.setSpecMatSalvPayAmount(settle.getSpecialMaterialSelfAmount() != null ? settle.getSpecialMaterialSelfAmount().toString() : "");
        // 范围外大额救助
        req.setLargeSalvPayAmountOu(settle.getOutsideLargeAmountSelfAmount() != null ? settle.getOutsideLargeAmountSelfAmount().toString() : "");
        // 全民补充保险-特药救助
        req.setSuppNationSpecDrugPayAmount(settle.getAllSupplementInsAmount() != null ? settle.getAllSupplementInsAmount().toString() : "");
        // 特病救助
        req.setSpecILLSalvPayAmount(settle.getSpecialDiseaseSelfAmount() != null ? settle.getSpecialDiseaseSelfAmount().toString() : "");
        // 范围内大病救助
        req.setLargeSalvPayAmountIn(settle.getInsideLargeAmountPayment() != null ? settle.getInsideLargeAmountPayment().toString() : "");
        // 超限救助
        req.setOverSalvPayAmount(settle.getBeyondLimitHelpPayment() != null ? settle.getBeyondLimitHelpPayment().toString() : "");
        // 扶贫特惠救助
        req.setDiscountInsurePayAmount(settle.getPovertyWaiverInsurancePay() != null ? settle.getPovertyWaiverInsurancePay().toString() : "");
        req.setDepartmentName(sign.getDepartmentName());
        for(InsDSettlementDetails dt:details){
            detail=new BillDetailVo();
            detail.setBDetailNo(dt.getId());
            detail.setBno(dt.getSettleDetailId());
            detail.setDetailInvoiceId("");
            detail.setDocNumber(settle.getVisitCode().substring(7));
            detail.setItemDate(DateUtils.getStrDateFormat("yyyy-MM-dd",dt.getCreateTime()));
            detail.setItemId(dt.getMedicineId());
            detail.setItemName(dt.getMedicineName());
            detail.setYyItemId(dt.getMedicineId());
            detail.setYyItemName(dt.getMedicineName());
            detail.setItemType("1".equals(dt.getDetailType())?1:0);
            detail.setPrice(dt.getMedicinePrice());
            detail.setNumbers(dt.getMedicineTotal());
            detail.setUsageUnit(StringUtils.isNotBlank(dt.getMedicineTotalUnit())?dt.getMedicineTotalUnit():"份");
            detail.setSpecification(StringUtils.isNotBlank(dt.getSpecifications())?dt.getSpecifications():"次");
            detail.setCosts(new BigDecimal(dt.getTotalCost()));
            detail.setDeptCode(sign.getDepartmentId());
            detail.setDeptName(sign.getDepartmentName());
            detail.setAKF005(sign.getDoctorId());
            detail.setDocName(sign.getDoctorName());
            detail.setZPhysicianAP("");
            detail.setDocLevel("");
            detail.setUsage(dt.getMedicineRoute()+"");
            detail.setDousage(dt.getMedicineDcyl());
            detail.setFrequencyInterval(dt.getMedicineUsage()+"");
            detail.setUsageDays(dt.getMedicineDays()+"");
            detail.setSelfProportion(new BigDecimal(dt.getSelfProportion()).setScale(2));
            detail.setEligibleAmount(new BigDecimal(dt.getTotalCost()).subtract(new BigDecimal(dt.getSelfCost())).subtract(new BigDecimal(dt.getSelfPaymentCost())));
            billDetailList.add(detail);
        }
        req.setBillDetailList(billDetailList);
        String message = this.toXml(req);
        uploadExceptionLog.setSerialNumber(req.getSerialNumber());
        uploadExceptionLog.setTradeCode(req.getTradeCode());
        uploadExceptionLog.setUploadInfo(message);
        uploadExceptionLog.setClinicNo(req.getYljgdm());
        return uploadExceptionLog;
    }

    public UploadExceptionLog hospitalConfirmSettleData(ClcClinicIns clinicIns,String visitCode,int status){
        RequestVo req=new RequestVo();
        UploadExceptionLog uploadExceptionLog = new UploadExceptionLog();
        req.setTradeCode("uploadDocStatus");
        req.setVersion("");
        req.setSerialNumber(visitCode.substring(7));
        req.setYljgdm(clinicIns.getInsCode());
        req.setYljgxzqh("即墨区");
        req.setAgentIP("");
        req.setAgentMAC("");
        req.setJysj(DateUtils.getCurrent("yyyy-MM-dd HH:mm:ss"));
        req.setStatus(status);
        String message = this.toXml(req);
        uploadExceptionLog.setSerialNumber(req.getSerialNumber());
        uploadExceptionLog.setTradeCode(req.getTradeCode());
        uploadExceptionLog.setUploadInfo(message);
        uploadExceptionLog.setClinicNo(req.getYljgdm());
        uploadExceptionLog.setStatus(req.getStatus());
        return uploadExceptionLog;
    }

    public UploadExceptionLog clinicPreSettleData(InsDSettlement settle, InsClinicSettlement insClinicSettlement, List<InsDSettlementDetails> details, ClcClinicIns clinicIns) {
        RequestVo req = new RequestVo();
        UploadExceptionLog uploadExceptionLog = new UploadExceptionLog();
        List<BillDetailVo> billDetailList=new ArrayList<>();
        BillDetailVo detail=null;
        req.setTradeCode("uploadPatBillInfo");
        req.setVersion("");
        req.setYljgdm(clinicIns.getInsCode());
        req.setYljgmc(clinicIns.getClinicName());
        req.setYljgxzqh("即墨区");
        req.setAgentIP("");
        req.setJysj(DateUtils.getStrDateFormat("yyyy-MM-dd",settle.getSettlementTime()));
        req.setSerialNumber(insClinicSettlement.getVisitCode().substring(7));
        req.setSettleTransactionId(settle.getSettleTransactionId());
        req.setHsNumber(insClinicSettlement.getHospitalCode());
        req.setPatientIdstr(insClinicSettlement.getPatientInsuranceId());
        req.setHsPatientName(insClinicSettlement.getPatientName());
        req.setCbrxzqh("即墨区");
        req.setBenefitTypeCode(insClinicSettlement.getInsPersonType().contains("职")?"1":"2");
        req.setBenefitType(insClinicSettlement.getInsPersonType().contains("职")?"职工":"居民");
        req.setBmiConveredAmount(insClinicSettlement.getInsurancePay());
        req.setDetailInvoiceId(insClinicSettlement.getDetailInvoiceId());
        req.setAge(DateUtils.getYearByBirthday(DateUtils.getStrDateFormat("yyyy-MM-dd",insClinicSettlement.getPatientBirth())));
        req.setCkc892(DateUtils.getStrDateFormat("yyyy-MM-dd",settle.getSettlementTime()));
        req.setSettleTransactionId(settle.getSettleTransactionId());
        req.setDetailInvoiceId("");
        req.setPersonalTotalScore(settle.getPersonalTotalScore().toString());
        req.setInsideLargeAmountPayment(settle.getInsideLargeAmountPayment().toString());
        req.setAllSupplementInsAmount(settle.getAllSupplementInsAmount().toString());
        req.setPremiumsPaymentAmount(settle.getPremiumsPaymentAmount().toString());
        req.setLowerInsPaymentAmountThisYear(settle.getLowerInsPaymentAmountThisYear().toString());
        req.setInsType(insTypeToCode(settle.getInsType()));
        req.setPatientBenefitGroupCode("-1");
        req.setBenefitgroupId(this.userTypeToCode(settle.getInsType()));
        req.setMpName(settle.getInsType());
        req.setGender("女".equals(insClinicSettlement.getPatientSex())?0:1);
        req.setPatientBirth(DateUtils.getStrDateFormat("yyyy-MM-dd",insClinicSettlement.getPatientBirth()));
        req.setMCardNo(insClinicSettlement.getInsuranceCardId());
        req.setMedicalType(this.settleTypeToCode(settle.getSettlementBizType()));
        req.setMedicalTypeName(this.settleTypeToName(settle.getSettlementBizType()));
        req.setCardType("1");
        req.setCardNo(insClinicSettlement.getIdCard());
        req.setPayUnit(clinicIns.getClinicName());
        req.setHsStatus("0");
        req.setContact(insClinicSettlement.getPatientPhone());
        req.setDocNumber(insClinicSettlement.getDetailInvoiceId());
        req.setBno(insClinicSettlement.getDetailInvoiceId());
        if("4".equals(insClinicSettlement.getTransforId())){
            req.setMedicalType("51001");
        }else{
            req.setMedicalType("1100"+insClinicSettlement.getTransforId());
        }
        req.setJzwybh(insClinicSettlement.getVisitCode().substring(7));
        req.setBdate(DateUtils.getStrDateFormat("yyyy-MM-dd HH:mm:ss",settle.getSettlementTime()!=null?settle.getSettlementTime():new Date()));
        req.setHospitalId(clinicIns.getInsCode());
        req.setHospitalType("4");
        req.setHospitalLevel("-2");
        req.setDeptCode(insClinicSettlement.getDepartmentId());
        req.setAkf005(insClinicSettlement.getDoctorId());
        req.setDoctorName(insClinicSettlement.getDoctorName());
        req.setDiagnosisIn(insClinicSettlement.getDiagnosis());
        req.setHsDiagnosisInName(insClinicSettlement.getDiagnosisValue());
        req.setDiagnosisOut(insClinicSettlement.getDiagnosis());
        req.setHsDiagnosisOutName(insClinicSettlement.getDiagnosisValue());
        req.setIcd1(insClinicSettlement.getDiagnosis1());
        req.setIcd2(insClinicSettlement.getDiagnosis2());
        req.setIcd3(insClinicSettlement.getDiagnosis3());
        req.setIcd4("");
        req.setIcd5("");
        req.setIcd6("");
        req.setIcd7("");
        req.setIcd8("");
        req.setIcd9("");
        req.setIcd10("");
        req.setIcd11("");
        req.setIcd12("");
        req.setIcd13("");
        req.setIcd14("");
        req.setIcd15("");
        req.setIcd16("");
        req.setInDate(DateUtils.getStrDateFormat("yyyy-MM-dd",settle.getSettlementTime()));
        req.setOutDate(DateUtils.getStrDateFormat("yyyy-MM-dd",settle.getSettlementTime()));
        req.setSettleDate(DateUtils.getStrDateFormat("yyyy-MM-dd",settle.getSettlementTime()));
        req.setCDate(DateUtils.getStrDateFormat("yyyy-MM-dd",insClinicSettlement.getCreateTime()));
        req.setTotalCost(settle.getTotalScore());
        req.setMtCode("1");
        req.setRefund("0");
        req.setRefundBNo("");
        req.setHName(clinicIns.getClinicName());
        req.setHName(clinicIns.getClinicName());
        req.setFhid(clinicIns.getInsCode());
        req.setFHName(clinicIns.getClinicName());
        req.setTHName("");
        req.setDPVisit("");
        req.setOHReasonCode("");
        req.setCDBNo("");
        req.setCdicd("");
        req.setIsPregnant("0");
        req.setIsLactation("0");
        req.setHeight("");
        req.setWeight("");
        req.setTinHosp("");
        req.setChargeBNo("");
        req.setDPMpName("");
        req.setDPDist("");
        req.setBed("");
        // 医疗年度
        // 费用总额
        req.setTotalJe(settle.getTotalScore() != null ?settle.getTotalScore().toString() : "");
        // 起付线支付金额
        req.setPayUpLine(settle.getSelfPaymentStartLine() != null ? settle.getSelfPaymentStartLine().toString() : "");
        // 全额统筹
        req.setTotalTCJe(settle.getTotalOrdination() != null ? settle.getTotalOrdination().toString() : "");
        // 部分统筹
        req.setPartTcJe(settle.getPartOrdination() != null ? settle.getPartOrdination().toString() : "");
        // 全额自费
        req.setTotaLSelfAmount(settle.getPersonalTotalScore() != null ? settle.getPersonalTotalScore().toString() : "");
        // 救助范围外全额自费
        req.setSelfPayUpSvr(settle.getOutsideLargeAmountSelfAmount() != null ? settle.getOutsideLargeAmountSelfAmount().toString() : "");
        // 部分自费
        // 账户支付
        req.setAccPayJe(settle.getAccountPayment() != null ? settle.getAccountPayment().toString() : "");
        // 统筹支付
        req.setTcPayJe(settle.getOrdinateTotalScore() != null ? settle.getOrdinateTotalScore().toString() : "");
        // 离休账户支付
        req.setSvtPayJe(settle.getAccountPayment() != null ? settle.getAccountPayment().toString() : "");
        // 公务员补贴
        req.setSvtOffer(settle.getAgentRescueTotalScore() != null ? settle.getAgentRescueTotalScore().toString() : "");
        // 个人现金支付
        req.setGrXjPayJe(settle.getPersonalCash() != null ? settle.getPersonalCash().toString() : "");
        // 特药救助
        req.setSpecDrugSalvPayAmont(settle.getSpecialHelpPayment() != null ? settle.getSpecialHelpPayment().toString() : "");
        // 特材救助
        req.setSpecMatSalvPayAmount(settle.getSpecialMaterialSelfAmount() != null ? settle.getSpecialMaterialSelfAmount().toString() : "");
        // 范围外大额救助
        req.setLargeSalvPayAmountOu(settle.getOutsideLargeAmountSelfAmount() != null ? settle.getOutsideLargeAmountSelfAmount().toString() : "");
        // 全民补充保险-特药救助
        req.setSuppNationSpecDrugPayAmount(settle.getAllSupplementInsAmount() != null ? settle.getAllSupplementInsAmount().toString() : "");
        // 特病救助
        req.setSpecILLSalvPayAmount(settle.getSpecialDiseaseSelfAmount() != null ? settle.getSpecialDiseaseSelfAmount().toString() : "");
        // 范围内大病救助
        req.setLargeSalvPayAmountIn(settle.getInsideLargeAmountPayment() != null ? settle.getInsideLargeAmountPayment().toString() : "");
        // 超限救助
        req.setOverSalvPayAmount(settle.getBeyondLimitHelpPayment() != null ? settle.getBeyondLimitHelpPayment().toString() : "");
        // 扶贫特惠救助
        req.setDiscountInsurePayAmount(settle.getPovertyWaiverInsurancePay() != null ? settle.getPovertyWaiverInsurancePay().toString() : "");
        req.setDepartmentName(insClinicSettlement.getDepartmentName());
        for(InsDSettlementDetails dt:details){
            detail=new BillDetailVo();
            detail.setBDetailNo(dt.getId());
            detail.setBno(dt.getSettleDetailId().substring(7));
            detail.setDetailInvoiceId(insClinicSettlement.getDetailInvoiceId());
            detail.setDocNumber(settle.getVisitCode().substring(7));
            detail.setItemDate(DateUtils.getStrDateFormat("yyyy-MM-dd",dt.getCreateTime()));
            detail.setItemId(dt.getMedicineId());
            detail.setItemName(dt.getMedicineName());
            detail.setYyItemId(dt.getMedicineId());
            detail.setYyItemName(dt.getMedicineName());
            detail.setItemType("1".equals(dt.getDetailType())?1:0);
            detail.setPrice(dt.getMedicinePrice());
            detail.setNumbers(dt.getMedicineTotal());
            detail.setUsageUnit(StringUtils.isNotBlank(dt.getMedicineTotalUnit())?dt.getMedicineTotalUnit():"份");
            detail.setSpecification(StringUtils.isNotBlank(dt.getSpecifications())?dt.getSpecifications():"次");
            detail.setCosts(new BigDecimal(dt.getTotalCost()));
            detail.setDeptCode(insClinicSettlement.getDepartmentId());
            detail.setDeptName(insClinicSettlement.getDepartmentName());
            detail.setAKF005(insClinicSettlement.getDoctorId());
            detail.setDocName(insClinicSettlement.getDoctorName());
            detail.setZPhysicianAP("");
            detail.setDocLevel("");
            detail.setUsage(dt.getMedicineRoute()+"");
            detail.setDousage(dt.getMedicineDcyl());
            detail.setFrequencyInterval(dt.getMedicineUsage()+"");
            detail.setUsageDays(dt.getMedicineDays()+"");
            detail.setSelfProportion(new BigDecimal(dt.getSelfProportion()).setScale(2));
            detail.setEligibleAmount(new BigDecimal(dt.getTotalCost()).subtract(new BigDecimal(dt.getSelfCost())).subtract(new BigDecimal(dt.getSelfPaymentCost())));
            billDetailList.add(detail);
        }
        req.setBillDetailList(billDetailList);
        String message = this.toXml(req);
        uploadExceptionLog.setSerialNumber(req.getSerialNumber());
        uploadExceptionLog.setTradeCode(req.getTradeCode());
        uploadExceptionLog.setUploadInfo(message);
        uploadExceptionLog.setClinicNo(req.getYljgdm());
        return uploadExceptionLog;
    }

    public UploadExceptionLog clinicConfirmSettleData(ClcClinicIns clinicIns,String visitCode,int status){
        RequestVo req=new RequestVo();
        UploadExceptionLog uploadExceptionLog = new UploadExceptionLog();
        req.setTradeCode("uploadDocStatus");
        req.setVersion("");
        req.setSerialNumber(visitCode.substring(7));
        req.setYljgdm(clinicIns.getInsCode());
        req.setYljgxzqh("即墨区");
        req.setAgentIP("");
        req.setAgentMAC("");
        req.setJysj(DateUtils.getCurrent("yyyy-MM-dd HH:mm:ss"));
        req.setStatus(status);
        String message = this.toXml(req);
        uploadExceptionLog.setSerialNumber(req.getSerialNumber());
        uploadExceptionLog.setTradeCode(req.getTradeCode());
        uploadExceptionLog.setUploadInfo(message);
        uploadExceptionLog.setClinicNo(req.getYljgdm());
        uploadExceptionLog.setStatus(req.getStatus());
        return uploadExceptionLog;
    }

    private String settleTypeToCode(String settlementType){
        String code="";
        switch (settlementType){
            case "A":
                code="12021";
                break;
            case "B":
                code="12022";
                break;
            case "C":
                code="12023";
                break;
            case "F":
                code="12026";
                break;
            case "G":
                code="12027";
                break;
            case "I":
                code="12028";
                break;
            case "J":
                code="12029";
                break;
            case "K":
                code="12030";
                break;
            case "P":
                code="12035";
                break;
            case "Q":
                code="12036";
                break;
            default:
                break;
        }
        return code;
    }

    private int getAgeByBirth(Date birthday) {
        int age = 0;
        try {
            Calendar now = Calendar.getInstance();
            now.setTime(new Date());// 当前时间

            Calendar birth = Calendar.getInstance();
            birth.setTime(birthday);

            if (birth.after(now)) {//如果传入的时间，在当前时间的后面，返回0岁
                age = 0;
            } else {
                age = now.get(Calendar.YEAR) - birth.get(Calendar.YEAR);
                if (now.get(Calendar.DAY_OF_YEAR) > birth.get(Calendar.DAY_OF_YEAR)) {
                    age += 1;
                }
            }
            return age;
        } catch (Exception e) {
            return 0;
        }
    }

    private String settleTypeToName(String settlementType){
        String name = "";
        switch (settlementType){
            case "11001":
                name = "医保门诊社区普通门诊";
                break;
            case "11002":
                name = "医保门诊大病";
                break;
            case "A":
                name="院护";
                break;
            case "B":
                name="家护";
                break;
            case "C":
                name="专护";
                break;
            case "F":
                name="巡护（社区）";
                break;
            case "G":
                name="巡护（村卫生室）";
                break;
            case "I":
                name="长期照护";
                break;
            case "J":
                name="短期照护";
                break;
            case "K":
                name="日间照护";
                break;
            case "P":
                name="巡护（机构）";
                break;
            case "Q":
                name="巡护（居家）";
                break;
            default:
                break;
        }
        return name;
    }

    private String userTypeToCode(String insType) {
        if (StringUtils.contains(insType, "在职职工")) {
            return "01";
        }
        if (StringUtils.contains(insType, "退休职工")) {
            return "02";
        }
        if (StringUtils.contains(insType, "农民工")) {
            return "03";
        } if (StringUtils.contains(insType, "在职公务员")) {
            return "04";
        }
        if (StringUtils.contains(insType, "退休公务员")) {
            return "05";
        }
        if (StringUtils.contains(insType, "退休一类保健")) {
            return "06";
        }
        if (StringUtils.contains(insType, "退休二类保健")) {
            return "07";
        }
        if (StringUtils.contains(insType, "副司级离休")) {
            return "08";
        }
        if (StringUtils.contains(insType, "在职一类保健")) {
            return "16";
        }
        if (StringUtils.contains(insType, "在职二类保健")) {
            return "17";
        }
        if (StringUtils.contains(insType, "老年居民")) {
            return "21";
        }
        if (StringUtils.contains(insType, "重度残疾人员")) {
            return "22";
        }
        if (StringUtils.contains(insType, "城镇非从业居民")) {
            return "23";
        }
        if (StringUtils.contains(insType, "少年儿童")) {
            return "24";
        }
        if (StringUtils.contains(insType, "大学生")) {
            return "25";
        }
        if (StringUtils.contains(insType, "独生子女")) {
            return "26";
        }
        if (StringUtils.contains(insType, "一类城乡居民")) {
            return "27";
        }
        if (StringUtils.contains(insType, "二类城乡居民")) {
            return "28";
        }
        if (StringUtils.contains(insType, "在职劳模")) {
            return "31";
        }
        if (StringUtils.contains(insType, "退休劳模")) {
            return "32";
        }
        return "01";
    }

    private String insTypeToCode(String insType) {
        if (StringUtils.contains(insType, "职")) {
            return "1";
        }
        if (StringUtils.contains(insType, "居")) {
            return "2";
        }
        if (StringUtils.contains(insType, "公务员")) {
            return "1";
        } if (StringUtils.contains(insType, "保健")) {
            return "1";
        }
        if (StringUtils.contains(insType, "离休")) {
            return "1";
        }
        if (StringUtils.contains(insType, "少年儿童")) {
            return "2";
        }
        if (StringUtils.contains(insType, "大学生")) {
            return "2";
        }
        if (StringUtils.contains(insType, "独生子女")) {
            return "2";
        }
        return "01";
    }


    /**
     * 将对象转为xml格式
     * @param obj
     * @return
     */
    private static String toXml(Object obj){
        XStream xstream = new XStream(new XppDriver(new
                XmlFriendlyReplacer("_- ", "_")));
        xstream.processAnnotations(obj.getClass()); //让类注解生效
        return xstream.toXML(obj);
    }

    private static RequestVo toObj(String xml){
        XStream xstream = new XStream(new DomDriver());
        xstream.processAnnotations(RequestVo.class);
        xstream.alias( "BillDetail", BillDetailVo. class);
        xstream.alias( "BillDetailList", BillDetailVo. class);
        xstream.setClassLoader(RequestVo.class.getClassLoader());
        RequestVo requestVo1 = (RequestVo) xstream.fromXML(xml);
        return requestVo1;
    }


}
