package cn.hnthyy.thmz.controller.mz;

import cn.hnthyy.thmz.Utils.JsonUtil;
import cn.hnthyy.thmz.Utils.TokenUtil;
import cn.hnthyy.thmz.comment.UserLoginToken;
import cn.hnthyy.thmz.common.Constants;
import cn.hnthyy.thmz.entity.MzException;
import cn.hnthyy.thmz.entity.his.mz.*;
import cn.hnthyy.thmz.entity.his.zd.ZdChargeItem;
import cn.hnthyy.thmz.entity.his.zy.ZyZdAuditItem;
import cn.hnthyy.thmz.entity.thmz.PayInfo;
import cn.hnthyy.thmz.entity.thmz.User;
import cn.hnthyy.thmz.enums.ConfirmFlagEnum;
import cn.hnthyy.thmz.enums.PayMarkEnum;
import cn.hnthyy.thmz.enums.YesNoEnum;
import cn.hnthyy.thmz.pageDto.MzChargeDetailPageDto;
import cn.hnthyy.thmz.service.his.mz.*;
import cn.hnthyy.thmz.service.his.zd.ZdChargeItemService;
import cn.hnthyy.thmz.service.his.zd.ZdUnitCodeService;
import cn.hnthyy.thmz.service.his.zy.ZyZdAuditItemService;
import cn.hnthyy.thmz.service.thmz.TsmzService;
import cn.hnthyy.thmz.vo.*;
import com.auth0.jwt.interfaces.DecodedJWT;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

@Slf4j
@RestController
public class MzChargeDetailController {
    @Autowired
    private MzChargeDetailService mzChargeDetailService;
    @Autowired
    private ZdUnitCodeService zdUnitCodeService;
    @Autowired
    private EmployeeService employeeService;
    @Autowired
    private MzBillItemService mzBillItemService;
    @Autowired
    private MzReceiptSerialService mzReceiptSerialService;
    @Autowired
    private MzPatientMiService mzPatientMiService;
    @Autowired
    private ZyZdAuditItemService zyZdAuditItemService;
    @Autowired
    private ZdChargeItemService zdChargeItemService;
    @Autowired
    private MzChargeDetailYbService mzChargeDetailYbService;
    @Autowired
    private TsmzService tsmzService;

    /**
     * 查询费用列表
     *
     * @return
     */
    @UserLoginToken
    @RequestMapping(value = "/listMzChargeDetail", method = {RequestMethod.POST})
    public Map<String, Object> listMzChargeDetail(@RequestBody MzChargeDetailPageDto mzChargeDetailPageDto, HttpServletRequest httpServletRequest) {
        Map<String, Object> resultMap = new HashMap<>();
        try {
            if (mzChargeDetailPageDto == null || mzChargeDetailPageDto.getMzChargeDetail() == null) {
                resultMap.put("code", -1);
                resultMap.put("message", "费用列表查询参数不能为空");
                return resultMap;
            }
            PageViewVo pageViewVo = new PageViewVo();
            MzChargeDetail mzChargeDetail = mzChargeDetailPageDto.getMzChargeDetail();
            List<MzChargeDetail> mzChargeDetails = new ArrayList<>();
            if (PayMarkEnum.NO_CHARGE.code.equals(mzChargeDetail.getPayMark())) {
                if (StringUtils.isNotBlank(mzChargeDetail.getPatientId())) {
                    MzPatientMi mzPatientMi = mzPatientMiService.queryByPatientId(mzChargeDetail.getPatientId());
                    if(mzPatientMi==null){
                        resultMap.put("code", -1);
                        resultMap.put("message", "病人不存在！");
                        return resultMap;
                    }
                    mzChargeDetails.addAll(mzChargeDetailService.unPaidToFullChargeDetail(mzChargeDetail.getPatientId(),mzPatientMi.getName()));
                }
                if (StringUtils.isNotBlank(mzChargeDetail.getName())) {
                    List<MzPatientMi> mzPatientMis = mzPatientMiService.queryByName(mzChargeDetail.getName());
                    if (mzPatientMis != null && mzPatientMis.size() > 0) {
                        for (MzPatientMi m : mzPatientMis) {
                            if (m != null && StringUtils.isNotBlank(m.getPatientId())) {
                                mzChargeDetails.addAll(mzChargeDetailService.unPaidToFullChargeDetail(m.getPatientId(),m.getName()));
                            }
                        }
                    }
                }
                //if(StringUtils.isNotBlank(mzChargeDetail.get()))
                pageViewVo.setPageSize(100);
                pageViewVo.setTotal(mzChargeDetails.size());
            } else {
                if (mzChargeDetailPageDto.getSerialNo() != null) {
                    MzReceiptSerial mzReceiptSerial = mzReceiptSerialService.queryReceiptSerialBySerialNo(mzChargeDetailPageDto.getSerialNo());
                    if (mzReceiptSerial == null) {
                        pageViewVo.setTotal(0);
                        pageViewVo.setData(Collections.EMPTY_LIST);
                        resultMap.put("code", 0);
                        resultMap.put("message", "查询费用列表信息成功，但是当前机制号无对应的缴费信息");
                        resultMap.put("pageViewVo", pageViewVo);
                        return resultMap;
                    }
                    mzChargeDetail.setPatientId(mzReceiptSerial.getPatientId());
                    mzChargeDetail.setTimes(mzReceiptSerial.getTimes());
                }
                if (StringUtils.isBlank(mzChargeDetail.getName())) {
                    mzChargeDetail.setName(null);
                } else {
                    mzChargeDetail.setName("%" + mzChargeDetail.getName() + "%");
                }
                if (StringUtils.isBlank(mzChargeDetail.getPatientId())) {
                    mzChargeDetail.setPatientId(null);
                }
                if (StringUtils.isBlank(mzChargeDetail.getWarnDept())) {
                    mzChargeDetail.setWarnDept(null);
                }
                if (StringUtils.isBlank(mzChargeDetail.getDoctorCode())) {
                    mzChargeDetail.setDoctorCode(null);
                }
                if (YesNoEnum.YES.equals(mzChargeDetailPageDto.getOwnData())) {
                    User tokenUser = TokenUtil.getUser(httpServletRequest);
                    mzChargeDetailPageDto.setOpId(tokenUser.getUserIdCode());
                }
                pageViewVo.setPageIndex(mzChargeDetailPageDto.getPageIndex());
                pageViewVo.setPageSize(mzChargeDetailPageDto.getPageSize());
                //mzChargeDetailService.refshOldSystemReceiptData();
                pageViewVo.setTotal(mzChargeDetailService.countMzChargeDetail(mzChargeDetailPageDto));
                mzChargeDetails = mzChargeDetailService.queryMzChargeDetailWithPage(mzChargeDetailPageDto);
            }
            mzChargeDetailService.formatMzChargeDetail(mzChargeDetails);
            pageViewVo.setData(mzChargeDetails);
            resultMap.put("code", 0);
            resultMap.put("message", "查询费用列表信息成功");
            resultMap.put("pageViewVo", pageViewVo);
            return resultMap;
        } catch (MzException e) {
            log.error("查询费用列表失败，错误信息{}", e);
            resultMap.put("code", -1);
            resultMap.put("message", "查询费用列表失败,错误原因：" + e.getMessage());
            return resultMap;
        } catch (Exception e) {
            e.printStackTrace();
            resultMap.put("code", -1);
            resultMap.put("message", "查询费用列表失败，系统出错，请联系管理员");
            log.error("查询费用列表失败，系统异常，错误信息{}", e.getMessage());
            return resultMap;
        }
    }


//    /**
//     * 构造包含病人信息的挂号记录视图
//     *
//     * @param mzChargeDetails
//     * @return
//     */
//    private void formatMzChargeDetail(List<MzChargeDetail> mzChargeDetails) {
//        if (mzChargeDetails == null) {
//            return;
//        }
//        List<String> doctorCodes = mzChargeDetails.stream().filter(u -> StringUtils.isNotBlank(u.getDoctorCode())).map-util.js(u -> u.getDoctorCode()).collect(Collectors.toList());
//        Map<String, String> employeeMap = null;
//        List<Employee> employees = employeeService.queryByCodes(doctorCodes);
//        if (employees != null) {
//            employeeMap = employees.stream().collect(Collectors.toMap(Employee::getEmployeeCode, Employee::getEmployeeName));
//        }
//        for (MzChargeDetail mzChargeDetail : mzChargeDetails) {
//            if (mzChargeDetail != null) {
//                mzChargeDetail.setWarnDept(zdUnitCodeService.queryDeptNameByIdInCache(mzChargeDetail.getWarnDept()));
//                if (employeeMap != null) {
//                    String doctorCode = employeeMap.get(mzChargeDetail.getDoctorCode());
//                    mzChargeDetail.setDoctorCode(doctorCode == null ? "" : doctorCode);
//                }
//                if (mzChargeDetail.getAmount() != null) {
//                    mzChargeDetail.setAmount(mzChargeDetail.getAmount().setScale(1, BigDecimal.ROUND_HALF_UP));
//                }
//            }
//        }
//    }


    /**
     * 查询费用明细列表
     *
     * @return
     */
    @UserLoginToken
    @RequestMapping(value = "/getMzChargeDetailByBillItem", method = {RequestMethod.POST})
    public Map<String, Object> getMzChargeDetailByBillItem(@RequestBody MzChargeDetail mzChargeDetail) {
        Map<String, Object> resultMap = new HashMap<>();
        try {
            if (mzChargeDetail == null) {
                resultMap.put("code", -1);
                resultMap.put("message", "费用明细列表查询参数不能为空");
                return resultMap;
            }
            if (StringUtils.isBlank(mzChargeDetail.getPatientId())) {
                resultMap.put("code", -1);
                resultMap.put("message", "病人编码不能为空");
                return resultMap;
            }
            if (mzChargeDetail.getTimes() == null) {
                resultMap.put("code", -1);
                resultMap.put("message", "病人就诊次数不能为空");
                return resultMap;
            }
            if (StringUtils.isBlank(mzChargeDetail.getBillItemCode())) {
                resultMap.put("code", -1);
                resultMap.put("message", "费用类型不能为空");
                return resultMap;
            }
            List<MzChargeDetail> mzChargeDetailList;
            if (PayMarkEnum.NO_CHARGE.code.equals(mzChargeDetail.getPayMark())) {
                mzChargeDetailList = mzChargeDetailService.getTempMzChargeDetailListForUnPaid(mzChargeDetail);
            } else {
                if (mzChargeDetail.getReceiptNo() == null) {
                    resultMap.put("code", -1);
                    resultMap.put("message", "缴费次数不能为空");
                    return resultMap;
                }
                List<String> billItemTypes = new ArrayList<>();
                if ("0".equals(mzChargeDetail.getBillItemCode())) {
                    billItemTypes.add("010");
                    billItemTypes.add("011");
                } else if ("1".equals(mzChargeDetail.getBillItemCode())) {
                    billItemTypes.add("012");
                } else if ("2".equals(mzChargeDetail.getBillItemCode())) {
                    billItemTypes.add("010");
                    billItemTypes.add("011");
                    billItemTypes.add("012");
                    billItemTypes.add("020");
                    billItemTypes.add("TC");
                }
                mzChargeDetailList = mzChargeDetailService.queryMzChargeDetailByBillItemCode(mzChargeDetail.getPatientId(), mzChargeDetail.getTimes(),mzChargeDetail.getReceiptNo(), mzChargeDetail.getPayMark(), mzChargeDetail.getBillItemCode(), billItemTypes);
            }
            mzChargeDetailList = mzChargeDetailService.getMzChargeDetails(mzChargeDetailList);
            resultMap.put("code", 0);
            resultMap.put("message", "查询费用明细列表信息成功");
            resultMap.put("data", mzChargeDetailList);
            return resultMap;
        } catch (MzException e) {
            resultMap.put("code", -1);
            resultMap.put("message", "缴费失败，" + e.getMessage());
            log.error("缴费失败，系统异常，错误信息{}", e);
            return resultMap;
        } catch (Exception e) {
            e.printStackTrace();
            resultMap.put("code", -1);
            resultMap.put("message", "查询费用明细列表失败，系统出错，请联系管理员");
            log.error("查询费用明细列表失败");
            return resultMap;
        }
    }

//    /**
//     * 将套餐归类，并计算总费用
//     *
//     * @param mzChargeDetailList
//     * @return
//     */
//    private List<MzChargeDetail> getMzChargeDetails(List<MzChargeDetail> mzChargeDetailList) {
//        if (mzChargeDetailList != null) {
//            for (MzChargeDetail md : mzChargeDetailList) {
//                md.setAmount((md.getUnitPrice() == null ? BigDecimal.ZERO : md.getUnitPrice()).multiply(BigDecimal.valueOf(md.getQuantity() == null ? 1D : md.getQuantity())).multiply(BigDecimal.valueOf(md.getDrugWin() == null ? 1D : md.getDrugWin())).setScale(2, BigDecimal.ROUND_HALF_UP));
//                if (!Constants.YJ_GROUP_NO.equals(md.getGroupNo())) {
//                    YpZdDict ypZdDict = ypZdDictService.queryYpZdDictByCode(md.getChargeItemCode(), md.getSerial());
//                    if (ypZdDict != null) {
//                        md.setTcName(ypZdDict.getName());
//                    }
//                }
//            }
//            Collections.sort(mzChargeDetailList); // 按处方号排序
//        }
//        return mzChargeDetailList;
//    }


    /**
     * 收费
     *
     * @return
     */
    @UserLoginToken
    @RequestMapping(value = "/chargeFee", method = {RequestMethod.POST})
    public Map<String, Object> chargeFee(@RequestBody MzDepositFileVo mzDepositFileVo, HttpServletRequest httpServletRequest) {
        Map<String, Object> resultMap = new HashMap<>();
        try {
            if (mzDepositFileVo == null) {
                resultMap.put("code", -1);
                resultMap.put("message", "费用参数不能为空");
                return resultMap;
            }
            if (StringUtils.isBlank(mzDepositFileVo.getPatientId())) {
                resultMap.put("code", -1);
                resultMap.put("message", "病人编码不能为空");
                return resultMap;
            }
            if (mzDepositFileVo.getTimes() == null) {
                resultMap.put("code", -1);
                resultMap.put("message", "病人就诊次数不能为空");
                return resultMap;
            }
            if (mzDepositFileVo.getReceiptNo() == null) {
                resultMap.put("code", -1);
                resultMap.put("message", "病人结算次数不能为空");
                return resultMap;
            }
            if (mzDepositFileVo.getMzDepositFiles() == null || mzDepositFileVo.getMzDepositFiles().size() == 0) {
                resultMap.put("code", -1);
                resultMap.put("message", "费用方式不能为空");
                return resultMap;
            }
            String token = TokenUtil.getToken(httpServletRequest);
            if (StringUtils.isBlank(token)) {
                resultMap.put("code", -1);
                resultMap.put("message", "缴费失败,用户Token不存在");
                return resultMap;
            }
            DecodedJWT decodedJWT = TokenUtil.parseJWT(token);
            User tokenUser = (User) JsonUtil.jsontoObject(decodedJWT.getSubject(), User.class);
            List<MzReceiptSerial> mzReceiptSerials = mzReceiptSerialService.queryTallyReceiptSerialByIdAndTimes(mzDepositFileVo.getPatientId(), mzDepositFileVo.getTimes(),mzDepositFileVo.getReceiptNo());
            if (mzReceiptSerials != null && mzReceiptSerials.size() > 0) {
                //本院记账退费重收操作
//                for (MzDepositFile m : mzDepositFileVo.getMzDepositFiles()) {
//                    if (Constants.BYJZ.equals(m.getChequeType())) {
//                        resultMap.put("code", -1);
//                        resultMap.put("message", "本院记账退费重收不能再选择记账收费方式");
//                        return resultMap;
//                    }
//                }
                int receiptNo = mzChargeDetailService.chargeFeeForByjz(tokenUser.getUserIdCode(), mzDepositFileVo);
                resultMap.put("receiptNo", receiptNo);
            } else {
                int receiptNo =mzChargeDetailService.chargeFee(tokenUser.getUserIdCode(), mzDepositFileVo);
                resultMap.put("receiptNo", receiptNo);
            }
            resultMap.put("code", 0);
            resultMap.put("message", "缴费成功");
            return resultMap;
        } catch (MzException e) {
            e.printStackTrace();
            resultMap.put("code", -1);
            resultMap.put("message", "缴费失败，" + e.getMessage());
            log.error("缴费失败，系统异常，错误信息【{}】", e);
            return resultMap;
        } catch (Exception e) {
            e.printStackTrace();
            resultMap.put("code", -1);
            resultMap.put("message", "缴费失败，系统出错，请联系管理员");
            log.error("缴费失败，系统异常" + e);
            return resultMap;
        }
    }


    /**
     * 修改病人姓名  120病人缴费时调用
     *
     * @param mzChargeDetail
     * @return
     */
    @UserLoginToken
    @RequestMapping(value = "/changePatientIdName", method = {RequestMethod.POST})
    public Map<String, Object> changePatientIdName(@RequestBody MzChargeDetail mzChargeDetail) {
        Map<String, Object> resultMap = new HashMap<>();
        try {
            if (mzChargeDetail == null) {
                resultMap.put("code", -1);
                resultMap.put("message", "参数不能为空");
                return resultMap;
            }
            if (StringUtils.isBlank(mzChargeDetail.getName())) {
                resultMap.put("code", -1);
                resultMap.put("message", "病人姓名不能为空");
                return resultMap;
            }
            if (StringUtils.isBlank(mzChargeDetail.getPatientId())) {
                resultMap.put("code", -1);
                resultMap.put("message", "病人编码不能为空");
                return resultMap;
            }
            if (mzChargeDetail.getTimes() == null) {
                resultMap.put("code", -1);
                resultMap.put("message", "病人就诊次数集合不能为空");
                return resultMap;
            }
            mzChargeDetailService.modifyNameByPatientIdAndTimes(mzChargeDetail.getName(), mzChargeDetail.getPatientId(), mzChargeDetail.getTimes());
            resultMap.put("code", 0);
            resultMap.put("message", "病人姓名更新成功");
            return resultMap;
        } catch (Exception e) {
            resultMap.put("code", -1);
            resultMap.put("message", "病人姓名更新失败，系统出错，请联系管理员");
            log.error("病人姓名更新失败，系统异常，错误信息{}", e.getMessage());
            return resultMap;
        }
    }


    /**
     * 查询退费明细列表
     *
     * @return
     */
    @UserLoginToken
    @RequestMapping(value = "/getRefundFeeDetail", method = {RequestMethod.POST})
    public Map<String, Object> getRefundFeeDetail(@RequestBody MzChargeDetail mzChargeDetail) {
        Map<String, Object> resultMap = new HashMap<>();
        try {
            if (mzChargeDetail == null) {
                resultMap.put("code", -1);
                resultMap.put("message", "查询退费明细列表参数不能为空");
                return resultMap;
            }
            if (StringUtils.isBlank(mzChargeDetail.getPatientId())) {
                resultMap.put("code", -1);
                resultMap.put("message", "病人编码不能为空");
                return resultMap;
            }
            if (mzChargeDetail.getTimes() == null) {
                resultMap.put("code", -1);
                resultMap.put("message", "病人就诊次数不能为空");
                return resultMap;
            }
            if (mzChargeDetail.getReceiptNo() == null) {
                resultMap.put("code", -1);
                resultMap.put("message", "病人就缴费次数不能为空");
                return resultMap;
            }
            mzChargeDetail.setPayMark(PayMarkEnum.CHARGED.code);
            List<MzChargeDetail> mzChargeDetailList = mzChargeDetailService.queryChargeDetail(mzChargeDetail);
            List<BillItem> mzBillItems = mzBillItemService.queryMzBillItem();
            Map<String, String> mzBillItemMap = null;
            if (mzBillItems != null) {
                mzBillItemMap = mzBillItems.stream().collect(Collectors.toMap(BillItem::getCode, BillItem::getName));
            }
            List<MzChargeDetail> removeList = new ArrayList<>();
            if (mzChargeDetailList != null && mzChargeDetailList.size() > 0) {
                MzChargeDetailYb mzChargeDetailYb = new  MzChargeDetailYb();
                mzChargeDetailYb.setPatientId(mzChargeDetail.getPatientId());
                mzChargeDetailYb.setTimes(mzChargeDetail.getTimes());
                mzChargeDetailYb.setReceiptNo(mzChargeDetail.getReceiptNo());
                int count = mzChargeDetailYbService.queryTmCount(mzChargeDetailYb);
                for (MzChargeDetail md : mzChargeDetailList) {
                    if ("TC".equals(md.getBillItemCode()) || Constants.SSWRF.equals(md.getBillItemCode())) {
                        removeList.add(md);
                        continue;
                    }
                    if (mzBillItemMap != null) {
                        md.setBillItemCode(mzBillItemMap.get(md.getBillItemCode()));
                    }
                    md.setExecDept(zdUnitCodeService.queryDeptNameByIdInCache(md.getExecDept()));
                    md.setAmount((md.getUnitPrice() == null ? BigDecimal.ZERO : md.getUnitPrice()).multiply(BigDecimal.valueOf(md.getQuantity() == null ? 1D : md.getQuantity())).multiply(BigDecimal.valueOf(md.getDrugWin() == null ? 1D : md.getDrugWin())));
                    if(count>0){
                        //特门必须全退
                        md.setConfirmFlag(ConfirmFlagEnum.DONE.code);
                    }
                }
            }
            mzChargeDetailList.removeAll(removeList);
            mzChargeDetailService.getMzChargeDetails(mzChargeDetailList);
            resultMap.put("code", 0);
            resultMap.put("message", "查询退费明细列表信息成功");
            resultMap.put("data", mzChargeDetailList);
            return resultMap;
        } catch (Exception e) {
            e.printStackTrace();
            resultMap.put("code", -1);
            resultMap.put("message", "查询退费明细列表失败，系统出错，请联系管理员");
            log.error("查询退费明细列表失败，系统异常，错误信息{}", e.getMessage());
            return resultMap;
        }
    }


    /**
     * 获取退费后新产生的缴费信息
     *
     * @return
     */
    @UserLoginToken
    @RequestMapping(value = "/getNewListForRefundFee", method = {RequestMethod.POST})
    public Map<String, Object> getNewListForRefundFee(@RequestBody MzDepositFileVo mzDepositFileVo, HttpServletRequest httpServletRequest) {
        Map<String, Object> resultMap = new HashMap<>();
        try {
            if (mzDepositFileVo == null) {
                resultMap.put("code", -1);
                resultMap.put("message", "退费参数不能为空");
                return resultMap;
            }
            if (StringUtils.isBlank(mzDepositFileVo.getPatientId())) {
                resultMap.put("code", -1);
                resultMap.put("message", "病人编码参数不能为空");
                return resultMap;
            }
            if (mzDepositFileVo.getTimes() == null) {
                resultMap.put("code", -1);
                resultMap.put("message", "病人就诊次数参数不能为空");
                return resultMap;
            }
            if (mzDepositFileVo.getReceiptNo() == null) {
                resultMap.put("code", -1);
                resultMap.put("message", "病人结算次数参数不能为空");
                return resultMap;
            }
            if (StringUtils.isBlank(mzDepositFileVo.getChargeItemCodes())) {
                resultMap.put("code", -1);
                resultMap.put("message", "没有选择需要退费的收费明细，无法退费");
                return resultMap;
            }
            String token = TokenUtil.getToken(httpServletRequest);
            if (StringUtils.isBlank(token)) {
                resultMap.put("code", -1);
                resultMap.put("message", "退费失败,用户Token不存在");
                return resultMap;
            }
            MzChargeDetailPageDto mzChargeDetailPageDto = new MzChargeDetailPageDto();
            mzChargeDetailPageDto.setPageIndex(0);
            mzChargeDetailPageDto.setPageSize(10);
            mzChargeDetailPageDto.setMzChargeDetail(new MzChargeDetail(mzDepositFileVo.getPatientId(), mzDepositFileVo.getTimes()));
            mzChargeDetailPageDto.getMzChargeDetail().setPayMark(PayMarkEnum.CHARGED.code);
            List<MzChargeDetail> oriMzChargeDetails = mzChargeDetailService.queryMzChargeDetailWithPage(mzChargeDetailPageDto);
            MzChargeDetail oriMzChargeDetail = oriMzChargeDetails.get(0);
            if(oriMzChargeDetails.size()>1){
                for (MzChargeDetail mz:oriMzChargeDetails){
                    if(mz.getReceiptNo().equals(mzDepositFileVo.getReceiptNo())){
                        oriMzChargeDetail=mz;
                    }
                }
            }
            if (oriMzChargeDetail.getAmount() != null) {
                oriMzChargeDetail.setAmount(oriMzChargeDetail.getAmount().setScale(1, BigDecimal.ROUND_HALF_UP));
            }
            BigDecimal oriAmount = BigDecimal.ZERO;
            if (oriMzChargeDetail != null) {
                oriAmount = oriMzChargeDetail.getAmount();
            }
            DecodedJWT decodedJWT = TokenUtil.parseJWT(token);
            User tokenUser = (User) JsonUtil.jsontoObject(decodedJWT.getSubject(), User.class);
            List<MzChargeDetail> mzChargeDetails = mzChargeDetailService.getNewListForRefundFee(tokenUser.getUserIdCode(), mzDepositFileVo, YesNoEnum.NO);
            PageViewVo pageViewVo = new PageViewVo();
            if (mzChargeDetails == null || mzChargeDetails.size() == 0) {
                MzChargeDetail returnMzChargeDetail = new MzChargeDetail();
                returnMzChargeDetail.setPatientId(mzDepositFileVo.getPatientId());
                returnMzChargeDetail.setName(oriMzChargeDetails.get(0).getName());
                returnMzChargeDetail.setAmount(BigDecimal.ZERO);
                returnMzChargeDetail.setOriAmount(oriAmount);
                returnMzChargeDetail.setRefundFee(oriAmount);
                pageViewVo.setTotal(0);
                pageViewVo.setData(Arrays.asList(returnMzChargeDetail));
                resultMap.put("code", 0);
                resultMap.put("message", "预退费操作成功");
                resultMap.put("pageViewVo", pageViewVo);
                resultMap.put("mzChargeDetails", mzChargeDetails);
                return resultMap;
            }
            MzChargeDetail returnMzChargeDetail = getMzChargeDetail(mzDepositFileVo.getPatientId(), mzChargeDetails.get(0).getTimes(), mzChargeDetails);
            returnMzChargeDetail.setOriAmount(oriAmount);
            returnMzChargeDetail.setRefundFee(oriAmount.subtract(returnMzChargeDetail.getAmount()).setScale(1, BigDecimal.ROUND_HALF_UP));
            List<MzChargeDetail> realMzChargeDetails = Arrays.asList(returnMzChargeDetail);
            pageViewVo.setTotal(realMzChargeDetails.size());
            mzChargeDetailService.formatMzChargeDetail(realMzChargeDetails);
            pageViewVo.setData(realMzChargeDetails);
            resultMap.put("code", 0);
            resultMap.put("message", "预退费操作成功");
            resultMap.put("pageViewVo", pageViewVo);
            resultMap.put("mzChargeDetails", mzChargeDetails);
            return resultMap;
        } catch (MzException e){
            resultMap.put("code", -1);
            resultMap.put("message", e.getMessage());
            log.error("预退费操作失败，系统异常，错误信息{}", e);
            return resultMap;
        } catch (Exception e){
            e.printStackTrace();
            resultMap.put("code", -1);
            resultMap.put("message", "预退费操作失败，系统出错，请联系管理员");
            log.error("预退费操作失败，系统异常，错误信息{}", e.getMessage());
            return resultMap;
        }
    }


    /**
     * 将收费明细列表转成总计费用
     *
     * @param patientId
     * @param times
     * @param mzChargeDetails
     * @return
     */
    private MzChargeDetail getMzChargeDetail(String patientId, Integer times, List<MzChargeDetail> mzChargeDetails) {
        MzChargeDetail returnMzChargeDetail = new MzChargeDetail();
        returnMzChargeDetail.setSerialNo(0);
        returnMzChargeDetail.setPatientId(patientId);
        returnMzChargeDetail.setTimes(times);
        returnMzChargeDetail.setAmount(BigDecimal.ZERO);
        for (MzChargeDetail md : mzChargeDetails) {
            if (StringUtils.isBlank(returnMzChargeDetail.getName())) {
                returnMzChargeDetail.setName(md.getName());
            }
            if (returnMzChargeDetail.getReceiptNo() == null) {
                returnMzChargeDetail.setReceiptNo(md.getReceiptNo());
            }
            if (StringUtils.isBlank(returnMzChargeDetail.getDoctorCode())) {
                returnMzChargeDetail.setDoctorCode(md.getDoctorCode());
            }
            if (StringUtils.isBlank(returnMzChargeDetail.getWarnDept())) {
                returnMzChargeDetail.setWarnDept(md.getWarnDept());
            }
            if (returnMzChargeDetail.getPriceTime() == null) {
                returnMzChargeDetail.setPriceTime(md.getPriceTime());
            }
            BigDecimal price= (md.getUnitPrice() == null ? BigDecimal.ZERO : md.getUnitPrice()).setScale(2, BigDecimal.ROUND_HALF_UP);
            if(BigDecimal.ZERO.compareTo(price)==0){
                price=BigDecimal.valueOf(0.01);
            }
            BigDecimal tempAmount = price.multiply(BigDecimal.valueOf(md.getQuantity() == null ? 1D : md.getQuantity())).multiply(BigDecimal.valueOf(md.getDrugWin() == null ? 1D : md.getDrugWin()));
            returnMzChargeDetail.setAmount(returnMzChargeDetail.getAmount().add(tempAmount));
        }
        returnMzChargeDetail.setAmount(returnMzChargeDetail.getAmount().setScale(1, BigDecimal.ROUND_HALF_UP));
        return returnMzChargeDetail;
    }


    /**
     * 获取退费后新产生的缴费明细分类信息
     *
     * @return
     */
    @UserLoginToken
    @RequestMapping(value = "/getNewListForRefundFeeByBillItem", method = {RequestMethod.POST})
    public Map<String, Object> getNewListForRefundFeeByBillItem(@RequestBody MzDepositFileVo mzDepositFileVo, HttpServletRequest httpServletRequest) {
        Map<String, Object> resultMap = new HashMap<>();
        try {
            if (mzDepositFileVo == null) {
                resultMap.put("code", -1);
                resultMap.put("message", "退费参数不能为空");
                return resultMap;
            }
            if (StringUtils.isBlank(mzDepositFileVo.getPatientId())) {
                resultMap.put("code", -1);
                resultMap.put("message", "病人编码参数不能为空");
                return resultMap;
            }
            if (mzDepositFileVo.getTimes() == null) {
                resultMap.put("code", -1);
                resultMap.put("message", "病人就诊次数参数不能为空");
                return resultMap;
            }
            if (StringUtils.isBlank(mzDepositFileVo.getChargeItemCodes())) {
                resultMap.put("code", -1);
                resultMap.put("message", "没有选择需要退费的收费明细，无法退费");
                return resultMap;
            }
            if (StringUtils.isBlank(mzDepositFileVo.getBillItemCode())) {
                resultMap.put("code", -1);
                resultMap.put("message", "费用类型不能为空");
                return resultMap;
            }
            String token = TokenUtil.getToken(httpServletRequest);
            if (StringUtils.isBlank(token)) {
                resultMap.put("code", -1);
                resultMap.put("message", "退费失败,用户Token不存在");
                return resultMap;
            }
            DecodedJWT decodedJWT = TokenUtil.parseJWT(token);
            User tokenUser = (User) JsonUtil.jsontoObject(decodedJWT.getSubject(), User.class);
            List<MzChargeDetail> mzChargeDetails = mzChargeDetailService.getTempMzChargeDetailListForNewListForRefundFee(tokenUser.getUserIdCode(), mzDepositFileVo, YesNoEnum.NO);
            mzChargeDetails = mzChargeDetailService.getMzChargeDetails(mzChargeDetails);
            resultMap.put("code", 0);
            resultMap.put("message", "查询费用明细列表信息成功");
            resultMap.put("data", mzChargeDetails);
            return resultMap;
        } catch (Exception e) {
            e.printStackTrace();
            resultMap.put("code", -1);
            resultMap.put("message", "预退费操作失败，系统出错，请联系管理员");
            log.error("预退费操作失败，系统异常，错误信息{}", e.getMessage());
            return resultMap;
        }
    }


    /**
     * 保存退费信息
     *
     * @return
     */
    @UserLoginToken
    @RequestMapping(value = "/saveRefundFee", method = {RequestMethod.POST})
    public Map<String, Object> saveRefundFee(@RequestBody MzDepositFileVo mzDepositFileVo, HttpServletRequest httpServletRequest) {
        Map<String, Object> resultMap = new HashMap<>();
        try {
            if (mzDepositFileVo == null) {
                resultMap.put("code", -1);
                resultMap.put("message", "退费参数不能为空");
                return resultMap;
            }
            if (StringUtils.isBlank(mzDepositFileVo.getPatientId())) {
                resultMap.put("code", -1);
                resultMap.put("message", "病人编码参数不能为空");
                return resultMap;
            }
            if (mzDepositFileVo.getTimes() == null) {
                resultMap.put("code", -1);
                resultMap.put("message", "病人就诊次数参数不能为空");
                return resultMap;
            }
            if (mzDepositFileVo.getReceiptNo() == null) {
                resultMap.put("code", -1);
                resultMap.put("message", "病人缴费次数参数不能为空");
                return resultMap;
            }
            if (StringUtils.isBlank(mzDepositFileVo.getChargeItemCodes())) {
                resultMap.put("code", -1);
                resultMap.put("message", "没有选择需要退费的收费明细，无法退费");
                return resultMap;
            }
            String token = TokenUtil.getToken(httpServletRequest);
            if (StringUtils.isBlank(token)) {
                resultMap.put("code", -1);
                resultMap.put("message", "退费失败,用户Token不存在");
                return resultMap;
            }
            DecodedJWT decodedJWT = TokenUtil.parseJWT(token);
            User tokenUser = (User) JsonUtil.jsontoObject(decodedJWT.getSubject(), User.class);
            //如果返回的是0，表示全退，大于0，表示新的收费记录的就诊次数
            int times = mzChargeDetailService.refundFee(tokenUser.getUserIdCode(), mzDepositFileVo);
            resultMap.put("code", 0);
            resultMap.put("times", times);
            resultMap.put("patientId", mzDepositFileVo.getPatientId());
            resultMap.put("message", "退费操作成功");
            return resultMap;
        } catch (MzException e) {
            resultMap.put("code", -1);
            resultMap.put("message", e.getMessage());
            log.error("退费操作失败，系统异常，错误信息{}", e);
            return resultMap;
        } catch (Exception e) {
            e.printStackTrace();
            resultMap.put("code", -1);
            resultMap.put("message", "退费操作失败，系统出错，请联系管理员");
            log.error("退费操作失败，系统异常，错误信息{}", e.getMessage());
            return resultMap;
        }
    }


    /**
     * 查询病人缴费记录
     *
     * @return
     */
    @UserLoginToken
    @RequestMapping(value = "/getChargeListByPatient", method = {RequestMethod.POST})
    public Map<String, Object> getChargeListByPatient(@RequestBody ChargeFeeParamsVo chargeFeeParamsVo) {
        Map<String, Object> resultMap = new HashMap<>();
        try {
            if (chargeFeeParamsVo == null) {
                resultMap.put("code", -1);
                resultMap.put("message", "检索参数不能为空");
                return resultMap;
            }
            if (chargeFeeParamsVo.getBeginDate() == null) {
                resultMap.put("code", -1);
                resultMap.put("message", "检索开始时间不能为空");
                return resultMap;
            }
            if (chargeFeeParamsVo.getEndDate() == null) {
                resultMap.put("code", -1);
                resultMap.put("message", "检索结束时间不能为空");
                return resultMap;
            }
            if (StringUtils.isBlank(chargeFeeParamsVo.getPatientId())) {
                chargeFeeParamsVo.setPatientId(null);
            } else {
                chargeFeeParamsVo.setPatientId("%" + chargeFeeParamsVo.getPatientId() + "%");
            }
            if (StringUtils.isBlank(chargeFeeParamsVo.getName())) {
                chargeFeeParamsVo.setName(null);
            } else {
                chargeFeeParamsVo.setName("%" + chargeFeeParamsVo.getName() + "%");
            }
            if (StringUtils.isBlank(chargeFeeParamsVo.getSerialNo())) {
                chargeFeeParamsVo.setSerialNo(null);
            } else {
                chargeFeeParamsVo.setSerialNo("%" + chargeFeeParamsVo.getSerialNo() + "%");
            }
            resultMap.put("code", 0);
            resultMap.put("mzChargeDetailList", mzChargeDetailService.queryChargeListByPatient(chargeFeeParamsVo.getHisData(), chargeFeeParamsVo.getPatientId(), chargeFeeParamsVo.getName(), chargeFeeParamsVo.getSerialNo(), chargeFeeParamsVo.getBeginDate(), chargeFeeParamsVo.getEndDate()));
            resultMap.put("message", "查询病人缴费记录成功");
            return resultMap;
        } catch (Exception e) {
            e.printStackTrace();
            resultMap.put("code", -1);
            resultMap.put("message", "查询病人缴费记录失败，系统出错，请联系管理员");
            log.error("查询病人缴费记录失败，系统异常，错误信息{}", e.getMessage());
            return resultMap;
        }
    }


    /**
     * 根据病人编码和收费流水号查询缴费明细
     *
     * @return
     */
    @UserLoginToken
    @RequestMapping(value = "/getChargeDetailByPatient", method = {RequestMethod.POST})
    public Map<String, Object> getChargeDetailByPatient(@RequestBody ChargeFeeParamsVo chargeFeeParamsVo, HttpServletRequest httpServletRequest) {
        Map<String, Object> resultMap = new HashMap<>();
        try {
            if (chargeFeeParamsVo == null) {
                resultMap.put("code", -1);
                resultMap.put("message", "检索参数不能为空");
                return resultMap;
            }
            if (StringUtils.isBlank(chargeFeeParamsVo.getPatientId())) {
                resultMap.put("code", -1);
                resultMap.put("message", "病人编号不能为空");
                return resultMap;
            }
            if (StringUtils.isBlank(chargeFeeParamsVo.getSerialNo())) {
                resultMap.put("code", -1);
                resultMap.put("message", "缴费流水号不能为空");
                return resultMap;
            }
            List<Map<String, Object>> data = mzChargeDetailService.queryChargeDetailByPatient(chargeFeeParamsVo.getHisData(), chargeFeeParamsVo.getPatientId(), chargeFeeParamsVo.getSerialNo());
            BigDecimal totalPriceCount = BigDecimal.ZERO;
            totalPriceCount = getBigDecimal(data, totalPriceCount);
            User tokenUser = TokenUtil.getUser(httpServletRequest);
            MzReceiptSerial mzReceiptSerial = mzReceiptSerialService.queryReceiptDetailsByReceiptSn(Integer.valueOf(chargeFeeParamsVo.getSerialNo()));
            if(mzReceiptSerial!=null){
                Employee opEmployee = employeeService.queryByUserCode(mzReceiptSerial.getOperatorId());
                if (opEmployee != null) {
                    mzReceiptSerial.setOperatorId(opEmployee.getEmployeeName());
                }
            }
            resultMap.put("code", 0);
            resultMap.put("data", data);
            resultMap.put("totalPriceCount", totalPriceCount);
            resultMap.put("user", tokenUser);
            resultMap.put("mzReceiptSerial", mzReceiptSerial);
            resultMap.put("message", "查询病人缴费记录成功");
            return resultMap;
        } catch (MzException e) {
            log.error("根据病人编码和收费流水号查询缴费明细失败，错误信息{}", e);
            resultMap.put("code", -1);
            resultMap.put("message", "根据病人编码和收费流水号查询缴费明细失败");
            return resultMap;
        } catch (Exception e) {
            e.printStackTrace();
            resultMap.put("code", -1);
            resultMap.put("message", "根据病人编码和收费流水号查询缴费明细失败，系统出错，请联系管理员");
            log.error("根据病人编码和收费流水号查询缴费明细失败，系统异常，错误信息{}", e.getMessage());
            return resultMap;
        }
    }


    /**
     * 查询病人的所有缴费明细
     *
     * @return
     */
    @UserLoginToken
    @RequestMapping(value = "/getAllChargeDetailByPatient", method = {RequestMethod.POST})
    public Map<String, Object> getAllChargeDetailByPatient(@RequestBody ChargeFeeParamsVo chargeFeeParamsVo, HttpServletRequest httpServletRequest) {
        Map<String, Object> resultMap = new HashMap<>();
        try {
            if (chargeFeeParamsVo == null) {
                resultMap.put("code", -1);
                resultMap.put("message", "检索参数不能为空");
                return resultMap;
            }
            if (chargeFeeParamsVo.getBeginDate() == null) {
                resultMap.put("code", -1);
                resultMap.put("message", "检索开始时间不能为空");
                return resultMap;
            }
            if (chargeFeeParamsVo.getEndDate() == null) {
                resultMap.put("code", -1);
                resultMap.put("message", "检索结束时间不能为空");
                return resultMap;
            }
            if (StringUtils.isBlank(chargeFeeParamsVo.getPatientId())) {
                resultMap.put("code", -1);
                resultMap.put("message", "病人id不能为空");
                return resultMap;
            }
            List<Map<String, Object>> mzChargeDetailList = mzChargeDetailService.queryChargeListByPatient(chargeFeeParamsVo.getHisData(), "%" + chargeFeeParamsVo.getPatientId() + "%", null, null, chargeFeeParamsVo.getBeginDate(), chargeFeeParamsVo.getEndDate());
            List<Map<String, Object>> data = new ArrayList<>();
            if (mzChargeDetailList != null) {
                StringBuilder sbf = new StringBuilder();
                List<String> receiptBillList = new ArrayList<>();
                int index =0;
                for (Map<String, Object> map : mzChargeDetailList) {
                    if (map != null) {
                        Integer realNo = (Integer) map.get("real_no");
                        data.addAll(mzChargeDetailService.queryChargeDetailByPatient(chargeFeeParamsVo.getHisData(), chargeFeeParamsVo.getPatientId(), realNo.toString()));
                        MzReceiptSerial mzReceiptSerial = mzReceiptSerialService.queryReceiptDetailsByReceiptSn(realNo);
                        if(mzReceiptSerial!=null && StringUtils.isNotBlank(mzReceiptSerial.getReceiptBill())){
                            if(sbf.length()==0){
                                sbf.append(mzReceiptSerial.getReceiptBill());
                            }else {
                                sbf.append(",").append(mzReceiptSerial.getReceiptBill());
                            }
                            //每6个发票号换一次行
                            index++;
                            if(index%6==0){
                                receiptBillList.add(sbf.toString());
                                sbf.setLength(0);
                            }
                        }
                    }
                }
                if(sbf.toString().length()>0){
                    receiptBillList.add(sbf.toString());
                }
                if(sbf.length()>0){
                    resultMap.put("receiptBillList", receiptBillList);
                }
            }
            BigDecimal totalPriceCount = BigDecimal.ZERO;
            totalPriceCount = getBigDecimal(data, totalPriceCount);
            User tokenUser = TokenUtil.getUser(httpServletRequest);
            resultMap.put("code", 0);
            resultMap.put("data", data);
            resultMap.put("totalPriceCount", totalPriceCount);
            resultMap.put("user", tokenUser);
            resultMap.put("message", "查询病人缴费记录成功");
            return resultMap;
        } catch (Exception e) {
            e.printStackTrace();
            resultMap.put("code", -1);
            resultMap.put("message", "查询病人缴费记录失败，系统出错，请联系管理员");
            log.error("查询病人缴费记录失败，系统异常，错误信息{}", e.getMessage());
            return resultMap;
        }
    }

    private BigDecimal getBigDecimal(List<Map<String, Object>> data, BigDecimal totalPriceCount) {
        if (data != null && data.size() > 0) {
            for (Map<String, Object> entity : data) {
                Double totalPriceD = (Double) entity.get("total_price");
                BigDecimal totalPrice = BigDecimal.ZERO;
                if (totalPriceD != null) {
                    totalPrice = BigDecimal.valueOf(totalPriceD);
                }
                if (totalPrice != null) {
                    totalPriceCount = totalPriceCount.add(totalPrice);
                }
            }
            Employee employee = employeeService.queryByUserCode((String) data.get(0).get("doctor_code"));
            if (employee != null) {
                data.get(0).put("doctor_code", employee.getEmployeeName());
            }
            String warnDept = zdUnitCodeService.queryDeptNameByIdInCache((String) data.get(0).get("warn_dept"));
            if (StringUtils.isNotBlank(warnDept)) {
                data.get(0).put("warn_dept", warnDept);
            }
            Employee opEmployee = employeeService.queryByUserCode((String) data.get(0).get("op_id"));
            if (opEmployee != null) {
                data.get(0).put("op_id", opEmployee.getEmployeeName());
            }
        }
        return totalPriceCount.setScale(1, BigDecimal.ROUND_HALF_UP);
    }


    /**
     * 查询科室核算报表 caseType = 1 申请科室核算报表  0 执行科室核算报表
     *
     * @return
     */
    @UserLoginToken
    @RequestMapping(value = "/getDepetBusinessReport", method = {RequestMethod.POST})
    public Map<String, Object> getDepetBusinessReport(@RequestBody ThmzmxsrParamsVo thmzmxsrParamsVo) {
        Map<String, Object> resultMap = new HashMap<>();
        try {
            if (thmzmxsrParamsVo == null) {
                resultMap.put("code", -1);
                resultMap.put("message", "查询科室核算报表失败,参数为空");
                return resultMap;
            }
            if (thmzmxsrParamsVo.getBeginDate() == null) {
                resultMap.put("code", -1);
                resultMap.put("message", "查询科室核算报表失败,开始时间为空");
                return resultMap;
            }
            if (thmzmxsrParamsVo.getEndDate() == null) {
                resultMap.put("code", -1);
                resultMap.put("message", "查询科室核算报表失败,结束时间为空");
                return resultMap;
            }
            if (StringUtils.isBlank(thmzmxsrParamsVo.getCaseType())) {
                resultMap.put("code", -1);
                resultMap.put("message", "查询科室核算报表失败,核算报表类型为空");
                return resultMap;
            }
            if (StringUtils.isBlank(thmzmxsrParamsVo.getExecDept())) {
                thmzmxsrParamsVo.setExecDept(null);
            }
            resultMap.put("code", 0);
            resultMap.put("message", "查询科室核算报表成功");
            thmzmxsrParamsVo.setHisData(YesNoEnum.NO);
            List<Map<String, Object>> depetBusinessReports = mzChargeDetailService.queryDepetBusinessReport(thmzmxsrParamsVo);
            thmzmxsrParamsVo.setHisData(YesNoEnum.YES);
            //历史数据
            List<Map<String, Object>> depetBusinessReportsHis = mzChargeDetailService.queryDepetBusinessReport(thmzmxsrParamsVo);
            if (fomartThmzBussinessReport(resultMap, depetBusinessReports, depetBusinessReportsHis)){
                return resultMap;
            }
            resultMap.put("code", -1);
            resultMap.put("message", "未查询到科室核算报表");
            return resultMap;
        } catch (Exception e) {
            e.printStackTrace();
            log.error("查询科室核算报表失败，错误信息{}", e.getMessage());
            resultMap.put("code", -1);
            resultMap.put("message", "查询科室核算报表失败");
            return resultMap;
        }
    }

    private boolean fomartThmzBussinessReport(Map<String, Object> resultMap, List<Map<String, Object>> depetBusinessReports, List<Map<String, Object>> depetBusinessReportsHis) {
        if (depetBusinessReports != null && depetBusinessReports.size() > 0) {
            String defaultDept ="defaultDept";
            List<BillItem> mzBillItems = mzBillItemService.queryZyBillItem();
            Map<String, String> mzBillItemMap = null;
            if (mzBillItems != null) {
                mzBillItemMap = mzBillItems.stream().collect(Collectors.toMap(BillItem::getCode, BillItem::getName));
            }
            Set<Date> repeatSet = new HashSet<>();
            //父类码列表
            List<Map<String, Object>> parentList = new ArrayList<>();
            //科室列表
            List<Map<String, Object>> depetList = new ArrayList<>();
            //科室排重集
            Set<String> depetSet = new HashSet<>();
            //父类码与核算码的关系
            Map<String, List<String>> parentMap = new HashMap<>();
            List<ZyZdAuditItem> zyZdAuditItems= zyZdAuditItemService.querytAll();
            //实际项目与父类码对应关系,因为数据查询中的父类码不准
            Map<String, ZyZdAuditItem> auditMap =  zyZdAuditItems.stream().collect(Collectors.toMap(ZyZdAuditItem::getCode,zyZdAuditItem->zyZdAuditItem));
            if(depetBusinessReports.size()>0){
                List<String> chargeBillCodes= new ArrayList<>(depetBusinessReports.stream().map(d-> (String)d.get("charge_bill_code")).collect(Collectors.toSet()));
                //构造收费编码与核算码关系
                List<ZdChargeItem> zdChargeItemList=zdChargeItemService.queryZdChargeItemByCodeList(chargeBillCodes);
                Map<String, String> zdChargeItemMap = new HashMap<>();
                for (ZdChargeItem zdChargeItem:zdChargeItemList){
                    zdChargeItemMap.put(zdChargeItem.getCode(),zdChargeItem.getAuditCode());
                }
               // Map<String, String> zdChargeItemMap = zdChargeItemList.stream().collect(Collectors.toMap(ZdChargeItem::getCode, ZdChargeItem::getAuditCode));
                for (Map<String, Object> map : depetBusinessReports) {
                    repeatSet.add((Date) map.get("charge_dcount_date"));
                    String auditCode= zdChargeItemMap.get(map.get("charge_bill_code"));
                    ZyZdAuditItem zyZdAuditItem=auditMap.get(auditCode);
                    if(zyZdAuditItem!=null){
                        map.put("parent",zyZdAuditItem.getParentCode());
                        map.put("audit_code",zyZdAuditItem.getName());
                    }else {
                        log.info("");
                    }
                    map.put("exec_dept",zdUnitCodeService.queryDeptNameByIdInCache((String) map.get("exec_dept")));
                    fomartData(mzBillItemMap, parentList, depetList, depetSet, parentMap, map);
                }

            }
            if(depetBusinessReportsHis !=null && depetBusinessReportsHis.size()>0){
                List<String> chargeBillCodes= new ArrayList<>(depetBusinessReportsHis.stream().map(d-> (String)d.get("charge_bill_code")).collect(Collectors.toSet()));
                //构造收费编码与核算码关系
                List<ZdChargeItem> zdChargeItemList=zdChargeItemService.queryZdChargeItemByCodeList(chargeBillCodes);
                Map<String, String> zdChargeItemMap = new HashMap<>();
                for (ZdChargeItem zdChargeItem:zdChargeItemList){
                    zdChargeItemMap.put(zdChargeItem.getCode(),zdChargeItem.getAuditCode());
                }
                for (Map<String, Object> map : depetBusinessReportsHis) {
                    if (repeatSet.contains(map.get("charge_dcount_date"))) {
                        continue;
                    }
                    String auditCode= zdChargeItemMap.get(map.get("charge_bill_code"));
                    ZyZdAuditItem zyZdAuditItem=auditMap.get(auditCode);
                    if(zyZdAuditItem!=null){
                        map.put("parent",zyZdAuditItem.getParentCode());
                        map.put("audit_code",zyZdAuditItem.getName());
                    }else {
                        log.info("");
                    }
                    map.put("exec_dept",zdUnitCodeService.queryDeptNameByIdInCache((String) map.get("exec_dept")));
                    depetBusinessReports.add(map);
                    fomartData(mzBillItemMap, parentList, depetList, depetSet, parentMap, map);
                }
            }
            Map<String,BigDecimal> formatMap = new HashMap<>();

            StringBuffer sbf = new StringBuffer();
            for (Map<String, Object> map : depetBusinessReports) {
                sbf.setLength(0);
                sbf.append(map.get("audit_code")).append("_").append(map.get("exec_dept"));
                String key = sbf.toString();
                BigDecimal hadAmount= formatMap.get(key);
                BigDecimal thisAmount=(BigDecimal)map.get("total_charge");
                if(hadAmount==null){
                    hadAmount=BigDecimal.ZERO;
                }
                if(thisAmount==null){
                    thisAmount=BigDecimal.ZERO;
                }
                hadAmount=hadAmount.add(thisAmount);
                formatMap.put(key,hadAmount);
            }
            //按部门统计的总额
            Map<String,BigDecimal> depeAmounts = new HashMap<>();
            //按核算码统计的总额
            Map<String,BigDecimal> auditCodeAmounts = new HashMap<>();
            List<List<BigDecimal>> realDatas = new ArrayList<>();
            boolean hasNullKey = false;
            for (int j=0;j<parentList.size();j++){
                Map<String, Object> parent = parentList.get(j);
                List<String> auditCodeList = (List<String>)parent.get("hsmList");
                for (int k = 0;k<auditCodeList.size();k++){
                    List<BigDecimal> tempList = new ArrayList<>();
                    for (int i =0;i<depetList.size();i++){
                        sbf.setLength(0);
                        sbf.append(auditCodeList.get(k)).append("_").append(depetList.get(i).get("exec_dept"));
                        BigDecimal tempAmount=formatMap.get(sbf.toString());
                        tempList.add(tempAmount);
                        if(tempAmount!=null){
                            String execDept =(String) depetList.get(i).get("exec_dept");
                            if(execDept==null){
                                execDept=defaultDept;
                                hasNullKey=true;
                            }
                            BigDecimal countDeptAmont=depeAmounts.get(execDept);
                            if(countDeptAmont==null){
                                countDeptAmont=BigDecimal.ZERO;
                            }
                            countDeptAmont=countDeptAmont.add(tempAmount);
                            depeAmounts.put(execDept,countDeptAmont);

                            BigDecimal countAuditAmont=auditCodeAmounts.get(auditCodeList.get(k));
                            if(countAuditAmont==null){
                                countAuditAmont=BigDecimal.ZERO;
                            }
                            countAuditAmont=countAuditAmont.add(tempAmount);
                            auditCodeAmounts.put(auditCodeList.get(k),countAuditAmont);
                        }
                    }
                    realDatas.add(tempList);
                }
            }
            BigDecimal totalAmount = BigDecimal.ZERO;
            for (Map<String, Object> map:depetList){
                BigDecimal deptAmount=depeAmounts.get(map.get("exec_dept"));
                if(hasNullKey && map.get("exec_dept")==null){
                    deptAmount=depeAmounts.get(defaultDept);
                }
                if(deptAmount!=null){
                    totalAmount=totalAmount.add(deptAmount);
                }
                map.put("amount",deptAmount);
            }
            List<BigDecimal> hsmAmounts = new ArrayList<>();
            for (Map<String, Object> map:parentList){
                List<String> auditCodeList = (List<String>)map.get("hsmList");
                for (String str:auditCodeList){
                    hsmAmounts.add(auditCodeAmounts.get(str));
                }
            }
            resultMap.put("message", "查询科室核算报表成功");
            resultMap.put("depetList", depetList);
            resultMap.put("parentList", parentList);
            resultMap.put("realDatas", realDatas);
            resultMap.put("hsmAmounts", hsmAmounts);
            resultMap.put("totalAmount", totalAmount);
            return true;
        }
        return false;
    }


    /**
     * 将数据库数据格式转成页面表格需要格式  结构化数据
     *
     * @param mzBillItemMap
     * @param parentList
     * @param depetList
     * @param depetSet
     * @param parentMap
     * @param map
     */
    private void fomartData(Map<String, String> mzBillItemMap, List<Map<String, Object>> parentList, List<Map<String, Object>> depetList, Set<String> depetSet, Map<String, List<String>> parentMap, Map<String, Object> map) {
        String execDept = (String) map.get("exec_dept");
        if (!depetSet.contains(execDept)) {
            depetSet.add(execDept);
            Map<String, Object> deptTemp = new HashMap<>();
          //  deptTemp.put("execDeptName", zdUnitCodeService.queryDeptNameByIdInCache(execDept));
            deptTemp.put("exec_dept", execDept);
            depetList.add(deptTemp);
        }
        String parent = (String) map.get("parent");
        List<String> auditCodeList = parentMap.get(parent);
        if (auditCodeList == null) {
            Map<String, Object> parentTemp = new HashMap<>();
            parentTemp.put("parentName", mzBillItemMap.get(parent));
            parentTemp.put("parentCode", parent);
            auditCodeList = new ArrayList<>();
            auditCodeList.add((String) map.get("audit_code"));
            parentTemp.put("hsmList", auditCodeList);
            parentList.add(parentTemp);
            parentMap.put(parent, auditCodeList);
        } else {
            String auditCode = (String) map.get("audit_code");
            if (!auditCodeList.contains(auditCode)) {
                auditCodeList.add(auditCode);
            }
        }
    }




    /**
     * 获取病人特门与自费金额
     *
     * @return
     */
    @UserLoginToken
    @RequestMapping(value = "/getTmFee", method = {RequestMethod.POST})
    public Map<String, Object> getTmFee(@RequestBody MzChargeDetailYb mzChargeDetailYb, HttpServletRequest httpServletRequest) {
        Map<String, Object> resultMap = new HashMap<>();
        try {
            if (mzChargeDetailYb == null) {
                resultMap.put("code", -1);
                resultMap.put("message", "获取病人特门与自费金额参数不能为空");
                return resultMap;
            }
            if (StringUtils.isBlank(mzChargeDetailYb.getPatientId())) {
                resultMap.put("code", -1);
                resultMap.put("message", "病人编码不能为空");
                return resultMap;
            }
            if (mzChargeDetailYb.getTimes() == null) {
                resultMap.put("code", -1);
                resultMap.put("message", "病人就诊次数不能为空");
                return resultMap;
            }
            if (mzChargeDetailYb.getReceiptNo() == null) {
                resultMap.put("code", -1);
                resultMap.put("message", "缴费次数不能为空");
                return resultMap;
            }
            int count = mzChargeDetailYbService.queryTmCount(mzChargeDetailYb);
            if(count>0){
                String token = TokenUtil.getToken(httpServletRequest);
                if (StringUtils.isBlank(token)) {
                    resultMap.put("code", -1);
                    resultMap.put("message", "获取病人特门与自费金额失败,用户Token不存在");
                    return resultMap;
                }
                DecodedJWT decodedJWT = TokenUtil.parseJWT(token);
                User tokenUser = (User) JsonUtil.jsontoObject(decodedJWT.getSubject(), User.class);
                PayInfo result= tsmzService.uploadFees(tokenUser.getUserIdCode(), mzChargeDetailYb.getPatientId(),mzChargeDetailYb.getTimes(),mzChargeDetailYb.getReceiptNo());
                if(result.getCode()!=0){
                    resultMap.put("code", -1);
                    resultMap.put("message", result.getErrorMessage());
                    return resultMap;
                }
                resultMap.put("data", result);
            }
            resultMap.put("code", 0);
            resultMap.put("message", "获取病人特门与自费金额成功");
            return resultMap;
        } catch (Exception e) {
            e.printStackTrace();
            resultMap.put("code", -1);
            resultMap.put("message", "获取病人特门与自费金额失败，系统出错，请联系管理员");
            log.error("获取病人特门与自费金额失败");
            return resultMap;
        }
    }




    /**
     * 取消病人特门费用上传
     *
     * @return
     */
    @UserLoginToken
    @RequestMapping(value = "/cancelTmFee", method = {RequestMethod.POST})
    public Map<String, Object> cancelTmFee(@RequestBody MzChargeDetailYb mzChargeDetailYb, HttpServletRequest httpServletRequest) {
        Map<String, Object> resultMap = new HashMap<>();
        try {
            if (mzChargeDetailYb == null) {
                resultMap.put("code", -1);
                resultMap.put("message", "取消病人特门费用上传参数不能为空");
                return resultMap;
            }
            if (StringUtils.isBlank(mzChargeDetailYb.getPatientId())) {
                resultMap.put("code", -1);
                resultMap.put("message", "病人编码不能为空");
                return resultMap;
            }
            if (mzChargeDetailYb.getTimes() == null) {
                resultMap.put("code", -1);
                resultMap.put("message", "病人就诊次数不能为空");
                return resultMap;
            }
            if (mzChargeDetailYb.getReceiptNo() == null) {
                resultMap.put("code", -1);
                resultMap.put("message", "缴费次数不能为空");
                return resultMap;
            }
            int count = mzChargeDetailYbService.queryTmCount(mzChargeDetailYb);
            if(count>0){
                String token = TokenUtil.getToken(httpServletRequest);
                if (StringUtils.isBlank(token)) {
                    resultMap.put("code", -1);
                    resultMap.put("message", "取消病人特门费用上传失败,用户Token不存在");
                    return resultMap;
                }
                DecodedJWT decodedJWT = TokenUtil.parseJWT(token);
                User tokenUser = (User) JsonUtil.jsontoObject(decodedJWT.getSubject(), User.class);
                PayInfo result= tsmzService.retractFees(tokenUser.getUserIdCode(), mzChargeDetailYb.getPatientId(),mzChargeDetailYb.getTimes(),mzChargeDetailYb.getReceiptNo());
                resultMap.put("data", result);
            }
            resultMap.put("code", 0);
            resultMap.put("message", "取消病人特门费用上传成功");
            return resultMap;
        } catch (Exception e) {
            e.printStackTrace();
            resultMap.put("code", -1);
            resultMap.put("message", "取消病人特门费用上传失败，系统出错，请联系管理员");
            log.error("取消病人特门费用上传失败");
            return resultMap;
        }
    }


    /**
     * 保存处方信息
     *
     * @param mzPrescriptionVo
     * @return
     */
    @UserLoginToken
    @RequestMapping(value = "/savePrescription", method = {RequestMethod.POST})
    public Map<String, Object> savePrescription(@RequestBody MzPrescriptionVo mzPrescriptionVo, HttpServletRequest httpServletRequest) {
        Map<String, Object> resultMap = new HashMap<>();
        try {
            User tokenUser = TokenUtil.getUser(httpServletRequest);
            if (tokenUser == null) {
                resultMap.put("code", -1);
                resultMap.put("message", "打印当前挂号的发票信息失败,用户Token不存在");
                return resultMap;
            }
            mzPrescriptionVo.setDoctorCode(tokenUser.getUserIdCode());
            mzPrescriptionVo.setVisitDeptCode(Constants.ZZBM);
            int num = mzChargeDetailService.savePrescription(mzPrescriptionVo);
            if (num == 1) {
                resultMap.put("code", 0);
                resultMap.put("message", "门诊处方保存成功");
                return resultMap;
            }
            resultMap.put("code", -1);
            resultMap.put("message", "门诊处方保存失败");
            return resultMap;
        } catch (MzException e) {
            resultMap.put("code", -1);
            resultMap.put("message", e.getMessage());
            log.error("系统异常，错误信息{}", e.getMessage());
            return resultMap;
        } catch (Exception e) {
            e.printStackTrace();
            resultMap.put("code", -1);
            resultMap.put("message", "门诊处方保存失败，请联系管理员");
            log.error("系统异常，错误信息{}", e.getMessage());
            return resultMap;
        }
    }




    /**
     * 修改收费方式
     * @param chequeType 新收费方式
     * @param receiptSn 流水号
     * @param oldChequeType 原付费方式
     * @return
     */
    @UserLoginToken
    @RequestMapping(value = "/updateChequType", method = {RequestMethod.GET})
    public Map<String, Object> updateChequType(@RequestParam String chequeType,@RequestParam Integer receiptSn,@RequestParam String oldChequeType, HttpServletRequest httpServletRequest) {
        Map<String, Object> resultMap = new HashMap<>();
        try {
            if(StringUtils.isBlank(chequeType)){
                resultMap.put("code", -1);
                resultMap.put("message", "新的收款方式不能为空");
                return resultMap;
            }
            if(StringUtils.isBlank(oldChequeType)){
                resultMap.put("code", -1);
                resultMap.put("message", "原收款方式不能为空");
                return resultMap;
            }
            if (receiptSn==null) {
                resultMap.put("code", -1);
                resultMap.put("message", "流水号不能为空");
                return resultMap;
            }
            User tokenUser = TokenUtil.getUser(httpServletRequest);
            if (tokenUser == null) {
                resultMap.put("code", -1);
                resultMap.put("message", "修改收费方式失败,用户Token不存在");
                return resultMap;
            }
            mzChargeDetailService.modifyChequType(chequeType,receiptSn,oldChequeType);
            resultMap.put("code", 0);
            resultMap.put("message", "修改收费方式成功");
            return resultMap;
        } catch (Exception e) {
            e.printStackTrace();
            resultMap.put("code", -1);
            resultMap.put("message", e.getMessage());
            log.error("修改收费方式失败，系统异常，错误信息{}", e.getMessage());
            return resultMap;
        }
    }



//    /**
//     * 同步备份库数据到正式库 修复记账的数据
//     * @param mzChargeDetail 新收费方式
//     * @return
//     */
//    @UserLoginToken
//    @RequestMapping(value = "/reSaveDetailForByjz", method = {RequestMethod.POST})
//    public Map<String, Object> reSaveDetailForByjz(@RequestBody MzChargeDetail mzChargeDetail) {
//        Map<String, Object> resultMap = new HashMap<>();
//        try {
//            if(mzChargeDetail==null){
//                resultMap.put("code", -1);
//                resultMap.put("message", "参数不能为空");
//                return resultMap;
//            }
//            if(StringUtils.isBlank(mzChargeDetail.getPatientId())){
//                resultMap.put("code", -1);
//                resultMap.put("message", "患者ID不能为空");
//                return resultMap;
//            }
//            if(mzChargeDetail.getTimes()==null){
//                resultMap.put("code", -1);
//                resultMap.put("message", "就诊次数不能为空");
//                return resultMap;
//            }
//            if (mzChargeDetail.getReceiptNo()==null) {
//                resultMap.put("code", -1);
//                resultMap.put("message", "缴费次数不能为空");
//                return resultMap;
//            }
//            mzChargeDetailService.reSaveDetailFromBak(mzChargeDetail);
//            resultMap.put("code", 0);
//            resultMap.put("message", "同步备份库数据到正式库成功");
//            return resultMap;
//        } catch (Exception e) {
//            e.printStackTrace();
//            resultMap.put("code", -1);
//            resultMap.put("message", e.getMessage());
//            log.error("同步备份库数据到正式库失败，系统异常，错误信息{}", e.getMessage());
//            return resultMap;
//        }
//    }



}
