package com.clx.performance.service.impl;


import com.clx.performance.dao.*;
import com.clx.performance.enums.*;
import com.clx.performance.model.*;
import com.clx.performance.param.pc.PoundAuditParam;
import com.clx.performance.service.OrderChildLogService;
import com.clx.performance.service.OrderChildPoundAuditService;
import com.clx.performance.service.OrderGoodsService;
import com.clx.performance.vo.pc.OrderChildPoundAuditDetailVO;
import com.msl.common.exception.ServiceSystemException;
import com.msl.user.data.UserSessionData;
import com.msl.user.utils.TokenUtil;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

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

/**
 * @author liruixin
 * Date 2023-09-19
 * Time 13:25
 */
@Slf4j
@Service
@AllArgsConstructor
public class OrderChildPoundAuditServiceImpl  implements OrderChildPoundAuditService {

    private final OrderGoodsTruckBindDao orderGoodsTruckBindDao;
    private final OrderChildImageDao orderChildImageDao;

    private final OrderChildPoundAuditDao orderChildPoundAuditDao;

    private final OrderChildPoundLogDao orderChildPoundLogDao;

    private final OrderChildDao orderChildDao;

    private final OrderGoodsDao orderGoodsDao;

    private final OrderGoodsService orderGoodsService;

    private final OrderChildLogService orderChildLogService;


    @Override
    public OrderChildPoundAuditDetailVO getPoundAuditDetail(String childNo) {
        OrderChildPoundAudit poundAuditDetail = orderChildPoundAuditDao.getPoundAuditDetail(childNo).orElseThrow(PerformanceResultEnum.DATA_NOT_FIND);
        List<OrderChildImage> loadImages = orderChildImageDao.getImages(childNo, OrderChildImage.Type.LOAD.getCode());
        List<OrderChildImage> unloadImages = orderChildImageDao.getImages(childNo, OrderChildImage.Type.UNLOAD.getCode());
        OrderChildPoundAuditDetailVO vo = new OrderChildPoundAuditDetailVO();
        vo.setChildNo(childNo);
        vo.setLoadImages(loadImages.stream().map(OrderChildImage::getImage).collect(Collectors.toList()));
        vo.setUnloadImages(unloadImages.stream().map(OrderChildImage::getImage).collect(Collectors.toList()));
        vo.setLoadNet(poundAuditDetail.getLoadNet());
        vo.setUnloadNet(poundAuditDetail.getUnloadNet());
        vo.setUnloadPoundNo(poundAuditDetail.getUnloadPoundNo());
        vo.setStatus(poundAuditDetail.getStatus());
        vo.setRemark(poundAuditDetail.getRemark());
        vo.setRejectType(poundAuditDetail.getRejectType());
        return vo;
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updatePoundAudit(PoundAuditParam param) {
        //运单详情
        OrderChild orderChild = orderChildDao.getByChildNo(param.getChildNo()).orElseThrow(PerformanceResultEnum.DATA_NOT_FIND);

        if(OrderChildEnum.CANCEL_lIST.contains(orderChild.getStatus())){
            throw new ServiceSystemException(PerformanceResultEnum.ORDER_CHILD_CANCELED);
        }
        //待审核磅单
        OrderChildPoundAudit poundAuditDetail = orderChildPoundAuditDao.getPoundAuditDetail(param.getChildNo()).orElseThrow(PerformanceResultEnum.DATA_NOT_FIND);
        if(!Objects.equals(poundAuditDetail.getStatus(),OrderChildPoundAuditEnum.Status.AUDIT.getCode())){
            throw new ServiceSystemException(PerformanceResultEnum.ORDER_CHILD_STATUS_CHANGED);
        }

        OrderGoods orderGoods = orderGoodsDao.getByOrderGoodsNo(orderChild.getOrderGoodsNo()).orElseThrow(PerformanceResultEnum.ORDER_INVALID);

        //磅单审核对象赋值
        poundAuditDetail.setStatus(param.getStatus());
        poundAuditDetail.setRejectType(param.getRejectType());
        poundAuditDetail.setRemark(param.getRemark());
        poundAuditDetail.setId(null);
        poundAuditDetail.setCreateTime(null);
        poundAuditDetail.setModifiedTime(null);

        BigDecimal dif = param.getLoadNet().subtract(orderChild.getLoadNet());

        Integer type = OrderChildLogEnum.Type.POUND_AUDIT.getCode();
        if(Objects.equals(param.getStatus(), OrderChildPoundAuditEnum.Status.REJECT.getCode())){
            type = OrderChildLogEnum.Type.POUND_AUDIT_REJECT.getCode();
        }else{
            if(Objects.nonNull(param.getLoadNet())){
                poundAuditDetail.setLoadNet(param.getLoadNet());
                orderChild.setLoadNet(param.getLoadNet());
            }

            if(Objects.nonNull(param.getUnloadNet())){
                poundAuditDetail.setUnloadNet(param.getUnloadNet());
                orderChild.setUnloadNet(param.getUnloadNet());
            }
        }
        orderChild.setWeight(orderChildWeightCalc(orderChild));
        orderChild.setFreight(orderChildFreightCalc(orderChild));

        // 更新装车净重
        updateOrderGoodsAmountLoad(orderGoods, dif);

        //更新运单数据
        orderChild.setPoundStatus(param.getStatus());
        orderChildDao.updatePoundAuditStatus(orderChild);

        //保存磅单审核数据
        orderChildPoundAuditDao.saveEntity(poundAuditDetail);

        UserSessionData loginUserInfo = TokenUtil.getLoginUserInfo();
        OrderChildPoundLog poundLog = OrderChildPoundLog.builder().childNo(param.getChildNo()).status(param.getStatus()).createType(OrderChildLogEnum.CreateType.PLATFORM.getCode())
                .remark(OrderChildPoundAuditEnum.Status.getByCode(param.getStatus()).get().getMsg()).createBy(loginUserInfo.getUserNo()).createName(loginUserInfo.getUserName()).build();

        //保存磅单审核日志数据
        orderChildPoundLogDao.saveEntity(poundLog);

        //保存运单日志数据
        orderChildLogService.saveOrderChildLog(param.getChildNo(),type,OrderChildLogEnum.Type.getByCode(type).get().getMsg(),
                OrderChildLogEnum.CreateType.PLATFORM.getCode(), loginUserInfo.getUserNo(),loginUserInfo.getUserName());

    }

    /**
     * 装车补偿
     */
    private void updateOrderGoodsAmountLoad(OrderGoods orderGoods, BigDecimal dif){
        int i = dif.compareTo(BigDecimal.ZERO);
        if (i == 0){
            return;
        } else if (i > 0) {
            if (orderGoods.getOrderGoodsStatus().equals(OrderGoodsStatusEnum.Status.CANCEL.getCode())
                    || orderGoods.getOrderGoodsStatus().equals(OrderGoodsStatusEnum.Status.COMPLETED.getCode())
                    || orderGoods.getOrderGoodsStatus().equals(OrderGoodsStatusEnum.Status.SUCCESS.getCode())
            ) {
                throw new ServiceSystemException(PerformanceResultEnum.ORDER_GOODS_STATUS_NOT_GET);
            }

            if (orderGoods.getResidueTransportWeight().compareTo(dif) < 0) {
                throw new ServiceSystemException(PerformanceResultEnum.ORDER_GOODS_WEIGHT_NOT_HAVE);
            }
        }

        int count = orderChildDao.countValidByOrderGoodsNo(orderGoods.getOrderGoodsNo())-1;

        Integer status;
        if (count == 0){
            status = OrderGoodsStatusEnum.Status.PAYING.getCode();
        }
        else {
            status = OrderGoodsStatusEnum.Status.GO_TO_SEND.getCode();
        }

        orderGoodsService.updateOrderGoodsReduceWeightAndStatusAmountLoad(orderGoods, dif, status);
    }

    /**
     * 运单拉运吨数计算
     */
    public BigDecimal orderChildWeightCalc(OrderChild orderChild){
            return orderChild.getUnloadNet().compareTo(orderChild.getLoadNet()) < 0? orderChild.getUnloadNet() : orderChild.getLoadNet();
    }

    /**
     * 运费计算
     */
    public BigDecimal orderChildFreightCalc(OrderChild orderChild){
        BigDecimal totalFreight = orderChild.getFreightPrice().multiply(orderChild.getWeight());
        BigDecimal dif = orderChild.getUnloadNet().subtract(orderChild.getLoadNet());
        if (dif.compareTo(BigDecimal.ZERO) < 0){
            totalFreight = totalFreight.add(orderChild.getLossPrice().multiply(dif));
        }

        return totalFreight.setScale(0, RoundingMode.HALF_UP);
    }

}
