package cn.hnthyy.thmz.service.impl.his.mz;

import cn.hnthyy.thmz.Utils.DateUtil;
import cn.hnthyy.thmz.common.Constants;
import cn.hnthyy.thmz.entity.MzException;
import cn.hnthyy.thmz.entity.his.mz.*;
import cn.hnthyy.thmz.entity.thmz.Receipt;
import cn.hnthyy.thmz.entity.thmz.User;
import cn.hnthyy.thmz.enums.PayMarkEnum;
import cn.hnthyy.thmz.enums.YesNoEnum;
import cn.hnthyy.thmz.mapper.his.mz.MzChargeDetailMapper;
import cn.hnthyy.thmz.mapper.his.mz.MzDepositFileMapper;
import cn.hnthyy.thmz.mapper.his.mz.MzReceiptSerialMapper;
import cn.hnthyy.thmz.mapper.his.mz.MzVisitTableMapper;
import cn.hnthyy.thmz.mapper.thmz.ReceiptMapper;
import cn.hnthyy.thmz.service.his.mz.MzPatientMiService;
import cn.hnthyy.thmz.service.his.mz.MzReceiptSerialService;
import cn.hnthyy.thmz.service.his.mz.MzSerialNoService;
import cn.hnthyy.thmz.service.his.mz.MzVisitTableService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.*;
import java.util.List;

@Service
public class MzReceiptSerialServiceImpl implements MzReceiptSerialService {
    @SuppressWarnings("all")
    @Autowired
    private MzReceiptSerialMapper mzReceiptSerialMapper;
    @SuppressWarnings("all")
    @Autowired
    private ReceiptMapper receiptMapper;
    @SuppressWarnings("all")
    @Autowired
    private MzChargeDetailMapper mzChargeDetailMapper;
    @SuppressWarnings("all")
    @Autowired
    private MzDepositFileMapper mzDepositFileMapper;
    @SuppressWarnings("all")
    @Autowired
    private MzVisitTableMapper mzVisitTableMapper;
    @Autowired
    private MzSerialNoService mzSerialNoService;
    @Autowired
    private MzPatientMiService mzPatientMiService;
    @Autowired
    private MzVisitTableService mzVisitTableService;

    @Override
    public List<MzReceiptSerial> queryTallyReceiptSerial(String patientId) {
        return mzReceiptSerialMapper.selectTallyReceiptSerial(patientId);
    }

    @Override
    public BigDecimal queryTallyTotalCharge(String patientId) {
        return mzReceiptSerialMapper.selectTallyTotalCharge(patientId);
    }

    @Override
    public int saveMzReceiptSerial(MzReceiptSerial mzReceiptSerial) {
        return mzReceiptSerialMapper.insertMzReceiptSerial(mzReceiptSerial);
    }

    @Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.DEFAULT, timeout = 36000, rollbackFor = Exception.class)
    @Override
    public int batchSaveMzReceiptSerial(List<MzReceiptSerial> mzReceiptSerials) {

        if (mzReceiptSerials.size() == 0) {
            return 0;
        }
        if (mzReceiptSerials.size() <= 20) {
            mzReceiptSerialMapper.batchInsertMzReceiptSerial(mzReceiptSerials);
        } else {
            List<MzReceiptSerial> tempList = new ArrayList<>();
            for (MzReceiptSerial md : mzReceiptSerials) {
                tempList.add(md);
                if (tempList.size() == 20) {
                    mzReceiptSerialMapper.batchInsertMzReceiptSerial(tempList);
                    tempList.clear();
                }
            }
            if (tempList.size() > 0) {
                mzReceiptSerialMapper.batchInsertMzReceiptSerial(tempList);
            }
        }
        return mzReceiptSerials.size();
    }

    @Override
    public MzReceiptSerial queryAllSerialForThisTime(String patientId, Integer times, Integer receiptNo) {
//        String receiptSerialTableName="mz_receipt_serial";
//        MzReceiptSerial mzReceiptSerial= mzReceiptSerialMapper.selectAllSerialForThisTime(patientId, times, receiptNo,receiptSerialTableName);
//        if(mzReceiptSerial!=null){
//            return mzReceiptSerial;
//        }
//        receiptSerialTableName="mz_receipt_serial_b";
//        return mzReceiptSerialMapper.selectAllSerialForThisTime(patientId, times, receiptNo,receiptSerialTableName);
        return mzReceiptSerialMapper.selectAllSerialForThisTime(patientId, times, receiptNo);
    }

    @Override
    public List<MzReceiptSerial> queryPrintedSerialForThisTime(String patientId, Integer times, String receiptBill) {
        String receiptSerialTableName="mz_receipt_serial";
        List<MzReceiptSerial> mzReceiptSerialList= mzReceiptSerialMapper.selectPrintedSerialForThisTime(patientId, times, receiptBill,receiptSerialTableName);
        if(mzReceiptSerialList!=null && mzReceiptSerialList.size()>0){
            return mzReceiptSerialList;
        }
        receiptSerialTableName="mz_receipt_serial_b";
        return mzReceiptSerialMapper.selectPrintedSerialForThisTime(patientId, times, receiptBill,receiptSerialTableName);
    }

    @Override
    public List<MzReceiptSerial> queryTallyReceiptSerialByIdAndTimes(String patientId, Integer times, Integer receiptNo) {
        return mzReceiptSerialMapper.selectTallyReceiptSerialByIdAndTimes(patientId, times, receiptNo);
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.DEFAULT, timeout = 36000, rollbackFor = Exception.class)
    public String printReceiptSerial(MzReceiptSerial mzReceiptSerial, User user) throws MzException {
        Receipt receipt = receiptMapper.selectByUserIdCode(user.getUserIdCode());
        if (receipt == null || StringUtils.isBlank(receipt.getReceiptCurrent())) {
            throw new MzException("用户id=" + user.getUserName() + "没有可用的门诊发票,请先维护发票。");
        }
        //mzChargeDetailMapper.updatePrintFlag(mzReceiptSerial.getPatientId(), Arrays.asList(mzReceiptSerial.getTimes()));
        MzReceiptSerial updateMzReceiptSerial = new MzReceiptSerial(mzReceiptSerial.getPatientId(), mzReceiptSerial.getTimes());
        updateMzReceiptSerial.setReceiptNo(mzReceiptSerial.getReceiptNo());
        updateMzReceiptSerial.setChequeType(mzReceiptSerial.getChequeType());
        updateMzReceiptSerial.setReceiptBill(receipt.getReceiptCurrent());
        updateMzReceiptSerial.setOperatorId(user.getUserIdCode());
        updateMzReceiptSerial.setPayId(mzReceiptSerial.getOperatorId());
        if (mzReceiptSerial.getDcountDate() != null) {
            //日结不为空，说明是手机自助缴费且已经日结过了，需要将原来日结时间设置到缴费日结字段，因为发票打印成功会重置原来的日结时间和日结状态
            updateMzReceiptSerial.setChargeDcountDate(mzReceiptSerial.getDcountDate());
            updateMzReceiptSerial.setChargeDcountNo(mzReceiptSerial.getDcountNo());
        }
        //如果是手机缴费，设置缴费方式为自助缴费
        if (Constants.BRZZJF_CODE.equals(mzReceiptSerial.getOperatorId()) && Constants.BYJZ.equals(mzReceiptSerial.getChequeType())) {
            MzDepositFile mzDepositFile = mzDepositFileMapper.selectMzDepositFileBySerialNo(mzReceiptSerial.getSerialNo(),null).get(0);
            if (Constants.WX.equals(mzDepositFile.getChequeType())) {
                updateMzReceiptSerial.setNewChequeType(Constants.ZZWX);
            } else if (Constants.ZFB.equals(mzDepositFile.getChequeType())) {
                updateMzReceiptSerial.setNewChequeType(Constants.ZZZFB);
            }
            mzDepositFileMapper.updateChequeType(updateMzReceiptSerial.getNewChequeType(), mzDepositFile.getReceiptSn(),null);
        }
        int num = mzReceiptSerialMapper.updateBzByReceiptNo(updateMzReceiptSerial);
        if (num == 0) {
            throw new MzException("已经打印过发票，请勿重复打印，如果需要重新打印，请点击重新打印或者作废打印");
        }
        mzReceiptSerialMapper.updateMzReceiptSerialByReceiptNo(updateMzReceiptSerial);
        if (receipt.getReceiptCurrent() == receipt.getReceiptEnd()) {
            //此时发票号已经用完，当前发票号是最后一个
            receipt.setReceiptCurrent(null);
        } else {
            Integer temp = Integer.valueOf(receipt.getReceiptCurrent()) + 1;
            receipt.setReceiptCurrent(temp.toString());
        }
        receipt.setUpdateDate(new Date());
        receiptMapper.updateReceipt(receipt);
        mzReceiptSerial.setReceiptBill(updateMzReceiptSerial.getReceiptBill());
        return updateMzReceiptSerial.getReceiptBill();
    }

    @Override
    public MzReceiptSerial queryReceiptSerialBySerialNo(Integer serialNo) {
        return mzReceiptSerialMapper.selectReceiptDetailsBySerialNo(serialNo);
    }

    /**
     * 根据发票流水号查询发票信息
     *
     * @param receiptSn
     * @return
     */
    @Override
    public MzReceiptSerial queryReceiptDetailsByReceiptSn(Integer receiptSn) {
        MzReceiptSerial mzReceiptSerial= mzReceiptSerialMapper.selectReceiptDetailsByReceiptSn(receiptSn,"mz_receipt_serial");
        if(mzReceiptSerial!=null){
            return mzReceiptSerial;
        }
        return mzReceiptSerialMapper.selectReceiptDetailsByReceiptSn(receiptSn,"mz_receipt_serial_b");
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.DEFAULT, timeout = 36000, rollbackFor = Exception.class)
    public String obsoleteAndRepPrint(MzReceiptSerial mzReceiptSerial, User user) throws MzException {
        Receipt receipt = receiptMapper.selectByUserIdCode(user.getUserIdCode());
        if (receipt == null || StringUtils.isBlank(receipt.getReceiptCurrent())) {
            throw new MzException("用户id=" + user.getUserName() + "没有可用的发票,请先维护发票。");
        }
        MzVisitTable mzVisitTable = mzVisitTableService.queryByPatientIdAndTimes(mzReceiptSerial.getPatientId(), mzReceiptSerial.getTimes());
        if (mzVisitTable == null) {
            throw new MzException("当前病人就诊基础资料【MzVisitTable】不存在，请检查");
        }
        Integer receiptNo = mzVisitTable.getReceiptNo() + 1;
        Integer oriSerialNo = mzReceiptSerial.getSerialNo();
        int serialNo = mzSerialNoService.getSerialNo();
        //将原发票作废
        MzReceiptSerial updateMzReceiptSerial = new MzReceiptSerial(mzReceiptSerial.getPatientId(), mzReceiptSerial.getTimes());
        updateMzReceiptSerial.setPayMark(PayMarkEnum.CANCELLATION.code);
        updateMzReceiptSerial.setReceiptNo(mzReceiptSerial.getReceiptNo());
        updateMzReceiptSerial.setChequeType(mzReceiptSerial.getChequeType());
        mzReceiptSerialMapper.updateMzReceiptSerialByReceiptNo(updateMzReceiptSerial);
        //创建新发票
        mzReceiptSerial.setReceiptNo(receiptNo);
        mzReceiptSerial.setSerialNo(serialNo);
        mzReceiptSerial.setReceiptSn(serialNo);
        mzReceiptSerial.setReceiptBill(receipt.getReceiptCurrent());
        mzReceiptSerial.setDeptNo(YesNoEnum.NO.code.toString());
        mzReceiptSerial.setOperatorId(user.getUserIdCode());
        mzReceiptSerial.setDcountDate(null);
        mzReceiptSerial.setDcountNo(YesNoEnum.NO.code);
        mzReceiptSerialMapper.insertMzReceiptSerial(mzReceiptSerial);
        //更新收费明细表发票流水号
        Date now = new Date();
        mzChargeDetailMapper.updateBySerialNo(receiptNo, mzReceiptSerial.getSerialNo(), oriSerialNo);
        List<MzDepositFile> mzDepositFiles = mzDepositFileMapper.selectMzDepositFileBySerialNo(oriSerialNo,null);
        //原收费方式记录设置为作废
        mzDepositFileMapper.updatePayMark(PayMarkEnum.CANCELLATION.code, oriSerialNo,mzReceiptSerial.getChequeType());
        for (MzDepositFile mzDepositFile : mzDepositFiles) {
            if(Constants.BYJZ.equals(mzDepositFile.getChequeType())){
                continue;
            }
            //新增新的收费方式记录
            mzDepositFile.setReceiptNo(mzReceiptSerial.getReceiptNo());
            mzDepositFile.setReceiptSn(mzReceiptSerial.getSerialNo());
            mzDepositFile.setSerialNo(mzReceiptSerial.getSerialNo());
            mzDepositFile.setChargeDate(now);
            //mzDepositFile.setDcountNo(YesNoEnum.NO.code);
            //mzDepositFile.setDcountDate(null);
            mzDepositFileMapper.insertMzDepositFile(mzDepositFile);
        }
        if (receipt.getReceiptCurrent() == receipt.getReceiptEnd()) {
            //此时发票号已经用完，当前发票号是最后一个
            receipt.setReceiptCurrent(null);
        } else {
            Integer temp = Integer.valueOf(receipt.getReceiptCurrent()) + 1;
            receipt.setReceiptCurrent(temp.toString());
        }
        receipt.setUpdateDate(now);
        receiptMapper.updateReceipt(receipt);
        MzVisitTable updateMzVisitTable = new MzVisitTable();
        updateMzVisitTable.setPatientId(mzReceiptSerial.getPatientId());
        updateMzVisitTable.setTimes(mzReceiptSerial.getTimes());
        updateMzVisitTable.setReceiptNo(receiptNo);
        mzVisitTableMapper.updateMzVisitTable(updateMzVisitTable);
        return mzReceiptSerial.getReceiptBill();
    }

    @Override
    public List<Map<String, Object>> queryChargeListByPatient(List<String> patientIds, String serialNo, Date beginDate, Date endDate, String tableName) {
        List<Map<String, Object>> list=  mzReceiptSerialMapper.selectChargeListByPatient(patientIds,serialNo,beginDate,endDate,tableName);
        Map<String,String> patientIdMap = new HashMap<>();
        for (Map<String, Object> map : list) {
            String patientIdTemp = (String) map.get("patient_id");
            String name =patientIdMap.get(patientIdTemp);
            if(StringUtils.isBlank(name)){
                MzPatientMi mzPatientMi= mzPatientMiService.queryByPatientId(patientIdTemp);
                name=mzPatientMi.getName();
                patientIdMap.put(patientIdTemp,name);
            }
            map.put("name",name);
        }
        return list;
    }

    @Override
    public BigDecimal querySumByPatientId(String beginDate, String endDate, String patientId) {
        return mzReceiptSerialMapper.selectSumByPatientId(beginDate,endDate,patientId);
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.DEFAULT, timeout = 36000, rollbackFor = Exception.class)
    public int repairDataFromBack(String patientId, Integer times, Integer receiptNo) {
        Date date=mzReceiptSerialMapper.selectChargeDateThisTime(patientId, times, receiptNo);
        if(date==null){
            return 0;
        }
        Date beginDate =DateUtil.getFirstSecond(date);
        Date endDate=DateUtil.getLastSecond(date);
        List<MzReceiptSerial> mzReceiptSerialList= mzReceiptSerialMapper.selectAllItemByChargeDate(patientId,beginDate,endDate);
        if (mzReceiptSerialList==null || mzReceiptSerialList.size()==0){
            return 0;
        }
        MzChargeDetail mzChargeDetail = new MzChargeDetail();
        mzChargeDetail.setPatientId(patientId);
        int num =0;
        for (MzReceiptSerial mr:mzReceiptSerialList){
            if(mr==null){
                continue;
            }
            mzReceiptSerialMapper.repairDataFromBack(patientId, mr.getTimes(), mr.getReceiptNo());
            mzReceiptSerialMapper.deleteFromBak(patientId, mr.getTimes(), mr.getReceiptNo());
            mzChargeDetail.setTimes(mr.getTimes());
            mzChargeDetail.setReceiptNo(mr.getReceiptNo());
            mzChargeDetailMapper.reInsertDetail(mzChargeDetail);
            mzChargeDetailMapper.deleteFromBak(mzChargeDetail);
            num++;
        }
        return num;
    }

}
