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

import cn.hutool.json.JSONUtil;
import com.clx.performance.component.IdGenerateSnowFlake;
import com.clx.performance.component.ThirdComponent;
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.dto.OrderChildSyncDTO;
import com.clx.performance.enums.IdTypeEnum;
import com.clx.performance.enums.OwnerAccountEnum;
import com.clx.performance.enums.PerformanceResultEnum;
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.feign.TransportFeignService;
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.param.feign.transport.ThirdOrderChildBrokerParam;
import com.clx.performance.service.TransportSyncService;
import com.clx.performance.service.settle.SettlementMqService;
import com.clx.performance.service.settle.SettlementService;
import com.clx.performance.vo.feign.transport.ThirdOrderChildBrokerResultVO;
import com.msl.common.dto.HttpDTO;
import com.msl.common.exception.ServiceSystemException;
import com.msl.common.result.Result;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

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

@Slf4j
@Service
public class SettlementServiceImpl implements SettlementService {


    @Autowired
    private OrderChildDao orderChildDao;
    @Autowired
    private SettlementOwnerDetailDao settlementOwnerDetailDao;
    @Autowired
    private SettlementDriverDetailDao settlementDriverDetailDao;
    @Autowired
    private SettlementMqService settlementMqService;
    @Autowired
    private TransportSyncService transportSyncService;
    @Autowired
    private OrderGoodsDao orderGoodsDao;
    @Autowired
    private OwnerRunningWaterRecordDao ownerRunningWaterRecordDao;
    @Autowired
    private IdGenerateSnowFlake idGenerateSnowFlake;

    @Autowired
    private TransportFeignService transportFeignService;

    @Autowired
    private OwnerAccountDao ownerAccountDao;


    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateSettlementDetailInvoiceType(String childNo, Integer invoiceType) {
        OrderChild orderChild = orderChildDao.getByChildNo(childNo).orElseThrow(PerformanceResultEnum.ORDER_CHILD_NO_FOUND);
        SettlementOwnerDetail settlementOwnerDetail = settlementOwnerDetailDao.getByChildNo(childNo).orElseThrow(PerformanceResultEnum.DATA_NOT_FIND);
        SettlementDriverDetail settlementDriverDetail = settlementDriverDetailDao.getByChildNo(childNo).orElseThrow(PerformanceResultEnum.DATA_NOT_FIND);

        if (settlementOwnerDetail.getInvoiceType() != null) {return;}
        // 开票金额
        settlementOwnerDetail.setInvoiceFreight(invoiceFreightCalc(orderChild.getSettlementWay(),settlementOwnerDetail));
        invoiceType = SettlementOwnerEnum.InvoiceType.ORDINARY.getCode();

        OrderGoods orderGoods = orderGoodsDao.getByOrderGoodsNo(orderChild.getOrderGoodsNo()).get();
        //是否通过风控,调用网络货运
        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);
        log.info("OrderChildSyncDTO信息为:{}", JSONUtil.parse(bean));
        if (bean.getCode() == 0) {
            Integer status = bean.getData().getStatus();
            BigDecimal ans = settlementOwnerDetail.getFreight().subtract(settlementOwnerDetail.getLossFreight());
            if (status == 1) {
                //通过风控
                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 subtract = frozen.subtract(takeOut);
                log.info("冻结预付运费:{}, 扣除的流水总和：{}", frozen, takeOut);
                invoiceType = SettlementOwnerEnum.InvoiceType.ONLINE.getCode();

                if (subtract.compareTo(BigDecimal.ZERO) <= 0) {
                    settlementOwnerDetail.setPrepayFreight(BigDecimal.ZERO);
                } else {
                    if (subtract.subtract(ans).compareTo(BigDecimal.ZERO) >= 0) {
                        OwnerAccount account = ownerAccountDao.getAccountByOwnerUserNoAndAccountType(orderChild.getOwnerUserNo(),
                                OwnerAccountEnum.AccountTypeStatus.PREPAID_FREIGHT_ACCOUNT.getCode());
                        settlementOwnerDetail.setPrepayFreight(ans);

                        //生成扣除流水
                        OwnerRunningWaterRecord runningWaterRecord = new OwnerRunningWaterRecord();
                        runningWaterRecord.setOwnerUserName(orderChild.getOwnerName());
                        runningWaterRecord.setMobile(orderChild.getDriverMobile());
                        runningWaterRecord.setCreateBy("系统");
                        runningWaterRecord.setOrderId(orderChild.getId());
                        runningWaterRecord.setOrderNo(orderChild.getOrderNo());
                        runningWaterRecord.setOrderChildId(orderChild.getId());
                        runningWaterRecord.setOrderChildNo(orderChild.getChildNo());
                        runningWaterRecord.setRelationId(null);
                        runningWaterRecord.setAlterationBalance(ans);
                        runningWaterRecord.setFrozenBalance(subtract.subtract(ans));
                        runningWaterRecord.setUsableBalance(account.getUsableBalance());
                        runningWaterRecord.setTakeOutBalance(ans);
                        runningWaterRecord.setAccountBalance(account.getAccountBalance().subtract(ans));
                        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);
                    } else {
                        settlementOwnerDetail.setPrepayFreight(BigDecimal.ZERO);
                    }
                }

            } else {
                settlementDriverDetail.setPrepayFreightFlag(0);
                settlementOwnerDetail.setPrepayFreight(BigDecimal.ZERO);
                settlementOwnerDetail.setFinalPaymentStatus(SettlementOwnerDetailEnum.FinalPaymentStatus.NO.getCode());
            }
        } else {
            throw new ServiceSystemException(PerformanceResultEnum.ORDER_CHILD_SYNC_ERROR);

        }

        if (SettlementOwnerEnum.InvoiceType.ONLINE.getCode().equals(invoiceType) && settlementOwnerDetail.getPrepayFreight().compareTo(BigDecimal.ZERO) > 0) {
            settlementDriverDetail.setPrepayFreightFlag(1);
        }


        settlementOwnerDetail.setInvoiceType(invoiceType);
        settlementDriverDetail.setInvoiceType(invoiceType);
        // 结算金额
        settlementOwnerDetail.setSettlementFreight(settlementFreightCalc(orderChild.getSettlementWay(),settlementOwnerDetail));

        //设置司机预付运费标示
        if (settlementOwnerDetail.getPrepayFreight().compareTo(BigDecimal.ZERO) > 0) {
            settlementDriverDetail.setPrepayFreightFlag(1);
        } else {
            settlementDriverDetail.setPrepayFreightFlag(0);
        }

//        // 网运单更新预付运费
//        if (Objects.equals(settlementOwnerDetail.getInvoiceType(), SettlementOwnerEnum.InvoiceType.ONLINE.getCode())) {
//            settlementOwnerDetail.setPrepayFreight(updatePrepayFreightPay(settlementOwnerDetail.getChildNo(),
//                    settlementOwnerDetail.getFreight(), settlementOwnerDetail.getLossFreight()));
//        }

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

        // 发送mq 通过开票标识
        settlementMqService.invoiceTypeSync(childNo, invoiceType);

    }

    /**
     * 预付运费支付
     */
    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 invoiceFreightCalc(Integer settlementWay,SettlementOwnerDetail settlementOwnerDetail){
        if(Objects.equals(settlementWay, SettlementWayEnum.WayType.LOAD.getCode())){ //订单结算方式为“装车净重”时，开票金额=实际净重*平台运费报价-货损金额。
            return settlementOwnerDetail.getWeight().multiply(settlementOwnerDetail.getFreightPrice())
                    .subtract(settlementOwnerDetail.getLossFreight());
        }else{ //订单结算方式为“卸车净重”时，开票金额=实际净重*平台运费报价。
            return settlementOwnerDetail.getWeight().multiply(settlementOwnerDetail.getFreightPrice());
        }
    }

    /**
     * 结算金额
     */
    private BigDecimal settlementFreightCalc(Integer settlementWay,SettlementOwnerDetail settlementOwnerDetail){
        if(Objects.equals(settlementWay, SettlementWayEnum.WayType.LOAD.getCode())){ //订单结算方式为“装车净重”时，结算金额=实际净重*平台运费报价-预付运费-货损金额。
            return settlementOwnerDetail.getWeight().multiply(settlementOwnerDetail.getFreightPrice())
                    .subtract(settlementOwnerDetail.getPrepayFreight()).subtract(settlementOwnerDetail.getLossFreight());
        }else{ //订单结算方式为“卸车净重”时，结算金额=实际净重*平台运费报价-预付运费
            return settlementOwnerDetail.getWeight().multiply(settlementOwnerDetail.getFreightPrice()).subtract(settlementOwnerDetail.getPrepayFreight());
        }
    }
}
