package com.prolog.rdc.tms.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.google.common.collect.Lists;
import com.prolog.common.util.ToolKits;
import com.prolog.framework.common.message.RestMessage;
import com.prolog.framework.core.exception.BizException;
import com.prolog.framework.core.restriction.Criteria;
import com.prolog.framework.core.restriction.Order;
import com.prolog.framework.core.restriction.Restriction;
import com.prolog.framework.core.restriction.Restrictions;
import com.prolog.product.core.framework.entity.UserEntity;
import com.prolog.product.core.framework.util.PlgFxUsrUtils;
import com.prolog.rdc.tms.config.enums.InTransitPositionTypeEnum;
import com.prolog.rdc.tms.constant.DataDictionaryConstant;
import com.prolog.rdc.tms.dao.mapper.TmsGpsDataMapper;
import com.prolog.rdc.tms.dao.mapper.TmsLoadingBillDetailMapper;
import com.prolog.rdc.tms.dao.mapper.TmsLoadingBillHeaderMapper;
import com.prolog.rdc.tms.dao.mapper.TmsShipbillHeaderMapper;
import com.prolog.rdc.tms.dao.mapper.TmsVehicleGPSMapper;
import com.prolog.rdc.tms.model.dto.DeviceGpsDTO;
import com.prolog.rdc.tms.model.dto.TmsVehicleGpsDTO;
import com.prolog.rdc.tms.model.dto.e6.TrackDetailDTO;
import com.prolog.rdc.tms.model.dto.fleetManagement.DeviceByOneDTO;
import com.prolog.rdc.tms.model.dto.g7.HistoryLocationByGpsnoDTO;
import com.prolog.rdc.tms.model.entity.TmsGpsDataModel;
import com.prolog.rdc.tms.model.entity.TmsLoadingBillDetailModel;
import com.prolog.rdc.tms.model.entity.TmsLoadingBillHeaderModel;
import com.prolog.rdc.tms.model.entity.TmsShipbillHeaderModel;
import com.prolog.rdc.tms.model.entity.line.TmsVehicleGPSModel;
import com.prolog.rdc.tms.model.vo.e6.TrackDetailVO;
import com.prolog.rdc.tms.model.vo.g7.HistoryLocationByGpsnoVO;
import com.prolog.rdc.tms.rmi.feign.InterfaceFeign;
import com.prolog.rdc.tms.service.ShipBillGpsService;
import com.prolog.rdc.tms.service.fleetManagement.DeviceService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

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

/**
 * @author hongbo.pan
 * @date 2023/2/6
 */
@Service
public class ShipBillGpsServiceImpl implements ShipBillGpsService {

    public static final String E6 = "易流";
    public static final String G7 = "G7";

    @Autowired
    private TmsShipbillHeaderMapper tmsShipbillHeaderMapper;

    @Autowired
    private TmsLoadingBillHeaderMapper tmsLoadingBillHeaderMapper;

    @Autowired
    private TmsLoadingBillDetailMapper tmsLoadingBillDetailMapper;

    @Autowired
    private TmsGpsDataMapper tmsGpsDataMapper;

    @Autowired
    private TmsVehicleGPSMapper tmsVehicleGPSMapper;

    @Autowired
    private DeviceService deviceService;

    @Autowired
    private InterfaceFeign interfaceFeign;

    @Override
    public Object getTrackByShipBillId(String positionType, String shipBillId) {
        if (InTransitPositionTypeEnum.DEVICE.getCode().equals(positionType)) {
            return getDeviceTrackByShipBillId(shipBillId);
        } else if (InTransitPositionTypeEnum.DEVICE_LINK.getCode().equals(positionType)) {
            return getDeviceLinkTrackByShipBillId(shipBillId);
        }
        return getWechatTrackByShipBillId(shipBillId);
    }

    @Override
    public List<TmsVehicleGpsDTO> getWechatTrackByShipBillId(String shipBillId) {
        List<TmsVehicleGpsDTO> tmsVehicleGpsDTOList = Lists.newArrayList();
        Criteria crt = Criteria.forClass(TmsVehicleGPSModel.class);
        TmsVehicleGPSModel tmsVehicleGpsModel = new TmsVehicleGPSModel();
        crt.restrictionBuilder().eq(tmsVehicleGpsModel::getShipbillId, shipBillId).build();
        crt.orderAscBy(tmsVehicleGpsModel::getUpdatetime, tmsVehicleGpsModel::getCreatetime);
        List<TmsVehicleGPSModel> tmsVehicleGpsModelList = tmsVehicleGPSMapper.findByCriteria(crt);
        if (CollectionUtil.isNotEmpty(tmsVehicleGpsModelList)) {
            tmsVehicleGpsDTOList = tmsVehicleGpsModelList.stream().map(model ->
                    BeanUtil.toBean(model, TmsVehicleGpsDTO.class)).collect(Collectors.toList());
        }
        return tmsVehicleGpsDTOList;
    }

    @Override
    public List<DeviceGpsDTO> getDeviceTrackByShipBillId(String shipBillId) {
        TmsShipbillHeaderModel tmsShipbillHeaderModel = tmsShipbillHeaderMapper.findById(shipBillId, TmsShipbillHeaderModel.class);
        if (ObjectUtil.isNull(tmsShipbillHeaderModel)) {
            throw new BizException("运单【" + shipBillId + "】不存在");
        }
        List<DeviceGpsDTO> deviceGpsDTOList = Lists.newArrayList();
        if (tmsShipbillHeaderModel.getStatus() <= DataDictionaryConstant.SHIPBILL_STATUS_QY) {
            return deviceGpsDTOList;
        }
        if (StrUtil.isBlank(tmsShipbillHeaderModel.getVehicleDeviceCode())) {
            return deviceGpsDTOList;
        }
        UserEntity user = PlgFxUsrUtils.getUserEntity();
        Criteria criteria = Criteria.forClass(TmsGpsDataModel.class);
        Restriction r1 = Restrictions.in(TmsGpsDataModel::getDeviceCode, tmsShipbillHeaderModel.getVehicleDeviceCode().split(","));
        Restriction r2 = Restrictions.eq(TmsGpsDataModel::getEnterpriseId, user.getEnterpriseId());
        Restriction r3 = ToolKits.isEmpty(tmsShipbillHeaderModel.getDepartureTime()) ? null : Restrictions.ge(TmsGpsDataModel::getGpsDate, tmsShipbillHeaderModel.getDepartureTime());
        Restriction r4 = ToolKits.isEmpty(tmsShipbillHeaderModel.getDeliveryTime()) ? null : Restrictions.le(TmsGpsDataModel::getGpsDate, tmsShipbillHeaderModel.getDeliveryTime());
        criteria.setRestriction(Restrictions.and(r1, r2, r3, r4));
        criteria.setOrder(Order.newInstance().asc(TmsGpsDataModel::getGpsDate));
        List<TmsGpsDataModel> tmsGpsDataModelList = tmsGpsDataMapper.findByCriteria(criteria);
        if (CollectionUtil.isNotEmpty(tmsGpsDataModelList)) {
            criteria = Criteria.forClass(TmsLoadingBillDetailModel.class);
            r1 = Restrictions.eq(TmsLoadingBillDetailModel::getShipbillId, tmsShipbillHeaderModel.getShipbillId());
            r2 = Restrictions.eq(TmsLoadingBillDetailModel::getEnterpriseId, user.getEnterpriseId());
            criteria.setRestriction(Restrictions.and(r1, r2));
            criteria.setOrder(Order.newInstance().desc(TmsLoadingBillDetailModel::getCreatetime));
            List<TmsLoadingBillDetailModel> loadingBillDetailModels = tmsLoadingBillDetailMapper.findByCriteria(criteria);
            ToolKits.isParamNull(loadingBillDetailModels, "未找到对应的调度单明细");
            TmsLoadingBillDetailModel loadingBillDetailModel = loadingBillDetailModels.get(0);
            TmsLoadingBillHeaderModel finalTmsLoadingBillHeaderModel =
                    tmsLoadingBillHeaderMapper.findById(loadingBillDetailModel.getLoadingBillId(), TmsLoadingBillHeaderModel.class);
            deviceGpsDTOList = tmsGpsDataModelList.stream().map(model -> {
                DeviceGpsDTO dto = BeanUtil.toBean(model, DeviceGpsDTO.class);
                dto.setDriverId(finalTmsLoadingBillHeaderModel.getDriverId());
                dto.setDriverCode(finalTmsLoadingBillHeaderModel.getDriverCode());
                dto.setDriverName(finalTmsLoadingBillHeaderModel.getDriverName());
                dto.setDriverPhoneNumber(finalTmsLoadingBillHeaderModel.getDriverPhoneNumber());
                dto.setVehicleId(finalTmsLoadingBillHeaderModel.getVehicleId());
                dto.setVehicleCode(finalTmsLoadingBillHeaderModel.getVehicleCode());
                dto.setVehiclePlateNumber(finalTmsLoadingBillHeaderModel.getVehiclePlateNumber());
                dto.setShipbillId(tmsShipbillHeaderModel.getShipbillId());
                dto.setShipbillNo(tmsShipbillHeaderModel.getShipbillNo());
                dto.setLoadingBillNo(finalTmsLoadingBillHeaderModel.getLoadingBillNo());
                dto.setLoadingBillId(finalTmsLoadingBillHeaderModel.getLoadingBillId());
                return dto;
            }).collect(Collectors.toList());
        }
        return deviceGpsDTOList;
    }

    @Override
    public List<DeviceGpsDTO> getDeviceLinkTrackByShipBillId(String shipBillId) {
        TmsShipbillHeaderModel tmsShipbillHeaderModel = tmsShipbillHeaderMapper.findById(shipBillId, TmsShipbillHeaderModel.class);
        if (ObjectUtil.isNull(tmsShipbillHeaderModel)) {
            throw new BizException("运单【" + shipBillId + "】不存在");
        }
        Criteria crt = Criteria.forClass(TmsLoadingBillDetailModel.class);
        Restriction r1 = Restrictions.eq("shipbillId", shipBillId);
        crt.setRestriction(Restrictions.and(r1));
        crt.setOrder(Order.newInstance().desc(TmsLoadingBillDetailModel::getCreatetime));
        List<TmsLoadingBillDetailModel> tmsLoadingBillDetailModels = tmsLoadingBillDetailMapper.findByCriteria(crt);
        ToolKits.isParamNull(tmsLoadingBillDetailModels, "未找到对应的调度单明细");
        TmsLoadingBillDetailModel loadingBillDetailModel = tmsLoadingBillDetailModels.get(0);
        TmsLoadingBillHeaderModel loadingBillHeaderModel = tmsLoadingBillHeaderMapper.findById(loadingBillDetailModel.getLoadingBillId(), TmsLoadingBillHeaderModel.class);
        if (StrUtil.isBlank(loadingBillHeaderModel.getVehicleDeviceCode())) {
            return Lists.newArrayList();
        }
        DeviceByOneDTO deviceByOneDTO = getDeviceCompanyName(loadingBillHeaderModel.getVehicleDeviceId());
        Date startDate = tmsShipbillHeaderModel.getDepartureTime();
        Date endDate = tmsShipbillHeaderModel.getDeliveryTime() == null ? DateUtil.date() : tmsShipbillHeaderModel.getDeliveryTime();
        List<DeviceGpsDTO> deviceLinkGpsDTOList = getTrackByDeviceCompanyName(loadingBillHeaderModel.getVehiclePlateNumber(),
                deviceByOneDTO.getCompanyName(), startDate, endDate);
        deviceLinkGpsDTOList = deviceLinkGpsDTOList.stream().peek(deviceLinkGpsDTO -> {
            deviceLinkGpsDTO.setDriverName(loadingBillHeaderModel.getDriverName());
            deviceLinkGpsDTO.setDriverPhoneNumber(loadingBillHeaderModel.getDriverPhoneNumber());
            deviceLinkGpsDTO.setLoadingBillId(loadingBillHeaderModel.getLoadingBillId());
            deviceLinkGpsDTO.setShipbillId(shipBillId);
            deviceLinkGpsDTO.setDeviceCode(deviceLinkGpsDTO.getDeviceCode());
        }).collect(Collectors.toList());
        return deviceLinkGpsDTOList;
    }

    /**
     * 获取设备生产厂商
     * @param deviceId
     * @return
     */
    private DeviceByOneDTO getDeviceCompanyName(String deviceId) {
        deviceId = deviceId.split(",")[0];
        DeviceByOneDTO deviceByOneDTO =  deviceService.getOne(Long.valueOf(deviceId));
        if (!E6.equals(deviceByOneDTO.getCompanyName()) && !G7.equals(deviceByOneDTO.getCompanyName())) {
            throw new BizException("设备生产厂商错误，" + deviceByOneDTO.getCompanyName());
        }
        return deviceByOneDTO;
    }

    /**
     * getTrackByDeviceCompanyName
     * @param vehiclePlateNumber
     * @param deviceCompanyName
     * @param startDate
     * @param endDate
     * @return
     */
    private List<DeviceGpsDTO> getTrackByDeviceCompanyName(String vehiclePlateNumber, String deviceCompanyName, Date startDate, Date endDate) {
        if (E6.equals(deviceCompanyName)) {
            TrackDetailVO vo = new TrackDetailVO();
            vo.setBtime(startDate);
            vo.setEtime(endDate);
            vo.setVehicle(vehiclePlateNumber);
            RestMessage<List<TrackDetailDTO>> trackDetailList = interfaceFeign.getTrackDetail(vo);
            if (!trackDetailList.isSuccess()) {
                throw new BizException("易流设备轨迹，设备直连报错，vehiclePlateNumber=" + vehiclePlateNumber);
            }
            return trackDetailList.getData().stream().map(trackDetailDTO -> {
                DeviceGpsDTO deviceLinkGpsDTO = new DeviceGpsDTO();
                deviceLinkGpsDTO.setVehiclePlateNumber(vehiclePlateNumber);
                deviceLinkGpsDTO.setLongitude(trackDetailDTO.getLon02());
                deviceLinkGpsDTO.setLatitude(trackDetailDTO.getLat02());
                deviceLinkGpsDTO.setGpsDate(trackDetailDTO.getGpsTime());
                deviceLinkGpsDTO.setCurrentVelocity(trackDetailDTO.getSpeed());
                deviceLinkGpsDTO.setVehicleDirection(trackDetailDTO.getDirection());
                deviceLinkGpsDTO.setPlaceName(trackDetailDTO.getPlaceName());
                return deviceLinkGpsDTO;
            }).collect(Collectors.toList());
        } else if (G7.equals(deviceCompanyName)) {
            HistoryLocationByGpsnoVO vo = new HistoryLocationByGpsnoVO();
            vo.setPlateNum(vehiclePlateNumber);
            vo.setFrom(startDate);
            vo.setTo(endDate);
            RestMessage<List<HistoryLocationByGpsnoDTO>> historyLocationByVehExecute = interfaceFeign.historyLocationByVehExecute(vo);
            if (!historyLocationByVehExecute.isSuccess()) {
                throw new BizException("g7设备轨迹，设备直连报错，vehiclePlateNumber=" + vehiclePlateNumber);
            }
            return historyLocationByVehExecute.getData().stream().map(historyLocationByGpsnoDTO -> {
                DeviceGpsDTO deviceLinkGpsDTO = new DeviceGpsDTO();
                deviceLinkGpsDTO.setVehiclePlateNumber(vehiclePlateNumber);
                deviceLinkGpsDTO.setLongitude(historyLocationByGpsnoDTO.getLng());
                deviceLinkGpsDTO.setLatitude(historyLocationByGpsnoDTO.getLat());
                deviceLinkGpsDTO.setGpsDate(DateUtil.date(Long.valueOf(historyLocationByGpsnoDTO.getTime())));
                deviceLinkGpsDTO.setCurrentVelocity(NumberUtil.toBigDecimal(historyLocationByGpsnoDTO.getSpeed()));
                deviceLinkGpsDTO.setVehicleDirection(NumberUtil.toBigDecimal(historyLocationByGpsnoDTO.getCourse()));
                return deviceLinkGpsDTO;
            }).collect(Collectors.toList());
        }
        return null;
    }
}
