package com.clx.performance.dao.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.clx.performance.dao.OrderChildDao;
import com.clx.performance.enums.OrderChildEnum;
import com.clx.performance.mapper.OrderChildMapper;
import com.clx.performance.model.OrderChild;
import com.clx.performance.param.app.PageOrderChildOfDriverParam;
import com.clx.performance.param.app.PageOrderChildOfDriverSearchParam;
import com.clx.performance.param.app.owner.PageOwnerOrderChildListParam;
import com.clx.performance.param.pc.*;
import com.clx.performance.vo.app.OrderChildVO;
import com.clx.performance.vo.pc.PageCarrierOrderChildVO;
import com.clx.performance.vo.pc.PageOrderChildPoundAuditVO;
import com.msl.common.base.Optional;
import com.msl.common.base.PageParam;
import com.msl.common.dao.impl.BaseDaoImpl;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Repository;

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

/**
 * @Author: aiqinguo
 * @Description: 运单表
 * @Date: 2023/09/18 11:34:50
 * @Version: 1.0
 */
@Repository
public class OrderChildDaoImpl extends BaseDaoImpl<OrderChildMapper, OrderChild, Integer> implements OrderChildDao {

    @Override
    public boolean updateStatus(OrderChild item) {
        return update(lUdWrapper()
                .eq(OrderChild::getId, item.getId())
                .set(OrderChild::getStatus, item.getStatus())
        );
    }

    @Override
    public boolean updateArriveReceiveAddress(OrderChild item) {
        return update(lUdWrapper()
                .eq(OrderChild::getId, item.getId())
                .set(OrderChild::getStatus, item.getStatus())
                .set(OrderChild::getArriveReceiveTime, item.getArriveReceiveTime())
        );
    }

    @Override
    public boolean updateLoad(OrderChild item) {
        return update(lUdWrapper()
                .eq(OrderChild::getId, item.getId())
                .set(OrderChild::getLoadRough, item.getLoadRough())
                .set(OrderChild::getLoadTare, item.getLoadTare())
                .set(OrderChild::getLoadNet, item.getLoadNet())

                .set(OrderChild::getLoadTime, item.getLoadTime())
                .set(OrderChild::getWeight, item.getWeight())
                .set(OrderChild::getFreight, item.getFreight())
                .set(OrderChild::getStatus, item.getStatus())
        );
    }

    @Override
    public boolean updateUnload(OrderChild item) {
        return update(lUdWrapper()
                .eq(OrderChild::getId, item.getId())
                .set(OrderChild::getUnloadPoundNo, item.getUnloadPoundNo())
                .set(OrderChild::getUnloadRough, item.getUnloadRough())
                .set(OrderChild::getUnloadTare, item.getUnloadTare())
                .set(OrderChild::getUnloadNet, item.getUnloadNet())

                .set(OrderChild::getUnloadTime, item.getUnloadTime())
                .set(OrderChild::getPoundStatus, item.getPoundStatus())
                .set(OrderChild::getWeight, item.getWeight())
                .set(OrderChild::getFreight, item.getFreight())
                .set(OrderChild::getStatus, item.getStatus())
        );
    }

    @Override
    public boolean updateLoadAndUnload(OrderChild item) {
        return update(lUdWrapper()
                .eq(OrderChild::getId, item.getId())

                .set(OrderChild::getUnloadPoundNo, item.getUnloadPoundNo())
                .set(OrderChild::getLoadRough, item.getLoadRough())
                .set(OrderChild::getLoadTare, item.getLoadTare())
                .set(OrderChild::getLoadNet, item.getLoadNet())

                .set(OrderChild::getUnloadRough, item.getUnloadRough())
                .set(OrderChild::getUnloadTare, item.getUnloadTare())
                .set(OrderChild::getUnloadNet, item.getUnloadNet())

                .set(OrderChild::getWeight, item.getWeight())
                .set(OrderChild::getFreight, item.getFreight())
                .set(OrderChild::getPoundStatus, item.getPoundStatus())
        );
    }

    @Override
    public boolean updatePoundAuditStatus(OrderChild item) {
        return update(lUdWrapper()
                .eq(OrderChild::getId, item.getId())
                .set(OrderChild::getPoundStatus, item.getPoundStatus())
                .set(OrderChild::getLoadNet, item.getLoadNet())
                .set(OrderChild::getUnloadNet, item.getUnloadNet())
                .set(OrderChild::getLoadRough, item.getLoadRough())
                .set(OrderChild::getLoadTare, item.getLoadTare())
                .set(OrderChild::getUnloadRough, item.getUnloadRough())
                .set(OrderChild::getUnloadTare, item.getUnloadTare())
                .set(OrderChild::getWeight, item.getWeight())
                .set(OrderChild::getFreight, item.getFreight())
        );
    }

    @Override
    public boolean updateDriverConfirm(OrderChild item) {
        return update(lUdWrapper()
                .eq(OrderChild::getId, item.getId())
                .set(OrderChild::getStatus, item.getStatus())
                .set(OrderChild::getConfirmTime, item.getConfirmTime())
        );
    }

    @Override
    public boolean updateSettlement(OrderChild item) {
        return update(lUdWrapper()
                .eq(OrderChild::getId, item.getId())
                .set(OrderChild::getStatus, item.getStatus())
                .set(OrderChild::getFinishTime, item.getFinishTime())
                .set(OrderChild::getSettleTime, item.getSettleTime())
        );
    }

    @Override
    public boolean updateCancel(OrderChild item) {
        return update(lUdWrapper()
                .eq(OrderChild::getId, item.getId())
                .set(OrderChild::getCancelRemark, item.getCancelRemark())
                .set(OrderChild::getCancelType, item.getCancelType())
                .set(OrderChild::getCancelDetail, item.getCancelDetail())
                .set(OrderChild::getCancelTime, item.getCancelTime())
                .set(OrderChild::getFinishTime, item.getFinishTime())
                .set(OrderChild::getStatus, item.getStatus())
        );
    }


    @Override
    public Optional<OrderChild> getByChildNo(String childNo) {
        return Optional.of(childNo)
                .map(item -> lQrWrapper()
                        .eq(OrderChild::getChildNo, item)
                )
                .map(super::getOne);
    }

    @Override
    public long countOfCancel(Long userNo, LocalDateTime startTime, LocalDateTime endTime) {
        return count(lQrWrapper()
                .eq(OrderChild::getUserNo, userNo)
                .eq(OrderChild::getStatus, OrderChildEnum.Status.DRIVER_CANCEL.getCode())
                .ge(OrderChild::getCreateTime, startTime)
                .le(OrderChild::getCreateTime, endTime)
        );
    }

    @Override
    public long countOfTransitByOrderGoodsNo(String orderGoodsNo) {
        return count(lQrWrapper()
                .eq(OrderChild::getOrderGoodsNo, orderGoodsNo)
                .lt(OrderChild::getStatus, OrderChildEnum.Status.UNSETTLE.getCode())
        );
    }

    @Override
    public IPage<OrderChildVO> pageOrderChildOfDriver(PageOrderChildOfDriverParam param) {
        Page<OrderChildVO> page = Page.of(param.getPage(), param.getPageSize());
        return baseMapper.pageOrderChildOfDriver(page,param);
    }

    @Override
    public IPage<OrderChildVO> pageSearchOrderChildOfDriver(PageOrderChildOfDriverSearchParam param) {
        Page<OrderChildVO> page = Page.of(param.getPage(), param.getPageSize());
        return baseMapper.pageSearchOrderChildOfDriver(page,param);
    }

    @Override
    public IPage<PageOrderChildPoundAuditVO> pagePoundAuditList(PagePoundAuditParam param) {
        Page<PageOrderChildPoundAuditVO> page = Page.of(param.getPage(), param.getPageSize());
        return baseMapper.pagePoundAuditList(page,param);
    }

    @Override
    public IPage<PageCarrierOrderChildVO> pageCarrierOrderChildList(PageCarrierOrderChildParam param) {
        Page<PageCarrierOrderChildVO> page = Page.of(param.getPage(), param.getPageSize());
        return baseMapper.pageCarrierOrderChildList(page,param);
    }

    @Override
    public Optional<List<OrderChild>> getOrderChildInfoByOrderGoodsNo(String orderGoodsNo) {
        return Optional.of(list(lQrWrapper().eq(OrderChild::getOrderGoodsNo, orderGoodsNo)));
    }

    @Override
    public OrderChild getGoingLatestOrderChild(Long driverUserNo) {
        return getOne(lQrWrapper().eq(OrderChild::getDriverUserNo,driverUserNo)
                .le(OrderChild::getStatus,OrderChildEnum.Status.UNLOAD.getCode())
                .orderByDesc(OrderChild::getId)
                .last("limit 1"));
    }

    @Override
    public OrderChild getGoingLatestOrderChildByOrderNo(String orderNo) {
        return getOne(lQrWrapper().eq(OrderChild::getOrderNo,orderNo)
                .le(OrderChild::getStatus,OrderChildEnum.Status.UNLOAD.getCode())
                .orderByDesc(OrderChild::getId)
                .last("limit 1"));
    }

    @Override
    public int countValidByOrderGoodsNo(String orderGoodsNo) {
        return baseMapper.countValidByOrderGoodsNo(orderGoodsNo);
    }

    @Override
    public Integer getOrderChildTotalByUserNo(Long userNo) {
        LambdaQueryWrapper<OrderChild> query = new LambdaQueryWrapper();
        query.eq(OrderChild :: getUserNo,userNo);
        query.in(OrderChild :: getStatus,OrderChildEnum.Status.UNSETTLE.getCode(),OrderChildEnum.Status.COMPLETE.getCode());
        return baseMapper.selectCount(query).intValue();
    }

    @Override
    public Page<OrderChild> pageOrderChild(PageMonitorOrderChildQCParam param) {
        LambdaQueryWrapper<OrderChild> query = new LambdaQueryWrapper();

        if(StringUtils.isNotBlank(param.getTruckNo())){
            query.eq(OrderChild :: getTruckNo,param.getTruckNo());
        }
        if(StringUtils.isNotBlank(param.getSendAddress())){
            query.like(OrderChild :: getSendAddress,param.getSendAddress());
        }
        query.in(OrderChild :: getStatus,param.getStatus());
        query.orderByDesc(OrderChild :: getCreateTime);
        return baseMapper.selectPage(Page.of(param.getPage(), param.getPageSize()),query);

    }

    @Override
    public boolean updateArriveSendAddress(OrderChild item) {
        return update(lUdWrapper()
                .eq(OrderChild::getId, item.getId())
                .set(OrderChild::getStatus, item.getStatus())
                .set(OrderChild :: getArriveSendTime,item.getArriveSendTime())
        );


    }

    @Override
    public int countCompleteByTruckNoAndPayFinishTime(String truckNo, String beginTime, String endTime, List<String> orderGoodsNoList) {
        return (int)count(lQrWrapper()
                .eq(OrderChild::getTruckNo, truckNo)
                .ge(OrderChild::getConfirmTime, beginTime)
                .le(OrderChild::getConfirmTime, endTime)
                .ge(OrderChild::getStatus, OrderChildEnum.Status.UNSETTLE.getCode())
                .le(OrderChild::getStatus, OrderChildEnum.Status.COMPLETE.getCode())
                .in(OrderChild::getOrderGoodsNo, orderGoodsNoList)
        );
    }

    @Override
    public List<OrderChild> selectResidueWeight(String orderNo, Integer status) {
        return baseMapper.selectList(lQrWrapper().eq(OrderChild::getOrderNo,orderNo)
                .lt(ObjectUtil.isNotEmpty(status),OrderChild::getStatus, status)
        );
    }

    @Override
    public List<OrderChild> selectResidueWeightByOrderGoodsNo(String orderGoodsNo, Integer status) {
        return baseMapper.selectList(lQrWrapper().eq(OrderChild::getOrderGoodsNo,orderGoodsNo)
                .lt(ObjectUtil.isNotEmpty(status),OrderChild::getStatus, status)
        );
    }

    @Override
    public List<OrderChild> selectResidueWeightByOrderGoodsNo(String orderGoodsNo, Integer status, List<String> truckList) {
        return baseMapper.selectList(lQrWrapper().eq(OrderChild::getOrderGoodsNo,orderGoodsNo)
                .lt(ObjectUtil.isNotEmpty(status),OrderChild::getStatus, status)
                .in(CollectionUtil.isNotEmpty(truckList),OrderChild::getTruckNo, truckList)
        );
    }


    @Override
    public List<OrderChild> selectArriveSendOrderChild(String orderGoodsNo) {
        //查询小于 40 未到达货源地的运单
        return baseMapper.selectList(lQrWrapper().eq(OrderChild::getOrderGoodsNo, orderGoodsNo)
                .lt(OrderChild::getStatus, OrderChildEnum.Status.ARRIVE_SEND.getCode())
        );
    }

    @Override
    public List<OrderChild> selectArriveSendOrderChildGe(String orderGoodsNo) {
        //查询大于 40 未到达货源地的运单
        return baseMapper.selectList(lQrWrapper().eq(OrderChild::getOrderGoodsNo, orderGoodsNo)
                .ge(OrderChild::getStatus, OrderChildEnum.Status.ARRIVE_SEND.getCode())
                .le(OrderChild::getStatus, OrderChildEnum.Status.COMPLETE.getCode())
        );
    }

    @Override
    public void batchUpdateOrderChildStatus(Integer status, String remark, String cancelTime, String finishTime, List<String> childNoList) {
        baseMapper.updateOrderGoodsSetResidueWeight(status,remark, cancelTime, finishTime, childNoList);
    }

    @Override
    public List<OrderChild> selectOrderChildListByOrderGoodsNoAndStatusGE(String orderGoodsNo, Integer status) {
        return baseMapper.selectList(lQrWrapper().eq(OrderChild::getOrderGoodsNo, orderGoodsNo)
                .ge(ObjectUtil.isNotNull(status),OrderChild::getStatus, status)
                .le(ObjectUtil.isNotNull(status),OrderChild::getStatus, OrderChildEnum.Status.COMPLETE.getCode())
        );    }

    @Override
    public List<OrderChild> selectListByOrderGoodsList(List<String> orderGoodsList) {
        return baseMapper.selectList(lQrWrapper().in(OrderChild::getOrderGoodsNo, orderGoodsList));
    }

    @Override
    public List<OrderChild> getOrderChildByOrderNo(String orderNo) {
        LambdaQueryWrapper<OrderChild> query = new LambdaQueryWrapper();
        query.in(OrderChild :: getOrderNo,orderNo);
        return baseMapper.selectList(query);
    }

    @Override
    public List<OrderChild> listOrderChild(List<Integer> status) {
        LambdaQueryWrapper<OrderChild> query = new LambdaQueryWrapper();
        query.in(OrderChild :: getStatus,status);
        return baseMapper.selectList(query);

    }


    @Override
    public List<OrderChild> getOrderChildBussInfo(String truckNo) {
        LambdaQueryWrapper<OrderChild> query = new LambdaQueryWrapper();
        query.eq(OrderChild::getTruckNo, truckNo)
                .in(OrderChild::getStatus, OrderChildEnum.Status.UNSETTLE.getCode(),OrderChildEnum.Status.COMPLETE.getCode());
        return baseMapper.selectList(query);
    }

    @Override
    public List<OrderChild> selectListByOrderGoodsNo(String orderGoodsNo) {
        //查询小于 100（完成）的运单都属于在途
        return baseMapper.selectList(lQrWrapper().eq(OrderChild::getOrderGoodsNo, orderGoodsNo)
                .notIn(OrderChild::getStatus, OrderChildEnum.Status.DRIVER_CANCEL.getCode(),OrderChildEnum.Status.PLATFORM_CANCEL.getCode(),OrderChildEnum.Status.OWNER_CANCEL.getCode())
        );
    }

    @Override
    public List<OrderChild> listOrderChildByOrderNoAndStatus(String orderNo, List<Integer> status) {
        return baseMapper.selectList(
                lQrWrapper()
                        .eq(OrderChild::getOrderNo,orderNo)
                        .in(OrderChild :: getStatus,status)
        );
    }

    @Override
    public List<OrderChild> selectInTransitOrderChild(String orderNo) {
        return baseMapper.selectList(lQrWrapper().eq(OrderChild::getOrderNo, orderNo)
                .lt(OrderChild::getStatus, OrderChildEnum.Status.UNLOAD.getCode())
        );
    }

    @Override
    public List<OrderChild> selectInTransitOrderChildLtUnsettle(String orderNo) {
        return baseMapper.selectList(lQrWrapper().eq(OrderChild::getOrderNo, orderNo)
                .lt(OrderChild::getStatus, OrderChildEnum.Status.UNSETTLE.getCode())
        );
    }

    @Override
    public List<OrderChild> selectInTransitOrderChildByOrderGoodsNo(String orderGoodsNo) {
        return baseMapper.selectList(lQrWrapper().eq(OrderChild::getOrderGoodsNo, orderGoodsNo)
                .lt(OrderChild::getStatus, OrderChildEnum.Status.UNLOAD.getCode())
        );    }

    @Override
    public OrderChild findLastTruckChild(String orderNo) {
        return getOne(lQrWrapper().eq(OrderChild::getOrderNo,orderNo)
                .notIn(OrderChild::getStatus,OrderChildEnum.DTS_LISTEN_CANCEL_lIST)
                .orderByDesc(OrderChild::getCreateTime)
                .last("limit 1"));
    }

    @Override
    public BigDecimal listAfterArrayReceiveChild(String orderNo) {
        return baseMapper.listAfterArrayReceiveChild(orderNo);
    }

    @Override
    public OrderChild getLastTruckChild(String orderNo) {
        return getOne(lQrWrapper().eq(OrderChild::getOrderNo,orderNo)
                .ge(OrderChild::getStatus,OrderChildEnum.Status.ARRIVE_RECEIVE.getCode())
                .le(OrderChild::getStatus,OrderChildEnum.Status.COMPLETE.getCode())
                .orderByDesc(OrderChild::getArriveReceiveTime)
                .last("limit 1"));
    }

    @Override
    public OrderChildVO findArtificialCancelOrder(String orderChildNo) {
        return baseMapper.findArtificialCancelOrder(orderChildNo);
    }

    @Override
    public IPage<OrderChildVO> orderChildCancelRecord(OrderChildCancelRecordParam param) {
        Page<OrderChildVO> page = Page.of(param.getPage(), param.getPageSize());
        return baseMapper.orderChildCancelRecord(page,param);
    }

    @Override
    public List<OrderChild> selectInOrderChildNoList(List<String> childNoList) {
        return baseMapper.selectList(lQrWrapper()
                .in(OrderChild::getChildNo, childNoList)
        );    }


    @Override
    public BigDecimal getLinePoundDifferenceRatioAvg(Integer sendSystemAddressId, Integer receiveSystemAddressId, String beginTime) {
        return baseMapper.getLinePoundDifferenceRatioAvg(sendSystemAddressId, receiveSystemAddressId, beginTime);
    }

    @Override
    public Integer getLineArriveSendAddressToUnloadTimeAvg(Integer sendSystemAddressId, Integer receiveSystemAddressId, String beginTime) {
        return baseMapper.getLineArriveSendAddressToUnloadTimeAvg(sendSystemAddressId, receiveSystemAddressId, beginTime);

    }

    @Override
    public void updateSendSystemAddress(Integer ownerAddressId, Integer systemAddressId) {
        update(lUdWrapper()
                .eq(OrderChild::getSendAddressId, ownerAddressId)
                .set(OrderChild::getSendSystemAddressId, systemAddressId)
        );
    }

    @Override
    public void updateReceiveSystemAddress(Integer ownerAddressId, Integer systemAddressId) {
        update(lUdWrapper()
                .eq(OrderChild::getReceiveAddressId, ownerAddressId)
                .set(OrderChild::getReceiveSystemAddressId, systemAddressId)
        );
    }
    @Override
    public List<Double> getLossNet(OrderChildReportParam param) {
        return baseMapper.getLossNet(param);
    }

    @Override
    public BigDecimal getLastDriverFreightByTransportLine(Integer sendSystemAddressId, Integer receiveSystemAddressId) {
        LambdaQueryWrapper<OrderChild> query = new LambdaQueryWrapper<>();
        query.eq(OrderChild :: getSendSystemAddressId,sendSystemAddressId);
        query.eq(OrderChild :: getReceiveSystemAddressId,receiveSystemAddressId);
        query.le(OrderChild::getStatus, OrderChildEnum.Status.COMPLETE.getCode());
        query.orderByDesc(OrderChild :: getCreateTime);
        query.last("limit 1");
        OrderChild child = baseMapper.selectOne(query);
        if(Objects.nonNull(child)){
            return child.getFreightPrice();
        }
        return BigDecimal.ZERO;
    }

    @Override
    public OrderChild getOrderCompleteLastTruck(String orderNo) {
        LambdaQueryWrapper<OrderChild> query = new LambdaQueryWrapper<>();
        query.eq(OrderChild ::getOrderNo,orderNo);
        query.ge(OrderChild :: getStatus,OrderChildEnum.Status.ARRIVE_SEND.getCode());
        query.le(OrderChild :: getStatus,OrderChildEnum.Status.COMPLETE.getCode());
        query.orderByDesc(OrderChild :: getArriveReceiveTime);
        query.last("limit 1");
        return baseMapper.selectOne(query);
    }

    @Override
    public Long haveArriveReceiveChild(String orderNo) {
        LambdaQueryWrapper<OrderChild> query = new LambdaQueryWrapper<>();
        query.eq(OrderChild ::getOrderNo,orderNo);
        query.lt(OrderChild :: getStatus,OrderChildEnum.Status.ARRIVE_RECEIVE.getCode());
        return baseMapper.selectCount(query);
    }



    @Override
    public List<OrderChild> selectListWithEmptyCarList() {
        return baseMapper.selectList(lQrWrapper()
                .le(OrderChild :: getStatus,OrderChildEnum.Status.UNSETTLE.getCode())
                .ge(OrderChild :: getStatus,OrderChildEnum.Status.CREATED.getCode())
        );
    }

    @Override
    public Page<OrderChild> getMonthAgoByUserNo(Long userNo, LocalDateTime monthAgo, PageParam param) {
        LambdaQueryWrapper<OrderChild> query = new LambdaQueryWrapper<>();
        query.and(i ->
                i.eq(OrderChild :: getDriverUserNo,userNo).or()
                        .eq(OrderChild :: getTruckOwnUserNo,userNo)
        );
        query.ge(OrderChild :: getCreateTime,monthAgo);
        query.orderByDesc(OrderChild :: getCreateTime);
        return baseMapper.selectPage(Page.of(param.getPage(), param.getPageSize()),query);
    }

    @Override
    public IPage<OrderChild> pageOwnerOrderChildList(PageOwnerOrderChildListParam param) {
        LambdaQueryWrapper<OrderChild> query = new LambdaQueryWrapper<>();
        query.eq(OrderChild :: getOwnerUserNo,param.getOwnerUserNo());
        if(StringUtils.isNotBlank(param.getSearchNo())){
            query.and(i ->
                    i.eq(OrderChild :: getChildNo,param.getSearchNo()).or()
                            .eq(OrderChild :: getTruckNo,param.getSearchNo()).or()
                            .eq(OrderChild :: getOrderNo,param.getSearchNo()));
        }
        if(CollectionUtil.isNotEmpty(param.getStatus())){query.in(OrderChild :: getStatus,param.getStatus());}
        if(StringUtils.isNotBlank(param.getBeginTime())){query.ge(OrderChild :: getCreateTime,param.getBeginTime());}
        if(StringUtils.isNotBlank(param.getEndTime())){query.le(OrderChild :: getCreateTime,param.getEndTime());}
        query.orderByDesc(OrderChild :: getCreateTime);
        return baseMapper.selectPage(Page.of(param.getPage(), param.getPageSize()),query);
    }
}
