package com.clx.performance.service.impl.settle;

import cn.hutool.json.JSONUtil;
import com.clx.order.enums.InvoicingCompanyEnum;
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.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.enums.IdTypeEnum;
import com.clx.performance.enums.OwnerAccountEnum;
import com.clx.performance.enums.PerformanceResultEnum;
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.OwnerLoanThawEvent;
import com.clx.performance.extranal.order.InvoicingCompanyService;
import com.clx.performance.model.OrderChild;
import com.clx.performance.model.OrderGoods;
import com.clx.performance.model.OwnerAccount;
import com.clx.performance.model.OwnerRunningWaterRecord;
import com.clx.performance.model.settle.SettlementDriverDetail;
import com.clx.performance.model.settle.SettlementOwnerDetail;
import com.clx.performance.service.settle.SettlementCommonService;
import com.clx.performance.service.settle.SettlementMqService;
import com.clx.performance.service.settle.SettlementService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.core.MessageBuilder;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

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

@Slf4j
@Service
public class SettlementServiceImpl implements SettlementService {

    @Autowired
    private OrderChildDao orderChildDao;
    @Autowired
    private OrderGoodsDao orderGoodsDao;
    @Autowired
    private SettlementOwnerDetailDao settlementOwnerDetailDao;
    @Autowired
    private SettlementDriverDetailDao settlementDriverDetailDao;
    @Autowired
    private SettlementMqService settlementMqService;
    @Autowired
    private OwnerRunningWaterRecordDao ownerRunningWaterRecordDao;
    @Autowired
    private IdGenerateSnowFlake idGenerateSnowFlake;
    @Autowired
    private OwnerAccountDao ownerAccountDao;
    @Autowired
    private RabbitTemplate rabbitTemplate;

    @Autowired
    private ApplicationEventPublisher applicationEventPublisher;
    @Autowired
    private InvoicingCompanyService invoicingCompanyService;
    @Autowired
    private SettlementConfig settlementConfig;
    @Autowired
    private SettlementCommonService settlementCommonService;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateSettlementDetailInvoiceType(String childNo, Integer invoiceType) {
        OrderChild orderChild = orderChildDao.getByChildNo(childNo).orElseThrow(PerformanceResultEnum.ORDER_CHILD_NO_FOUND);
        OrderGoods orderGoods = orderGoodsDao.getByOrderGoodsNo(orderChild.getOrderGoodsNo()).orElseThrow(PerformanceResultEnum.DATA_NOT_FIND);

        SettlementOwnerDetail settlementOwnerDetail = settlementOwnerDetailDao.getByChildNo(childNo).orElseThrow(PerformanceResultEnum.DATA_NOT_FIND);
        SettlementDriverDetail settlementDriverDetail = settlementDriverDetailDao.getByChildNo(childNo).orElseThrow(PerformanceResultEnum.DATA_NOT_FIND);
        log.info("开始 更新网络标识 {} , {}",orderChild.getChildNo()  ,settlementDriverDetail.getSettlementFreight().compareTo(BigDecimal.ZERO));
        if (settlementDriverDetail.getSettlementFreight().compareTo(BigDecimal.ZERO) <= 0) {
            settlementDriverDetail.setPrepayFreightFlag(SettlementDriverEnum.PrepayFreightFlag.NO_PAY.getCode());
            settlementOwnerDetail.setPrepayFreight(BigDecimal.ZERO);
        } else {

            // 发mq （同步网络货运）
            Message message = MessageBuilder.withBody(JSONUtil.parse(orderChild).toString().getBytes()).build();
            rabbitTemplate.send(
                    RabbitKeyConstants.ORDER_CHILD_SYNC_TRANSPORT_EXCHANGE, RabbitKeyConstants.ORDER_CHILD_SYNC_TRANSPORT_ROUTE_KEY, message
            );
            return;
        }

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

        log.info("当前货主结算信息{},车主结算信息：{}", JSONUtil.parse(settlementOwnerDetail), JSONUtil.parse(settlementDriverDetail));
        settlementOwnerDetailDao.updateInvoiceType(settlementOwnerDetail);
        settlementDriverDetailDao.updateInvoiceTypeAndPrepayFreightFlag(settlementDriverDetail);

        //普通单解冻
        applicationEventPublisher.publishEvent(new OwnerLoanThawEvent(this, childNo));
        // 发送mq 结算统计
        settlementMqService.settlementStatistics(childNo, invoiceType);

    }

    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 updatePrepayFreightPay(String childNo, BigDecimal freight, BigDecimal lossFreight) {
        //开票金额
        BigDecimal prepayFreight = freight.subtract(lossFreight);
        if (prepayFreight.compareTo(BigDecimal.ZERO) <= 0) {
            return BigDecimal.ZERO;
        }

        //扣减预付运费


        return prepayFreight;

    }

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

}
