package com.ywt.mg.services;

import com.ywt.mg.core.utils.Checker;
import com.ywt.mg.core.utils.DateUtil;
import com.ywt.mg.core.utils.ExcelHelper;
import com.ywt.mg.core.utils.FormatUtil;
import com.ywt.mg.domain.entities.OrderPayment;
import com.ywt.mg.domain.entities.RefundLog;
import com.ywt.mg.domain.models.ConstantDef;
import com.ywt.mg.domain.models.ExcelDataMap;
import com.ywt.mg.domain.models.enums.*;
import com.ywt.mg.domain.models.pojo.ExcelCollectPojo;
import com.ywt.mg.domain.ywtDrugEntities.Pharmacy;
import com.ywt.mg.domain.ywtDrugEntities.PrescriptionDrugView;
import com.ywt.mg.domain.ywtDrugEntities.PrescriptionInfo;
import com.ywt.mg.params.prescription.QueryPrescriptionListRequest;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;

import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

@Service
public class PrescriptionServices {

    private static final Logger logger = LoggerFactory.getLogger(PrescriptionServices.class);


    @Autowired
    private JdbcTemplate ywtDrugJdbcTemplate;

    @Autowired
    private OrderPaymentService orderPaymentService;

    @Autowired
    private PharmacyCacheService pharmacyCacheService;

    @Autowired
    private CommonServices commonServices;

    @Autowired
    private DownloadRecordService downloadRecordService;

    @Autowired
    private RefundLogService refundLogService;

    /**
     * 根据条件查询用药记录
     *
     * @param request
     * @return
     */
    public List<PrescriptionInfo> downloadPrescriptionlistNew(QueryPrescriptionListRequest request) {
        Map<String, Object> map = getQueryMapCommonNew(request);
        List<Object> paramList = (List<Object>) map.get("paramList");
        String whereSql = (String) map.get("whereSql");

        // 分页查找
        StringBuilder sqlBuilder = new StringBuilder();
        // 拼凑sql语句
        sqlBuilder.append("select * from ywt_drug.prescription_info where ")
                .append(whereSql)
                .append("order by create_on desc");
        List<PrescriptionInfo> list = ywtDrugJdbcTemplate.query(sqlBuilder.toString(), paramList.toArray(), new BeanPropertyRowMapper<>(PrescriptionInfo.class));
        return list;
    }


    /**
     * 抽取公共的sql查找语句
     */
    public Map<String, Object> getQueryMapCommonNew(QueryPrescriptionListRequest request) {
        List<Object> paramList = new ArrayList<>();
        String whereSql = " ( 1=1 )";

        String doctorname = request.getDoctorname();
        if (!Checker.isNull(doctorname)) {
            whereSql += " and ( doctor_name like ?)";
            paramList.add("%" + doctorname + "%");
        }

        String patientname = request.getPatientname();
        if (!Checker.isNull(patientname)) {
            whereSql += " and ( patient_name like ?)";
            paramList.add("%" + patientname + "%");
        }
        String deptname = request.getDeptname();
        if (!Checker.isNull(deptname)) {
            whereSql += " and ( dept like ?)";
            paramList.add("%" + deptname + "%");
        }
        String source = request.getSource();
        if (!Checker.isNull(source)) {
            whereSql += " and ( source = ?)";
            paramList.add(Integer.parseInt(source));
        }
        String pharmacyId = request.getPharmacyId();
        if (!Checker.isNull(pharmacyId)) {
            whereSql += " and ( pharmacy_id = ?)";
            paramList.add(Integer.parseInt(pharmacyId));
        }
        String deliveryMethod = request.getDeliveryMethod();
        if (!Checker.isNull(deliveryMethod)) {
            whereSql += " and ( delivery_method = ?)";
            paramList.add(Integer.parseInt(deliveryMethod));
        }

        // 1待支付，2-配送中/待取药，3、已完成(不包括已评价的),4、已退费，5、不通过 （存在ext_status字段），6、已评价， 7-已过期，8-待评价, 10-退费中
        String status = request.getStatus();
        if (!Checker.isNone(status)) {
            int statusInt = Integer.parseInt(status);
            if (statusInt == 1) {
                // 只查找待支付的，不查找已过期的，需要计算时间
                //把日期往后前推3天.整数往后推,负数往前移动
                Date date = DateUtil.getRelativeDate(new Date(), ConstantDef.OVERDUE_DAY_NUM);
                whereSql += " and ( status = ? and create_on > ? ) ";
                paramList.add(statusInt);
                paramList.add(date);
            } else if (statusInt == 2) {
                // 查找只是配送中/待取药 （不包含不通过的）
                whereSql += " and ( ((ext_status & ?) != ? or ext_status is null) && status = ?  ) ";
                paramList.add(PrescriptionInfoExtStatusEnum.PresNoPass.getValue());
                paramList.add(PrescriptionInfoExtStatusEnum.PresNoPass.getValue());
                paramList.add(PrescriptionInfoStatusEnum.Dispatching.getValue());
            } else if (statusInt == 3) {
                // 查找只是已完成的，只有广三的有已完成的状态
                whereSql += " and ( status = ? and pharmacy_id = ? ) ";
                paramList.add(PrescriptionInfoStatusEnum.Finished.getValue());
                paramList.add(ConstantDef.GUANGSAN_PHARMACY_ID);
            } else if (statusInt == 5) {
                // 查找只是不通过的，退费的不找出来，已评价的也不找出来
                whereSql += " and ( (ext_status & ?) = ? and ext_status < ? and status != ? ) ";
                paramList.add(PrescriptionInfoExtStatusEnum.PresNoPass.getValue());
                paramList.add(PrescriptionInfoExtStatusEnum.PresNoPass.getValue());
                paramList.add(2 * PrescriptionInfoExtStatusEnum.PresNoPass.getValue());
                paramList.add(PrescriptionInfoStatusEnum.HaveARefund.getValue());
            } else if (statusInt == 6) {
                // 查找已评价的
                whereSql += " and ( (ext_status & ?) = ? and status != ? and pharmacy_id = ? ) ";
                paramList.add(PrescriptionInfoExtStatusEnum.Evaluate.getValue());
                paramList.add(PrescriptionInfoExtStatusEnum.Evaluate.getValue());
                paramList.add(PrescriptionInfoStatusEnum.HaveARefund.getValue());
                paramList.add(ConstantDef.TAIHE_PHARMACY_ID);
            } else if (statusInt == 7) {
                // 根据原型图，订单3天未支付，状态变为已过期
                //把日期往后前推3天.整数往后推,负数往前移动
                Date date = DateUtil.getRelativeDate(new Date(), ConstantDef.OVERDUE_DAY_NUM);
                whereSql += " and ( status = ? or (status = ? and create_on < ?)) ";
                paramList.add(PrescriptionInfoStatusEnum.EXPIRED.getValue());
                paramList.add(PrescriptionInfoStatusEnum.WaitForPayment.getValue());
                paramList.add(date);
            } else if (statusInt == 8) {
                // 查找只是待评价的, 顺丰返回完成状态，需要排除不通过的
                whereSql += " and ( (ext_status & ?) != ? and status = ?  and (ext_status & ?) != ? and pharmacy_id = ?  ) ";
                paramList.add(PrescriptionInfoExtStatusEnum.Evaluate.getValue());
                paramList.add(PrescriptionInfoExtStatusEnum.Evaluate.getValue());
                paramList.add(PrescriptionInfoStatusEnum.Finished.getValue());
                paramList.add(PrescriptionInfoExtStatusEnum.PresNoPass.getValue());
                paramList.add(PrescriptionInfoExtStatusEnum.PresNoPass.getValue());
                paramList.add(ConstantDef.TAIHE_PHARMACY_ID);
            } else if (statusInt == 10) {
                whereSql += " and ( refund_status = ? ) ";
                paramList.add(RefundStatusEnum.PENDING.getValue());
            } else {
                whereSql += " and ( status = ? ) and ( refund_status != ?  or refund_status is null )   ";
                paramList.add(statusInt);
                paramList.add(RefundStatusEnum.PENDING.getValue());
            }
        }

        String paymentStatus = request.getPaymentStatus();
        if (!Checker.isNone(paymentStatus)) {
            whereSql += " and ( payment_status = ? ) ";
            paramList.add(Integer.parseInt(paymentStatus));
        }

        String preBizNo = request.getPreBizNo();
        if (!Checker.isNone(preBizNo)) {
            whereSql += " and ( pre_biz_no like ? ) ";
            paramList.add("%" + preBizNo + "%");
        }
        String bizNo3th = request.getBizNo3th();
        if (!Checker.isNone(bizNo3th)) {
            whereSql += " and ( biz_no_3th like ? ) ";
            paramList.add("%" + bizNo3th + "%");
        }
        String sendNo = request.getSendNo();
        if (!Checker.isNone(sendNo)) {
            whereSql += " and ( send_no like ? ) ";
            paramList.add("%" + sendNo + "%");
        }
        String paymentChannel = request.getPaymentChannel();
        if (!Checker.isNone(paymentChannel)) {
            whereSql += " and ( payment_channel = ? ) ";
            paramList.add(Integer.parseInt(paymentChannel));
        }

        String paymentNo = request.getPaymentNo();
        if (!Checker.isNone(paymentNo)) {
            whereSql += " and ( payment_no like ? ) ";
            paramList.add("%" + paymentNo.trim() + "%");
        }

        String cancelStatus = request.getCancelStatus();
        if (!Checker.isNone(cancelStatus)) {
            whereSql += " and ( cancel_status = ? ) ";
            paramList.add(Integer.parseInt(cancelStatus));
        }

        String orderNo = request.getOrderNo();
        if (!Checker.isNone(orderNo)) {
            whereSql += " and ( order_no like ? ) ";
            paramList.add("%" + orderNo.trim() + "%");
        }

        String Format_Date = "yyyy-MM-dd";
        SimpleDateFormat format = new SimpleDateFormat(Format_Date);

        String createTimeEnd = Checker.getStringValue(request.getCreateTimeEnd());
        String createTimeStart = Checker.getStringValue(request.getCreateTimeStart());
        String payTimeEnd = Checker.getStringValue(request.getPayTimeEnd());
        String payTimeStart = Checker.getStringValue(request.getPayTimeStart());
        String refundTimeEnd = Checker.getStringValue(request.getRefundTimeEnd());
        String refundTimeStart = Checker.getStringValue(request.getRefundTimeStart());
        String billEndTime = Checker.getStringValue(request.getBillEndTime());
        String billStartTime = Checker.getStringValue(request.getBillStartTime());
        try {
            // 创建时间
            if (!Checker.isNull(createTimeEnd)) {
                whereSql += " and ( create_on < ?)";
                Date date = format.parse(createTimeEnd);
                //把日期往后增加一天.整数往后推,负数往前移动
                Calendar calendar = new GregorianCalendar();
                calendar.setTime(date);
                calendar.add(calendar.DATE, 1);
                date = calendar.getTime();   //这个时间就是日期往后推一天的结果

                paramList.add(date);
            }
            if (!Checker.isNull(createTimeStart)) {
                whereSql += " and ( create_on >= ?)";
                Date date = format.parse(createTimeStart);
                paramList.add(date);
            }

            // 支付时间
            if (!Checker.isNull(payTimeEnd)) {
                whereSql += " and ( pay_time < ?)";
                Date date = format.parse(payTimeEnd);
                //把日期往后增加一天.整数往后推,负数往前移动
                Calendar calendar = new GregorianCalendar();
                calendar.setTime(date);
                calendar.add(calendar.DATE, 1);
                date = calendar.getTime();   //这个时间就是日期往后推一天的结果

                paramList.add(date);
            }
            if (!Checker.isNull(payTimeStart)) {
                whereSql += " and ( pay_time >= ?)";
                Date date = format.parse(payTimeStart);
                paramList.add(date);
            }

            // 退费时间搜索
            if (!Checker.isNull(refundTimeEnd)) {
                whereSql += " and (refund_time < ?)";
                Date date = format.parse(refundTimeEnd);
                //把日期往后增加一天.整数往后推,负数往前移动
                Calendar calendar = new GregorianCalendar();
                calendar.setTime(date);
                calendar.add(calendar.DATE, 1);
                date = calendar.getTime();   //这个时间就是日期往后推一天的结果

                paramList.add(date);
            }
            if (!Checker.isNull(refundTimeStart)) {
                whereSql += " and ( refund_time >= ?)";
                Date date = format.parse(refundTimeStart);
                paramList.add(date);
            }
            // 对账时间搜索
            if (!Checker.isNull(billEndTime)) {
                whereSql += " and ( pay_time < ? or refund_time < ?)";
                Date date = format.parse(billEndTime);
                //把日期往后增加一天.整数往后推,负数往前移动
                Calendar calendar = new GregorianCalendar();
                calendar.setTime(date);
                calendar.add(calendar.DATE, 1);
                date = calendar.getTime();   //这个时间就是日期往后推一天的结果

                paramList.add(date);
                paramList.add(date);
            }
            if (!Checker.isNull(billStartTime)) {
                whereSql += " and ( pay_time >= ? or refund_time >= ?)";
                Date date = format.parse(billStartTime);
                paramList.add(date);
                paramList.add(date);
            }

        } catch (Exception e) {
            e.printStackTrace();
            logger.error("getQueryMapCommonNew():createTimeEnd:{}\t,createTimeStart:{}\t,payTimeEnd:{}\t,payTimeStart:{}\t," +
                            "refundTimeEnd:{}\t,refundTimeStart:{}\t,billEndTime:{}\t,billStartTime:{}\t", createTimeEnd, createTimeStart, payTimeEnd,
                    payTimeStart, refundTimeEnd, refundTimeStart, billEndTime, billStartTime);
        }

        String transactionId = request.getTransactionId();
        try {
            // 处理交易流水号，考虑到性能，直接采用全匹配到方式
            if (!Checker.isNull(transactionId)) {
                OrderPayment orderPayment = orderPaymentService.getOrderPaymentByTransactionId(transactionId);
                if (!Checker.isNone(orderPayment)) {
                    whereSql += " and ( order_id = ? )";
                    paramList.add(orderPayment.getOrderId());
                } else {
                    whereSql += " and ( order_id = -1 )";
                }
            }
        } catch (Exception e) {
            logger.error("PrescriptionServices#getQueryMapCommonNew(transactionId={} ):\n {} ", transactionId, e.getMessage(), e);
        }
        Map map = new HashMap();
        map.put("whereSql", whereSql);
        map.put("paramList", paramList);
        return map;
    }


    public void downloadPrescriptionlist(int downloadRecordId, String fileName, QueryPrescriptionListRequest request) {
        try {
            String col0 = "订单号";
            String col1 = "支付流水号";
            String col2 = "取药方式";
            String col3 = "医生姓名";
            String col4 = "患者姓名";
            String col5 = "来源";
            String col6 = "药房";
            String col7 = "状态";
            String col8 = "支付状态";
            String col9 = "支付渠道";
            String col10 = "总金额";
            String col11 = "创建时间";
            String col12 = "支付时间";
            String col13 = "退款时间";
            String col14 = "退款状态";
            String col15 = "退费流水号";
            String col16 = "备注";
            String col17 = "作废状态";
            String col18 = "作废备注";

            String[] columns = new String[]{col0, col1, col2, col3, col4, col5, col6, col7, col8, col9, col10,
                    col11, col12, col13, col14, col15, col16, col17, col18};
            int payTotal = 0, refundTotal = 0, realTotal = 0,
                    weChatPay = 0, weChatRefundTotal = 0, weChatRealTotal = 0,
                    aliPay = 0, aliRefundTotal = 0, aliRealTotal = 0,
                    cashPay = 0, cashRefundTotal = 0, cashRealTotal = 0,
                    medicalCardPay = 0, medicalCardRefundTotal = 0, medicalCardRealTotal = 0,
                    posPay = 0, posRefundTotal = 0, posRealTotal = 0,
                    medicalInsurancePay = 0, medicalInsuranceRefundTotal = 0, medicalInsuranceRealTotal = 0,
                    icbcPay = 0, icbcRefundTotal = 0, icbcRealTotal = 0;
            List<PrescriptionInfo> prescriptionInfoList = downloadPrescriptionlistNew(request);
            ExcelDataMap map = new ExcelDataMap(columns);
            if (!Checker.isNone(prescriptionInfoList)) {
                SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm");

                Map<Integer, Pharmacy> pharmacyMap = pharmacyCacheService.getPharmacyMap();
                for (PrescriptionInfo p : prescriptionInfoList) {

                    map.getStringListSafely(col0).add(p.getOrderNo());
                    map.getStringListSafely(col1).add(p.getPaymentNo());
                    int deliveryMethodInt = Checker.getIntegerValue(p.getDeliveryMethod());
                    String deliveryMethodStr = getDeliveryMethodStr(deliveryMethodInt);
//                        map.getStringListSafely(col2).add(transactionId);
                    map.getStringListSafely(col3).add(p.getDoctorName());
                    map.getStringListSafely(col4).add(p.getPatientName());
                    String sourceStr = PrescriptionInfoSourceEnum.getSource(p.getSource()).getDisplayName();
                    map.getStringListSafely(col5).add(sourceStr);
                    Pharmacy pharmacy = pharmacyMap.get(Checker.getIntegerValue(p.getPharmacyId()));
                    String pharmacyName = !Checker.isNone(pharmacy) ? pharmacy.getName() : "";
                    String statusStr = getPrescriptionInfoStatusStr(p);
                    map.getStringListSafely(col6).add(pharmacyName);
                    map.getStringListSafely(col7).add(statusStr);
                    map.getStringListSafely(col8).add(PaymentStatusEnum.getPaymentStatus(p.getPaymentStatus()).getDisplayName());
                    map.getStringListSafely(col9).add(PresPaymentChannelEnum.valueOf(Checker.getIntegerValue(p.getPaymentChannel())).getDisplayName());
                    String total = FormatUtil.decimalFormat(p.getTotalPrice() / 100.0);
                    map.getStringListSafely(col10).add(total);
                    map.getStringListSafely(col11).add(sdf.format(p.getCreateOn()));
                    String payTime = !Checker.isNone(p.getPayTime()) ? sdf.format(p.getPayTime()) : "";
                    map.getStringListSafely(col12).add(payTime);
                    String refundTime = !Checker.isNone(p.getRefundTime()) ? sdf.format(p.getRefundTime()) : "";
                    String refundStatus = Checker.isNone(p.getRefundStatus()) ? "" : RefundStatusEnum.getDisplayName(p.getRefundStatus());
                    map.getStringListSafely(col13).add(refundTime);
                    map.getStringListSafely(col14).add(refundStatus);
                    map.getStringListSafely(col15).add(Checker.getStringValue(p.getRefundNo()));
                    map.getStringListSafely(col16).add(Checker.getStringValue(p.getRemarks()));
                    int cancelStatusInt = Checker.getIntegerValue(p.getCancelStatus());
                    String cancelStatusStr = getPrescriptionInfoCancelStatusStr(cancelStatusInt);
                    map.getStringListSafely(col17).add(cancelStatusStr);
                    map.getStringListSafely(col18).add(Checker.getStringValue(p.getCancelRemark()));

                    //统计支付总额和退费总额
                    int paymentStatusInt = Checker.getIntegerValue(p.getPaymentStatus());
                    int presStatus = Checker.getIntegerValue(p.getStatus());
                    int payChanelInt = Checker.getIntegerValue(p.getPaymentChannel());

                    if (presStatus == PrescriptionInfoStatusEnum.HaveARefund.getValue()) {
                        refundTotal += Checker.getIntegerValue(p.getTotalPrice());

                        if (payChanelInt == PresPaymentChannelEnum.WeChat.getValue()) {
                            weChatRefundTotal += Checker.getIntegerValue(p.getTotalPrice());
                        } else if (payChanelInt == PresPaymentChannelEnum.AliPay.getValue()) {
                            aliRefundTotal += Checker.getIntegerValue(p.getTotalPrice());
                        } else if (payChanelInt == PresPaymentChannelEnum.Cash.getValue()) {
                            cashRefundTotal += Checker.getIntegerValue(p.getTotalPrice());
                        } else if (payChanelInt == PresPaymentChannelEnum.MedicalCard.getValue()) {
                            medicalCardRefundTotal += Checker.getIntegerValue(p.getTotalPrice());
                        } else if (payChanelInt == PresPaymentChannelEnum.POS.getValue()) {
                            posRefundTotal += Checker.getIntegerValue(p.getTotalPrice());
                        } else if (payChanelInt == PresPaymentChannelEnum.MedicalInsurance.getValue()) {
                            medicalInsuranceRefundTotal += Checker.getIntegerValue(p.getTotalPrice());
                        } else if (payChanelInt == PresPaymentChannelEnum.ICBC.getValue()) {
                            icbcRefundTotal += Checker.getIntegerValue(p.getTotalPrice());
                        }
                    }
                    if (paymentStatusInt == PaymentStatusEnum.Success.getValue()) {
                        payTotal += Checker.getIntegerValue(p.getTotalPrice());

                        if (payChanelInt == PresPaymentChannelEnum.WeChat.getValue()) {
                            weChatPay += Checker.getIntegerValue(p.getTotalPrice());
                        } else if (payChanelInt == PresPaymentChannelEnum.AliPay.getValue()) {
                            aliPay += Checker.getIntegerValue(p.getTotalPrice());
                        } else if (payChanelInt == PresPaymentChannelEnum.Cash.getValue()) {
                            cashPay += Checker.getIntegerValue(p.getTotalPrice());
                        } else if (payChanelInt == PresPaymentChannelEnum.MedicalCard.getValue()) {
                            medicalCardPay += Checker.getIntegerValue(p.getTotalPrice());
                        } else if (payChanelInt == PresPaymentChannelEnum.POS.getValue()) {
                            posPay += Checker.getIntegerValue(p.getTotalPrice());
                        } else if (payChanelInt == PresPaymentChannelEnum.MedicalInsurance.getValue()) {
                            medicalInsurancePay += Checker.getIntegerValue(p.getTotalPrice());
                        } else if (payChanelInt == PresPaymentChannelEnum.ICBC.getValue()) {
                            icbcPay += Checker.getIntegerValue(p.getTotalPrice());
                        }
                    }

                }

            }
            int size = prescriptionInfoList.size();
            List<ExcelCollectPojo> itemList = getStatisticsData(size, payTotal, refundTotal, weChatPay, weChatRefundTotal,
                    aliPay, aliRefundTotal,
                    cashPay, cashRefundTotal,
                    medicalCardPay, medicalCardRefundTotal,
                    posPay, posRefundTotal,
                    medicalInsurancePay, medicalInsuranceRefundTotal,
                    icbcPay, icbcRefundTotal);
            downloadRecordService.createFileAndUploadOssAndSaveToDataBase(fileName, downloadRecordId, map, itemList);


        } catch (Exception e) {
            logger.error("/prescription/downloadPrescriptionlist(): {}", e.getMessage(), e);
            e.printStackTrace();
        }
    }

    /**
     * 得到处方的配送方法
     *
     * @param value 1-快递，2-自取
     * @return 中文状态
     */
    private String getDeliveryMethodStr(int value) {
        if (value == 1) {
            return "快递";
        }
        if (value == 2) {
            return "自取";
        }
        return "";
    }

    /**
     * 公司后台：得到处方状态
     * <p>
     * pharmacyId ：1 - 医院生殖中心1楼药房（广三），2-南方医院太和分院药房（太和）
     *
     * @param p {@link PrescriptionInfo}
     * @return 处方状态
     */
    public String getPrescriptionInfoStatusStr(PrescriptionInfo p) {
        return commonServices.getCompanyPrescriptionStatusStr(p);
    }

    /**
     * 0-初始状态，1-作废申请中，2-已作废，3-作废失败
     *
     * @param cancelStatusInt 作废状态（数字）
     * @return 作废状态
     */
    public String getPrescriptionInfoCancelStatusStr(int cancelStatusInt) {
        switch (cancelStatusInt) {
            case 1:
                return "作废申请中";
            case 2:
                return "已作废";
            case 3:
                return "作废失败";
            default:
                return "";
        }
    }

    private List<ExcelCollectPojo> getStatisticsData(int size, int payTotal, int refundTotal, int weChatPay, int weChatRefundTotal,
                                                     int aliPay, int aliRefundTotal,
                                                     int cashPay, int cashRefundTotal,
                                                     int medicalCardPay, int medicalCardRefundTotal,
                                                     int posPay, int posRefundTotal,
                                                     int medicalInsurancePay, int medicalInsuranceRefundTotal,
                                                     int icbcPay, int icbcRefundTotal) {
        int startRows = size + 3;
        int startColumn = 3;

        List<ExcelCollectPojo> customExcelItemList = new ArrayList<>();
        customExcelItemList.add(new ExcelCollectPojo(startColumn + 1, startRows, new String[]{"支付总额", FormatUtil.intShrink100ToStr(payTotal)}));
        customExcelItemList.add(new ExcelCollectPojo(startColumn + 3, startRows, new String[]{"退款总额", FormatUtil.intShrink100ToStr(refundTotal)}));
        customExcelItemList.add(new ExcelCollectPojo(startColumn + 5, startRows, new String[]{"实际支付金额", FormatUtil.intShrink100ToStr(payTotal - refundTotal)}));
        startRows += 1;

        customExcelItemList.add(new ExcelCollectPojo(startColumn + 1, startRows, new String[]{"微信支付总额", FormatUtil.intShrink100ToStr(weChatPay)}));
        customExcelItemList.add(new ExcelCollectPojo(startColumn + 3, startRows, new String[]{"微信退费总额", FormatUtil.intShrink100ToStr(weChatRefundTotal)}));
        customExcelItemList.add(new ExcelCollectPojo(startColumn + 5, startRows, new String[]{"微信实际支付金额", FormatUtil.intShrink100ToStr(weChatPay - weChatRefundTotal)}));
        startRows += 1;

        customExcelItemList.add(new ExcelCollectPojo(startColumn + 1, startRows, new String[]{"支付宝支付", FormatUtil.intShrink100ToStr(aliPay)}));
        customExcelItemList.add(new ExcelCollectPojo(startColumn + 3, startRows, new String[]{"支付宝退费总额", FormatUtil.intShrink100ToStr(refundTotal)}));
        customExcelItemList.add(new ExcelCollectPojo(startColumn + 5, startRows, new String[]{"支付宝实际金额", FormatUtil.intShrink100ToStr(aliPay - aliRefundTotal)}));
        startRows += 1;

        customExcelItemList.add(new ExcelCollectPojo(startColumn + 1, startRows, new String[]{"现金支付", FormatUtil.intShrink100ToStr(cashPay)}));
        customExcelItemList.add(new ExcelCollectPojo(startColumn + 3, startRows, new String[]{"现金退费总额", FormatUtil.intShrink100ToStr(cashRefundTotal)}));
        customExcelItemList.add(new ExcelCollectPojo(startColumn + 5, startRows, new String[]{"现金实际金额", FormatUtil.intShrink100ToStr(cashPay - cashRefundTotal)}));
        startRows += 1;

        customExcelItemList.add(new ExcelCollectPojo(startColumn + 1, startRows, new String[]{"诊疗卡支付", FormatUtil.intShrink100ToStr(medicalCardPay)}));
        customExcelItemList.add(new ExcelCollectPojo(startColumn + 3, startRows, new String[]{"诊疗卡退款总额", FormatUtil.intShrink100ToStr(medicalCardRefundTotal)}));
        customExcelItemList.add(new ExcelCollectPojo(startColumn + 5, startRows, new String[]{"诊疗卡实际支付金额", FormatUtil.intShrink100ToStr(medicalCardPay - medicalCardRefundTotal)}));
        startRows += 1;

        customExcelItemList.add(new ExcelCollectPojo(startColumn + 1, startRows, new String[]{"POS支付", FormatUtil.intShrink100ToStr(posPay)}));
        customExcelItemList.add(new ExcelCollectPojo(startColumn + 3, startRows, new String[]{"POS退款总额", FormatUtil.intShrink100ToStr(posRefundTotal)}));
        customExcelItemList.add(new ExcelCollectPojo(startColumn + 5, startRows, new String[]{"POS实际支付金额", FormatUtil.intShrink100ToStr(posPay - posRefundTotal)}));
        startRows += 1;

        customExcelItemList.add(new ExcelCollectPojo(startColumn + 1, startRows, new String[]{"医保支付", FormatUtil.intShrink100ToStr(medicalInsurancePay)}));
        customExcelItemList.add(new ExcelCollectPojo(startColumn + 3, startRows, new String[]{"医保退款总额", FormatUtil.intShrink100ToStr(medicalInsuranceRefundTotal)}));
        customExcelItemList.add(new ExcelCollectPojo(startColumn + 5, startRows, new String[]{"医保实际支付金额", FormatUtil.intShrink100ToStr(medicalInsurancePay - medicalInsuranceRefundTotal)}));
        startRows += 1;

        customExcelItemList.add(new ExcelCollectPojo(startColumn + 1, startRows, new String[]{"工行支付", FormatUtil.intShrink100ToStr(icbcPay)}));
        customExcelItemList.add(new ExcelCollectPojo(startColumn + 3, startRows, new String[]{"工行退款总额", FormatUtil.intShrink100ToStr(refundTotal)}));
        customExcelItemList.add(new ExcelCollectPojo(startColumn + 5, startRows, new String[]{"工行实际支付金额", FormatUtil.intShrink100ToStr(icbcPay - icbcRefundTotal)}));


        return customExcelItemList;
    }


    public List<PrescriptionDrugView> getPrescriptionDrugView(QueryPrescriptionListRequest request) {
        Map<String, Object> map = getQueryMapCommon(request);
        List<Object> paramList = (List<Object>) map.get("paramList");
        String whereSql = (String) map.get("whereSql");

        StringBuilder sqlBuilder = new StringBuilder();
        // 拼凑sql语句
        sqlBuilder.append("select * from ywt_drug.prescription_drug_view where ")
                .append(whereSql)
                .append("order by id desc");
        List<PrescriptionDrugView> list = ywtDrugJdbcTemplate.query(sqlBuilder.toString(), paramList.toArray(), new BeanPropertyRowMapper<>(PrescriptionDrugView.class));
        return list;
    }

    public Map<String, Object> getQueryMapCommon(QueryPrescriptionListRequest request) {
        List<Object> paramList = new ArrayList<>();
        String whereSql = " ( 1=1 )";

        String doctorname = request.getDoctorname();
        if (!Checker.isNull(doctorname)) {
            whereSql += " and ( doctor_name like ?)";
            paramList.add("%" + doctorname + "%");
        }


        String patientname = request.getPatientname();
        if (!Checker.isNull(patientname)) {
            whereSql += " and ( patient_name like ?)";
            paramList.add("%" + patientname + "%");
        }

        String deptname = request.getDeptname();
        if (!Checker.isNull(deptname)) {
            whereSql += " and ( dept like ?)";
            paramList.add("%" + deptname + "%");
        }

        String source = request.getSource();
        if (!Checker.isNull(source)) {
            whereSql += " and ( source = ?)";
            paramList.add(Integer.parseInt(source));
        }
        String pharmacyId = request.getPharmacyId();
        if (!Checker.isNull(pharmacyId)) {
            whereSql += " and ( pharmacy_id = ?)";
            paramList.add(Integer.parseInt(pharmacyId));
        }

        String deliveryMethod = request.getDeliveryMethod();
        if (!Checker.isNull(deliveryMethod)) {
            whereSql += " and ( delivery_method = ?)";
            paramList.add(Integer.parseInt(deliveryMethod));
        }

        // 1待支付，2-配送中/待取药，3、已完成(不包括已评价的),4、已退费，5、不通过 （存在ext_status字段），6、已评价， 7-已过期，8-待评价, 10-退费中
        String status = request.getStatus();
        if (!Checker.isNone(status)) {
            int statusInt = Integer.parseInt(status);
            if (statusInt == 1) {
                // 只查找待支付的，不查找已过期的，需要计算时间
                //把日期往后前推3天.整数往后推,负数往前移动
                Date date = DateUtil.getRelativeDate(new Date(), ConstantDef.OVERDUE_DAY_NUM);
                whereSql += " and ( status = ? and create_on > ? ) ";
                paramList.add(statusInt);
                paramList.add(date);
            } else if (statusInt == 2) {
                // 查找只是配送中/待取药 （不包含不通过的）
                whereSql += " and ( ((ext_status & ?) != ? or ext_status is null) && status = ?  ) ";
                paramList.add(PrescriptionInfoExtStatusEnum.PresNoPass.getValue());
                paramList.add(PrescriptionInfoExtStatusEnum.PresNoPass.getValue());
                paramList.add(PrescriptionInfoStatusEnum.Dispatching.getValue());
            } else if (statusInt == 3) {
                // 查找只是已完成的，只有广三的有已完成的状态
                whereSql += " and ( status = ? and pharmacy_id = ? ) ";
                paramList.add(PrescriptionInfoStatusEnum.Finished.getValue());
                paramList.add(ConstantDef.GUANGSAN_PHARMACY_ID);
            } else if (statusInt == 5) {
                // 查找只是不通过的，退费的不找出来，已评价的也不找出来
                whereSql += " and ( (ext_status & ?) = ? and ext_status < ? and status != ? ) ";
                paramList.add(PrescriptionInfoExtStatusEnum.PresNoPass.getValue());
                paramList.add(PrescriptionInfoExtStatusEnum.PresNoPass.getValue());
                paramList.add(2 * PrescriptionInfoExtStatusEnum.PresNoPass.getValue());
                paramList.add(PrescriptionInfoStatusEnum.HaveARefund.getValue());
            } else if (statusInt == 6) {
                // 查找已评价的
                whereSql += " and ( (ext_status & ?) = ? and status != ? and pharmacy_id = ? ) ";
                paramList.add(PrescriptionInfoExtStatusEnum.Evaluate.getValue());
                paramList.add(PrescriptionInfoExtStatusEnum.Evaluate.getValue());
                paramList.add(PrescriptionInfoStatusEnum.HaveARefund.getValue());
                paramList.add(ConstantDef.TAIHE_PHARMACY_ID);
            } else if (statusInt == 7) {
                // 根据原型图，订单3天未支付，状态变为已过期
                //把日期往后前推3天.整数往后推,负数往前移动
                Date date = DateUtil.getRelativeDate(new Date(), ConstantDef.OVERDUE_DAY_NUM);
                whereSql += " and ( status = ? or (status = ? and create_on < ?)) ";
                paramList.add(PrescriptionInfoStatusEnum.EXPIRED.getValue());
                paramList.add(PrescriptionInfoStatusEnum.WaitForPayment.getValue());
                paramList.add(date);
            } else if (statusInt == 8) {
                // 查找只是待评价的, 顺丰返回完成状态，需要排除不通过的
                whereSql += " and ( (ext_status & ?) != ? and status = ?  and (ext_status & ?) != ? and pharmacy_id = ?  ) ";
                paramList.add(PrescriptionInfoExtStatusEnum.Evaluate.getValue());
                paramList.add(PrescriptionInfoExtStatusEnum.Evaluate.getValue());
                paramList.add(PrescriptionInfoStatusEnum.Finished.getValue());
                paramList.add(PrescriptionInfoExtStatusEnum.PresNoPass.getValue());
                paramList.add(PrescriptionInfoExtStatusEnum.PresNoPass.getValue());
                paramList.add(ConstantDef.TAIHE_PHARMACY_ID);
            } else {
                if (statusInt != 10) {
                    whereSql += " and ( status = ? ) ";
                    paramList.add(statusInt);
                }
            }

            // 退费中
            if (statusInt == 10) {
                whereSql += " and ( refund_status = ?  ) ";
                paramList.add(RefundStatusEnum.PENDING.getValue());
            } else {
                whereSql += " and ( refund_status != ?  ) ";
                paramList.add(RefundStatusEnum.PENDING.getValue());
            }

        }

        String paymentStatus = request.getPaymentStatus();
        if (!Checker.isNone(paymentStatus)) {
            whereSql += " and ( payment_status = ? ) ";
            paramList.add(Integer.parseInt(paymentStatus));
        }

        String preBizNo = request.getPreBizNo();
        if (!Checker.isNone(preBizNo)) {
            whereSql += " and ( pre_biz_no like ? ) ";
            paramList.add("%" + preBizNo + "%");
        }
        String bizNo3th = request.getBizNo3th();
        if (!Checker.isNone(bizNo3th)) {
            whereSql += " and ( biz_no_3th like ? ) ";
            paramList.add("%" + bizNo3th + "%");
        }
        String sendNo = request.getSendNo();
        if (!Checker.isNone(sendNo)) {
            whereSql += " and ( send_no like ? ) ";
            paramList.add("%" + sendNo + "%");
        }
        String paymentChannel = request.getPaymentChannel();
        if (!Checker.isNone(paymentChannel)) {
            whereSql += " and ( payment_channel = ? ) ";
            paramList.add(Integer.parseInt(paymentChannel));
        }

        String paymentNo = request.getPaymentNo();
        if (!Checker.isNone(paymentNo)) {
            whereSql += " and ( payment_no like ? ) ";
            paramList.add("%" + paymentNo.trim() + "%");
        }

        String cancelStatus = request.getCancelStatus();
        if (!Checker.isNone(cancelStatus)) {
            whereSql += " and ( cancel_status = ? ) ";
            paramList.add(Integer.parseInt(cancelStatus));
        }

        String orderNo = request.getOrderNo();
        if (!Checker.isNone(orderNo)) {
            whereSql += " and ( order_no like ? ) ";
            paramList.add("%" + orderNo.trim() + "%");
        }

        String Format_Date = "yyyy-MM-dd";
        SimpleDateFormat format = new SimpleDateFormat(Format_Date);

        String createTimeEnd = request.getCreateTimeEnd();
        String createTimeStart = request.getCreateTimeStart();
        String payTimeEnd = request.getPayTimeEnd();
        String payTimeStart = request.getPayTimeStart();
        String refundTimeEnd = request.getRefundTimeEnd();
        String refundTimeStart = request.getRefundTimeStart();

        try {
            // 创建时间
            if (!Checker.isNull(createTimeEnd)) {
                whereSql += " and ( create_on < ?)";
                Date date = format.parse(createTimeEnd);
                //把日期往后增加一天.整数往后推,负数往前移动
                Calendar calendar = new GregorianCalendar();
                calendar.setTime(date);
                calendar.add(calendar.DATE, 1);
                date = calendar.getTime();   //这个时间就是日期往后推一天的结果

                paramList.add(date);
            }
            if (!Checker.isNull(createTimeStart)) {
                whereSql += " and ( create_on >= ?)";
                Date date = format.parse(createTimeStart);
                paramList.add(date);
            }

            // 支付时间
            if (!Checker.isNull(payTimeEnd)) {
                whereSql += " and ( pay_time < ?)";
                Date date = format.parse(payTimeEnd);
                //把日期往后增加一天.整数往后推,负数往前移动
                Calendar calendar = new GregorianCalendar();
                calendar.setTime(date);
                calendar.add(calendar.DATE, 1);
                date = calendar.getTime();   //这个时间就是日期往后推一天的结果

                paramList.add(date);
            }
            if (!Checker.isNull(payTimeStart)) {
                whereSql += " and ( pay_time >= ?)";
                Date date = format.parse(payTimeStart);
                paramList.add(date);
            }

            // 退费时间搜索
            if (!Checker.isNull(refundTimeEnd)) {
                whereSql += " and (refund_time < ?)";
                Date date = format.parse(refundTimeEnd);
                //把日期往后增加一天.整数往后推,负数往前移动
                Calendar calendar = new GregorianCalendar();
                calendar.setTime(date);
                calendar.add(calendar.DATE, 1);
                date = calendar.getTime();   //这个时间就是日期往后推一天的结果

                paramList.add(date);
            }
            if (!Checker.isNull(refundTimeStart)) {
                whereSql += " and ( refund_time >= ?)";
                Date date = format.parse(refundTimeStart);
                paramList.add(date);
            }
            // 对账时间搜索


        } catch (Exception e) {
            e.printStackTrace();
        }
        Map map = new HashMap();
        map.put("whereSql", whereSql);
        map.put("paramList", paramList);
        return map;
    }

    public void downloadPrescriptionDrugList(int downloadRecordId, String fileName, QueryPrescriptionListRequest request) {
        try {
            String col0 = "订单号";
            String col1 = "药品名";
            String col2 = "规格";
            String col3 = "数量";
            String col4 = "单价";
            String col5 = "总价";
            String col6 = "支付时间";
            String col7 = "退费时间";
            String col8 = "药房";
            String[] columns = new String[]{col0, col1, col2, col3, col4, col5, col6, col7, col8};
            List<PrescriptionDrugView> list = getPrescriptionDrugView(request);
            ExcelDataMap map = new ExcelDataMap(columns);
            if (!Checker.isNone(list)) {
                Map<Integer, Pharmacy> ma = pharmacyCacheService.getPharmacyMap();
                for (PrescriptionDrugView d : list) {
                    String orderNo = Checker.getStringValue(d.getOrderNo());
                    String drugName = Checker.getStringValue(d.getDrugName());
                    String spec = Checker.getStringValue(d.getDrugSpec());
                    String quan = Checker.getStringValue(d.getQuantity() + "");
                    String price = FormatUtil.intShrink100ToStr(d.getPrice());
                    String total = FormatUtil.intShrink100ToStr(d.getTotal());
                    String payTime = FormatUtil.createTimeFormatDetail(d.getPayTime());
                    String refundTime = FormatUtil.createTimeFormatDetail(d.getRefundTime());
                    //药房
                    Pharmacy pharmacy = ma.getOrDefault(Checker.getIntegerValue(d.getPharmacyId()), null);
                    String pharmacyName = "";
                    if (!Checker.isNone(pharmacy)) {
                        pharmacyName = Checker.getStringValue(pharmacy.getName());
                    }
                    map.getStringListSafely(col0).add(orderNo);
                    map.getStringListSafely(col1).add(drugName);
                    map.getStringListSafely(col2).add(spec);
                    map.getStringListSafely(col3).add(quan);
                    map.getStringListSafely(col4).add(price);
                    map.getStringListSafely(col5).add(total);
                    map.getStringListSafely(col6).add(payTime);
                    map.getStringListSafely(col7).add(refundTime);
                    map.getStringListSafely(col8).add(pharmacyName);


                }

            }
            int size = list.size();
            List<ExcelCollectPojo> itemList = new ArrayList<>();
            downloadRecordService.createFileAndUploadOssAndSaveToDataBase(fileName, downloadRecordId, map, itemList);
        } catch (Exception e) {
            logger.error("/prescription/downloadPrescriptionDrugList(): {}", e.getMessage(), e);
            e.printStackTrace();
        }
    }

    public void downloadPrescriptionBillList(int downloadRecordId, String fileName, QueryPrescriptionListRequest request) {
        try {
            String col0 = "交易类型*";
            String col1 = "系统参考号*";
            String col2 = "交易金额*";
            String col3 = "交易日期*";
            String col4 = "订单号";
            String col5 = "类型";
            String[] columns = new String[]{col0, col1, col2, col3, col4, col5};
            request.setPaymentStatus(PaymentStatusEnum.Success.getValue() + "");
            request.setPaymentChannel(PaymentChannelEnum.WeChat.getValue() + "");
            List<PrescriptionInfo> prescriptionInfoList = downloadPrescriptionlistNew(request);
            ExcelDataMap map = new ExcelDataMap(columns);
            if (!Checker.isNone(prescriptionInfoList)) {
                // 得到支付的记录日志（需要从 order_payment 获取 transaction_id 字段）
                List<OrderPayment> orderPaymentList = orderPaymentService.getOrderPaymentListByPrescriptionInfoList(prescriptionInfoList);
                // 得到退款的记录日志（需要从 refund_log 获取 refund_id 字段）
                Date billStartTime = DateUtil.stringToDate(request.getBillStartTime() + ConstantDef.BILL_TIME_START_FORMAT);
                Date billEndTime = DateUtil.stringToDate(request.getBillEndTime() + ConstantDef.BILL_TIME_END_FORMAT);
                for (PrescriptionInfo p : prescriptionInfoList) {
                    if (!Checker.isNone(p) && Checker.getIntegerValue(p.getPaymentStatus()) == PaymentStatusEnum.Success.getValue()
                            && Checker.getIntegerValue(p.getPaymentChannel()) == PaymentChannelEnum.WeChat.getValue()
                            && !Checker.isNone(p.getPayTime())) {
                        // "交易类型", "交易流水号", "交易金额", "交易时间", "订单号", "类型"
                        Date paymentTime = Checker.getDateValue(p.getPayTime());
                        if (!Checker.isNone(paymentTime) && paymentTime.after(billStartTime) && paymentTime.before(billEndTime)) {
                            String type = ConstantDef.BILL_PAYMENT_STR;
                            // 交易流水号
                            String transactionId = orderPaymentService.getTransactionIdByOrderId(orderPaymentList, Checker.getIntegerValue(p.getOrderId()));
                            // 交易金额
                            int total = Checker.getIntegerValue(p.getTotalPrice()) + Checker.getIntegerValue(p.getFreight());
                            String totalStr = FormatUtil.intShrink100ToStr(total);
                            // 交易时间
                            String paymentTimeStr = FormatUtil.createTimeFormatDetail(p.getPayTime());
                            // 订单号
                            String orderNo = Checker.getStringValue(p.getOrderNo());
                            // 类型
                            String typeStr = "处方";

                            map.getStringListSafely(col0).add(type);
                            map.getStringListSafely(col1).add(transactionId);
                            map.getStringListSafely(col2).add(totalStr);
                            map.getStringListSafely(col3).add(paymentTimeStr);
                            map.getStringListSafely(col4).add(orderNo);
                            map.getStringListSafely(col5).add(typeStr);
                        }
                    }
                }
                List<RefundLog> refundLogList = refundLogService.getRefundLogListByPrescriptionInfoList(prescriptionInfoList);
                // 得到支付的excel
                // 得到退款的处方订单
                List<PrescriptionInfo> refundPrescriptionInfoList = getRefundPrescriptionInfoList(prescriptionInfoList);
                // 最后处理退款的部分
                for (PrescriptionInfo p : prescriptionInfoList) {
                    if (!Checker.isNone(p) && Checker.getIntegerValue(p.getRefundStatus()) == RefundStatusEnum.SUCCESS.getValue()) {
                        // "交易类型", "交易流水号", "交易金额", "交易时间", "订单号", "类型"
                        Date refundTime = Checker.getDateValue(p.getRefundTime());
                        if (!Checker.isNone(refundTime) && refundTime.after(billStartTime) && refundTime.before(billEndTime)) {
                            String type = ConstantDef.BILL_REFUND_STR;
                            String transactionId = refundLogService.getRefundIdByRefundNo(refundLogList, p.getRefundNo());
                            // 交易金额
                            int total = Checker.getIntegerValue(p.getTotalPrice()) + Checker.getIntegerValue(p.getFreight());
                            String totalStr = FormatUtil.intShrink100ToStr(total);
                            // 交易时间
                            String refundTimeStr = FormatUtil.createTimeFormatDetail(p.getRefundTime());
                            // 订单号
                            String orderNo = Checker.getStringValue(p.getOrderNo());
                            // 类型
                            String typeName = "处方";


                            map.getStringListSafely(col0).add(type);
                            map.getStringListSafely(col1).add(transactionId);
                            map.getStringListSafely(col2).add(totalStr);
                            map.getStringListSafely(col3).add(refundTimeStr);
                            map.getStringListSafely(col4).add(orderNo);
                            map.getStringListSafely(col5).add(typeName);
                        }
                    }
                }
            }
            int size = prescriptionInfoList.size();
            List<ExcelCollectPojo> itemList = new ArrayList<>();
            downloadRecordService.createFileAndUploadOssAndSaveToDataBase(fileName, downloadRecordId, map, itemList);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private List<PrescriptionInfo> getRefundPrescriptionInfoList(List<PrescriptionInfo> items) {
        if (!Checker.isNone(items)) {
            return items.stream().filter(p -> Checker.getIntegerValue(p.getRefundStatus()) == RefundStatusEnum.SUCCESS.getValue()).collect(Collectors.toList());
        }
        return new ArrayList<>();
    }

}
