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

import cn.hutool.core.bean.BeanUtil;
import com.google.common.collect.Lists;
import com.prolog.common.util.ToolKits;
import com.prolog.framework.common.message.RestMessage;
import com.prolog.framework.core.restriction.Criteria;
import com.prolog.framework.core.restriction.Restriction;
import com.prolog.framework.core.restriction.RestrictionBuilder;
import com.prolog.framework.core.restriction.Restrictions;
import com.prolog.rdc.tms.app.constant.DataDictionaryConstant;
import com.prolog.rdc.tms.app.dao.mapper.TmsLoadingBillDetailMapper;
import com.prolog.rdc.tms.app.dao.mapper.TmsLoadingBillHeaderMapper;
import com.prolog.rdc.tms.app.dao.mapper.TmsShipbillHeaderMapper;
import com.prolog.rdc.tms.app.model.dto.NavigationLoadingBillDTO;
import com.prolog.rdc.tms.app.model.dto.NavigationLoadingBillDetailDTO;
import com.prolog.rdc.tms.app.model.entity.TmsLoadingBillDetailModel;
import com.prolog.rdc.tms.app.model.entity.TmsLoadingBillHeaderModel;
import com.prolog.rdc.tms.app.model.entity.TmsShipbillHeaderModel;
import com.prolog.rdc.tms.app.model.vo.NavigationLoadingBillDetailQueryVO;
import com.prolog.rdc.tms.app.model.vo.NavigationLoadingBillQueryVO;
import com.prolog.rdc.tms.app.service.NavigationService;
import com.prolog.rdc.tms.app.util.PublicMethods;
import com.prolog.rdc.tms.rmi.feign.MaindataFeign;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * @author yaohai
 * @version v1.0.0
 * @since 2023/08/28 14:47
 **/
@Service
@Slf4j
public class NavigationServiceImpl implements NavigationService {

    @Resource
    private TmsLoadingBillHeaderMapper loadingBillHeaderMapper;

    @Resource
    private TmsLoadingBillDetailMapper loadingBillDetailMapper;

    @Resource
    private TmsShipbillHeaderMapper shipbillHeaderMapper;

    @Autowired
    private MaindataFeign maindataTmsResource;

    @Override
    public List<NavigationLoadingBillDTO> getLoadingBillByDriverId(NavigationLoadingBillQueryVO queryVO) {
        ToolKits.isParamNull(queryVO, "参数不能为空");
        ToolKits.isParamNull(queryVO.getDriverId(), "司机ID不能为空");
        ToolKits.isParamNull(queryVO.getEnterpriseId(), "企业ID不能为空");
        //响应结果
        List<NavigationLoadingBillDTO> result = new ArrayList<>();

        //查询指派给该司机的启运、部分送达的派车单
        Criteria criteria = new Criteria(TmsLoadingBillHeaderModel.class);
        Restriction r1 = new RestrictionBuilder()
                .eq(TmsLoadingBillHeaderModel::getDriverId, queryVO.getDriverId())
                .eq(TmsLoadingBillHeaderModel::getEnterpriseId, queryVO.getEnterpriseId())
                .in(TmsLoadingBillHeaderModel::getStatus, new Integer[]{DataDictionaryConstant.LOADING_BILL_STATUS_QY, DataDictionaryConstant.LOADING_BILL_STATUS_SD_PART})
                .build();
        criteria.setRestriction(r1);
        criteria.orderAscBy(TmsLoadingBillHeaderModel::getStatus, TmsLoadingBillHeaderModel::getCreatetime);
        List<TmsLoadingBillHeaderModel> loadingBillHeaderModelList = loadingBillHeaderMapper.findByCriteria(criteria);
        if (ToolKits.isNotEmpty(loadingBillHeaderModelList)) {
            result = loadingBillHeaderModelList.stream().map(loadingBillHeader -> {
                NavigationLoadingBillDTO dto = BeanUtil.copyProperties(loadingBillHeader, NavigationLoadingBillDTO.class);
                //查询待完成任务数，运输状态为配送中
                Criteria detailCriteria = new Criteria(TmsLoadingBillDetailModel.class);
                Restriction detailR1 = new RestrictionBuilder()
                        .eq(TmsLoadingBillDetailModel::getLoadingBillId, loadingBillHeader.getLoadingBillId())
                        .eq(TmsLoadingBillDetailModel::getTransportStatus, DataDictionaryConstant.TRANSPORT_STATUS_SHIPPING)
                        .build();
                detailCriteria.setRestriction(detailR1);
                long unShipBillNum = loadingBillDetailMapper.findCountByCriteria(detailCriteria);
                dto.setUnShipbillNumber(Integer.valueOf(Long.toString(unShipBillNum)));
                NavigationLoadingBillDetailQueryVO detailQueryVO = new NavigationLoadingBillDetailQueryVO();
                detailQueryVO.setLoadingBillId(loadingBillHeader.getLoadingBillId());
                detailQueryVO.setCheckFinshi(1);
                List<NavigationLoadingBillDetailDTO> detailDTOS = this.getLoadingBillDetail(detailQueryVO);
                dto.setDetailDTOS(detailDTOS);
                Optional<NavigationLoadingBillDetailDTO> minOptional = detailDTOS.stream().filter(e -> e.getShippingOrder() != null).min(Comparator.comparing(NavigationLoadingBillDetailDTO::getShippingOrder));
                if (minOptional.isPresent()) {
                    dto.setStartCity(minOptional.get().getShipperCityName());
                }
                Optional<NavigationLoadingBillDetailDTO> maxOptional = detailDTOS.stream().filter(e -> e.getShippingOrder() != null).max(Comparator.comparing(NavigationLoadingBillDetailDTO::getShippingOrder));
                if (maxOptional.isPresent()) {
                    dto.setEndtCity(maxOptional.get().getConsigneeCityName());
                }
                return dto;
            }).collect(Collectors.toList());
        }
        return result;
    }

    @Override
    public List<NavigationLoadingBillDetailDTO> getLoadingBillDetail(NavigationLoadingBillDetailQueryVO queryVO) {
        ToolKits.isParamNull(queryVO, "参数不能为空");
        ToolKits.isParamNull(queryVO.getLoadingBillId(), "派车单ID不能为空");
        ToolKits.isParamNull(queryVO.getCheckFinshi(), "是否仅待完成不能为空");
        List<NavigationLoadingBillDetailDTO> result = new ArrayList<>();
        //查询派车下任务详情
        Criteria criteria = new Criteria(TmsLoadingBillDetailModel.class);
        Restriction restriction = new RestrictionBuilder()
                .eq(TmsLoadingBillDetailModel::getLoadingBillId, queryVO.getLoadingBillId())
                .build();
        criteria.setRestriction(restriction);
        List<TmsLoadingBillDetailModel> loadingBillDetailModelList = loadingBillDetailMapper.findByCriteria(criteria);
        if (ToolKits.isNotEmpty(loadingBillDetailModelList)) {
            List<Map<String, Object>> shipperTypeData = Lists.newArrayList();
            List<Map<String, Object>> consigneeTypeData = Lists.newArrayList();
            // 发货方类型
            RestMessage<List<Map<String, Object>>> restMessage6 = maindataTmsResource.getDropDownById(DataDictionaryConstant.SHIPPER_TYPE, null, null, null);
            if (!restMessage6.isSuccess()) {
                throw new RuntimeException("发货方类型翻译失败!");
            } else {
                shipperTypeData = restMessage6.getData();
            }
            // 收货方类型
            RestMessage<List<Map<String, Object>>> restMessage7 = maindataTmsResource.getDropDownById(DataDictionaryConstant.CONSIGNEE_TYPE, null, null, null);
            if (!restMessage7.isSuccess()) {
                throw new RuntimeException("收货方类型翻译失败!");
            } else {
                consigneeTypeData = restMessage7.getData();
            }

            List<String> shipBillIdList = loadingBillDetailModelList.stream().map(TmsLoadingBillDetailModel::getShipbillId).distinct().collect(Collectors.toList());
            Criteria shipBillCriteria = new Criteria(TmsShipbillHeaderModel.class);
            Restriction r1 = Restrictions.in(TmsShipbillHeaderModel::getShipbillId, shipBillIdList.toArray());
            Restriction r2 = queryVO.getCheckFinshi() == 1 ? null : Restrictions.in(TmsShipbillHeaderModel::getTransportStatus, new Integer[]{DataDictionaryConstant.TRANSPORT_STATUS_PENDING_SHIP, DataDictionaryConstant.TRANSPORT_STATUS_SHIPPING});
            shipBillCriteria.setRestriction(Restrictions.and(r1, r2));
            List<TmsShipbillHeaderModel> shipbillHeaderModelList = shipbillHeaderMapper.findByCriteria(shipBillCriteria);
            for (TmsShipbillHeaderModel shipbillHeaderModel : shipbillHeaderModelList) {
                NavigationLoadingBillDetailDTO dto = BeanUtil.copyProperties(shipbillHeaderModel, NavigationLoadingBillDetailDTO.class);
                if (ToolKits.isNotEmpty(dto.getDepartureTime()) && ToolKits.isNotEmpty(dto.getDeliveryTime())) {
                    long minutes = TimeUnit.MILLISECONDS.toMinutes(dto.getDeliveryTime().getTime() - dto.getDepartureTime().getTime());
                    dto.setTotalTime(minutes);
                }
                StringBuffer consigneeProvinceCityDistrict = new StringBuffer();
                // 目的地
                consigneeProvinceCityDistrict.append(dto.getConsigneeProvinceName());
                consigneeProvinceCityDistrict.append(dto.getConsigneeCityName());
                consigneeProvinceCityDistrict.append(dto.getConsigneeDistrictName());
                consigneeProvinceCityDistrict.append(dto.getConsigneeAddress());
                dto.setConsigneeProvinceCityDistrict(consigneeProvinceCityDistrict.toString());
                // 始发地
                StringBuffer shipperProvinceCityDistrict = new StringBuffer();
                shipperProvinceCityDistrict.append(dto.getShipperProvinceName());
                shipperProvinceCityDistrict.append(dto.getShipperCityName());
                shipperProvinceCityDistrict.append(dto.getShipperDistrictName());
                shipperProvinceCityDistrict.append(dto.getShipperAddress());
                dto.setShipperProvinceCityDistrict(shipperProvinceCityDistrict.toString());

                // 类型翻译
                dto.setShipperTypeName(PublicMethods.change(shipperTypeData, String.valueOf(dto.getShipperType())));
                dto.setConsigneeTypeName(PublicMethods.change(consigneeTypeData, String.valueOf(dto.getConsigneeType())));

                result.add(dto);
            }
        }
        return result;
    }
}
