package com.sckw.transport.service;

import com.alibaba.fastjson2.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.sckw.core.common.enums.NumberConstant;
import com.sckw.core.model.enums.CarWaybillEnum;
import com.sckw.core.utils.BeanUtils;
import com.sckw.core.utils.CollectionUtils;
import com.sckw.core.web.constant.HttpStatus;
import com.sckw.core.web.context.LoginUserHolder;
import com.sckw.core.web.response.HttpResult;
import com.sckw.excel.utils.ValidUtil;
import com.sckw.fleet.api.RemoteFleetService;
import com.sckw.mongo.enums.BusinessTypeEnum;
import com.sckw.mongo.model.SckwWaybillOrder;
import com.sckw.mongo.model.TableTops;
import com.sckw.stream.model.SckwBusSum;
import com.sckw.system.api.RemoteSystemService;
import com.sckw.transport.dao.*;
import com.sckw.transport.model.KwtLogisticsOrderAddress;
import com.sckw.transport.model.KwtLogisticsOrderCirculate;
import com.sckw.transport.model.KwtLogisticsOrderGoods;
import com.sckw.transport.model.KwtWaybillOrder;
import com.sckw.transport.model.dto.UpdateDriverCarDTO;
import com.sckw.transport.model.vo.WaybillOrderVO;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.stream.function.StreamBridge;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.ObjectUtils;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author lfdc
 * @description 司机端service
 * @date 2023-07-14 13:07:57
 */
@Slf4j
@Service
public class DriverService {

    @DubboReference(version = "1.0.0", group = "design", check = false)
    RemoteSystemService remoteSystemService;

    @DubboReference(version = "1.0.0", group = "design", check = false)
    RemoteFleetService remoteFleetService;

    @Autowired
    MongoTemplate mongoTemplate;

    @Autowired
    StreamBridge streamBridge;

    @Autowired
    private KwtWaybillOrderMapper waybillOrderMapper;

    @Autowired
    private KwtWaybillOrderTrackMapper waybillOrderTrackMapper;

    @Autowired
    private KwtWaybillOrderTicketMapper waybillOrderTicketMapper;

    @Autowired
    private KwtLogisticsOrderMapper logisticsOrderMapper;

    @Autowired
    private KwtLogisticsOrderUnitMapper logisticsOrderUnitMapper;

    @Autowired
    private KwtLogisticsOrderAddressMapper logisticsOrderAddressMapper;

    @Autowired
    private KwtLogisticsOrderGoodsMapper logisticsOrderGoodsMapper;

    @Autowired
    private KwtLogisticsOrderCirculateMapper logisticsOrderCirculateMapper;


    /**
     * @param id
     * @return
     */
    public HttpResult statistics(Long id) {
        /**
         * 当前司机端页面 页面【计划】=1；【出车】=2；【执行】=3；【完结】=4
         * 计划:对应运单状态的[待接单]
         * 出车:对应运单状态的[待出车]
         * 执行:对应[已出车][到达装货地点]、[已装货]、[到达卸货地点]
         * 完结: 对应[已卸货]、[已核单]
         * */
        List<Long> status = new ArrayList<>();
        List<TableTops> list = new ArrayList<>();
        status.add(CarWaybillEnum.PENDING_ORDER.getCode().longValue());
        TableTops top = waybillOrderMapper.statistics(id, status);
        top.setName("计划");
        top.setValue(String.valueOf(NumberConstant.ONE));
        status.clear();
        status.add(CarWaybillEnum.PENDING_VEHICLE.getCode().longValue());
        TableTops top1 = waybillOrderMapper.statistics(id, status);
        top1.setName("出车");
        top1.setValue(String.valueOf(NumberConstant.TWO));
        status.clear();
        status.add(CarWaybillEnum.EXIT_COMPLETED.getCode().longValue());
        status.add(CarWaybillEnum.WAIT_LOADING.getCode().longValue());
        status.add(CarWaybillEnum.COMPLETION_LOADING.getCode().longValue());
        status.add(CarWaybillEnum.WAIT_UNLOADING.getCode().longValue());
        TableTops top2 = waybillOrderMapper.statistics(id, status);
        top2.setName("执行");
        top2.setValue(String.valueOf(NumberConstant.THREE));
        status.clear();
        status.add(CarWaybillEnum.COMPLETION_UNLOADING.getCode().longValue());
        status.add(CarWaybillEnum.APPROVAL_PASS.getCode().longValue());
        TableTops top3 = waybillOrderMapper.statistics(id, status);
        top3.setName("完结");
        top3.setValue(String.valueOf(NumberConstant.FOUR));
        list.add(top);
        list.add(top1);
        list.add(top2);
        list.add(top3);
        return HttpResult.ok(list);
    }

    /**
     * 根据当前登录 id获取派给当前id的车辆运单
     *
     * @param id   司机id
     * @param type 展示页签类型
     * @return
     */
    public HttpResult getWaybillDriverDetail(Long id, String type) {
        /**
         * 当前司机端页面 页面【计划】=1；【出车】=2；【执行】=3；【完结】=4
         * 计划:对应运单状态的[待接单]
         * 出车:对应运单状态的[待出车]
         * 执行:对应[已出车][到达装货地点]、[已装货]、[到达卸货地点]
         * 完结: 对应[已卸货]、[已核单]
         * */
        HttpResult result = new HttpResult();
        List<Long> tripStatus = new ArrayList<>();
        List<Long> loopStatus = new ArrayList<>();
        if (String.valueOf(NumberConstant.ONE).equals(type)) {
            tripStatus.add(CarWaybillEnum.PENDING_ORDER.getCode().longValue());
        } else if (String.valueOf(NumberConstant.TWO).equals(type)) {
            tripStatus.add(CarWaybillEnum.PENDING_VEHICLE.getCode().longValue());
            loopStatus.add(CarWaybillEnum.PENDING_VEHICLE.getCode().longValue());
        } else if (String.valueOf(NumberConstant.THREE).equals(type)) {
            tripStatus.add(CarWaybillEnum.EXIT_COMPLETED.getCode().longValue());
            tripStatus.add(CarWaybillEnum.WAIT_LOADING.getCode().longValue());
            tripStatus.add(CarWaybillEnum.COMPLETION_LOADING.getCode().longValue());
            tripStatus.add(CarWaybillEnum.WAIT_UNLOADING.getCode().longValue());

            loopStatus.add(CarWaybillEnum.EXIT_COMPLETED.getCode().longValue());
            loopStatus.add(CarWaybillEnum.WAIT_LOADING.getCode().longValue());
            loopStatus.add(CarWaybillEnum.COMPLETION_LOADING.getCode().longValue());
            loopStatus.add(CarWaybillEnum.WAIT_UNLOADING.getCode().longValue());
        } else if (String.valueOf(NumberConstant.FOUR).equals(type)) {
            tripStatus.add(CarWaybillEnum.COMPLETION_UNLOADING.getCode().longValue());
            tripStatus.add(CarWaybillEnum.APPROVAL_PASS.getCode().longValue());

            loopStatus.add(CarWaybillEnum.COMPLETION_UNLOADING.getCode().longValue());
            loopStatus.add(CarWaybillEnum.APPROVAL_PASS.getCode().longValue());
        } else {
            result.setMsg("类型错误");
            result.setCode(HttpStatus.GLOBAL_EXCEPTION_CODE);
            return result;
        }
        List<WaybillOrderVO> orderVOList = new ArrayList<>();
        /**趟次*/
        tripPackageData(id, tripStatus, orderVOList);
        /**循环*/
        loopPackageData(id, loopStatus, orderVOList);
        orderVOList = orderVOList.stream().sorted(Comparator.comparing(WaybillOrderVO::getCreateTime)).collect(Collectors.toList());
        return HttpResult.ok(orderVOList);
    }

    /**
     * 组装循环单据信息
     * @param id
     * @param loopStatus
     * @param orderVOList
     */
    private void loopPackageData(Long id, List<Long> loopStatus, List<WaybillOrderVO> orderVOList) {
        if (CollectionUtils.isEmpty(loopStatus)) {
            List<KwtLogisticsOrderCirculate> list = logisticsOrderCirculateMapper.selectList(new LambdaQueryWrapper<KwtLogisticsOrderCirculate>()
                    .eq(KwtLogisticsOrderCirculate::getDriverId, id)
                    .isNull(KwtLogisticsOrderCirculate::getWOrderId)
                    .eq(KwtLogisticsOrderCirculate::getStatus, NumberConstant.ZERO));
            if (CollectionUtils.isNotEmpty(list)) {
                for (KwtLogisticsOrderCirculate circulate : list) {
                    KwtLogisticsOrderAddress loadAddress = logisticsOrderAddressMapper.selectOne(new LambdaQueryWrapper<KwtLogisticsOrderAddress>()
                            .eq(KwtLogisticsOrderAddress::getLOrderId, circulate.getLOrderId()).eq(KwtLogisticsOrderAddress::getAddressType, NumberConstant.ONE));
                    KwtLogisticsOrderAddress unloadAddress = logisticsOrderAddressMapper.selectOne(new LambdaQueryWrapper<KwtLogisticsOrderAddress>()
                            .eq(KwtLogisticsOrderAddress::getLOrderId, circulate.getLOrderId()).eq(KwtLogisticsOrderAddress::getAddressType, NumberConstant.TWO));
                    KwtLogisticsOrderGoods orderGoods = logisticsOrderGoodsMapper.selectOne(new LambdaQueryWrapper<KwtLogisticsOrderGoods>()
                            .eq(KwtLogisticsOrderGoods::getLOrderId, circulate.getLOrderId()));
                    List<KwtWaybillOrder> waybillOrders = waybillOrderMapper.selectList(new LambdaQueryWrapper<KwtWaybillOrder>()
                            .eq(KwtWaybillOrder::getLOrderId, circulate.getLOrderId()).eq(KwtWaybillOrder::getDriverId, id));
                    for (KwtWaybillOrder waybill : waybillOrders) {
                        WaybillOrderVO vo = new WaybillOrderVO();
                        vo.setLOrderId(circulate.getLOrderId());
                        vo.setLoadCityCode(loadAddress.getCityCode());
                        vo.setLoadCityName(loadAddress.getCityName());
                        vo.setLoadDetailAddress(loadAddress.getDetailAddress());
                        vo.setUnloadCityName(unloadAddress.getCityName());
                        vo.setUnloadCityCode(unloadAddress.getCityCode());
                        vo.setEntId(String.valueOf(waybill.getEntId()));
                        vo.setFirmName(remoteSystemService.queryEntCacheById(waybill.getEntId()).getFirmName());
                        vo.setGoodsName(orderGoods == null ? null : (orderGoods.getGoodsName() == null ? null : orderGoods.getGoodsName()));
                        vo.setGoodsCode(orderGoods == null ? null : (orderGoods.getSkuId() == null ? null : String.valueOf(orderGoods.getSkuId())));
                        vo.setWOrderId(waybill.getId());
                        vo.setWOrderNo(waybill.getWOrderNo());
                        vo.setCreateTime(waybill.getCreateTime());
                        vo.setStartTime(waybill.getStartTime());
                        vo.setEndTime(waybill.getEndTime());
                        /**查询车队服务dubbo 2023-07-24 司机端不展示 车队信息改为展示物流公司*/
//                        remoteFleetService.findTruck()
//                        vo.setFleetName();
//                        vo.setFleetId();
//                        vo.setTruckFleetName();
                        vo.setEntrustAmount(waybill.getEntrustAmount());
                        vo.setType(waybill.getType());
                        vo.setTruckNo(waybill.getTruckNo());
                        orderVOList.add(vo);
                    }
                }
            }
        } else {
            List<Long> list = logisticsOrderCirculateMapper.selectDriverOrderByStatus(id, loopStatus);
            if (CollectionUtils.isNotEmpty(list)) {
                for (Long aLong : list) {
                    KwtLogisticsOrderAddress loadAddress = logisticsOrderAddressMapper.selectOne(new LambdaQueryWrapper<KwtLogisticsOrderAddress>()
                            .eq(KwtLogisticsOrderAddress::getLOrderId, aLong).eq(KwtLogisticsOrderAddress::getAddressType, NumberConstant.ONE));
                    KwtLogisticsOrderAddress unloadAddress = logisticsOrderAddressMapper.selectOne(new LambdaQueryWrapper<KwtLogisticsOrderAddress>()
                            .eq(KwtLogisticsOrderAddress::getLOrderId, aLong).eq(KwtLogisticsOrderAddress::getAddressType, NumberConstant.TWO));
                    KwtLogisticsOrderGoods orderGoods = logisticsOrderGoodsMapper.selectOne(new LambdaQueryWrapper<KwtLogisticsOrderGoods>()
                            .eq(KwtLogisticsOrderGoods::getLOrderId, aLong));
                    List<KwtWaybillOrder> waybillOrders = waybillOrderMapper.selectList(new LambdaQueryWrapper<KwtWaybillOrder>()
                            .eq(KwtWaybillOrder::getLOrderId, aLong).eq(KwtWaybillOrder::getDriverId, id));
                    for (KwtWaybillOrder waybill : waybillOrders) {
                        WaybillOrderVO vo = new WaybillOrderVO();
                        vo.setLOrderId(aLong);
                        vo.setLoadCityCode(loadAddress.getCityCode());
                        vo.setLoadCityName(loadAddress.getCityName());
                        vo.setLoadDetailAddress(loadAddress.getDetailAddress());
                        vo.setUnloadCityName(unloadAddress.getCityName());
                        vo.setUnloadCityCode(unloadAddress.getCityCode());
                        vo.setEntId(String.valueOf(waybill.getEntId()));
                        vo.setFirmName(remoteSystemService.queryEntCacheById(waybill.getEntId()).getFirmName());
                        vo.setGoodsName(orderGoods == null ? null : (orderGoods.getGoodsName() == null ? null : orderGoods.getGoodsName()));
                        vo.setGoodsCode(orderGoods == null ? null : (orderGoods.getSkuId() == null ? null : String.valueOf(orderGoods.getSkuId())));
                        vo.setWOrderId(waybill.getId());
                        vo.setWOrderNo(waybill.getWOrderNo());
                        vo.setCreateTime(waybill.getCreateTime());
                        vo.setStartTime(waybill.getStartTime());
                        vo.setEndTime(waybill.getEndTime());
                        /**查询车队服务dubbo 2023-07-24 司机端不展示 车队信息改为展示物流公司*/
//                    vo.setFleetName();
//                    vo.setFleetId();
//                    vo.setTruckFleetName();
                        vo.setEntrustAmount(waybill.getEntrustAmount());
                        vo.setType(waybill.getType());
                        vo.setTruckNo(waybill.getTruckNo());
                        orderVOList.add(vo);
                    }
                }
            }
        }
    }

    /**
     * 趟次展示数据组装
     * @param id
     * @param tripStatus
     * @param orderVOList
     */
    private void tripPackageData(Long id, List<Long> tripStatus, List<WaybillOrderVO> orderVOList) {
        List<Long> list = waybillOrderMapper.selectDriverOrder(id, tripStatus);
        if (CollectionUtils.isNotEmpty(list)) {
            for (Long aLong : list) {
                KwtLogisticsOrderAddress loadAddress = logisticsOrderAddressMapper.selectOne(new LambdaQueryWrapper<KwtLogisticsOrderAddress>()
                        .eq(KwtLogisticsOrderAddress::getLOrderId, aLong).eq(KwtLogisticsOrderAddress::getAddressType, NumberConstant.ONE));
                KwtLogisticsOrderAddress unloadAddress = logisticsOrderAddressMapper.selectOne(new LambdaQueryWrapper<KwtLogisticsOrderAddress>()
                        .eq(KwtLogisticsOrderAddress::getLOrderId, aLong).eq(KwtLogisticsOrderAddress::getAddressType, NumberConstant.TWO));
                KwtLogisticsOrderGoods orderGoods = logisticsOrderGoodsMapper.selectOne(new LambdaQueryWrapper<KwtLogisticsOrderGoods>()
                        .eq(KwtLogisticsOrderGoods::getLOrderId, aLong));
                List<KwtWaybillOrder> waybillOrders = waybillOrderMapper.selectList(new LambdaQueryWrapper<KwtWaybillOrder>()
                        .eq(KwtWaybillOrder::getLOrderId, aLong).eq(KwtWaybillOrder::getDriverId, id));
                for (KwtWaybillOrder waybill : waybillOrders) {
                    WaybillOrderVO vo = new WaybillOrderVO();
                    vo.setLOrderId(aLong);
                    vo.setLoadCityCode(loadAddress.getCityCode());
                    vo.setLoadCityName(loadAddress.getCityName());
                    vo.setLoadDetailAddress(loadAddress.getDetailAddress());
                    vo.setUnloadCityName(unloadAddress.getCityName());
                    vo.setUnloadCityCode(unloadAddress.getCityCode());
                    vo.setEntId(String.valueOf(waybill.getEntId()));
                    vo.setFirmName(remoteSystemService.queryEntCacheById(waybill.getEntId()).getFirmName());
                    vo.setGoodsName(orderGoods == null ? null : (orderGoods.getGoodsName() == null ? null : orderGoods.getGoodsName()));
                    vo.setGoodsCode(orderGoods == null ? null : (orderGoods.getSkuId() == null ? null : String.valueOf(orderGoods.getSkuId())));
                    vo.setWOrderId(waybill.getId());
                    vo.setWOrderNo(waybill.getWOrderNo());
                    vo.setCreateTime(waybill.getCreateTime());
                    vo.setStartTime(waybill.getStartTime());
                    vo.setEndTime(waybill.getEndTime());
                    //todo 查询车队服务dubbo
//                    vo.setFleetName();
//                    vo.setFleetId();
//                    vo.setTruckFleetName();
                    vo.setEntrustAmount(waybill.getEntrustAmount());
                    vo.setType(waybill.getType());
                    vo.setTruckNo(waybill.getTruckNo());
                    orderVOList.add(vo);
                }
            }
        }
    }

    /**
     * 更换司机
     *
     * @param dto
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public HttpResult updateDriver(UpdateDriverCarDTO dto) {
        HttpResult httpResult = new HttpResult();
        httpResult.setCode(HttpStatus.SUCCESS_CODE);
        HttpResult result = ValidUtil.serviceValid(dto);
        if (HttpStatus.SUCCESS_CODE != result.getCode()) {
            httpResult.setCode(HttpStatus.GLOBAL_EXCEPTION_CODE);
            httpResult.setMsg(result.getMsg());
            return httpResult;
        }
        /**【不分循环趟次】更换司机：【待接单】、【待出车】、【已出车】、【到达装货地点】、【已装货】、【到达卸货地点】可修改*/
        //更换司机（趟次派车(-卸货前)/循环派车(接单后-卸货前)）
        KwtWaybillOrder waybillOrder = waybillOrderMapper.selectOne(new LambdaQueryWrapper<KwtWaybillOrder>()
                .eq(KwtWaybillOrder::getStatus, dto.getWOrderId()));
        if (ObjectUtils.isEmpty(waybillOrder)) {
            throw new RuntimeException("运单不存在:" + dto.getWOrderNo());
        }
        if (waybillOrder.getStatus() > CarWaybillEnum.COMPLETION_UNLOADING.getCode()
                || waybillOrder.getStatus() <= CarWaybillEnum.PENDING_ORDER.getCode()) {
            throw new RuntimeException("该【" + dto.getWOrderNo() + "】运单不满足更换司机条件");
        }
        waybillOrderMapper.update(null, new LambdaUpdateWrapper<KwtWaybillOrder>()
                .eq(KwtWaybillOrder::getId, dto.getWOrderId())
                .set(KwtWaybillOrder::getDriverId, dto.getDriverId())
                .set(KwtWaybillOrder::getUpdateBy, LoginUserHolder.getUserId())
                .set(KwtWaybillOrder::getUpdateTime, new Date()));
        SckwWaybillOrder sckwWaybillOrder = mongoTemplate.findById(dto.getWOrderId(), SckwWaybillOrder.class);
        //更新mongodb
        SckwWaybillOrder updateParam = BeanUtils.copyProperties(sckwWaybillOrder, SckwWaybillOrder.class);
        updateParam.setDriverId(Long.valueOf(dto.getDriverId())).setDriverPhone(dto.getDriverPhone()).setDriverName(dto.getDriverName())
                .setDriverIdcard(dto.getDriverIdCard()).setTruckId(Long.parseLong(dto.getTruckId())).setTruckNo(dto.getTruckNo()).setUpdateTime(new Date()).setUpdateBy(LoginUserHolder.getUserId())
                .setUpdateByName(LoginUserHolder.getUserName()).setUpdateTime(new Date());
        SckwBusSum busSum = new SckwBusSum();
        busSum.setBusSumType(BusinessTypeEnum.WAYBILL_ORDER_TYPE.getName());
        busSum.setMethod(NumberConstant.TWO);
        busSum.setObject(updateParam);
        streamBridge.send("sckw-busSum", JSON.toJSONString(busSum));
        return httpResult;
    }

    /**
     * 承运订单-更换车辆
     *
     * @param dto
     * @return
     */
    public HttpResult updateCarCommit(UpdateDriverCarDTO dto) {
        HttpResult httpResult = new HttpResult();
        httpResult.setCode(HttpStatus.SUCCESS_CODE);
        HttpResult result = ValidUtil.serviceValid(dto);
        if (HttpStatus.SUCCESS_CODE != result.getCode()) {
            httpResult.setCode(HttpStatus.GLOBAL_EXCEPTION_CODE);
            httpResult.setMsg(result.getMsg());
            return httpResult;
        }
        /**【不分循环趟次】更换车辆：【待接单】、【待出车】可修改*/
        KwtWaybillOrder waybillOrder = waybillOrderMapper.selectOne(new LambdaQueryWrapper<KwtWaybillOrder>()
                .eq(KwtWaybillOrder::getStatus, dto.getWOrderId()));
        if (ObjectUtils.isEmpty(waybillOrder)) {
            throw new RuntimeException("运单不存在:" + dto.getWOrderNo());
        }
        if (waybillOrder.getStatus() > CarWaybillEnum.PENDING_VEHICLE.getCode()) {
            throw new RuntimeException("该【" + dto.getWOrderNo() + "】运单不满足更换车辆条件");
        }
        waybillOrderMapper.update(null, new LambdaUpdateWrapper<KwtWaybillOrder>()
                .eq(KwtWaybillOrder::getId, dto.getWOrderId())
                .set(KwtWaybillOrder::getTruckNo, dto.getTruckNo())
                .set(KwtWaybillOrder::getUpdateBy, LoginUserHolder.getUserId())
                .set(KwtWaybillOrder::getUpdateTime, new Date()));
        SckwWaybillOrder sckwWaybillOrder = mongoTemplate.findById(dto.getWOrderId(), SckwWaybillOrder.class);
        //更新mongodb
        SckwWaybillOrder updateParam = BeanUtils.copyProperties(sckwWaybillOrder, SckwWaybillOrder.class);
        updateParam.setTruckId(Long.parseLong(dto.getTruckId())).setTruckNo(dto.getTruckNo())
                .setTruckType(dto.getCarType()).setUpdateTime(new Date()).setUpdateBy(LoginUserHolder.getUserId())
                .setUpdateByName(LoginUserHolder.getUserName()).setUpdateTime(new Date());
        SckwBusSum busSum = new SckwBusSum();
        busSum.setBusSumType(BusinessTypeEnum.WAYBILL_ORDER_TYPE.getName());
        busSum.setMethod(NumberConstant.TWO);
        busSum.setObject(updateParam);
        streamBridge.send("sckw-busSum", JSON.toJSONString(busSum));
        return httpResult;
    }
}
