package com.ywt.mg.services;

import com.ywt.mg.core.SqlHelper;
import com.ywt.mg.core.utils.*;
import com.ywt.mg.domain.entities.NatOrder;
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.params.deposit.QueryDepositListRequest;
import com.ywt.mg.params.natOrder.NatOrderListRequest;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
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 NatOrderService {

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

    @Autowired
    private SqlHelper sqlHelper;

    @Autowired
    private AuthService authService;

    @Autowired
    private JdbcTemplate jdbcTemplate;

    @Autowired
    private OrderPaymentService orderPaymentService;

    @Autowired
    private HospitalCacheService hospitalCacheService;

    @Autowired
    private DownloadRecordService downloadRecordService;

    @Autowired
    private RefundLogService refundLogService;


    public List<NatOrder> queryNatOrderList(NatOrderListRequest request) throws Exception {
        Map<String, Object> map = queryNatOrderListCommon(request);
        String whereSql = (String) map.get(ConstantDef.KEY_WHERE_SQL);
        List<Object> paramList = (List<Object>) map.get(ConstantDef.KEY_PARAM_LIST);
        return sqlHelper.getListWithNoPage("*", whereSql, " id desc ", NatOrder.class, paramList.toArray());
    }

    private Map<String, Object> queryNatOrderListCommon(NatOrderListRequest request) throws Exception {
        List<Object> paramList = new ArrayList<>();
        // 只显示未删除和支付成功的记录
        String whereSql = " ( 1=1 and deleted = 0 and payment_status = 2 )";

        String paymentCode = Checker.getStringValue(request.getPaymentCode());
        if (!Checker.isNull(paymentCode)) {
            whereSql += " and ( payment_code = ?)";
            paramList.add(paymentCode);
        }

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

        String idCard = Checker.getStringValue(request.getIdCard());
        if (!Checker.isNull(idCard)) {
            whereSql += " and ( id_card = ?)";
            paramList.add(idCard);
        }

        String mobile = Checker.getStringValue(request.getMobile());
        if (!Checker.isNull(mobile)) {
            whereSql += " and ( mobile like ?)";
            paramList.add(mobile + "%");
        }

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

        String vaccineCode = Checker.getStringValue(request.getVaccineCode());
        if (!Checker.isNull(vaccineCode)) {
            whereSql += " and ( vaccine_code like ?)";
            paramList.add(vaccineCode + "%");
        }

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

        String orderStatus = Checker.getStringValue(request.getOrderStatus());
        if (!Checker.isNull(orderStatus)) {
            int orderStatusInt = Integer.parseInt(orderStatus);
            whereSql += " and ( (status & ?) = ? and status < ? ) ";
            paramList.add(orderStatusInt);
            paramList.add(orderStatusInt);
            paramList.add(2 * orderStatusInt);
        }

        int hospitalId = request.getHospitalId();
        if (hospitalId != -1) {
            whereSql += " and ( hospital_id = ?)";
            paramList.add(hospitalId);
        }

        // 对账时间搜索
        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("NatOrderService#queryNatOrderListCommon(transactionId={} ):\n {} ", transactionId, e.getMessage(), e);
        }

        String paymentStartTime = Checker.getStringValue(request.getPaymentStartTime());
        String paymentEndTime = Checker.getStringValue(request.getPaymentEndTime());
        Map<String, Object> map = sqlHelper.timeQuerySql(whereSql, paramList, "pay_time", paymentStartTime, paymentEndTime);

        String refundStartTime =  Checker.getStringValue(request.getRefundStartTime());
        String refundEndTime =  Checker.getStringValue(request.getRefundEndTime());
        map = sqlHelper.timeQuerySql(map, "refund_time", refundStartTime, refundEndTime);

        String confirmStartTime =  Checker.getStringValue(request.getConfirmStartTime());
        String confirmEndTime =  Checker.getStringValue(request.getConfirmEndTime());
        map = sqlHelper.timeQuerySql(map, "confirm_time", confirmStartTime, confirmEndTime, FormatUtil.FORMAT_DATE_SECOND);
        return map;
    }


    public void downloadNatOrderList(int downloadRecordId, String fileName, NatOrderListRequest request) {
        try {
            String col1 = "订单号", col1_1 = "支付流水号", col1_1_1 = "交易流水号", col2 = "医院", col3 = "患者姓名", col4 = "身份证号", col5 = "年龄", col6 = "性别", col7 = "手机号";
            String col8 = "缴费码", col9 = "疫苗码", col10 = "金额", col11 = "支付状态", col12 = "订单状态";
            String col13 = "支付时间", col14 = "退费时间", col15 = "预约时间", col16 = "执行时间", col17 = "备注";
            String[] columns = new String[]{col1, col1_1, col1_1_1, col2, col3, col4, col5, col6, col7, col8, col9, col10, col11, col12, col13, col14, col15, col16, col17};
            ExcelDataMap map = new ExcelDataMap(columns);
            List<NatOrder> list = queryNatOrderList(request);
            int payTotal = 0, refundTotal = 0, realityTotal = 0;
            List<OrderPayment> orderPaymentList = orderPaymentService.getOrderPaymentListByNatOrderList(list);
            for (NatOrder item : list) {
                // 交易流水号
                String transactionId = orderPaymentService.getTransactionIdByOrderId(orderPaymentList, Checker.getIntegerValue(item.getOrderId()));
                map.getStringListSafely(col1).add(Checker.getStringValue(item.getOrderNo()));
                map.getStringListSafely(col1_1).add(Checker.getStringValue(item.getPaymentNo()));
                map.getStringListSafely(col1_1_1).add(transactionId);
                map.getStringListSafely(col2).add(hospitalCacheService.getCacheHospitalNameByHospitalId(item.getHospitalId()));
                map.getStringListSafely(col3).add(Checker.getStringValue(item.getPatientName()));
                map.getStringListSafely(col4).add(Checker.getStringValue(item.getIdCard()));
                String idCard = Checker.getStringValue(item.getIdCard());
                if (!Checker.isNone(idCard)) {
                    int currentAge = IdCardUtil.getCurrentAge(idCard);
                    String sex = IdCardUtil.getSex(idCard);
                    map.getStringListSafely(col5).add(currentAge + "");
                    map.getStringListSafely(col6).add(sex);
                }

                map.getStringListSafely(col7).add(Checker.getStringValue(item.getMobile()));

                map.getStringListSafely(col8).add(Checker.getStringValue(item.getPaymentCode()));
                map.getStringListSafely(col9).add(Checker.getStringValue(item.getVaccineCode()));
                map.getStringListSafely(col10).add(FormatUtil.intShrink100ToStr(item.getAmount()));
                map.getStringListSafely(col11).add(PaymentStatusEnum.getPaymentStatus(item.getPaymentStatus()).getDisplayName());
                map.getStringListSafely(col12).add(NatOrderStatusEnum.valueOf(item.getStatus()).getDisplayName());

                map.getStringListSafely(col13).add(FormatUtil.createTimeFormatDetail(item.getPayTime()));
                map.getStringListSafely(col14).add(FormatUtil.createTimeFormatDetail(item.getRefundTime()));
                map.getStringListSafely(col15).add(FormatUtil.formatDate(item.getRegDate()) + " " + DatePeriodEnum.valueOf(item.getRegTimePeriod()).getDisplayName());
                map.getStringListSafely(col16).add(FormatUtil.createTimeFormatDetail(item.getConfirmTime()));
                map.getStringListSafely(col17).add(Checker.getStringValue(item.getRemark()));

                if (Checker.getIntegerValue(item.getPaymentStatus()) == PaymentStatusEnum.Success.getValue()) {
                    payTotal += Checker.getIntegerValue(item.getAmount());
                }
                if (Checker.getIntegerValue(item.getRefundStatus()) == RefundStatusEnum.SUCCESS.getValue()) {
                    refundTotal += Checker.getIntegerValue(item.getAmount());
                }
            }
            int size = list.size();
            List<ExcelCollectPojo> itemList = getStatisticsData(size, payTotal, refundTotal);
            downloadRecordService.createFileAndUploadOssAndSaveToDataBase(fileName, downloadRecordId, map, itemList);

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

    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 downloadNatOrderBillList(int downloadRecordId, String fileName, NatOrderListRequest request) {
        try {
            String col0 = "交易类型*";
            String col1 = "系统参考号*";
            String col2 = "交易金额*";
            String col3 = "交易日期*";
            String col4 = "订单号";
            String col5 = "类型";
            String[] columns = new String[]{col0, col1, col2, col3, col4, col5};
            List<NatOrder> natOrderList = queryNatOrderList(request);
            ExcelDataMap map = new ExcelDataMap(columns);
            if(!Checker.isNone(natOrderList)){
                List<OrderPayment> orderPaymentList = orderPaymentService.getOrderPaymentListByNatOrderList(natOrderList);
                // 得到退款的记录日志（需要从 refund_log 获取 refund_id 字段）
                List<RefundLog> refundLogList = refundLogService.getRefundLogListByNatOrderList(natOrderList);
                List<NatOrder> refundNatOrderList = getRefundNatOrderList(natOrderList);
                Date billStartTime = DateUtil.stringToDate(request.getBillStartTime() + ConstantDef.BILL_TIME_START_FORMAT);
                Date billEndTime = DateUtil.stringToDate(request.getBillEndTime() + ConstantDef.BILL_TIME_END_FORMAT);
                for (NatOrder p : natOrderList) {
                    if (!Checker.isNone(p) && Checker.getIntegerValue(p.getPaymentStatus()) == PaymentStatusEnum.Success.getValue()
                            && Checker.getIntegerValue(p.getPaymentChannel()) == PaymentChannelEnum.WeChat.getValue()
                            && Checker.getIntegerValue(p.getAmount()) > 0
                            && !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 = "核酸检测缴费";

                            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);

                        }
                    }
                }
                for (NatOrder p : refundNatOrderList) {
                    if (!Checker.isNone(p)
                            && Checker.getIntegerValue(p.getRefundStatus()) == RefundStatusEnum.SUCCESS.getValue()
                            && Checker.getIntegerValue(p.getAmount()) > 0) {
                        // "交易类型*", "系统参考号*", "交易金额*", "交易日期*", "订单号", "类型"
                        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);

                        }
                    }
                }
            }
            int size = natOrderList.size();
            List<ExcelCollectPojo> itemList = new ArrayList<>();
            downloadRecordService.createFileAndUploadOssAndSaveToDataBase(fileName, downloadRecordId, map, itemList);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

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