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.OrderChildService;
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;
    private final OrderChildService orderChildService;


    @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.setUnloadTare(poundAuditDetail.getUnloadTare());
        vo.setUnloadRough(poundAuditDetail.getUnloadRough());
        vo.setLoadRough(poundAuditDetail.getLoadRough());
        vo.setLoadTare(poundAuditDetail.getLoadTare());
        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);
        BigDecimal loadNet = param.getLoadRough().subtract(param.getLoadTare());
        if (loadNet.compareTo(new BigDecimal(99)) > 0) {
            throw new ServiceSystemException(PerformanceResultEnum.ORDER_CHILD_LOAD_NET_ERROR);
        }
        if (param.getLoadTare().compareTo(param.getLoadRough()) > 0) {
            throw new ServiceSystemException(PerformanceResultEnum.ORDER_CHILD_TRACE_GT_ROUGH);
        }

        BigDecimal unLoadNet = param.getUnloadRough().subtract(param.getUnloadTare());
        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 = loadNet.subtract(orderChild.getLoadNet());

        int type = OrderChildLogEnum.Type.POUND_AUDIT.getCode();
        if(Objects.equals(param.getStatus(), OrderChildPoundAuditEnum.Status.REJECT.getCode())){
            type = OrderChildLogEnum.Type.POUND_AUDIT_REJECT.getCode();
        }else{
            poundAuditDetail.setLoadNet(loadNet);
            poundAuditDetail.setUnloadNet(unLoadNet);
            poundAuditDetail.setLoadRough(param.getLoadRough());
            poundAuditDetail.setLoadTare(param.getLoadTare());
            poundAuditDetail.setUnloadRough(param.getUnloadRough());
            poundAuditDetail.setUnloadTare(param.getUnloadTare());
            orderChild.setLoadNet(loadNet);
            orderChild.setUnloadNet(unLoadNet);
            orderChild.setLoadRough(param.getLoadRough());
            orderChild.setLoadTare(param.getLoadTare());
            orderChild.setUnloadRough(param.getUnloadRough());
            orderChild.setUnloadTare(param.getUnloadTare());
        }
        orderChild.setWeight(orderChildWeightCalc(orderChild));
        orderChild.setFreight(orderChildFreightCalc(orderChild));

        // 更新装车净重
        updateOrderGoodsAmountLoad(orderGoods,orderChild.getChildNo(), 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).isPresent() ? OrderChildLogEnum.Type.getByCode(type).get().getMsg() :"",
                OrderChildLogEnum.CreateType.PLATFORM.getCode(), loginUserInfo.getUserNo(),loginUserInfo.getUserName());

    }

    /**
     * 装车补偿
     */
    private void updateOrderGoodsAmountLoad(OrderGoods orderGoods,String childNo, BigDecimal dif){
        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();
        }
        orderChildService.updateOrderGoodsAmountLoad(orderGoods,childNo,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);
    }

}
