/**
 * 空间数据服务API
 * 提供PostGIS风格的空间查询、几何计算和数据导出功能
 */

// ===== 类型定义 =====

export interface Point {
  lat: number;
  lng: number;
  alt?: number; // 海拔高度
}

export interface Polygon {
  points: Point[];
  holes?: Point[][]; // 多边形的孔洞
}

export interface Field {
  id: string;
  name: string;
  code: string;
  geometry: Polygon;
  properties?: Record<string, any>;
}

export interface SpatialQueryResult<T = any> {
  success: boolean;
  data: T;
  timestamp: string;
  executionTime: number; // 毫秒
}

// ===== 常量定义 =====

// WGS-84椭球参数
const WGS84_A = 6378137.0; // 长半轴（米）
const WGS84_B = 6356752.314245; // 短半轴（米）
const WGS84_F = 1 / 298.257223563; // 扁率

// 1亩 = 666.67平方米
const MU_TO_SQUARE_METERS = 666.67;

// ===== 1. 空间查询API =====

/**
 * 点面查询：判断点是否在多边形内
 * 使用射线法（Ray Casting Algorithm）
 */
export class SpatialQuery {
  /**
   * 点在多边形内查询
   * @param point 查询点
   * @param fields 地块列表
   * @returns 包含该点的地块列表
   */
  static pointInPolygon(point: Point, fields: Field[]): SpatialQueryResult<{
    matched: boolean;
    fields: Array<{
      field: Field;
      distanceToBorder: number; // 到边界的最短距离（米）
    }>;
  }> {
    const startTime = performance.now();
    const results: Array<{ field: Field; distanceToBorder: number }> = [];

    for (const field of fields) {
      if (this._isPointInPolygon(point, field.geometry.points)) {
        const distance = this._pointToPolygonDistance(point, field.geometry.points);
        results.push({ field, distanceToBorder: distance });
      }
    }

    const executionTime = performance.now() - startTime;

    return {
      success: true,
      data: {
        matched: results.length > 0,
        fields: results,
      },
      timestamp: new Date().toISOString(),
      executionTime,
    };
  }

  /**
   * 多边形相交查询
   * @param sourceField 源地块
   * @param targetFields 目标地块列表
   * @returns 与源地块相交的地块列表
   */
  static polygonIntersect(
    sourceField: Field,
    targetFields: Field[]
  ): SpatialQueryResult<{
    intersections: Array<{
      field: Field;
      intersectArea: number; // 相交面积（亩）
      intersectRatio: number; // 相交比例（%）
      intersectGeometry: Polygon; // 相交区域几何
    }>;
  }> {
    const startTime = performance.now();
    const intersections: Array<{
      field: Field;
      intersectArea: number;
      intersectRatio: number;
      intersectGeometry: Polygon;
    }> = [];

    const sourceArea = GeometryCalculator.calculateArea(sourceField.geometry);

    for (const targetField of targetFields) {
      if (targetField.id === sourceField.id) continue;

      if (this._polygonsIntersect(sourceField.geometry.points, targetField.geometry.points)) {
        const intersectGeometry = this._calculateIntersection(
          sourceField.geometry,
          targetField.geometry
        );
        const intersectArea = GeometryCalculator.calculateArea(intersectGeometry);
        const intersectRatio = (intersectArea / sourceArea) * 100;

        intersections.push({
          field: targetField,
          intersectArea,
          intersectRatio,
          intersectGeometry,
        });
      }
    }

    const executionTime = performance.now() - startTime;

    return {
      success: true,
      data: { intersections },
      timestamp: new Date().toISOString(),
      executionTime,
    };
  }

  /**
   * 相邻地块查询
   * @param sourceField 源地块
   * @param targetFields 目标地块列表
   * @returns 与源地块相邻的地块列表
   */
  static adjacentPolygons(
    sourceField: Field,
    targetFields: Field[]
  ): SpatialQueryResult<{
    adjacentFields: Array<{
      field: Field;
      sharedBorderLength: number; // 共享边界长度（米）
      sharedBorderPoints: Point[]; // 共享边界点
    }>;
  }> {
    const startTime = performance.now();
    const adjacentFields: Array<{
      field: Field;
      sharedBorderLength: number;
      sharedBorderPoints: Point[];
    }> = [];

    for (const targetField of targetFields) {
      if (targetField.id === sourceField.id) continue;

      const { isAdjacent, sharedBorder } = this._checkAdjacency(
        sourceField.geometry.points,
        targetField.geometry.points
      );

      if (isAdjacent && sharedBorder.length > 0) {
        const sharedBorderLength = GeometryCalculator.calculatePerimeter({
          points: sharedBorder,
        });

        adjacentFields.push({
          field: targetField,
          sharedBorderLength,
          sharedBorderPoints: sharedBorder,
        });
      }
    }

    const executionTime = performance.now() - startTime;

    return {
      success: true,
      data: { adjacentFields },
      timestamp: new Date().toISOString(),
      executionTime,
    };
  }

  /**
   * 缓冲区分析
   * @param sourceField 源地块
   * @param bufferDistance 缓冲区距离（米）
   * @param targetFields 目标地块列表
   * @returns 缓冲区内的地块列表
   */
  static bufferAnalysis(
    sourceField: Field,
    bufferDistance: number,
    targetFields: Field[]
  ): SpatialQueryResult<{
    bufferGeometry: Polygon;
    bufferArea: number; // 缓冲区面积（亩）
    fieldsInBuffer: Array<{
      field: Field;
      distance: number; // 最短距离（米）
      overlap: boolean; // 是否重叠
    }>;
  }> {
    const startTime = performance.now();

    // 生成缓冲区几何
    const bufferGeometry = this._createBuffer(sourceField.geometry, bufferDistance);
    const bufferArea = GeometryCalculator.calculateArea(bufferGeometry);

    const fieldsInBuffer: Array<{
      field: Field;
      distance: number;
      overlap: boolean;
    }> = [];

    for (const targetField of targetFields) {
      if (targetField.id === sourceField.id) continue;

      const distance = this._polygonToPolygonDistance(
        sourceField.geometry.points,
        targetField.geometry.points
      );

      if (distance <= bufferDistance) {
        const overlap = this._polygonsIntersect(
          bufferGeometry.points,
          targetField.geometry.points
        );
        fieldsInBuffer.push({
          field: targetField,
          distance,
          overlap,
        });
      }
    }

    const executionTime = performance.now() - startTime;

    return {
      success: true,
      data: {
        bufferGeometry,
        bufferArea,
        fieldsInBuffer,
      },
      timestamp: new Date().toISOString(),
      executionTime,
    };
  }

  // ===== 私有辅助方法 =====

  /**
   * 射线法判断点是否在多边形内
   */
  private static _isPointInPolygon(point: Point, polygon: Point[]): boolean {
    let inside = false;
    for (let i = 0, j = polygon.length - 1; i < polygon.length; j = i++) {
      const xi = polygon[i].lng,
        yi = polygon[i].lat;
      const xj = polygon[j].lng,
        yj = polygon[j].lat;

      const intersect =
        yi > point.lat !== yj > point.lat &&
        point.lng < ((xj - xi) * (point.lat - yi)) / (yj - yi) + xi;
      if (intersect) inside = !inside;
    }
    return inside;
  }

  /**
   * 计算点到多边形边界的最短距离
   */
  private static _pointToPolygonDistance(point: Point, polygon: Point[]): number {
    let minDistance = Infinity;

    for (let i = 0; i < polygon.length; i++) {
      const p1 = polygon[i];
      const p2 = polygon[(i + 1) % polygon.length];
      const distance = this._pointToSegmentDistance(point, p1, p2);
      minDistance = Math.min(minDistance, distance);
    }

    return minDistance;
  }

  /**
   * 计算点到线段的距离
   */
  private static _pointToSegmentDistance(point: Point, p1: Point, p2: Point): number {
    const dx = p2.lng - p1.lng;
    const dy = p2.lat - p1.lat;

    if (dx === 0 && dy === 0) {
      return GeometryCalculator.haversineDistance(point, p1);
    }

    const t = Math.max(
      0,
      Math.min(
        1,
        ((point.lng - p1.lng) * dx + (point.lat - p1.lat) * dy) / (dx * dx + dy * dy)
      )
    );

    const nearestPoint: Point = {
      lat: p1.lat + t * dy,
      lng: p1.lng + t * dx,
    };

    return GeometryCalculator.haversineDistance(point, nearestPoint);
  }

  /**
   * 判断两个多边形是否相交
   */
  private static _polygonsIntersect(poly1: Point[], poly2: Point[]): boolean {
    // 检查是否有顶点在另一个多边形内
    for (const point of poly1) {
      if (this._isPointInPolygon(point, poly2)) return true;
    }
    for (const point of poly2) {
      if (this._isPointInPolygon(point, poly1)) return true;
    }

    // 检查边是否相交
    for (let i = 0; i < poly1.length; i++) {
      const p1 = poly1[i];
      const p2 = poly1[(i + 1) % poly1.length];

      for (let j = 0; j < poly2.length; j++) {
        const p3 = poly2[j];
        const p4 = poly2[(j + 1) % poly2.length];

        if (this._segmentsIntersect(p1, p2, p3, p4)) return true;
      }
    }

    return false;
  }

  /**
   * 判断两条线段是否相交
   */
  private static _segmentsIntersect(p1: Point, p2: Point, p3: Point, p4: Point): boolean {
    const ccw = (A: Point, B: Point, C: Point) => {
      return (C.lat - A.lat) * (B.lng - A.lng) > (B.lat - A.lat) * (C.lng - A.lng);
    };

    return ccw(p1, p3, p4) !== ccw(p2, p3, p4) && ccw(p1, p2, p3) !== ccw(p1, p2, p4);
  }

  /**
   * 计算两个多边形的相交区域（简化实现）
   */
  private static _calculateIntersection(poly1: Polygon, poly2: Polygon): Polygon {
    // 这里使用简化算法，实际应用中应使用Sutherland-Hodgman算法
    const intersectPoints: Point[] = [];

    // 收集在两个多边形内的点
    for (const point of poly1.points) {
      if (this._isPointInPolygon(point, poly2.points)) {
        intersectPoints.push(point);
      }
    }

    for (const point of poly2.points) {
      if (this._isPointInPolygon(point, poly1.points)) {
        intersectPoints.push(point);
      }
    }

    // 如果没有交点，返回空多边形
    if (intersectPoints.length === 0) {
      return { points: [] };
    }

    // 计算凸包作为相交区域的近似
    return { points: this._convexHull(intersectPoints) };
  }

  /**
   * 计算凸包（Graham扫描算法）
   */
  private static _convexHull(points: Point[]): Point[] {
    if (points.length < 3) return points;

    // 找到最下最左的点
    let start = points[0];
    points.forEach((p) => {
      if (p.lat < start.lat || (p.lat === start.lat && p.lng < start.lng)) {
        start = p;
      }
    });

    // 按极角排序
    const sorted = points
      .filter((p) => p !== start)
      .sort((a, b) => {
        const angleA = Math.atan2(a.lat - start.lat, a.lng - start.lng);
        const angleB = Math.atan2(b.lat - start.lat, b.lng - start.lng);
        return angleA - angleB;
      });

    const hull: Point[] = [start];

    for (const point of sorted) {
      while (hull.length >= 2) {
        const p2 = hull[hull.length - 1];
        const p1 = hull[hull.length - 2];
        const cross =
          (p2.lng - p1.lng) * (point.lat - p1.lat) -
          (p2.lat - p1.lat) * (point.lng - p1.lng);
        if (cross <= 0) {
          hull.pop();
        } else {
          break;
        }
      }
      hull.push(point);
    }

    return hull;
  }

  /**
   * 检查两个多边形是否相邻
   */
  private static _checkAdjacency(
    poly1: Point[],
    poly2: Point[]
  ): { isAdjacent: boolean; sharedBorder: Point[] } {
    const sharedBorder: Point[] = [];
    const tolerance = 0.00001; // 约1米的容差

    for (let i = 0; i < poly1.length; i++) {
      const p1 = poly1[i];
      const p2 = poly1[(i + 1) % poly1.length];

      for (let j = 0; j < poly2.length; j++) {
        const p3 = poly2[j];
        const p4 = poly2[(j + 1) % poly2.length];

        // 检查边是否重合
        if (this._edgesOverlap(p1, p2, p3, p4, tolerance)) {
          if (sharedBorder.length === 0 || !this._pointsEqual(sharedBorder[sharedBorder.length - 1], p1, tolerance)) {
            sharedBorder.push(p1);
          }
          sharedBorder.push(p2);
        }
      }
    }

    return {
      isAdjacent: sharedBorder.length >= 2,
      sharedBorder,
    };
  }

  /**
   * 判断两条边是否重合
   */
  private static _edgesOverlap(
    p1: Point,
    p2: Point,
    p3: Point,
    p4: Point,
    tolerance: number
  ): boolean {
    return (
      (this._pointsEqual(p1, p3, tolerance) && this._pointsEqual(p2, p4, tolerance)) ||
      (this._pointsEqual(p1, p4, tolerance) && this._pointsEqual(p2, p3, tolerance))
    );
  }

  /**
   * 判断两个点是否相等（在容差范围内）
   */
  private static _pointsEqual(p1: Point, p2: Point, tolerance: number): boolean {
    return (
      Math.abs(p1.lat - p2.lat) < tolerance && Math.abs(p1.lng - p2.lng) < tolerance
    );
  }

  /**
   * 计算多边形到多边形的最短距离
   */
  private static _polygonToPolygonDistance(poly1: Point[], poly2: Point[]): number {
    let minDistance = Infinity;

    for (const point of poly1) {
      const distance = this._pointToPolygonDistance(point, poly2);
      minDistance = Math.min(minDistance, distance);
    }

    for (const point of poly2) {
      const distance = this._pointToPolygonDistance(point, poly1);
      minDistance = Math.min(minDistance, distance);
    }

    return minDistance;
  }

  /**
   * 创建缓冲区（简化实现）
   */
  private static _createBuffer(geometry: Polygon, distance: number): Polygon {
    const bufferPoints: Point[] = [];
    const points = geometry.points;

    // 简化算法：对每个顶点，在法线方向上偏移distance距离
    for (let i = 0; i < points.length; i++) {
      const prev = points[i === 0 ? points.length - 1 : i - 1];
      const curr = points[i];
      const next = points[(i + 1) % points.length];

      // 计算法向量
      const v1 = { lat: curr.lat - prev.lat, lng: curr.lng - prev.lng };
      const v2 = { lat: next.lat - curr.lat, lng: next.lng - curr.lng };

      // 计算平均法向量
      const normal = {
        lat: -(v1.lng + v2.lng),
        lng: v1.lat + v2.lat,
      };

      // 归一化
      const length = Math.sqrt(normal.lat * normal.lat + normal.lng * normal.lng);
      if (length > 0) {
        normal.lat /= length;
        normal.lng /= length;
      }

      // 偏移顶点（简化：使用度数偏移，实际应转换为米）
      const offsetDegrees = distance / 111320; // 约111.32km每度
      bufferPoints.push({
        lat: curr.lat + normal.lat * offsetDegrees,
        lng: curr.lng + normal.lng * offsetDegrees,
      });
    }

    return { points: bufferPoints };
  }
}

// ===== 2. 几何计算API =====

export class GeometryCalculator {
  /**
   * 计算多边形精确面积（考虑地球曲率）
   * 使用球面三角形面积公式
   */
  static calculateArea(geometry: Polygon): number {
    const points = geometry.points;
    if (points.length < 3) return 0;

    // 将多边形分解为三角形，计算球面三角形面积之和
    let totalArea = 0;
    const origin = points[0];

    for (let i = 1; i < points.length - 1; i++) {
      const area = this._sphericalTriangleArea(origin, points[i], points[i + 1]);
      totalArea += area;
    }

    // 转换为亩
    return totalArea / MU_TO_SQUARE_METERS;
  }

  /**
   * 计算球面三角形面积（L'Huilier定理）
   */
  private static _sphericalTriangleArea(p1: Point, p2: Point, p3: Point): number {
    const R = WGS84_A; // 使用WGS-84长半轴

    // 转换为弧度
    const lat1 = this._toRadians(p1.lat);
    const lng1 = this._toRadians(p1.lng);
    const lat2 = this._toRadians(p2.lat);
    const lng2 = this._toRadians(p2.lng);
    const lat3 = this._toRadians(p3.lat);
    const lng3 = this._toRadians(p3.lng);

    // 计算边长（球面距离）
    const a = this._sphericalDistance(lat2, lng2, lat3, lng3, R);
    const b = this._sphericalDistance(lat3, lng3, lat1, lng1, R);
    const c = this._sphericalDistance(lat1, lng1, lat2, lng2, R);

    // 半周长
    const s = (a + b + c) / 2;

    // L'Huilier定理
    const E = 4 * Math.atan(Math.sqrt(Math.tan(s / (2 * R)) * Math.tan((s - a) / (2 * R)) * Math.tan((s - b) / (2 * R)) * Math.tan((s - c) / (2 * R))));

    // 面积 = R² * E
    return R * R * E;
  }

  /**
   * 计算球面距离
   */
  private static _sphericalDistance(
    lat1: number,
    lng1: number,
    lat2: number,
    lng2: number,
    radius: number
  ): number {
    const dLat = lat2 - lat1;
    const dLng = lng2 - lng1;

    const a =
      Math.sin(dLat / 2) * Math.sin(dLat / 2) +
      Math.cos(lat1) * Math.cos(lat2) * Math.sin(dLng / 2) * Math.sin(dLng / 2);
    const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));

    return radius * c;
  }

  /**
   * 计算多边形周长（考虑地球曲率）
   */
  static calculatePerimeter(geometry: Polygon): number {
    const points = geometry.points;
    if (points.length < 2) return 0;

    let perimeter = 0;

    for (let i = 0; i < points.length; i++) {
      const p1 = points[i];
      const p2 = points[(i + 1) % points.length];
      perimeter += this.haversineDistance(p1, p2);
    }

    return perimeter;
  }

  /**
   * Haversine公式计算两点间距离（米）
   */
  static haversineDistance(p1: Point, p2: Point): number {
    const R = WGS84_A;

    const lat1 = this._toRadians(p1.lat);
    const lng1 = this._toRadians(p1.lng);
    const lat2 = this._toRadians(p2.lat);
    const lng2 = this._toRadians(p2.lng);

    return this._sphericalDistance(lat1, lng1, lat2, lng2, R);
  }

  /**
   * 计算多边形中心点（几何中心）
   */
  static calculateCentroid(geometry: Polygon): Point {
    const points = geometry.points;
    if (points.length === 0) return { lat: 0, lng: 0 };

    let sumLat = 0;
    let sumLng = 0;
    let sumArea = 0;

    for (let i = 0; i < points.length; i++) {
      const p1 = points[i];
      const p2 = points[(i + 1) % points.length];

      const cross = p1.lng * p2.lat - p2.lng * p1.lat;
      sumArea += cross;
      sumLat += (p1.lat + p2.lat) * cross;
      sumLng += (p1.lng + p2.lng) * cross;
    }

    sumArea /= 2;

    if (Math.abs(sumArea) < 1e-10) {
      // 如果面积接近0，使用简单平均
      const avgLat = points.reduce((sum, p) => sum + p.lat, 0) / points.length;
      const avgLng = points.reduce((sum, p) => sum + p.lng, 0) / points.length;
      return { lat: avgLat, lng: avgLng };
    }

    const centroidLat = sumLat / (6 * sumArea);
    const centroidLng = sumLng / (6 * sumArea);

    return { lat: centroidLat, lng: centroidLng };
  }

  /**
   * 计算包围盒（Bounding Box）
   */
  static calculateBoundingBox(geometry: Polygon): {
    minLat: number;
    maxLat: number;
    minLng: number;
    maxLng: number;
    center: Point;
  } {
    const points = geometry.points;
    if (points.length === 0) {
      return {
        minLat: 0,
        maxLat: 0,
        minLng: 0,
        maxLng: 0,
        center: { lat: 0, lng: 0 },
      };
    }

    let minLat = points[0].lat;
    let maxLat = points[0].lat;
    let minLng = points[0].lng;
    let maxLng = points[0].lng;

    for (const point of points) {
      minLat = Math.min(minLat, point.lat);
      maxLat = Math.max(maxLat, point.lat);
      minLng = Math.min(minLng, point.lng);
      maxLng = Math.max(maxLng, point.lng);
    }

    return {
      minLat,
      maxLat,
      minLng,
      maxLng,
      center: {
        lat: (minLat + maxLat) / 2,
        lng: (minLng + maxLng) / 2,
      },
    };
  }

  /**
   * 角度转弧度
   */
  private static _toRadians(degrees: number): number {
    return (degrees * Math.PI) / 180;
  }

  /**
   * 弧度转角度
   */
  private static _toDegrees(radians: number): number {
    return (radians * 180) / Math.PI;
  }
}

// ===== 3. 数据导出API =====

export class DataExporter {
  /**
   * 导出为GeoJSON格式
   */
  static exportToGeoJSON(fields: Field[]): string {
    const features = fields.map((field) => ({
      type: 'Feature',
      id: field.id,
      properties: {
        name: field.name,
        code: field.code,
        area: GeometryCalculator.calculateArea(field.geometry),
        perimeter: GeometryCalculator.calculatePerimeter(field.geometry),
        centroid: GeometryCalculator.calculateCentroid(field.geometry),
        ...field.properties,
      },
      geometry: {
        type: 'Polygon',
        coordinates: [field.geometry.points.map((p) => [p.lng, p.lat])],
      },
    }));

    const geoJSON = {
      type: 'FeatureCollection',
      crs: {
        type: 'name',
        properties: {
          name: 'EPSG:4326', // WGS-84
        },
      },
      features,
    };

    return JSON.stringify(geoJSON, null, 2);
  }

  /**
   * 导出为KML格式
   */
  static exportToKML(fields: Field[]): string {
    const placemarks = fields
      .map((field) => {
        const coords = field.geometry.points.map((p) => `${p.lng},${p.lat},0`).join(' ');

        return `
    <Placemark>
      <name>${field.name}</name>
      <description>
        编号: ${field.code}
        面积: ${GeometryCalculator.calculateArea(field.geometry).toFixed(2)} 亩
        周长: ${GeometryCalculator.calculatePerimeter(field.geometry).toFixed(0)} 米
      </description>
      <Polygon>
        <outerBoundaryIs>
          <LinearRing>
            <coordinates>${coords}</coordinates>
          </LinearRing>
        </outerBoundaryIs>
      </Polygon>
    </Placemark>`;
      })
      .join('\n');

    return `<?xml version="1.0" encoding="UTF-8"?>
<kml xmlns="http://www.opengis.net/kml/2.2">
  <Document>
    <name>地块数据</name>
    <description>智慧农业生产管理系统地块导出</description>
    ${placemarks}
  </Document>
</kml>`;
  }

  /**
   * 导出为Shapefile格式（WKT格式）
   */
  static exportToWKT(field: Field): string {
    const coords = field.geometry.points.map((p) => `${p.lng} ${p.lat}`).join(', ');
    return `POLYGON((${coords}))`;
  }

  /**
   * 导出为CSV格式
   */
  static exportToCSV(fields: Field[]): string {
    const headers = ['ID', '名称', '编号', '面积(亩)', '周长(米)', '中心点纬度', '中心点经度'];
    const rows = fields.map((field) => {
      const centroid = GeometryCalculator.calculateCentroid(field.geometry);
      return [
        field.id,
        field.name,
        field.code,
        GeometryCalculator.calculateArea(field.geometry).toFixed(2),
        GeometryCalculator.calculatePerimeter(field.geometry).toFixed(0),
        centroid.lat.toFixed(6),
        centroid.lng.toFixed(6),
      ];
    });

    const csvContent = [
      headers.join(','),
      ...rows.map((row) => row.join(',')),
    ].join('\n');

    return csvContent;
  }

  /**
   * 下载文件
   */
  static downloadFile(content: string, filename: string, mimeType: string): void {
    const blob = new Blob([content], { type: mimeType });
    const url = URL.createObjectURL(blob);
    const a = document.createElement('a');
    a.href = url;
    a.download = filename;
    a.click();
    URL.revokeObjectURL(url);
  }
}

// ===== 4. 空间索引（用于性能优化） =====

export class SpatialIndex {
  private rtree: Map<string, { bbox: any; field: Field }>;

  constructor() {
    this.rtree = new Map();
  }

  /**
   * 插入地块
   */
  insert(field: Field): void {
    const bbox = GeometryCalculator.calculateBoundingBox(field.geometry);
    this.rtree.set(field.id, { bbox, field });
  }

  /**
   * 快速查询可能相交的地块
   */
  query(bbox: {
    minLat: number;
    maxLat: number;
    minLng: number;
    maxLng: number;
  }): Field[] {
    const results: Field[] = [];

    for (const [_, item] of this.rtree) {
      if (this._bboxesIntersect(bbox, item.bbox)) {
        results.push(item.field);
      }
    }

    return results;
  }

  /**
   * 判断两个包围盒是否相交
   */
  private _bboxesIntersect(
    bbox1: { minLat: number; maxLat: number; minLng: number; maxLng: number },
    bbox2: { minLat: number; maxLat: number; minLng: number; maxLng: number }
  ): boolean {
    return !(
      bbox1.maxLat < bbox2.minLat ||
      bbox1.minLat > bbox2.maxLat ||
      bbox1.maxLng < bbox2.minLng ||
      bbox1.minLng > bbox2.maxLng
    );
  }
}