package com.fuyuanshen.equipment.utils.map;

import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.*;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.util.UriComponentsBuilder;

import java.net.URI;
import java.util.HashMap;
import java.util.Map;
import java.util.function.Consumer;

/**
 * 高德猎鹰轨迹服务 工具类
 * <p>
 * 优化点：
 * 1. 引入 Slf4j 增加日志记录
 * 2. 使用 UriComponentsBuilder 处理 URL 拼接和参数编码
 * 3. 统一异常处理和请求封装
 * 4. 提取常量
 * </p>
 * 官网文档：https://lbs.amap.com/api/track
 */
@Slf4j
@Component
public class AmapTrackUtil {

    private static final String BASE_URL = "https://tsapi.amap.com/v1/track";

//    @Value("${gaode.key:}")
    private final String key = "84a12a692ae378effdf741e16d584cd3";


    /* ========================== 1. 轨迹服务 ========================== */

    /** 创建服务 */
    public JSONObject createService(String name) {
        return sendRequest(HttpMethod.POST, "/service/add", builder -> builder.queryParam("name", name), null);
    }

    /** 更新服务 */
    public JSONObject updateService(String sid, String name) {
        return sendRequest(HttpMethod.POST, "/service/update",
                builder -> builder.queryParam("sid", sid).queryParam("name", name), null);
    }

    /** 查询服务列表 */
    public JSONObject listService() {
        return sendRequest(HttpMethod.GET, "/service/list", null, null);
    }

    /** 删除服务 */
    public JSONObject deleteService(String sid) {
        return sendRequest(HttpMethod.POST, "/service/delete", builder -> builder.queryParam("sid", sid), null);
    }

    /* ========================== 2. 终端 ========================== */

    /** 创建终端 */
    public JSONObject createTerminal(Long sid, String name) {
        return sendRequest(HttpMethod.POST, "/terminal/add",
                builder -> builder.queryParam("sid", sid).queryParam("name", name), null);
    }

    /** 查询终端列表 */
    public JSONObject listTerminal(Long sid, Long tid, String name, int page) {
        return sendRequest(HttpMethod.GET, "/terminal/list",
                builder -> {
                    builder.queryParam("sid", sid).queryParam("page", page);
                    if (StrUtil.isNotBlank(name)) {
                        builder.queryParam("name", name);
                    }
                    if (tid != null) {
                        builder.queryParam("tid", tid);
                    }
                }, null);
    }

    /** 查询终端列表 */
    public JSONObject searchTerminal(Long sid, String keywords, int page, int pageSize) {
        return sendRequest(HttpMethod.GET, "/terminal/list",
                builder -> builder.queryParam("sid", sid).queryParam("keywords", keywords).queryParam("page", page).queryParam("pageSize", pageSize), null);
    }

    /** 删除终端 */
    public JSONObject deleteTerminal(Long sid, Long tid) {
        return sendRequest(HttpMethod.POST, "/terminal/delete",
                builder -> builder.queryParam("sid", sid).queryParam("tid", tid), null);
    }

    /* ========================== 3. 轨迹 ========================== */

    /** 创建轨迹 */
    public JSONObject createTrace(Long sid, Long tid) {
        return sendRequest(HttpMethod.POST, "/trace/add",
                builder -> builder.queryParam("sid", sid).queryParam("tid", tid), null);
    }

    /** 查询轨迹（按 trid） */
    public JSONObject queryTrace(String sid, String tid, String trid) {
        return sendRequest(HttpMethod.GET, "/terminal/trsearch",
                builder -> builder.queryParam("sid", sid).queryParam("tid", tid).queryParam("trid", trid), null);
    }

    /** 查询轨迹（按时间段） */
    public JSONObject queryTrace(String sid, String tid, long start, long end) {
        return sendRequest(HttpMethod.GET, "/terminal/trsearch",
                builder -> builder.queryParam("sid", sid)
                        .queryParam("tid", tid)
                        .queryParam("starttime", start)
                        .queryParam("endtime", end), null);
    }

    /** 删除轨迹 */
    public JSONObject deleteTrace(Long sid, Long tid, Long trid) {
        return sendRequest(HttpMethod.POST, "/trace/delete",
                builder -> builder.queryParam("sid", sid).queryParam("tid", tid).queryParam("trid", trid), null);
    }

    /* ========================== 4. 轨迹点上传 ========================== */

    /**
     * 单点/批量上传轨迹点
     * 注意：上传点的参数较多，且位于 Body 中
     */
    public JSONObject uploadPoints(Long sid, Long tid, Long trid, Object points) {
        Map<String, Object> bodyMap = new HashMap<>();
        bodyMap.put("sid", sid);
        bodyMap.put("tid", tid);
        bodyMap.put("trid", trid);
        bodyMap.put("points", points);
        return sendRequest(HttpMethod.POST, "/point/upload", null, bodyMap);
    }

    /* ========================== 5. 围栏 ========================== */

    /** 创建圆形围栏 */
    public JSONObject createCircleFence(String name, String center, int radius, String sid, String... tids) {
        return sendRequest(HttpMethod.POST, "/geofence/add/circle", builder -> {
            builder.queryParam("name", name)
                    .queryParam("center", center)
                    .queryParam("radius", radius)
                    .queryParam("sid", sid);
            if (tids != null && tids.length > 0) {
                builder.queryParam("tids", String.join(",", tids));
            }
        }, null);
    }

    /** 创建多边形围栏 */
    public JSONObject createPolygonFence(String name, String points, String sid, String... tids) {
        return sendRequest(HttpMethod.POST, "/geofence/add/polygon", builder -> {
            builder.queryParam("name", name)
                    .queryParam("points", points)
                    .queryParam("sid", sid);
            if (tids != null && tids.length > 0) {
                builder.queryParam("tids", String.join(",", tids));
            }
        }, null);
    }

    /** 绑定/解绑终端到围栏 */
    public JSONObject bindTerminalToFence(String sid, String gfid, String... tids) {
        return sendRequest(HttpMethod.POST, "/geofence/terminal/bind",
                builder -> builder.queryParam("sid", sid)
                        .queryParam("gfid", gfid)
                        .queryParam("tids", String.join(",", tids))
                        .queryParam("enable", "1"), null);
    }

    /** 查询终端与围栏当前状态（在/不在） */
    public JSONObject queryTerminalFenceStatus(Long sid, String gfids, Long tid) {
        return sendRequest(HttpMethod.GET, "/geofence/status/terminal",
                builder -> {
                    builder.queryParam("sid", sid)
                            .queryParam("tid", tid);
                    if (gfids != null) {
                        builder.queryParam("gfids", gfids);
                    }
                }, null);
    }

    /** 删除围栏 */
    public JSONObject deleteFence(String sid, String gfid) {
        return sendRequest(HttpMethod.POST, "/geofence/delete",
                builder -> builder.queryParam("sid", sid).queryParam("gfid", gfid), null);
    }

    /* ========================== 6. 轨迹纠偏&里程 ========================== */

    /** 轨迹纠偏（驾车） */
    public JSONObject correctDriving(String sid, String tid, String trid, int gap, int angle, int speed, int accuracy) {
        return sendRequest(HttpMethod.POST, "/terminal/correct",
                builder -> builder.queryParam("sid", sid)
                        .queryParam("tid", tid)
                        .queryParam("trid", trid)
                        .queryParam("gap", gap)
                        .queryParam("angle", angle)
                        .queryParam("speed", speed)
                        .queryParam("accuracy", accuracy), null);
    }

    /** 计算轨迹里程 */
    public JSONObject calDistance(String sid, String tid, String trid) {
        return sendRequest(HttpMethod.GET, "/terminal/distance",
                builder -> builder.queryParam("sid", sid).queryParam("tid", tid).queryParam("trid", trid), null);
    }

    /* ========================== 7. 空间检索 ========================== */

    /** 圆形范围内终端检索 */
    public JSONObject searchTerminalInCircle(String sid, String center, int radius) {
        return sendRequest(HttpMethod.GET, "/terminal/aroundsearch",
                builder -> builder.queryParam("sid", sid).queryParam("center", center).queryParam("radius", radius), null);
    }

    /* ========================== 核心请求封装 ========================== */

    /**
     * 统一请求处理方法
     *
     * @param method         HTTP方法
     * @param path           API路径
     * @param paramsConsumer URL参数构建器
     * @param body           Body参数 (POST JSON时使用)
     * @return 响应JSONObject
     */
    private JSONObject sendRequest(HttpMethod method, String path,
                                   Consumer<UriComponentsBuilder> paramsConsumer,
                                   Object body) {
        try {
            UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl(BASE_URL + path)
                    .queryParam("key", key);
            if (paramsConsumer != null) paramsConsumer.accept(builder);
            String url = builder.build().encode().toString();

            String result;
            if (body == null) {
                result = method == HttpMethod.GET ?
                        HttpUtil.get(url) : HttpUtil.post(url, "");
            } else {
                String json = JSONUtil.toJsonStr(body);
                result = HttpUtil.post(url, json);
            }

            log.info("Gaode Track Request: {} {}", method, url);

            if (StrUtil.isNotBlank(result)) {
                JSONObject json = JSONUtil.parseObj(result);
                if (json.getInt("errcode", -1) != 10000) {
                    log.warn("高德轨迹服务错误: {}", json);
                }
                return json;
            } else {
                return createErrorJson(-1, "empty response");
            }
        } catch (Exception e) {
            log.error("高德轨迹服务异常", e);
            return createErrorJson(-1, e.getMessage());
        }
    }

    private JSONObject createErrorJson(int code, String msg) {
        JSONObject err = new JSONObject();
        err.set("errcode", code);
        err.set("errmsg", msg);
        return err;
    }
}