package com.clx.performance.dao.impl;

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.OrderGoodsDao;
import com.clx.performance.dto.CancelOrderGoodsWeightDTO;
import com.clx.performance.dto.OrderGoodsCancelWeightDTO;
import com.clx.performance.enums.OrderGoodsStatusEnum;
import com.clx.performance.mapper.OrderGoodsMapper;
import com.clx.performance.model.OrderGoods;
import com.clx.performance.model.OrderGoodsFleetOpenTruck;
import com.clx.performance.param.app.AppGoodsOrderSearchParam;
import com.clx.performance.param.app.OrderGoodsListPageParam;
import com.clx.performance.param.pc.GoodsOrderMapParam;
import com.clx.performance.param.pc.OrderGoodsEditParams;
import com.clx.performance.param.pc.PageOrderGoodsListParam;
import com.clx.performance.vo.app.OrderGoodsAPPVO;
import com.clx.performance.vo.pc.OrderGoodsVO;
import com.msl.common.base.Optional;
import com.msl.common.dao.impl.BaseDaoImpl;
import org.springframework.stereotype.Repository;

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

/**
 * @author kavin
 * Date 2023-09-17
 * Time 16:45
 */
@Repository
public class OrderGoodsDaoImpl extends BaseDaoImpl<OrderGoodsMapper, OrderGoods, Integer> implements OrderGoodsDao {

    @Override
    public String getMaxOrderGoodsId() {
        return baseMapper.getMaxOrderGoodsId();
    }

    @Override
    public Optional<OrderGoods> getByOrderGoodsNo(String orderGoodsNo) {
        return Optional.of(orderGoodsNo)
                .map(item -> lQrWrapper()
                        .eq(OrderGoods::getOrderGoodsNo, item)
                )
                .map(super::getOne);
    }

    @Override
    public Optional<OrderGoods> getOrderGoodsInfoByOrderGoodsNoForPC(String orderGoodsNo) {
        return Optional.of(orderGoodsNo)
                .map(item -> lQrWrapper()
                        .eq(OrderGoods::getOrderGoodsNo, item)
                )
                .map(super::getOne);
    }

    @Override
    public Optional<OrderGoods> getOrderGoodsInfoByOrderGoodsNoForAPP(String orderGoodsNo) {
        return Optional.of(orderGoodsNo)
                .map(item -> lQrWrapper()
                        .eq(OrderGoods::getOrderGoodsNo, item)
                )
                .map(super::getOne);
    }

    @Override
    public IPage<OrderGoodsVO> pageOrderGoodsList(PageOrderGoodsListParam param) {
        Page<OrderGoodsVO> page = Page.of(param.getPage(), param.getPageSize());
        return baseMapper.pageOrderGoodsList(page, param);
    }

    @Override
    public void updateOrderGoodsReduceWeightAndStatus(Integer id, BigDecimal orderChildWeight, Integer orderGoodsStatus) {
        baseMapper.updateOrderGoodsWeightAndStatus(id, orderChildWeight, orderGoodsStatus);
    }

    @Override
    public void updateOrderGoodsWeightAlreadyAndStatus(Integer id, BigDecimal residueWeight,Integer orderGoodsStatus) {
        baseMapper.updateOrderGoodsWeightAlreadyAndStatus(id, residueWeight, orderGoodsStatus);
    }

    @Override
    public IPage<OrderGoodsAPPVO> openOrderPageGoodsList(OrderGoodsListPageParam param,List<String> orderGoodsNoList) {
        Page<OrderGoodsAPPVO> page = Page.of(param.getPage(), param.getPageSize());
        return baseMapper.openOrderPageGoodsList(page,orderGoodsNoList);
    }

    @Override
    public IPage<OrderGoodsAPPVO> exclusiveOrderPageGoodsList(OrderGoodsListPageParam param, List<String> orderGoodsNoList) {
        Page<OrderGoodsAPPVO> page = Page.of(param.getPage(), param.getPageSize());

        return baseMapper.exclusiveOrderPageGoodsList(page, orderGoodsNoList);
    }

    @Override
    public void updateOrderGoodsStatusByOrderGoodsNo(String orderGoodsNo, Integer code) {
        baseMapper.updateOrderGoodsStatusByOrderGoodsNo(orderGoodsNo, code);
    }

    @Override
    public void saveBatchEntity(List<OrderGoods> orderGoodsList) {
        baseMapper.saveBatchEntity(orderGoodsList);
    }

    @Override
    public List<OrderGoods> getOrderGoodsListByOrderNo(String orderNo) {
        return baseMapper.selectList(lQrWrapper().eq(OrderGoods::getOrderNo, orderNo));
    }

    @Override
    public List<OrderGoods> getOrderGoodsListByOrderNoAndLastArriveSendTime(String orderNo, LocalDateTime lastArriveSendTime) {
        return baseMapper.selectList(lQrWrapper().eq(OrderGoods::getOrderNo, orderNo)
                        .eq(OrderGoods::getOrderGoodsStatus, OrderGoodsStatusEnum.Status.SUCCESS.getCode())
                .le(OrderGoods::getLastArriveSendTime, lastArriveSendTime)

        );

    }

    @Override
    public List<OrderGoods> getSendAddressSelect(GoodsOrderMapParam param) {
        LambdaQueryWrapper<OrderGoods> queryWrapper = new LambdaQueryWrapper();
        queryWrapper.eq(OrderGoods :: getReceiveAddressShorter,param.getReceiveAddress())
                .ge(OrderGoods :: getCreateTime,param.getBeginCreateTime())
                .le(OrderGoods :: getCreateTime,param.getEndCreateTime())
                .eq(OrderGoods :: getOrderGoodsStatus,param.getStatus());
        return baseMapper.selectList(queryWrapper);
    }

    @Override
    public Optional<List<OrderGoods>> getOrderGoodsList() {
        return Optional.ofEmpty(list(lQrWrapper()
                .eq(OrderGoods::getOrderGoodsStatus, OrderGoodsStatusEnum.Status.CREATED.getCode())
                .eq(OrderGoods::getOrderGoodsStatus, OrderGoodsStatusEnum.Status.PAYING.getCode())
                .eq(OrderGoods::getOrderGoodsStatus, OrderGoodsStatusEnum.Status.GO_TO_SEND.getCode())
                .eq(OrderGoods::getOrderGoodsStatus, OrderGoodsStatusEnum.Status.SUCCESS.getCode())
        ));
    }

    @Override
    public List<OrderGoods> listIntegralOrderGoodsSync() {
        return list(lQrWrapper()
                .in(OrderGoods::getOrderGoodsStatus,
                        OrderGoodsStatusEnum.Status.PAYING.getCode(),
                        OrderGoodsStatusEnum.Status.GO_TO_SEND.getCode(),
                        OrderGoodsStatusEnum.Status.SUCCESS.getCode())
        );
    }

    @Override
    public boolean updatePendingOrderFreightById(Integer id, BigDecimal pendingOrderFreight) {
        return update(lUdWrapper().eq(OrderGoods :: getId,id).set(OrderGoods :: getPendingOrderFreight,pendingOrderFreight));
    }

    @Override
    public boolean updatePendingOrderFreightByIdList(BigDecimal pendingOrderFreight, List<Integer> idList) {
        return update(lUdWrapper()
                .in(OrderGoods::getId,idList)
                .set(OrderGoods::getPendingOrderFreight,pendingOrderFreight)
        );

    }

    @Override
    public Boolean updateStopFlagByOrderNo(String orderNo, Integer stopFlag) {
        return update(lUdWrapper().eq(OrderGoods :: getOrderNo,orderNo).set(OrderGoods :: getStopFlag,stopFlag));
    }

    @Override
    public boolean updateOrderGoodsStatusAndRollbackResidueWeightByOrderGoodsNo(Integer orderGoodsId, Integer status) {
        return update(lUdWrapper().eq(OrderGoods :: getGoodsId,orderGoodsId)
                .set(OrderGoods :: getOrderGoodsStatus, status))
                ;
    }

    @Override
    public Integer updateOrderGoodsSetAlreadyWeight(BigDecimal alreadyWeight, Integer id) {
        return baseMapper.updateOrderGoodsSetAlreadyWeight(alreadyWeight,id);
    }

    @Override
    public Integer updateOrderGoodsSetResidueWeightAndAlreadyWeight(BigDecimal residueWeight, BigDecimal alreadyWeight, Integer id) {
        return baseMapper.updateOrderGoodsSetResidueWeightAndAlreadyWeight(residueWeight,alreadyWeight,id);
    }

    @Override
    public Integer updateOrderGoodsSetAlreadyWeightAndStatus(BigDecimal alreadyWeight, Integer status, Integer id) {
        return baseMapper.updateOrderGoodsSetAlreadyWeightAndStatus(alreadyWeight,status,id);
    }

    @Override
    public OrderGoodsVO findOrderGoodsById(Integer id) {
        return baseMapper.findOrderGoodsById(id);
    }

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

    @Override
    public Integer updateOrderGoods(OrderGoodsEditParams orderGoodsEditParams) {
        return baseMapper.updateOrderGoods(orderGoodsEditParams);
    }

    @Override
    public boolean batchUpdateOrderGoodsStatus(Integer status, List<Integer> ids) {
        return update(lUdWrapper().in(OrderGoods :: getId,ids)
                .set(OrderGoods :: getOrderGoodsStatus, status))
                ;
    }

    @Override
    public List<OrderGoods> getOrderGoodsListByOrderNoAndStatus(String orderNo) {
        return baseMapper.selectList(lQrWrapper().eq(OrderGoods::getOrderNo, orderNo)
                .ne(OrderGoods::getOrderGoodsStatus, OrderGoodsStatusEnum.Status.SUCCESS.getCode())
                .ne(OrderGoods::getOrderGoodsStatus, OrderGoodsStatusEnum.Status.CANCEL.getCode())
                .ne(OrderGoods::getOrderGoodsStatus, OrderGoodsStatusEnum.Status.COMPLETED.getCode())

        );
    }

    @Override
    public List<OrderGoodsAPPVO> getCancelOrderGoods(List<String> param) {
        return baseMapper.getCancelOrderGoods(param);
    }

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


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

    @Override
    public void updateReceiveSystemAddress(Integer ownerAddressId, Integer systemAddressId) {
        update(lUdWrapper()
                .eq(OrderGoods::getReceiveAddressId, ownerAddressId)
                .set(OrderGoods::getReceiveSystemAddressId, systemAddressId)
        );
    }


    @Override
    public List<Double> getFreightPrice( Integer sendAddressId,Integer receiveAddressId,String orderNo) {
        return baseMapper.getFreightPrice(orderNo,sendAddressId,receiveAddressId);
    }

    @Override
    public IPage<OrderGoodsAPPVO> indexOrderGoodsListSearch(AppGoodsOrderSearchParam param) {
        Page<OrderGoodsAPPVO> page = Page.of(param.getPage(), param.getPageSize());
        return baseMapper.indexOrderGoodsListSearch(page,param);
    }

    @Override
    public List<OrderGoodsFleetOpenTruck> queryProcessFleetOpenTruckList() {
        return baseMapper.queryProcessFleetOpenTruckList();
    }

    @Override
    public void cancelOrderGoods(String orderNo) {
        update(lUdWrapper()
                .eq(OrderGoods::getOrderNo, orderNo)
                .set(OrderGoods::getOrderGoodsStatus, OrderGoodsStatusEnum.Status.CANCEL.getCode())
        );
    }
    @Override
    public void batchCancel(List<Integer> idList) {
        update(lUdWrapper()
                .in(OrderGoods::getId, idList)
                .set(OrderGoods::getOrderGoodsStatus, OrderGoodsStatusEnum.Status.CANCEL.getCode())
        );
    }

    @Override
    public void batchCancelOrderGoods(List<CancelOrderGoodsWeightDTO> cancelOrderGoodsWeight) {
        baseMapper.batchCancelOrderGoods(cancelOrderGoodsWeight);
    }

    @Override
    public List<OrderGoods> listAfterCreatedByOrderNo(String orderNo) {
        return baseMapper.selectList(lQrWrapper().eq(OrderGoods::getOrderNo, orderNo)
                .ne(OrderGoods::getOrderGoodsStatus,OrderGoodsStatusEnum.Status.CREATED.getCode())
                .orderByDesc(OrderGoods :: getPendingOrderTime)
        );
    }


    @Override
    public List<OrderGoods> listAllByOrderNo(String orderNo) {
        return baseMapper.selectList(lQrWrapper().eq(OrderGoods::getOrderNo, orderNo)
                .ne(OrderGoods::getOrderGoodsStatus,OrderGoodsStatusEnum.Status.CREATED.getCode())
                .orderByDesc(OrderGoods :: getPendingOrderTime)
        );
    }

    @Override
    public void batchUpdateOrderGoodsPaying(List<OrderGoods> updateOrderGoods) {
        baseMapper.batchUpdateOrderGoodsPaying(updateOrderGoods);
    }

    @Override
    public void batchCancelOrderGoodsWeight(List<OrderGoodsCancelWeightDTO> cancelOrderGoodsList) {
        baseMapper.batchCancelOrderGoodsWeight(cancelOrderGoodsList);
    }

    @Override
    public OrderGoods queryLineNewestPendingFreight(Integer sendAddressId,Integer receiveAddressId) {
        LambdaQueryWrapper<OrderGoods> query = new LambdaQueryWrapper<>();
        query.eq(OrderGoods :: getSendAddressId,sendAddressId);
        query.eq(OrderGoods :: getReceiveAddressId,receiveAddressId);
        query.orderByDesc(OrderGoods :: getId);
        query.last("limit 1");
        return baseMapper.selectOne(query);

    }

    @Override
    public List<OrderGoods> queryLineAvgPendingFreight(Integer sendAddressId, Integer receiveAddressId,
            LocalDateTime begin,LocalDateTime end) {
        LambdaQueryWrapper<OrderGoods> query = new LambdaQueryWrapper<>();
        query.eq(OrderGoods :: getSendAddressId,sendAddressId);
        query.eq(OrderGoods :: getReceiveAddressId,receiveAddressId);
        query.ge(OrderGoods :: getCreateTime,begin);
        query.le(OrderGoods :: getCreateTime,end);
        return baseMapper.selectList(query);
    }

    @Override
    public boolean updateExtractWeightAndNeedTruckNum(String orderGoodsNo, BigDecimal extractWeight,
            Integer needTruckNum) {
        return update(lUdWrapper()
                .in(OrderGoods::getOrderGoodsNo, orderGoodsNo)
                .set(OrderGoods::getExtractWeight, extractWeight)
                .set(OrderGoods :: getNeedTruckNum,needTruckNum)
        );
    }
}
