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

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.exceptions.ExceptionUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Lists;
import com.prolog.common.util.ToolKits;
import com.prolog.framework.common.message.RestMessage;
import com.prolog.rdc.tms.constant.DataDictionaryConstant;
import com.prolog.rdc.tms.constant.SeriaNnumberConstant;
import com.prolog.rdc.tms.dao.mapper.ShipbillRouteDataMapper;
import com.prolog.rdc.tms.model.ShipbillRouteDataModel;
import com.prolog.rdc.tms.model.dto.AMapParseDistrictsDTO;
import com.prolog.rdc.tms.model.dto.AMapParseStepsDTO;
import com.prolog.rdc.tms.model.vo.AMapVO;
import com.prolog.rdc.tms.rmi.feign.MaindataFeign;
import com.prolog.rdc.tms.service.AMapService;
import com.prolog.rdc.tms.service.KD100Service;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.Consts;
import org.apache.http.NameValuePair;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import org.apache.ibatis.plugin.PluginException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

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

/**
 * 地图接口调用实现层
 *
 * @author :fanzw
 * @version :1.0.0
 * @className :KD100ServiceImpl
 * @creationTime :2022/11/28
 * @description :
 * @modifier :fanzw
 * @modifyTime :2022/11/28
 * @reviseRemarks:
 */
@Slf4j
@Service
public class AMapServiceImpl implements AMapService {

    @Value("${prolog.amap.key:2c39c21d367ba0c19a984b148c6cfa32}")
    private String gaoDeMapKey;

    @Value("${prolog.amap.url:https://restapi.amap.com/v5/direction/driving}")
    private String aMap_url;

    @Autowired
    private ShipbillRouteDataMapper shipbillRouteDataMapper;

    @Autowired
    private MaindataFeign maindataTmsResource;

    @Autowired
    private KD100Service kd100Service;

    public void getDrivingRouting(List<AMapVO> vos) {

        List<ShipbillRouteDataModel> routeDataModels = Lists.newArrayList();
        for (AMapVO data : vos) {
            List<AMapParseStepsDTO> routingList = null;
            try {
                routingList = getRouting(data);
                if (ToolKits.isEmpty(routingList)) {
                    log.info("三方物流单{}没有获取路径规则", data.getExpressNumber());
                    continue;
                }
            } catch (Exception e) {
                throw new PluginException(StrUtil.format("三方物流单{}获取路径规则异常{}", data.getExpressNumber(),e.getMessage()));
            }
            Date departureTime = data.getDepartureTime();
            for (AMapParseStepsDTO routingData : routingList) {
                ShipbillRouteDataModel routeDataModel = new ShipbillRouteDataModel();
                RestMessage<String> restMessageDetailId = maindataTmsResource.getCodeNumberByCode(SeriaNnumberConstant.SHIPBILL_ROUTE_DATA_ID, "L");
                if (!restMessageDetailId.isSuccess()) {
                    throw new PluginException(StrUtil.format("快递单{}获取运单路由表ID失败", data.getExpressNumber()));
                }
                String id = restMessageDetailId.getData();
                routeDataModel.setId(id);
                String city = routingData.getCities().get(0).getCity();
                String districts = routingData.getCities().get(0).getDistricts().stream().map(AMapParseDistrictsDTO::getName).collect(Collectors.joining(","));
                routeDataModel.setAreaName(city + districts);
                routeDataModel.setCarriersCode(data.getCarriersCode());
                routeDataModel.setExpressNumber(data.getExpressNumber());
                routeDataModel.setCarriersType(2);
                String cost = routingData.getCost().get(0).getDuration();
                if (ToolKits.isNotEmpty(cost)) {
                    Date routeDate = DateUtil.offsetSecond(departureTime, Integer.valueOf(cost));
                    routeDataModel.setRouteDate(DateUtil.format(routeDate, "yyyy-MM-dd HH:mm:ss"));
                    routeDataModel.setRouteTime(routeDate);
                } else {
                    routeDataModel.setRouteDate(DateUtil.format(departureTime, "yyyy-MM-dd HH:mm:ss"));
                    routeDataModel.setRouteTime(departureTime);
                }
                routeDataModel.setRouteContext(routingData.getInstruction());
                String areaCenter = routingData.getPolyline();
                if (ToolKits.isNotEmpty(areaCenter)) {
                    String[] areas = areaCenter.split(";");
                    String[] subAreas = areas[0].split(",");
                    if (subAreas.length == 2) {
                        routeDataModel.setLongitude(subAreas[0]);
                        routeDataModel.setLatitude(subAreas[1]);
                    } else {
                        continue;
                    }
                }
                routeDataModel.setCreatetime(DateUtil.date());
                routeDataModels.add(routeDataModel);
                departureTime = DateUtil.parse(routeDataModel.getRouteDate());
            }
            departureTime = null;
        }
        if (ToolKits.isNotEmpty(routeDataModels)) {
            shipbillRouteDataMapper.saveBatch(routeDataModels);
            kd100Service.saveGps(routeDataModels, DataDictionaryConstant.WHETHER_YES.toString());
        }
    }

    private List<AMapParseStepsDTO> getRouting(AMapVO data) throws Exception {

        CloseableHttpResponse response = null;
        try (CloseableHttpClient httpClient = HttpClientBuilder.create().build()) {
            List<NameValuePair> params = Lists.newArrayList();
            params.add(new BasicNameValuePair("key", gaoDeMapKey));
            params.add(new BasicNameValuePair("origin", StrUtil.format("{},{}", String.valueOf(data.getShipperLongitude()), String.valueOf(data.getShipperLatitude()))));
            params.add(new BasicNameValuePair("destination", StrUtil.format("{},{}", String.valueOf(data.getConsigneeLongitude()), String.valueOf(data.getConsigneeLatitude()))));
            params.add(new BasicNameValuePair("strategy", "2"));
            params.add(new BasicNameValuePair("show_fields", "cost,cities,polyline"));
            log.info("获取规划路径入参:{}",JSONObject.toJSONString(params));
            String uri = EntityUtils.toString(new UrlEncodedFormEntity(params, Consts.UTF_8));
            HttpGet request = new HttpGet(aMap_url + "?" + uri);
            response = httpClient.execute(request);
            String resultJson = EntityUtils.toString(response.getEntity());
            log.info("获取规划路径出参:{}",JSONObject.toJSONString(params));
            JSONObject jsonObject = JSONObject.parseObject(resultJson);
            JSONObject jsonObject1 = JSONObject.parseObject(jsonObject.getJSONObject("route").getJSONArray("paths").get(0).toString());
            List<AMapParseStepsDTO> dtos = jsonObject1.getJSONArray("steps").stream().map(obj -> {
                AMapParseStepsDTO dto = BeanUtil.copyProperties(obj, AMapParseStepsDTO.class);
                return dto;
            }).collect(Collectors.toList());
            dtos = dtos.stream().filter(dto -> NumberUtil.isGreater(BigDecimal.valueOf(Long.valueOf(dto.getStep_distance())), BigDecimal.valueOf(5000))).collect(Collectors.toList());
            return dtos;
        } catch (Exception e) {
            log.info("获取高德路径异常:{}",ExceptionUtil.stacktraceToString(e));
            throw new PluginException(ExceptionUtil.stacktraceToString(e));
        } finally {
            if (null != response) {
                response.close();
            }
        }
    }
}
