package com.clx.performance.listener;

import cn.hutool.json.JSONUtil;
import com.clx.order.enums.InvoicingCompanyEnum;
import com.clx.order.enums.OrderEnum;
import com.clx.order.enums.QuotationEnum;
import com.clx.order.vo.pc.carrier.InvoicingCompanyVO;
import com.clx.performance.component.IdGenerateSnowFlake;
import com.clx.performance.config.SettlementConfig;
import com.clx.performance.constant.RabbitKeyConstants;
import com.clx.performance.dao.OrderChildDao;
import com.clx.performance.dao.OrderChildSyncTransportInvoiceRecordDao;
import com.clx.performance.dao.OrderGoodsDao;
import com.clx.performance.dao.OwnerAccountDao;
import com.clx.performance.dao.OwnerRunningWaterRecordDao;
import com.clx.performance.dao.settle.SettlementDriverDetailDao;
import com.clx.performance.dao.settle.SettlementOwnerDetailDao;
import com.clx.performance.dto.OrderChildSyncDTO;
import com.clx.performance.dto.OwnerLoanMqDTO;
import com.clx.performance.enums.*;
import com.clx.performance.enums.settle.SettlementDriverEnum;
import com.clx.performance.enums.settle.SettlementOwnerDetailEnum;
import com.clx.performance.enums.settle.SettlementOwnerEnum;
import com.clx.performance.enums.settle.SettlementWayEnum;
import com.clx.performance.event.OwnerLoanEvent;
import com.clx.performance.extranal.order.InvoicingCompanyService;
import com.clx.performance.feign.TransportFeignService;
import com.clx.performance.model.*;
import com.clx.performance.model.settle.SettlementDriverDetail;
import com.clx.performance.model.settle.SettlementOwnerDetail;
import com.clx.performance.service.TransportSyncService;
import com.clx.performance.service.broker.OrderChildBrokerService;
import com.clx.performance.service.settle.NetworkDriverRunningWaterRecordService;
import com.clx.performance.service.settle.SettlementCommonService;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.stereotype.Component;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.List;
import java.util.Objects;

/**
 * 承运同步网络货运运单
 */
@Slf4j
@Component
@AllArgsConstructor
public class OrderChildSyncTransportListener {

    private final OrderGoodsDao orderGoodsDao;

    private final TransportSyncService transportSyncService;

    private final TransportFeignService transportFeignService;

    private final OwnerRunningWaterRecordDao ownerRunningWaterRecordDao;

    private final NetworkDriverRunningWaterRecordService networkDriverRunningWaterRecordService;

    private final OwnerAccountDao ownerAccountDao;

    private final IdGenerateSnowFlake idGenerateSnowFlake;

    private final SettlementOwnerDetailDao settlementOwnerDetailDao;

    private final SettlementDriverDetailDao settlementDriverDetailDao;

    private final OrderChildSyncTransportInvoiceRecordDao orderChildSyncTransportInvoiceRecordDao;

    private final ApplicationEventPublisher applicationEventPublisher;
    private final InvoicingCompanyService invoicingCompanyService;
    private final SettlementConfig settlementConfig;
    private final OrderChildBrokerService orderChildBrokerService;
    private final  OrderChildDao orderChildDao;

    private final SettlementCommonService settlementCommonService;
    /**
     * 承运同步网络货运运单
     */
    @RabbitListener(queues = RabbitKeyConstants.ORDER_CHILD_SYNC_TRANSPORT_QUEUE)
    public void onMessage(String message) {
        OrderChild orderChild = JSONUtil.toBean(message, OrderChild.class);
        //是否通过风控,调用网络货运
        try {
            OrderChild orderChildBase = orderChildDao.getByChildNo(orderChild.getChildNo()).orElseThrow(PerformanceResultEnum.ORDER_CHILD_NO_FOUND);
            log.info("当前OrderChildSyncTransportListener监听同步网络货运,运单{}", JSONUtil.parse(orderChildBase).toString());

            transportOrderChildProcess(orderChildBase);

        } catch (Exception e) {
            log.info("当前OrderChildSyncTransportListener监听同步网络货运失败,运单号{}, 错误信息{}", orderChild.getChildNo(), ExceptionUtils.getStackTrace(e));

        }
    }

    public void transportOrderChildProcess(OrderChild orderChild) {
        Integer invoiceType = SettlementOwnerEnum.InvoiceType.ORDINARY.getCode();

        OrderGoods orderGoods = orderGoodsDao.getByOrderGoodsNo(orderChild.getOrderGoodsNo()).get();

        SettlementOwnerDetail settlementOwnerDetail = settlementOwnerDetailDao.getByChildNo(orderChild.getChildNo()).orElseThrow(PerformanceResultEnum.DATA_NOT_FIND);
        SettlementDriverDetail settlementDriverDetail = settlementDriverDetailDao.getByChildNo(orderChild.getChildNo()).orElseThrow(PerformanceResultEnum.DATA_NOT_FIND);

//        // 同步网络货运(禁用网络货运同步)
//        ThirdOrderChildBrokerParam param = transportSyncService.generateOrderChildSync(orderChild, orderGoods, settlementOwnerDetail, settlementDriverDetail);
//        HttpDTO httpDTOResult = transportFeignService.orderChildSync(param);
//        String decrypt = ThirdComponent.decrypt(httpDTOResult.getData());
//        OrderChildSyncDTO bean = JSONUtil.toBean(decrypt, OrderChildSyncDTO.class);
//        extracted(orderChild, bean, JSONUtil.parse(bean).toString(), settlementOwnerDetail, invoiceType, settlementDriverDetail);

        if (Objects.equals(settlementOwnerDetail.getReportFlag(), OrderEnum.ReportFlag.NO.getCode())){
            // 不上报走普通单
            extracted(orderChild, settlementOwnerDetail, settlementDriverDetail, invoiceType, null);
        }
        else{

            try{
                // 同步broker
                orderChildBrokerService.orderChildSync(orderChild, orderGoods, settlementOwnerDetail, settlementDriverDetail);
            } catch (Exception e) {
                log.info("当前OrderChildSyncTransportListener监听同步网络货运失败,运单号{}, 错误信息{}", orderChild.getChildNo(), ExceptionUtils.getStackTrace(e));

            }

        }

    }

    public void extracted(OrderChild orderChild, OrderChildSyncDTO bean, String remark,
                          SettlementOwnerDetail settlementOwnerDetail,
                          Integer invoiceType, SettlementDriverDetail settlementDriverDetail) {

        if (null != bean  && bean.getCode() == 0 && null != bean.getData() && bean.getData().getStatus() == 1){
            invoiceType = SettlementOwnerEnum.InvoiceType.ONLINE.getCode();
        }
        extracted(orderChild, settlementOwnerDetail, settlementDriverDetail, invoiceType, remark);
    }
    public void extracted(OrderChild orderChild,
                          SettlementOwnerDetail settlementOwnerDetail,
                          SettlementDriverDetail settlementDriverDetail,
                          Integer invoiceType,
                          String remark) {

        OrderGoods orderGoods = orderGoodsDao.getByOrderGoodsNo(orderChild.getOrderGoodsNo()).get();

        // 未税 卸车减货损不用生成扣除相关流水逻辑
        if (Objects.equals(invoiceType, SettlementOwnerEnum.InvoiceType.ONLINE.getCode())
                && Objects.equals(orderGoods.getPlatformFreightQuotationTaxType(),QuotationEnum.PlatformFreightQuotationTaxType.NO.getCode())
                && Objects.equals(orderGoods.getSettlementWay(), SettlementWayEnum.WayType.UNLOAD_LOSS.getCode())) {
            settlementOwnerDetail.setPrepayFreight(BigDecimal.ZERO);
            settlementDriverDetail.setPrepayFreightFlag(SettlementDriverEnum.PrepayFreightFlag.NO_PAY.getCode());
            settlementOwnerDetail.setFinalPaymentStatus(SettlementOwnerDetailEnum.FinalPaymentStatus.NO.getCode());

            //生成提现记录
            networkDriverRunningWaterRecordService.generateNetworkCaseOutRecord(settlementDriverDetail);
        }
        else if (Objects.equals(invoiceType, SettlementOwnerEnum.InvoiceType.ONLINE.getCode())) {

            //通过风控
            List<OwnerRunningWaterRecord> runningWaterRecordList = ownerRunningWaterRecordDao.getOwnerRunningWaterRecord(orderChild.getOrderNo());
            BigDecimal frozen = runningWaterRecordList.stream().filter(item -> {
                return item.getRunningWaterType().equals(OwnerAccountEnum.RunningWaterStatus.FROZEN.getCode())
                        && item.getAccountType().equals(OwnerAccountEnum.AccountTypeStatus.PREPAID_FREIGHT_ACCOUNT.getCode())
                        ;
            }).map(OwnerRunningWaterRecord::getAlterationBalance).reduce(BigDecimal.ZERO, BigDecimal::add);

            BigDecimal takeOut = runningWaterRecordList.stream().filter(item -> {
                return item.getRunningWaterType().equals(OwnerAccountEnum.RunningWaterStatus.TAKE_OUT.getCode())
                        && item.getAccountType().equals(OwnerAccountEnum.AccountTypeStatus.PREPAID_FREIGHT_ACCOUNT.getCode())
                        ;
            }).map(OwnerRunningWaterRecord::getAlterationBalance).reduce(BigDecimal.ZERO, BigDecimal::add);
            //设置预付运费金额
            BigDecimal ans = getPrepayFreightPay(orderChild.getSettlementWay(), settlementOwnerDetail, frozen);
            BigDecimal subtract = frozen.subtract(takeOut);
            log.info("冻结预付运费:{}, 扣除的流水总和：{}", frozen, takeOut);
            settlementDriverDetail.setPrepayFreight(ans);

            //冻结的预付运费为0 或者 此刻预付运费也可能为0，那么就不用生成扣除相关流水逻辑
            if (subtract.compareTo(BigDecimal.ZERO) <= 0 || ans.compareTo(BigDecimal.ZERO) == 0) {
                settlementOwnerDetail.setPrepayFreight(BigDecimal.ZERO);
                settlementDriverDetail.setPrepayFreightFlag(SettlementDriverEnum.PrepayFreightFlag.NO_PAY.getCode());
            } else {
                if (subtract.subtract(ans).compareTo(BigDecimal.ZERO) >= 0) {
                    //账户扣钱并生成扣除流水
                    generateTakeOutRunningWatter(orderChild, ans, settlementOwnerDetail, settlementDriverDetail);
                    try {
                        //网络货运钱包账户
                        networkDriverRunningWaterRecordService.generateNetworkDriverRunningWaterRecord(
                                settlementDriverDetail,
                                NetworkDriverAccountEnum.RunningWaterStatus.SETTLEMENT.getCode()
                        );
                        //生成提现记录
                        networkDriverRunningWaterRecordService.generateNetworkCaseOutRecord(settlementDriverDetail);
                    } catch (Exception e) {
                        log.info("运单同步网络货运生成司机运单结算流水失败：{}", e.getMessage());
                    }

                } else {
                    settlementOwnerDetail.setPrepayFreight(BigDecimal.ZERO);
                    settlementDriverDetail.setPrepayFreightFlag(SettlementDriverEnum.PrepayFreightFlag.NO_PAY.getCode());
                }
            }
        }
        else {
            settlementDriverDetail.setPrepayFreightFlag(SettlementDriverEnum.PrepayFreightFlag.NO_PAY.getCode());
            settlementOwnerDetail.setPrepayFreight(BigDecimal.ZERO);
            settlementOwnerDetail.setFinalPaymentStatus(SettlementOwnerDetailEnum.FinalPaymentStatus.NO.getCode());
        }


        if (SettlementOwnerEnum.InvoiceType.ORDINARY.getCode().equals(invoiceType)) {
            if (settlementOwnerDetail.getSettlementFreight().compareTo(BigDecimal.ZERO) == 0) {
                settlementOwnerDetail.setFinalPaymentStatus(SettlementOwnerDetailEnum.FinalPaymentStatus.NO_REQUIRE.getCode());
            }
            // 如果开票标识为“普通单”时，开票费率从开票公司“五寨华祥”中获取
            InvoicingCompanyVO invoiceCompany = invoicingCompanyService.getInvoicingCompanyByGroupCode(
                    settlementConfig.getOrdinaryInvoiceCompanyGroupCode());
            //设置开票公司信息
            settlementOwnerDetail.setInvoicingCompanyId(invoiceCompany.getId());
            settlementOwnerDetail.setInvoicingCompanyShorterName(invoiceCompany.getCompanyShorterName());
            settlementOwnerDetail.setInvoicingCompanyGroupCode(invoiceCompany.getCompanyGroupCode());

            settlementOwnerDetail.setInvoiceServiceFeeRate(BigDecimal.ZERO);
            if (Objects.equals(invoiceCompany.getQuotationType(), InvoicingCompanyEnum.TaxType.TAX_EXCLUDED.getCode())) {
                settlementOwnerDetail.setInvoiceServiceFeeRate(
                        invoiceCompany.getServiceFeeRate() == null ? BigDecimal.ZERO : invoiceCompany.getServiceFeeRate());
            }

            settlementDriverDetail.setInvoicingCompanyId(invoiceCompany.getId());
            settlementDriverDetail.setInvoicingCompanyShorterName(invoiceCompany.getCompanyShorterName());
            settlementDriverDetail.setInvoicingCompanyGroupCode(invoiceCompany.getCompanyGroupCode());
        } else {
            if (settlementDriverDetail.getSettlementFreight().compareTo(BigDecimal.ZERO) == 0) {
                settlementOwnerDetail.setFinalPaymentStatus(SettlementOwnerDetailEnum.FinalPaymentStatus.NO_REQUIRE.getCode());
            }
        }
        settlementOwnerDetail.setInvoiceType(invoiceType);
        settlementOwnerDetail.setRemark(remark);
        settlementDriverDetail.setInvoiceType(invoiceType);

        // 开票服务费
        settlementOwnerDetail.setInvoiceServiceFee(settlementCommonService.invoiceServiceFeeCalc(orderChild.getSettlementWay(), settlementOwnerDetail));
        // 开票金额
        settlementOwnerDetail.setInvoiceFreight(settlementCommonService.invoiceFreightCalc(orderChild.getSettlementWay(),
                orderGoods.getInvoiceServiceFeeRate(), settlementOwnerDetail));

        // 结算金额
        settlementOwnerDetail.setSettlementFreight(settlementCommonService.settlementFreightCalc(orderChild.getSettlementWay(), settlementOwnerDetail));

        //货主借款事件处理
        OwnerLoanMqDTO dto = new OwnerLoanMqDTO();
        dto.setSettlementOwnerDetail(settlementOwnerDetail);
        dto.setSettlementDriverDetail(settlementDriverDetail);
        dto.setOrderChild(orderChild);
        applicationEventPublisher.publishEvent(new OwnerLoanEvent(this, dto));

    }

    private void generateTakeOutRunningWatter(OrderChild orderChild, BigDecimal ans, SettlementOwnerDetail settlementOwnerDetail, SettlementDriverDetail settlementDriverDetail) {
        OwnerAccount account = null;
        while (true) {
            account = ownerAccountDao.getAccountByOwnerUserNoAndAccountType(orderChild.getOwnerUserNo(),
                    OwnerAccountEnum.AccountTypeStatus.PREPAID_FREIGHT_ACCOUNT.getCode());
            OwnerAccount update = new OwnerAccount();
            update.setId(account.getId());
            update.setAccountBalance(ans);
            update.setModifiedTime(account.getModifiedTime());
            update.setFrozenBalance(ans);
            Integer i = ownerAccountDao.updateOwnerAccountForConfirm(update);
            if (null != i && i > 0) {
                break;
            }
        }
        account = ownerAccountDao.getAccountByOwnerUserNoAndAccountType(orderChild.getOwnerUserNo(),
                OwnerAccountEnum.AccountTypeStatus.PREPAID_FREIGHT_ACCOUNT.getCode());

        settlementOwnerDetail.setPrepayFreight(ans);
        settlementDriverDetail.setPrepayFreightFlag(SettlementDriverEnum.PrepayFreightFlag.PAYED.getCode());
        settlementOwnerDetail.setFinalPaymentStatus(SettlementOwnerDetailEnum.FinalPaymentStatus.NO_REQUIRE.getCode());


        OwnerRunningWaterRecord runningWaterRecord = new OwnerRunningWaterRecord();
        runningWaterRecord.setOwnerUserName(orderChild.getOwnerName());
        runningWaterRecord.setMobile(orderChild.getDriverMobile());
        runningWaterRecord.setCreateBy("系统");
        runningWaterRecord.setOrderNo(orderChild.getOrderNo());
        runningWaterRecord.setOrderChildId(orderChild.getId());
        runningWaterRecord.setOrderChildNo(orderChild.getChildNo());
        runningWaterRecord.setRelationId(null);
        runningWaterRecord.setAlterationBalance(ans);
        runningWaterRecord.setFrozenBalance(account.getFrozenBalance());
        runningWaterRecord.setUsableBalance(account.getUsableBalance());
        runningWaterRecord.setTakeOutBalance(ans);
        runningWaterRecord.setAccountBalance(account.getAccountBalance());
        runningWaterRecord.setOwnerUserNo(account.getOwnerUserNo());

        runningWaterRecord.setAccountType(OwnerAccountEnum.AccountTypeStatus.PREPAID_FREIGHT_ACCOUNT.getCode());
        runningWaterRecord.setRunningWaterType(OwnerAccountEnum.RunningWaterStatus.TAKE_OUT.getCode());
        runningWaterRecord.setRunningWaterNo(idGenerateSnowFlake.nextId(IdTypeEnum.Type.TAKE_OUT.getCode()));
        ownerRunningWaterRecordDao.saveEntity(runningWaterRecord);
    }

    private BigDecimal getPrepayFreightPay(Integer settlementWay, SettlementOwnerDetail settlementOwnerDetail, BigDecimal accountFrozenFreight) {
        //订单结算方式为“装车净重”时
        if (Objects.equals(settlementWay, SettlementWayEnum.WayType.LOAD.getCode())) {
            BigDecimal subtract = settlementOwnerDetail.getFreight().subtract(settlementOwnerDetail.getLossFreight());
            if (accountFrozenFreight.compareTo(subtract) >= 0) {
                return subtract;
            } else {
                return BigDecimal.ZERO;
            }
        } else {
            if (accountFrozenFreight.compareTo(settlementOwnerDetail.getFreight()) >= 0) {
                return settlementOwnerDetail.getFreight();
            } else {
                return BigDecimal.ZERO;
            }
        }
    }

}
