package com.ywt.mg.services;

import com.ywt.mg.core.SqlHelper;
import com.ywt.mg.core.utils.Checker;
import com.ywt.mg.core.utils.DateUtil;
import com.ywt.mg.core.utils.FormatUtil;
import com.ywt.mg.domain.entities.CheckUpOrder;
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.PaymentChannelEnum;
import com.ywt.mg.domain.models.enums.PaymentStatusEnum;
import com.ywt.mg.domain.models.enums.RefundStatusEnum;
import com.ywt.mg.domain.models.enums.SexEnum;
import com.ywt.mg.domain.models.pojo.ExcelCollectPojo;
import com.ywt.mg.params.checkupBooking.QueryCheckUpOrderListRequest;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
public class CheckUpOrderService {

    private Logger logger = LoggerFactory.getLogger(CheckUpOrderService.class);

    @Autowired
    private SqlHelper sqlHelper;

    @Autowired
    private OrderPaymentService orderPaymentService;

    @Autowired
    private RefundLogService refundLogService;

    @Autowired
    private DownloadRecordService downloadRecordService;


    private List<CheckUpOrder> queryCheckUpOrderListCommon(QueryCheckUpOrderListRequest request) throws Exception {
        // 时间查询处理
        Map<String, Object> map = queryCheckUpOrderListCommonMapNew(request);
        String whereSql = (String) map.get("whereSql");
        List<Object> paramList = (List<Object>) map.get("paramList");
        return sqlHelper.getListWithNoPage("*", whereSql, " id desc ", CheckUpOrder.class, paramList.toArray());
    }

    private Map<String, Object> queryCheckUpOrderListCommonMapNew(QueryCheckUpOrderListRequest request) throws Exception {
        List<Object> paramList = new ArrayList<>();
        String whereSql = " ( 1=1 )";

        String orderNo = request.getOrderNo();
        if (!Checker.isNull(orderNo)) {
            whereSql += " and ( order_no like ?)";
            paramList.add("%" + orderNo.trim() + "%");
        }
        String patientName = request.getPatientName();
        if (!Checker.isNull(patientName)) {
            whereSql += " and ( name like ?)";
            paramList.add("%" + patientName.trim() + "%");
        }
        String admId = request.getAdmId();
        if (!Checker.isNull(admId)) {
            whereSql += " and ( adm_id = ?)";
            paramList.add(admId.trim());
        }
        String regNo = request.getRegNo();
        if (!Checker.isNull(regNo)) {
            whereSql += " and ( reg_no = ?)";
            paramList.add(regNo.trim());
        }
        String paymentStatus = request.getPaymentStatus();
        if (!Checker.isNull(paymentStatus)) {
            whereSql += " and ( payment_status = ?)";
            paramList.add(Integer.parseInt(paymentStatus));
        }
        String hospitalId = request.getHospitalId();
        if (!Checker.isNone(hospitalId)) {
            int hospitalIdInt = Integer.parseInt(hospitalId);
            if (hospitalIdInt > 0 ) {
                whereSql += " and ( hospital_id = ?)";
                paramList.add(hospitalIdInt);
            }
        }
        whereSql += "and deleted = 0 ";

        // 对账时间搜索
        String billEndTime = request.getBillEndTime();
        String billStartTime = request.getBillStartTime();
        if (!Checker.isNull(billEndTime)) {
            whereSql += " and ( pay_time < ? or refund_time < ?)";
            Date date = FormatUtil.stringToDateDayTimeEnd(billEndTime);
            paramList.add(date);
            paramList.add(date);
        }
        if (!Checker.isNull(billStartTime)) {
            whereSql += " and ( pay_time >= ? or refund_time >= ?)";
            Date date = FormatUtil.stringToDateDayTimeStart(billStartTime);
            paramList.add(date);
            paramList.add(date);
        }
        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("CheckUpOrderService#queryCheckUpOrderListCommonMapNew(transactionId={} ):\n {} ", transactionId, e.getMessage(), e);
        }
        String paymentTimeStart = request.getPaymentTimeStart();
        String paymentTimeEnd = request.getPaymentTimeEnd();
        // 时间查询处理
        Map<String, Object> map = sqlHelper.timeQuerySql(whereSql, paramList, "pay_time", paymentTimeStart, paymentTimeEnd);
        return map;
    }

    public void downloadCheckUpOrderListNew(int downloadRecordId, String fileName, QueryCheckUpOrderListRequest request) {
        try {
//            String[] title = new String[]{"订单号", "支付流水号", "交易流水号", "患者姓名", "性别", "就诊ID", "登记号", "金额", "支付状态", "支付时间", "医院"};
            // 单元格
            String col0 = "订单号";
            String col1 = "支付流水号";
            String col2 = "交易流水号";
            String col3 = "患者姓名";
            String col4 = "性别";
            String col5 = "就诊ID";
            String col6 = "登记号";
            String col7 = "金额";
            String col8 = "支付状态";
            String col9 = "支付时间";
            String col10 = "医院";

            String[] columns = new String[]{col0, col1, col2, col3, col4, col5, col6, col7, col8, col9, col10};
            List<CheckUpOrder> list = queryCheckUpOrderListCommon(request);
            List<OrderPayment> orderPaymentList = orderPaymentService.getOrderPaymentListByCheckUpOrderList(list);
            ExcelDataMap map = new ExcelDataMap(columns);
            int payTotal = 0, refundTotal = 0;
            if (!Checker.isNone(list)) {
                for (CheckUpOrder p : list) {
                    if (!Checker.isNone(p)) {
                        String orderNoValue = p.getOrderNo();
                        String paymentNoValue = p.getPaymentNo();
                        String patientNameValue = p.getName();
                        String sexValue = SexEnum.valueOf(Checker.getIntegerValue(p.getSex())).getDisplayName();
                        String admIdValue = p.getAdmId();
                        String regNoValue = p.getRegNo();
                        String amountValue = FormatUtil.intShrink100ToStr(p.getAmount());
                        String paymentStatusValue = PaymentStatusEnum.getPaymentStatus(p.getPaymentStatus()).getDisplayName();
                        String paymentTimeValue = FormatUtil.createTimeFormatList(p.getPayTime());
                        String hospitalName = p.getHospitalName();
                        // 交易流水号
                        String transactionId = orderPaymentService.getTransactionIdByOrderId(orderPaymentList, Checker.getIntegerValue(p.getOrderId()));

                        if (Checker.getIntegerValue(p.getPaymentStatus()) == PaymentStatusEnum.Success.getValue()) {
                            payTotal += Checker.getIntegerValue(p.getAmount());
                        }
                        if (Checker.getIntegerValue(p.getRefundStatus()) == RefundStatusEnum.SUCCESS.getValue()) {
                            refundTotal += Checker.getIntegerValue(p.getAmount());
                        }

                        // "订单号", "支付流水号", "交易流水号", "患者姓名", "性别", "就诊ID", "登记号", "金额", "支付状态", "支付时间"
//                        String[] bodyStr = new String[]{orderNoValue, paymentNoValue, transactionId, patientNameValue, sexValue, admIdValue, regNoValue, amountValue, paymentStatusValue, paymentTimeValue, hospitalName};
                        // 写入excel的body
                        map.getStringListSafely(col0).add(orderNoValue);
                        map.getStringListSafely(col1).add(paymentNoValue);
                        map.getStringListSafely(col2).add(transactionId);
                        map.getStringListSafely(col3).add(patientNameValue);
                        map.getStringListSafely(col4).add(sexValue);
                        map.getStringListSafely(col5).add(admIdValue);
                        map.getStringListSafely(col6).add(regNoValue);
                        map.getStringListSafely(col7).add(amountValue);
                        map.getStringListSafely(col8).add(paymentStatusValue);
                        map.getStringListSafely(col9).add(paymentTimeValue);
                        map.getStringListSafely(col10).add(hospitalName);

                    }
                }
            }
            int size = list.size();
            List<ExcelCollectPojo> itemList = getStatisticsData(size, payTotal, refundTotal);
            downloadRecordService.createFileAndUploadOssAndSaveToDataBase(fileName, downloadRecordId, map, itemList);

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

    /**
     * 获取统计数据
     *
     * @param size        隔行
     * @param payTotal    总金额
     * @param refundTotal 退款金额
     * @return {@link List<ExcelCollectPojo> }
     */
    private List<ExcelCollectPojo> getStatisticsData(int size, int payTotal, int refundTotal) {
        int startRows = size + 3;
        int startColumn = 3;

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

    public void downloadOutPatientOrderBillListNew(int downloadRecordId, String fileName, QueryCheckUpOrderListRequest 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() + "");
            List<CheckUpOrder> checkUpOrderList = queryCheckUpOrderListCommon(request);
            ExcelDataMap map = new ExcelDataMap(columns);
            if (!Checker.isNone(checkUpOrderList)) {
                // 得到支付的记录日志（需要从 order_payment 获取 transaction_id 字段）
                List<OrderPayment> orderPaymentList = orderPaymentService.getOrderPaymentListByCheckUpOrderList(checkUpOrderList);
                // 得到退款的记录日志（需要从 refund_log 获取 refund_id 字段）
                List<RefundLog> refundLogList = refundLogService.getRefundLogListByCheckUpOrderList(checkUpOrderList);
                Date billStartTime = DateUtil.stringToDate(request.getBillStartTime() + ConstantDef.BILL_TIME_START_FORMAT);
                Date billEndTime = DateUtil.stringToDate(request.getBillEndTime() + ConstantDef.BILL_TIME_END_FORMAT);
                for (CheckUpOrder p : checkUpOrderList) {
                    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.getAmount());
                            String totalStr = FormatUtil.intShrink100ToStr(total);
                            // 交易时间
                            String paymentTimeStr = FormatUtil.createTimeFormatDetail(p.getPayTime());
                            // 订单号
                            String orderNo = Checker.getStringValue(p.getOrderNo());
                            // 类型
                            String typeStr = "体检缴费";
//                            String[] bodyStr = {type, transactionId, totalStr, paymentTimeStr, orderNo, 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<CheckUpOrder> refundCheckUpOrderList = getRefundCheckUpOrderList(checkUpOrderList);
                for (CheckUpOrder p : refundCheckUpOrderList) {
                    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.getAmount());
                            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);

//                            String[] bodyStr = {type, transactionId, totalStr, refundTimeStr, orderNo, typeName};
                        }
                    }
                }
            }
            int size = checkUpOrderList.size();
            List<ExcelCollectPojo> itemList = new ArrayList<>();
            downloadRecordService.createFileAndUploadOssAndSaveToDataBase(fileName, downloadRecordId, map, itemList);
        } catch (Exception e) {
            logger.error("/checkUp/downloadCheckUpOrderBillList(): {}", e.getMessage(), e);
            e.printStackTrace();
        }
    }

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

}
