package com.sckw.fleet.service;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.sckw.core.exception.BusinessException;
import com.sckw.core.model.base.BaseModel;
import com.sckw.core.model.enums.AddressTypeEnum;
import com.sckw.core.model.enums.CarWaybillV1Enum;
import com.sckw.core.utils.DateUtils;
import com.sckw.core.utils.LocUtils;
import com.sckw.core.utils.StringUtils;
import com.sckw.core.web.context.LoginUserHolder;
import com.sckw.core.web.response.BaseIotResult;
import com.sckw.core.web.response.result.PageDataResult;
import com.sckw.fleet.model.*;
import com.sckw.fleet.model.dto.KwfTruckRouteDto;
import com.sckw.fleet.model.request.DeleteTruckRoteReq;
import com.sckw.fleet.model.request.QueryTruckRouteByDriverReq;
import com.sckw.fleet.model.request.QueryTruckRoteReq;

import com.sckw.fleet.model.request.TruckRoteDetailReq;
import com.sckw.fleet.model.vo.QueryTruckRoteVo;
import com.sckw.fleet.model.vo.TruckRoteDetailVo;
import com.sckw.fleet.repository.*;
import com.sckw.transport.api.dubbo.TransportRemoteService;
import com.sckw.transport.api.feign.VehicleTraceClient;
import com.sckw.transport.api.model.dto.VehicleDataDTO;
import com.sckw.transport.api.model.dto.VehicleReturnData;
import com.sckw.transport.api.model.vo.KwtLogisticsOrderAddressVo;
import com.sckw.transport.api.model.vo.KwtWaybillOrderAddressVo;
import com.sckw.transport.api.model.vo.RWaybillOrderVo;
import com.sckw.transport.api.model.vo.WaybillOrderSubtaskVo;
import jakarta.annotation.Resource;
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * @author PC
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class KwfTruckRouteService {

    private final KwfTruckRouteRepository truckRouteRepository;
    private final KwfDriverRepository driverRepository;
    private final KwfFleetTruckRepository fleetTruckRepository;
    private final KwfTruckRepository truckRepository;
    private final VehicleTraceClient vehicleTraceClient;
    @Resource
    private  KwfFleetRepository fleetRepository;
    @DubboReference(version = "1.0.0", group = "design", check = false, timeout = 8000)
    private TransportRemoteService transportRemoteService;

    public PageDataResult<QueryTruckRoteVo> pageTruckRoute(QueryTruckRoteReq req) {
        log.info("分页查询车辆惯用路线,参数:{}", JSON.toJSONString(req));
        Long entId = LoginUserHolder.getEntId();
        //获取司机id
        Set<Long> driveIds = getDriveIds(req);
        //获取车队id
        Set<Long> fleetIds = getFleetIds(req);
        if (org.apache.commons.lang3.StringUtils.isNotBlank(req.getFleetId())){
            fleetIds.add(Long.valueOf(req.getFleetId()));
        }

        KwfTruckRouteDto kwfTruckRoute = new KwfTruckRouteDto();
        kwfTruckRoute.setFleetIds(fleetIds);
        kwfTruckRoute.setDriverIds(driveIds);
        kwfTruckRoute.setStartPoint(req.getStartPoint());
        kwfTruckRoute.setUnloadingPoint(req.getUnloadingPoint());
        kwfTruckRoute.setTruckNo(req.getTruckNo());
        kwfTruckRoute.setEntId(entId);
        IPage<KwfTruckRoute> truckRoutePage = truckRouteRepository.pageTruckRoute(req.getPageNum(), req.getPageSize(), kwfTruckRoute);
        List<KwfTruckRoute> records = truckRoutePage.getRecords();
        if (CollectionUtils.isEmpty(records)){
            return PageDataResult.empty(req.getPageNum(), req.getPageSize());
        }
        //获取车队id
        Set<Long> fleetIdList = records.stream()
                .map(KwfTruckRoute::getFleetId)
                .collect(Collectors.toSet());
        //查询车队信息
        List<KwfFleet> fleets =  fleetRepository.findByfleetIds(fleetIdList);
        //车队id映射车队
        Map<Long, KwfFleet> fleetIdAndFleetMap = fleets.stream().collect(Collectors.toMap(KwfFleet::getId, Function.identity(), (k1, k2) -> k1));
        Set<Long> driveIdList = records.stream()
                .map(KwfTruckRoute::getDriverId)
                .collect(Collectors.toSet());
        //查询司机信息
        List<KwfDriver> drivers = driverRepository.findByDriverIds(driveIdList);
        //司机id映射司机
        Map<Long, KwfDriver> driverIdAndDriverMap = drivers.stream()
                .collect(Collectors.toMap(BaseModel::getId, Function.identity(), (k1, k2) -> k1));
        //组织返回数据
        List<QueryTruckRoteVo> queryTruckRoteVos = records.stream()
                .map(r -> getQueryTruckRoteVo(r, fleetIdAndFleetMap, driverIdAndDriverMap))
                .collect(Collectors.toList());
        return PageDataResult.of(truckRoutePage, queryTruckRoteVos);
    }

    /**
     * 获取车队id
     * @param req 请求参数
     * @return 车队id集合
     */
    private Set<Long> getFleetIds(QueryTruckRoteReq req) {
        if (StringUtils.isBlank(req.getTruckNo())) {
            return Collections.emptySet();
        }
        KwfTruck kwfTruck = truckRepository.queryByTruckNo(req.getTruckNo());
        if (Objects.isNull(kwfTruck)) {
            return Collections.emptySet();
        }
        List<KwfFleetTruck> kwfFleetTrucks = fleetTruckRepository.queryByTruckId(kwfTruck.getId());
        if (CollectionUtils.isEmpty(kwfFleetTrucks)) {
            return Collections.emptySet();
        }
        return kwfFleetTrucks.stream()
                .map(KwfFleetTruck::getFleetId)
                .collect(Collectors.toSet());
    }

    /**
     * 返回司机id
     * @param req 请求参数
     * @return 驾驶员id集合
     */
    private Set<Long> getDriveIds(QueryTruckRoteReq req) {
        if (StringUtils.isBlank(req.getDriverName())) {
            return new HashSet<>();
        }
        //查询司机信息
        List<KwfDriver> drivers = driverRepository.findDriverByName(req.getDriverName());
        if (CollectionUtils.isEmpty(drivers)) {
            return new HashSet<>();
        }
        return drivers.stream()
                .map(BaseModel::getId)
                .collect(Collectors.toSet());
    }

    /**
     * 组织返回参数
     * @param r 路线信息
     * @param fleetIdAndFleetMap 车队id映射车队信息
     * @param driverIdAndDriverMap 驾驶员id映射驾驶员信息
     * @return 查询车辆惯用路线返回参数
     */
    private static QueryTruckRoteVo getQueryTruckRoteVo(KwfTruckRoute r, Map<Long, KwfFleet> fleetIdAndFleetMap, Map<Long, KwfDriver> driverIdAndDriverMap) {
        QueryTruckRoteVo queryTruckRoteVo = new QueryTruckRoteVo();
        queryTruckRoteVo.setId(r.getId());
        queryTruckRoteVo.setTruckNo(r.getTruckNo());
        queryTruckRoteVo.setStartPoint(r.getStartPoint());
        queryTruckRoteVo.setUnloadingPoint(r.getUnloadingPoint());
        queryTruckRoteVo.setFleetId(String.valueOf(r.getFleetId()));
        KwfFleet fleet = fleetIdAndFleetMap.getOrDefault(r.getFleetId(), new KwfFleet());
        queryTruckRoteVo.setFleetName(fleet.getName());
        KwfDriver driver = driverIdAndDriverMap.getOrDefault(r.getDriverId(), new KwfDriver());
        queryTruckRoteVo.setDriverName(driver.getName());
        queryTruckRoteVo.setDriverId(String.valueOf(r.getDriverId()));
        queryTruckRoteVo.setUpdateTime(DateUtils.format(r.getUpdateTime(),DateUtils.DATE_TIME_PATTERN));
        queryTruckRoteVo.setSortedTime(r.getShortestTime());
        return queryTruckRoteVo;
    }

    public Boolean deleteTruckRoute(DeleteTruckRoteReq req) {
        log.info("删除车辆惯用路线，请求参数 :{}", JSON.toJSONString(req));
        return truckRouteRepository.deleteTruckRoute(req.getId());

    }

    public TruckRoteDetailVo truckRouteDetail(@Valid TruckRoteDetailReq req) {
        log.info("查询车辆惯用路线详情，请求参数 :{}", JSON.toJSONString(req));
        KwfTruckRoute kwfTruckRoute = truckRouteRepository.findOneByDriverIdAndPoint(req.getDriverId(),req.getStartPoint(),req.getUnloadingPoint());
        if (Objects.isNull(kwfTruckRoute) || StringUtils.isBlank(kwfTruckRoute.getPointInfo())){
            return new TruckRoteDetailVo();
        }
        String pointInfo = kwfTruckRoute.getPointInfo();
        List<TruckRoteDetailVo.TruckRoteDetail> truckRoteDetails = JSON.parseArray(pointInfo, TruckRoteDetailVo.TruckRoteDetail.class);
        TruckRoteDetailVo truckRoteDetailVo = new TruckRoteDetailVo();
        truckRoteDetailVo.setStartPoint(kwfTruckRoute.getStartPoint());
        truckRoteDetailVo.setUnloadingPoint(kwfTruckRoute.getUnloadingPoint());
        truckRoteDetailVo.setTruckRoteDetails(truckRoteDetails);
        return truckRoteDetailVo;
    }

    /**
     * 根据司机ID和装货卸货地址查询常用路线
     * @param req 请求参数
     * @return 常用路线信息
     */
    public QueryTruckRoteVo queryTruckRouteByDriver(QueryTruckRouteByDriverReq req) {
        log.info("根据司机ID和装货卸货地址查询常用路线，请求参数 :{}", JSON.toJSONString(req));
        // 查询常用路线
        RWaybillOrderVo waybillOrderSubtaskVo = transportRemoteService.queryWaybillOrderByWayBillOrderId(req.getWayBillOrderId());
        // 根据运单号查询运单信息
        if (Objects.isNull(waybillOrderSubtaskVo)){
            throw new BusinessException("运单不存在");
        }
        if (StringUtils.isBlank(waybillOrderSubtaskVo.getTruckId())){
            log.info("车辆不存在,运单id：{}", waybillOrderSubtaskVo.getId());
            throw new BusinessException("车辆不存在");
        }
        String startLng= waybillOrderSubtaskVo.getStartLng();
        String startLat= waybillOrderSubtaskVo.getStartLat();
        String endLng =  waybillOrderSubtaskVo.getEndLng();
        String endLat = waybillOrderSubtaskVo.getEndLat();
        VehicleReturnData vehicleReturnData = getVehicleReturnData(String.valueOf(waybillOrderSubtaskVo.getTruckId()));
        if (Objects.nonNull(vehicleReturnData) && org.apache.commons.lang3.StringUtils.isNotBlank(vehicleReturnData.getLongitude()) && org.apache.commons.lang3.StringUtils.isNotBlank(vehicleReturnData.getLatitude())){
            startLat= vehicleReturnData.getLatitude();
            endLng =  vehicleReturnData.getLongitude();
        }
        LocUtils.RouteResult routeResult = generateRoutePointsWithDuration(startLng, startLat, endLng, endLat);
        // 如果生成了轨迹点，更新到数据库的point_info字段
        if (routeResult == null || StringUtils.isBlank(routeResult.getPointInfo())) {
            return new QueryTruckRoteVo();
        }
        List<LocUtils.RoutePoint> routePoints = JSON.parseArray(routeResult.getPointInfo(), LocUtils.RoutePoint.class);
        if (CollectionUtils.isEmpty(routePoints)) {
            return new QueryTruckRoteVo();
        }
        List<QueryTruckRoteVo.TruckRoteDetail> details = routePoints.stream().map(x -> {
            QueryTruckRoteVo.TruckRoteDetail truckRoteDetail = new QueryTruckRoteVo.TruckRoteDetail();
            truckRoteDetail.setTs(x.getTs());
            truckRoteDetail.setLongitude(x.getLongitude());
            truckRoteDetail.setLatitude(x.getLatitude());
            return truckRoteDetail;
        }).collect(Collectors.toList());
        // 组装返回数据
        QueryTruckRoteVo vo = new QueryTruckRoteVo();
        vo.setDriverName(waybillOrderSubtaskVo.getDriverName());
        vo.setDriverId(String.valueOf(waybillOrderSubtaskVo.getDriverId()));
        vo.setTruckId(String.valueOf(waybillOrderSubtaskVo.getTruckId()));
        vo.setTruckNo(waybillOrderSubtaskVo.getTruckNo());
        vo.setTruckRoteDetails(details);
        return vo;
    }

    public VehicleReturnData getVehicleReturnData(String truckId) {
        VehicleDataDTO vehicleDataDTO = new VehicleDataDTO();
        vehicleDataDTO.setCarNo(truckId);

        try {
            // 使用 Feign 调用查询实时位置
            BaseIotResult<VehicleReturnData> result = vehicleTraceClient.queryRealTimeLocation(vehicleDataDTO);
            log.info("查询实时轨迹返回数据: {}", JSON.toJSONString( result));
            if (result == null || !Objects.equals(result.getCode(), "0") || result.getData() == null) {
                log.warn("查询实时轨迹返回空数据, 车牌号: {}", truckId);
                return null;
            }

            return result.getData();
        } catch (Exception e) {
            log.error("查询任务轨迹异常, 车牌号: {}", truckId, e);
            return null;
        }
    }
    private LocUtils.RouteResult generateRoutePointsWithDuration(String startLng, String startLat, String endLng, String endLat) {
        try {
            log.info("开始调用高德API生成轨迹点位和耗时，起点: {},{} 终点: {},{}",
                    startLng, startLat, endLng, endLat);

            // 调用高德驾车路径规划API，生成20个轨迹点位和耗时
            LocUtils.RouteResult routeResult = com.sckw.core.utils.LocUtils.getDrivingRoutePointsWithDuration(
                    startLng,
                    startLat,
                    endLng,
                    endLat,
                    20,
                    null
            );

            if (routeResult != null && com.sckw.core.utils.StringUtils.isNotBlank(routeResult.getPointInfo())) {
                log.info("高德API生成轨迹点位成功，耗时: {}秒", routeResult.getDuration());
            } else {
                log.warn("高德API生成轨迹点位失败或返回空数据");
            }

            return routeResult;
        } catch (Exception e) {
            log.error("调用高德API生成轨迹点位异常", e);
            return null;
        }
    }
    private void saveTruckRote(QueryTruckRouteByDriverReq req,String startLng,String startLat,String endLng,String endLat) {
        RWaybillOrderVo rWaybillOrderVo = transportRemoteService.queryWaybillOrderByWayBillOrderId(req.getWayBillOrderId());
        KwfFleetTruck kwfFleetTruck = fleetTruckRepository.findFleetByTruckId(rWaybillOrderVo.getTruckId());
        // 在查询惯用路线之前，调用高德API生成装货地址和卸货地址之间的20个轨迹点位
        LocUtils.RouteResult routeResult = generateRoutePointsWithDuration(startLng, startLat, endLng, endLat);
        KwfTruckRoute kwfTruckRoute = new KwfTruckRoute();
        kwfTruckRoute.setFleetId(Optional.ofNullable(kwfFleetTruck).map(KwfFleetTruck::getFleetId).orElse(0L));
        kwfTruckRoute.setDriverId(req.getDriverId());
        kwfTruckRoute.setEntId(LoginUserHolder.getEntId());
        kwfTruckRoute.setStartPoint(req.getStartPoint());
        kwfTruckRoute.setUnloadingPoint(req.getUnloadingPoint());
        kwfTruckRoute.setLoadLng(startLng);
        kwfTruckRoute.setLoadLat(startLat);
        kwfTruckRoute.setUnloadLng(endLng);
        kwfTruckRoute.setUnloadLat(endLat);
        // 设置装货点和卸货点的耗时时间（单位：秒）
        if (routeResult != null && StringUtils.isNotBlank(routeResult.getDuration())) {
            kwfTruckRoute.setShortestTime(routeResult.getDuration());
        }
        // 如果生成了轨迹点，更新到数据库的point_info字段
        if (routeResult != null && StringUtils.isNotBlank(routeResult.getPointInfo())) {
            List<LocUtils.RoutePoint> routePoints = JSON.parseArray(routeResult.getPointInfo(), LocUtils.RoutePoint.class);
            if (CollectionUtils.isNotEmpty(routePoints)) {
                List<QueryTruckRoteVo.TruckRoteDetail> details = routePoints.stream().map(x -> {
                    QueryTruckRoteVo.TruckRoteDetail truckRoteDetail = new QueryTruckRoteVo.TruckRoteDetail();
                    truckRoteDetail.setTs(x.getTs());
                    truckRoteDetail.setLongitude(x.getLongitude());
                    truckRoteDetail.setLatitude(x.getLatitude());
                    return truckRoteDetail;
                }).collect(Collectors.toList());
                kwfTruckRoute.setPointInfo(JSON.toJSONString(details));
            }
            kwfTruckRoute.setTruckNo(rWaybillOrderVo.getTruckNo());
            kwfTruckRoute.setTruckId(rWaybillOrderVo.getTruckId());
            truckRouteRepository.save(kwfTruckRoute);
        }
    }
        /**
         * 调用高德API生成装货地址和卸货地址之间的20个轨迹点位信息和耗时
         * @param req 请求参数
         * @return 轨迹点位和耗时信息
         */
        private LocUtils.RouteResult generateRoutePointsWithDuration (RWaybillOrderVo req){
            try {
                log.info("开始调用高德API生成轨迹点位和耗时，起点: {},{} 终点: {},{}",
                        req.getStartLng(), req.getStartLat(), req.getEndLng(), req.getEndLat());

                // 调用高德驾车路径规划API，生成20个轨迹点位和耗时
                LocUtils.RouteResult routeResult = com.sckw.core.utils.LocUtils.getDrivingRoutePointsWithDuration(
                        req.getStartLng(),
                        req.getStartLat(),
                        req.getEndLng(),
                        req.getEndLat(),
                        20,
                         null
                );

                if (routeResult != null && StringUtils.isNotBlank(routeResult.getPointInfo())) {
                    log.info("高德API生成轨迹点位成功，耗时: {}秒", routeResult.getDuration());
                } else {
                    log.warn("高德API生成轨迹点位失败或返回空数据");
                }

                return routeResult;
            } catch (Exception e) {
                log.error("调用高德API生成轨迹点位异常", e);
                return null;
            }
        }

}
