package com.sckw.core.utils;

import java.io.IOException;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.sckw.core.model.constant.Global;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;

@Slf4j
public class LocUtils {

    static String GD_KEY = "739ace2ede6fe1e2f4ae3bcba890833c";

    /**
     * @param lng 经度
     * @param lat 纬度
     * @desc 通过gps查询位置信息-高德
     * @author zk
     * @date 2023/10/7
     **/
    public static String regeo(String lng, String lat) {
        if (StringUtils.isBlank(lng) || StringUtils.isBlank(lat)) {
            return null;
        }
        StringBuilder requestUrl = new StringBuilder();
        requestUrl.append("https://restapi.amap.com/v3/geocode/regeo?output=json&location="+ lng + Global.COMMA + lat);
        requestUrl.append("&key="+GD_KEY);
        requestUrl.append("&radius=1000&extensions=base");

        try {
            HttpClient httpClient = HttpClients.createDefault();
            HttpGet httpGet = new HttpGet(requestUrl.toString());
            HttpResponse response = httpClient.execute(httpGet);
            HttpEntity entity = response.getEntity();
            String responseStr = EntityUtils.toString(entity, "UTF-8");
            JSONObject resultJson = responseStr != null ? JSON.parseObject(responseStr) : null;
            Integer status = resultJson != null ? resultJson.getInteger("status") : null;
            if (status != null && status == Global.NUMERICAL_ONE) {
                JSONObject regeocode = resultJson.getJSONObject("regeocode");
                return regeocode != null ? regeocode.getString("formatted_address") : null;
            }

            return null;
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }


    /**
     * 调用高德驾车路径规划API，获取路径上均匀分布的轨迹点位以及耗时信息
     *
     * @param startLng    起点经度
     * @param startLat    起点纬度
     * @param endLng      终点经度
     * @param endLat      终点纬度
     * @param pointCount  需要生成的轨迹点数量
     * @return 包含轨迹点位和耗时的结果对象
     */
    public static RouteResult getDrivingRoutePointsWithDuration(String startLng, String startLat,
                                                                String endLng, String endLat, int pointCount,
                                                                LocalDate date) {
        if (StringUtils.isBlank(startLng) || StringUtils.isBlank(startLat) 
                || StringUtils.isBlank(endLng) || StringUtils.isBlank(endLat)) {
            return null;
        }
        
        // 构建高德驾车路径规划API请求
        StringBuilder requestUrl = new StringBuilder();
        requestUrl.append("https://restapi.amap.com/v3/direction/driving?");
        requestUrl.append("origin=").append(startLng).append(",").append(startLat);
        requestUrl.append("&destination=").append(endLng).append(",").append(endLat);
        requestUrl.append("&extensions=all&output=json");
        requestUrl.append("&key=").append(GD_KEY);

        try {
            HttpClient httpClient = HttpClients.createDefault();
            HttpGet httpGet = new HttpGet(requestUrl.toString());
            HttpResponse response = httpClient.execute(httpGet);
            HttpEntity entity = response.getEntity();
            String responseStr = EntityUtils.toString(entity, "UTF-8");
            
            log.info("高德驾车路径规划API响应: {}", responseStr);
            
            JSONObject resultJson = responseStr != null ? JSON.parseObject(responseStr) : null;
            if (resultJson == null || !"1".equals(resultJson.getString("status"))) {
                log.warn("高德API调用失败");
                return null;
            }
            
            // 解析耗时信息（单位：秒）
            String duration = parseDuration(resultJson);
            
            // 解析路径点位
            List<RoutePoint> allPoints = parseRoutePoints(resultJson);
            if (allPoints.isEmpty()) {
                return null;
            }
            
            // 从所有点位中均匀选取指定数量的点
            //List<RoutePoint> selectedPoints = selectUniformPoints(allPoints, pointCount);
            LocalDateTime now = LocalDateTime.now();
            if (Objects.nonNull( date)){
                now = date.atTime(LocalTime.now());
            }

            for (int i = 0; i < allPoints.size(); i++) {
                RoutePoint point = allPoints.get(i);
                point.setTs(now.plusMinutes(i * 5L));
               // selectedPoints.add(point);
            }

            RouteResult result = new RouteResult();
            result.setPointInfo(JSON.toJSONString(allPoints));
            result.setDuration(duration);
            
            return result;
        } catch (Exception e) {
            log.error("调用高德驾车路径规划API异常", e);
        }
        return null;
    }

    /**
     * 使用高德API计算两点之间的距离（驾车距离）
     *
     * @param startLng    起点经度
     * @param startLat    起点纬度
     * @param endLng      终点经度
     * @param endLat      终点纬度
     * @return 距离（千米），如果计算失败返回-1
     */
    public static double calculateDistanceByAmap(String startLng, String startLat, String endLng, String endLat) {
        log.info("开始调用高德API计算两点之间的距离，起点: {},{} 终点: {},{}",startLat, startLng, endLat, endLng);
        if (org.apache.commons.lang3.StringUtils.isAnyBlank(startLng, startLat, endLng, endLat)){
            log.warn("高德API计算距离参数不完整");
            return -1;
        }
        
        // 构建高德驾车路径规划API请求
        StringBuilder requestUrl = new StringBuilder();
        requestUrl.append("https://restapi.amap.com/v3/direction/driving?");
        requestUrl.append("origin=").append(startLng).append(",").append(startLat);
        requestUrl.append("&destination=").append(endLng).append(",").append(endLat);
        requestUrl.append("&extensions=base&output=json");
        requestUrl.append("&key=").append(GD_KEY);

        try {
            HttpClient httpClient = HttpClients.createDefault();
            HttpGet httpGet = new HttpGet(requestUrl.toString());
            HttpResponse response = httpClient.execute(httpGet);
            HttpEntity entity = response.getEntity();
            String responseStr = EntityUtils.toString(entity, "UTF-8");
            
            log.info("高德驾车路径规划API计算距离响应: {}", responseStr);
            
            JSONObject resultJson = responseStr != null ? JSON.parseObject(responseStr) : null;
            if (resultJson == null || !"1".equals(resultJson.getString("status"))) {
                log.warn("高德API计算距离调用失败");
                return -1;
            }
            
            // 解析距离信息（单位：米）
            Double distance = parseDistance(resultJson);
            if (distance != null) {
                // 将米转换为千米并保留2位小数
                return new BigDecimal(distance / 1000)
                        .setScale(2, RoundingMode.HALF_UP)
                        .doubleValue();
            }
            
            return -1;
        } catch (Exception e) {
            log.error("调用高德API计算距离异常", e);
            return -1;
        }
    }

    /**
     * 解析高德API返回的路径距离（单位：米）
     */
    private static Double parseDistance(JSONObject resultJson) {
        try {
            JSONObject route = resultJson.getJSONObject("route");
            if (route == null) return null;
            
            JSONArray paths = route.getJSONArray("paths");
            if (paths == null || paths.isEmpty()) return null;
            
            JSONObject path = paths.getJSONObject(0);
            // distance字段表示距离，单位：米
            String distanceStr = path.getString("distance");
            return Double.parseDouble(distanceStr);
        } catch (Exception e) {
            log.error("解析路径距离异常", e);
            return null;
        }
    }

    /**
     * 解析高德API返回的路径耗时（单位：秒）
     */
    private static String parseDuration(JSONObject resultJson) {
        try {
            JSONObject route = resultJson.getJSONObject("route");
            if (route == null) return null;
            
            JSONArray paths = route.getJSONArray("paths");
            if (paths == null || paths.isEmpty()) return null;
            
            JSONObject path = paths.getJSONObject(0);
            // duration字段表示预计行驶时间，单位：秒
            return path.getString("duration");
        } catch (Exception e) {
            log.error("解析路径耗时异常", e);
            return null;
        }
    }

    /**
     * 解析高德路径规划返回的所有路径点位
     */
    private static List<RoutePoint> parseRoutePoints(JSONObject resultJson) {
        List<RoutePoint> allPoints = new ArrayList<>();
        
        try {
            JSONObject route = resultJson.getJSONObject("route");
            if (route == null) return allPoints;
            
            JSONArray paths = route.getJSONArray("paths");
            if (paths == null || paths.isEmpty()) return allPoints;
            
            JSONObject path = paths.getJSONObject(0);
            JSONArray steps = path.getJSONArray("steps");
            if (steps == null || steps.isEmpty()) return allPoints;
            
            for (int i = 0; i < steps.size(); i++) {
                JSONObject step = steps.getJSONObject(i);
                String polyline = step.getString("polyline");
                if (StringUtils.isNotBlank(polyline)) {
                    String[] pointStrs = polyline.split(";");
                    for (String pointStr : pointStrs) {
                        String[] coords = pointStr.split(",");
                        if (coords.length == 2) {
                            RoutePoint point = new RoutePoint();
                            point.setLongitude(coords[0]);
                            point.setLatitude(coords[1]);
                            allPoints.add(point);
                        }
                    }
                }
            }
        } catch (Exception e) {
            log.error("解析高德路径点位异常", e);
        }
        
        return allPoints;
    }

    /**
     * 从所有点位中均匀选取指定数量的点
     */
    private static List<RoutePoint> selectUniformPoints(List<RoutePoint> allPoints, int pointCount) {
        List<RoutePoint> selectedPoints = new ArrayList<>();
        
        if (allPoints.isEmpty()) {
            return selectedPoints;
        }
        
        if (allPoints.size() <= pointCount) {
            LocalDateTime now = LocalDateTime.now();
            for (int i = 0; i < allPoints.size(); i++) {
                RoutePoint point = allPoints.get(i);
                point.setTs(now.plusMinutes(i * 5L));
                selectedPoints.add(point);
            }
            return selectedPoints;
        }
        
        double interval = (double) (allPoints.size() - 1) / (pointCount - 1);
        LocalDateTime now = LocalDateTime.now();
        
        for (int i = 0; i < pointCount; i++) {
            int index = (int) Math.round(i * interval);
            if (index >= allPoints.size()) index = allPoints.size() - 1;
            RoutePoint point = allPoints.get(index);
            point.setTs(now.plusMinutes(i * 5L));
            selectedPoints.add(point);
        }
        
        return selectedPoints;
    }

    /**
     * 路径点位信息
     */
    @Data
    public static class RoutePoint {
        private LocalDateTime ts;
        private String longitude;
        private String latitude;
    }

    /**
     * 路径结果信息（包含轨迹点位和耗时）
     */
    @Data
    public static class RouteResult {
        /** 轨迹点位JSON字符串 */
        private String pointInfo;
        /** 预计耗时（单位：秒） */
        private String duration;
    }

    public static void main(String[] args) {
        String res = regeo("118.879289", "38.052237");
        System.out.println(res);
    }
}