package com.ltgk.boat.utils;


import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.geotools.geojson.geom.GeometryJSON;
import org.locationtech.jts.geom.*;

import java.io.File;
import java.io.IOException;

/**
 * GeoJSON 文件解析工具类
 *
 * @author Qi ChengBin
 * @date 2025/05/26
 */
@Slf4j
public class GeoJsonLandChecker {

    private final GeometryFactory geometryFactory = new GeometryFactory(new PrecisionModel(), 4326);

    private Geometry landGeometry = null;

    public GeoJsonLandChecker(String geoJsonPath) {
        try {
            // 创建ObjectMapper对象
            ObjectMapper objectMapper = new ObjectMapper();

            // 解析JSON字符串为JsonNode对象
            JsonNode rootNode = objectMapper.readTree(new File(geoJsonPath));

            // 获取 features 数组中的第一个元素
            JsonNode featuresNode = rootNode.path("features").get(0);

            // 获取 geometry 对象
            JsonNode coordinatesNode = featuresNode.path("geometry");

            // 使用GeometryJSON解析GeoJSON
            GeometryJSON geometryJSON = new GeometryJSON();
            Geometry geometry = geometryJSON.read(coordinatesNode.toString());

            // 转换为二维几何图形 修复拓扑问题
            this.landGeometry = flattenTo2D(geometry).buffer(0);

        } catch (IOException e) {
            log.error("解析GeoJSON文件出错: {}", String.valueOf(e));
        }
    }

    /**
     * 将任意维度几何体转换为纯二维
     */
    private Geometry flattenTo2D(Geometry geometry) {
        if (geometry instanceof Polygon) {
            return rebuildPolygon((Polygon) geometry);
        } else if (geometry instanceof MultiPolygon) {
            return rebuildMultiPolygon((MultiPolygon) geometry);
        } else if (geometry instanceof GeometryCollection) {
            // 新增处理 GeometryCollection
            int numGeometries = geometry.getNumGeometries();
            Geometry[] flattened = new Geometry[numGeometries];
            for (int i = 0; i < numGeometries; i++) {
                flattened[i] = flattenTo2D(geometry.getGeometryN(i));
            }
            return geometryFactory.createGeometryCollection(flattened);
        }
        // 其他类型直接返回（如 Point、LineString 等）
        return geometry;
    }

    private Polygon rebuildPolygon(Polygon poly) {
        // 使用已剥离 Z 值的坐标
        Coordinate[] shellCoords = poly.getExteriorRing().getCoordinates();
        Coordinate[] flatShell = new Coordinate[shellCoords.length];

        // 强制二维转换
        for (int i = 0; i < shellCoords.length; i++) {
            Coordinate c = shellCoords[i];
            flatShell[i] = new CoordinateXY(c.x, c.y);
        }

        LinearRing shell = geometryFactory.createLinearRing(flatShell);

        // 处理洞口
        int holesCount = poly.getNumInteriorRing();
        LinearRing[] holes = new LinearRing[holesCount];

        for (int i = 0; i < holesCount; i++) {
            Coordinate[] holeCoords = poly.getInteriorRingN(i).getCoordinates();
            Coordinate[] flatHole = new Coordinate[holeCoords.length];

            // 强制二维转换
            for (int j = 0; j < holeCoords.length; j++) {
                Coordinate c = holeCoords[j];
                flatHole[j] = new CoordinateXY(c.x, c.y);
            }

            holes[i] = geometryFactory.createLinearRing(flatHole);
        }

        return geometryFactory.createPolygon(shell, holes);
    }

    private MultiPolygon rebuildMultiPolygon(MultiPolygon mp) {
        Polygon[] polygons = new Polygon[mp.getNumGeometries()];
        for (int i = 0; i < polygons.length; i++) {
            polygons[i] = (Polygon) flattenTo2D(mp.getGeometryN(i));
        }
        return geometryFactory.createMultiPolygon(polygons);
    }

    /**
     * 根据点的 纬度 和 经度 判断此点是否在陆地上
     *
     * @param longitude: 经度
     * @param latitude:  纬度
     * @return boolean
     * @author Qi ChengBin
     * @date 2025/5/27
     */
    public boolean isLand(double longitude, double latitude) {
//        GeometryFactory geometryFactory = new GeometryFactory();
//        Point point = geometryFactory.createPoint(new CoordinateXY(longitude, latitude));
//        return this.landGeometry.contains(point);

        Coordinate coord = new CoordinateXY(longitude, latitude);
        if (Double.isNaN(coord.x) || Double.isNaN(coord.y)) {
            return false; // 处理无效输入
        }
        Point point = this.geometryFactory.createPoint(coord);
        try {
            return this.landGeometry != null && this.landGeometry.contains(point);
        } catch (TopologyException e) {
            log.warn("几何运算异常: {}", e.getMessage());
            return false; // 降级处理
        }
    }
}
