package com.clx.performance.component;

import com.alibaba.fastjson.JSON;
import com.clx.performance.constant.RedisConstants;
import com.clx.performance.dao.OrderGoodsDriverTruckDao;
import com.clx.performance.dao.OrderGoodsFleetOpenTruckDao;
import com.clx.performance.dao.OrderGoodsTruckBindDao;
import com.clx.performance.enums.OrderGoodsTruckBindEnum;
import com.clx.performance.model.OrderGoodsDriverTruck;
import com.clx.performance.model.OrderGoodsFleetOpenTruck;
import com.clx.performance.model.OrderGoodsTruckBind;
import com.msl.common.base.Optional;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

import java.util.*;
import java.util.stream.Collectors;


@Slf4j
@Component
@AllArgsConstructor
public class GoodsOrderTruckRecordComponent {

    private final RedisTemplate<String, String> redisTemplate;

    private final OrderGoodsDriverTruckDao orderGoodsDriverTruckDao;

    private final OrderGoodsTruckBindDao orderGoodsTruckBindDao;

    private final OrderGoodsFleetOpenTruckDao orderGoodsFleetOpenTruckDao;


    public void saveTruckRecord(String orderGoodsNo, List<String> truckList) {
        redisTemplate.opsForSet().add(RedisConstants.ORDER_GOODS_TRUCK_RECORD + orderGoodsNo, truckList.toArray(new String[]{}));
        redisTemplate.opsForSet().add(RedisConstants.ORDER_GOODS_RECORD, RedisConstants.ORDER_GOODS_TRUCK_RECORD + orderGoodsNo);
    }

    //删除货单下的所有车牌号
    public void deleteTruckRecord(String orderGoodsNo) {
        redisTemplate.delete(RedisConstants.ORDER_GOODS_TRUCK_RECORD + orderGoodsNo);
        //redisTemplate.opsForSet().remove(RedisConstants.ORDER_GOODS_TRUCK_RECORD + orderGoodsNo,);
        redisTemplate.opsForSet().remove(RedisConstants.ORDER_GOODS_RECORD, RedisConstants.ORDER_GOODS_TRUCK_RECORD + orderGoodsNo);
    }

    //删除货单下的指定车牌号
    public void deleteTruckRecord(String orderGoodsNo, String truckNo) {
        redisTemplate.opsForSet().remove(RedisConstants.ORDER_GOODS_TRUCK_RECORD + orderGoodsNo, truckNo);
    }

    //公开
    public Set<String> getPublicTruckList() {
        Set<String> orderGoodsList = redisTemplate.opsForSet().members(RedisConstants.ORDER_GOODS_RECORD);
        if (orderGoodsList == null || orderGoodsList.isEmpty()) {
            return null;
        }

        return redisTemplate.opsForSet().union(orderGoodsList);
    }

    //定向
    public List<String> getPrivateTruckList(String orderGoodsNo, Long userNo) {
        Optional<List<OrderGoodsDriverTruck>> optional = orderGoodsDriverTruckDao.selectListByDriverUserNo(userNo);
        if (!optional.isPresent()) {
            return null;
        }
        List<String> truckList = optional.get().stream().map(OrderGoodsDriverTruck::getTruckNo).collect(Collectors.toList());
        truckList.retainAll(redisTemplate.opsForSet().members(RedisConstants.ORDER_GOODS_TRUCK_RECORD + orderGoodsNo));
        return truckList;

    }

    //释放全部车辆
    public void releaseAllDriverCard(String orderGoodsNo, String truckNo) {
        log.info("执行释放车辆,货单号：{},车牌号：{}", orderGoodsNo, truckNo);
        orderGoodsTruckBindDao.updateAllOrderGoodsBindStatus(orderGoodsNo, OrderGoodsTruckBindEnum.Status.SUCCESS.getCode(), truckNo);
        this.deleteTruckRecord(orderGoodsNo, truckNo);
    }

    //释放已接单车辆
    public void releaseDriverCard(String orderGoodsNo, String truckNo) {
        log.info("执行释放车辆,货单号：{},车牌号：{}", orderGoodsNo, truckNo);
        orderGoodsTruckBindDao.updateOrderGoodsBindStatus(orderGoodsNo, OrderGoodsTruckBindEnum.Status.SUCCESS.getCode(), truckNo);
        this.deleteTruckRecord(orderGoodsNo, truckNo);
    }

    //定向单接单时，如果接完后没有余量，则释放其他未接单的定向单记录
    public void releaseDriverAndTruckBind(String orderGoodsNo, String truckNo) {
        List<OrderGoodsTruckBind> truckBindList = orderGoodsTruckBindDao.selectListByOrderGoodsNo(orderGoodsNo);
        for (OrderGoodsTruckBind bind : truckBindList) {
            if (StringUtils.equals(truckNo, bind.getTruckNo())) {
                continue;
            }
            this.deleteTruckRecord(orderGoodsNo, bind.getTruckNo());
        }
        orderGoodsTruckBindDao.updateOrderGoodsBindStatusExpire(orderGoodsNo, truckNo);

    }
    //货单剩余吨数低于35吨时，自动恢复到订单，并释放未接单车辆
    public void releaseOrderGoodsDriverAndTruck(String orderGoodsNo) {
        List<OrderGoodsTruckBind> truckBindList = orderGoodsTruckBindDao.selectListByOrderGoodsNo(orderGoodsNo);
        List<Integer> ids = new ArrayList<>();
        for (OrderGoodsTruckBind bind : truckBindList) {
            if (Objects.equals(OrderGoodsTruckBindEnum.Status.NORMAL.getCode(),bind.getStatus())) {
                ids.add(bind.getId());
                this.deleteTruckRecord(orderGoodsNo, bind.getTruckNo());
            }
        }
        //释放车辆bind
        if(CollectionUtils.isNotEmpty(ids)){
            log.info("定向单进行车辆释放,货单编号:{},释放的绑定车辆的id集合:{}",orderGoodsNo,ids);
            orderGoodsTruckBindDao.updateTruckBindExpire(ids);
        }

    }

    public Set<String> getFleetPublicTruckList(String orderGoodsNo) {
        Set<String> orderGoodsList = redisTemplate.opsForSet().members(RedisConstants.ORDER_GOODS_RECORD);
        if (orderGoodsList == null || orderGoodsList.isEmpty()) {
            return null;
        }
        //当前系统所有的定向车辆
        Set<String> union = redisTemplate.opsForSet().union(orderGoodsList);

        Set<String> set = CollectionUtils.isEmpty(union)?new HashSet<>():union;
        Optional<OrderGoodsFleetOpenTruck> optional = orderGoodsFleetOpenTruckDao.getOneByField(
                OrderGoodsFleetOpenTruck::getOrderGoodsNo, orderGoodsNo);

        //车队运营系统未派发车辆
        if(!optional.isPresent()){
            log.error("货单号：{}，未在车队运营系统进行派发",orderGoodsNo);
            return  new HashSet<>();
        }
        List<String> fleetTruckNoList = JSON.parseArray(optional.get().getTruckListJson(),String.class);
        //车队派发的车辆去除掉定向车辆
        for (Iterator<String> it = fleetTruckNoList.iterator(); it.hasNext();) {
            if(set.contains(it.next())){
                it.remove();
            }
        }
        return new HashSet<>(fleetTruckNoList);
    }
}
