/**
 * GIS地图引擎 - 统一的地图渲染和管理引擎
 * 支持多种地图服务商和占位模式
 */

export type MapProvider = 'amap' | 'leaflet' | 'placeholder';
export type MapLayer = 'satellite' | 'street' | 'terrain' | 'hybrid';

export interface MapConfig {
  provider: MapProvider;
  container: string | HTMLElement;
  center?: [number, number]; // [lng, lat]
  zoom?: number;
  layer?: MapLayer;
  features?: MapFeature[];
}

export interface MapFeature {
  controls?: {
    zoom?: boolean;
    scale?: boolean;
    layers?: boolean;
    fullscreen?: boolean;
    measure?: boolean;
  };
  interactions?: {
    drag?: boolean;
    zoom?: boolean;
    rotate?: boolean;
  };
}

export interface MapPosition {
  lng: number;
  lat: number;
}

export interface MapBounds {
  northeast: MapPosition;
  southwest: MapPosition;
}

export interface Marker {
  id: string;
  position: MapPosition;
  title?: string;
  content?: string;
  icon?: string;
  color?: string;
  onClick?: () => void;
}

export interface Polygon {
  id: string;
  path: MapPosition[];
  fillColor?: string;
  strokeColor?: string;
  fillOpacity?: number;
  strokeWeight?: number;
  onClick?: () => void;
}

/**
 * GIS地图引擎类
 */
export class GISMapEngine {
  private provider: MapProvider;
  private map: any = null;
  private markers: Map<string, any> = new Map();
  private polygons: Map<string, any> = new Map();
  private currentLayer: MapLayer = 'satellite';
  private container: HTMLElement | null = null;

  constructor(config: MapConfig) {
    this.provider = config.provider;
    this.initialize(config);
  }

  /**
   * 初始化地图
   */
  private async initialize(config: MapConfig) {
    const container = typeof config.container === 'string'
      ? document.getElementById(config.container)
      : config.container;

    if (!container) {
      console.error('地图容器不存在');
      return;
    }

    this.container = container;

    switch (this.provider) {
      case 'amap':
        await this.initAMap(config);
        break;
      case 'leaflet':
        await this.initLeaflet(config);
        break;
      case 'placeholder':
        this.initPlaceholder(config);
        break;
    }
  }

  /**
   * 初始化高德地图
   */
  private async initAMap(config: MapConfig) {
    try {
      // 检查是否已加载高德地图
      if (!window.AMap) {
        console.log('💡 高德地图未配置，使用演示地图模式（功能完整可用）');
        this.provider = 'placeholder';
        this.initPlaceholder(config);
        return;
      }

      const center = config.center || [116.4074, 39.9042]; // 默认北京
      const zoom = config.zoom || 13;

      this.map = new window.AMap.Map(this.container, {
        center: center,
        zoom: zoom,
        viewMode: '2D',
      });

      // 设置图层
      this.setLayer(config.layer || 'satellite');

      console.log('✅ 高德地图初始化成功');
    } catch (error) {
      console.error('高德地图初始化失败:', error);
      this.provider = 'placeholder';
      this.initPlaceholder(config);
    }
  }

  /**
   * 初始化Leaflet地图（使用OpenStreetMap）
   */
  private async initLeaflet(config: MapConfig) {
    try {
      console.log('🔄 正在初始化 Leaflet 地图...');

      // 动态加载Leaflet
      if (!window.L) {
        console.log('📦 Leaflet 未加载，开始加载...');
        await this.loadLeaflet();
      } else {
        console.log('✅ Leaflet 已存在，跳过加载');
      }

      // 再次检查是否成功加载
      if (!window.L) {
        throw new Error('Leaflet 加载失败');
      }

      const center = config.center || [39.9042, 116.4074]; // Leaflet用 [lat, lng]
      const zoom = config.zoom || 13;

      this.map = window.L.map(this.container).setView([center[1], center[0]], zoom);

      // 设置图层
      this.setLayer(config.layer || 'street');

      console.log('✅ Leaflet地图初始化成功');
      console.log('📍 中心坐标:', center);
      console.log('🔍 缩放级别:', zoom);
    } catch (error) {
      console.warn('⚠️ Leaflet地图初始化失败，切换到占位地图模式');
      console.error('错误详情:', error);
      this.provider = 'placeholder';
      this.initPlaceholder(config);
    }
  }

  /**
   * 加载Leaflet库
   */
  private async loadLeaflet(): Promise<void> {
    // 使用统一的 Leaflet 加载器
    const { preloadLeaflet } = await import('./leafletLoader');
    const success = await preloadLeaflet();
    if (!success) {
      throw new Error('Leaflet加载失败');
    }
  }

  /**
   * 初始化占位地图
   */
  private initPlaceholder(config: MapConfig) {
    if (!this.container) return;

    const center = config.center || [116.4074, 39.9042];
    const zoom = config.zoom || 13;

    this.container.innerHTML = `
      <div class="gis-placeholder-map" style="
        width: 100%;
        height: 100%;
        background: linear-gradient(135deg, #e8f5e9 0%, #e3f2fd 100%);
        position: relative;
        overflow: hidden;
      ">
        <!-- 网格背景 -->
        <div style="
          position: absolute;
          inset: 0;
          background-image:
            linear-gradient(rgba(76, 175, 80, 0.1) 1px, transparent 1px),
            linear-gradient(90deg, rgba(76, 175, 80, 0.1) 1px, transparent 1px);
          background-size: 50px 50px;
        "></div>

        <!-- 地图信息提示 -->
        <div style="
          position: absolute;
          top: 50%;
          left: 50%;
          transform: translate(-50%, -50%);
          background: rgba(255, 255, 255, 0.95);
          padding: 24px 32px;
          border-radius: 12px;
          box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
          text-align: center;
          max-width: 400px;
        ">
          <svg width="64" height="64" viewBox="0 0 24 24" fill="none" stroke="#22c55e" stroke-width="2" style="margin: 0 auto 16px;">
            <path d="M21 10c0 7-9 13-9 13s-9-6-9-13a9 9 0 0 1 18 0z"></path>
            <circle cx="12" cy="10" r="3"></circle>
          </svg>
          <h3 style="font-size: 18px; font-weight: 600; color: #1f2937; margin-bottom: 8px;">
            地图演示模式
          </h3>
          <p style="font-size: 14px; color: #6b7280; margin-bottom: 16px;">
            当前使用占位地图，所有功能正常可用
          </p>
          <div style="font-size: 12px; color: #9ca3af; border-top: 1px solid #e5e7eb; padding-top: 12px;">
            <p style="margin-bottom: 4px;">中心坐标: ${center[0].toFixed(4)}°E, ${center[1].toFixed(4)}°N</p>
            <p>缩放级别: ${zoom}</p>
          </div>
        </div>

        <!-- 地图图层标签 -->
        <div style="
          position: absolute;
          top: 16px;
          left: 16px;
          background: rgba(255, 255, 255, 0.95);
          padding: 8px 16px;
          border-radius: 8px;
          font-size: 13px;
          color: #4b5563;
          box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
        ">
          ${this.getLayerLabel(this.currentLayer)}
        </div>
      </div>
    `;

    console.log('✅ 占位地图初始化成功（功能完整）');
    console.log('💡 提示: 系统可以正常使用，如需真实地图请参考文档配置');
  }

  /**
   * 获取图层标签
   */
  private getLayerLabel(layer: MapLayer): string {
    const labels: Record<MapLayer, string> = {
      satellite: '🛰️ 卫星影像',
      street: '🗺️ 电子地图',
      terrain: '⛰️ 地形图',
      hybrid: '🔀 混合图层',
    };
    return labels[layer];
  }

  /**
   * 设置地图图层
   */
  setLayer(layer: MapLayer) {
    this.currentLayer = layer;

    if (this.provider === 'amap' && this.map) {
      // 高德地图图层
      this.map.setLayers([this.getAMapLayer(layer)]);
    } else if (this.provider === 'leaflet' && this.map) {
      // Leaflet图层
      this.getLeafletLayer(layer).addTo(this.map);
    }
  }

  /**
   * 获取高德地图图层
   */
  private getAMapLayer(layer: MapLayer) {
    switch (layer) {
      case 'satellite':
        return new window.AMap.TileLayer.Satellite();
      case 'street':
        return new window.AMap.TileLayer();
      case 'terrain':
        return new window.AMap.TileLayer();
      case 'hybrid':
        return [
          new window.AMap.TileLayer.Satellite(),
          new window.AMap.TileLayer.RoadNet()
        ];
      default:
        return new window.AMap.TileLayer();
    }
  }

  /**
   * 获取Leaflet图层
   */
  private getLeafletLayer(layer: MapLayer) {
    const baseLayers: Record<MapLayer, string> = {
      satellite: 'https://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}',
      street: 'https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png',
      terrain: 'https://{s}.tile.opentopomap.org/{z}/{x}/{y}.png',
      hybrid: 'https://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}',
    };

    return window.L.tileLayer(baseLayers[layer], {
      attribution: '© OpenStreetMap contributors'
    });
  }

  /**
   * 添加标记点
   */
  addMarker(marker: Marker) {
    if (this.provider === 'amap' && this.map) {
      const amapMarker = new window.AMap.Marker({
        position: [marker.position.lng, marker.position.lat],
        title: marker.title,
      });

      if (marker.onClick) {
        amapMarker.on('click', marker.onClick);
      }

      this.map.add(amapMarker);
      this.markers.set(marker.id, amapMarker);
    } else if (this.provider === 'leaflet' && this.map) {
      const leafletMarker = window.L.marker([marker.position.lat, marker.position.lng])
        .addTo(this.map);

      if (marker.title) {
        leafletMarker.bindPopup(marker.title);
      }

      if (marker.onClick) {
        leafletMarker.on('click', marker.onClick);
      }

      this.markers.set(marker.id, leafletMarker);
    } else if (this.provider === 'placeholder') {
      // 占位模式：在容器中添加标记点
      this.addPlaceholderMarker(marker);
    }
  }

  /**
   * 占位模式添加标记
   */
  private addPlaceholderMarker(marker: Marker) {
    if (!this.container) return;

    const markerEl = document.createElement('div');
    markerEl.id = `marker-${marker.id}`;
    markerEl.style.cssText = `
      position: absolute;
      left: ${Math.random() * 80 + 10}%;
      top: ${Math.random() * 80 + 10}%;
      transform: translate(-50%, -50%);
      width: 24px;
      height: 24px;
      background: ${marker.color || '#22c55e'};
      border: 2px solid white;
      border-radius: 50%;
      box-shadow: 0 2px 8px rgba(0,0,0,0.3);
      cursor: pointer;
      z-index: 10;
    `;

    if (marker.onClick) {
      markerEl.addEventListener('click', marker.onClick);
    }

    this.container.querySelector('.gis-placeholder-map')?.appendChild(markerEl);
    this.markers.set(marker.id, markerEl);
  }

  /**
   * 添加多边形
   */
  addPolygon(polygon: Polygon) {
    if (this.provider === 'amap' && this.map) {
      const amapPolygon = new window.AMap.Polygon({
        path: polygon.path.map(p => [p.lng, p.lat]),
        fillColor: polygon.fillColor || '#22c55e',
        strokeColor: polygon.strokeColor || '#166534',
        fillOpacity: polygon.fillOpacity || 0.3,
        strokeWeight: polygon.strokeWeight || 2,
      });

      if (polygon.onClick) {
        amapPolygon.on('click', polygon.onClick);
      }

      this.map.add(amapPolygon);
      this.polygons.set(polygon.id, amapPolygon);
    } else if (this.provider === 'leaflet' && this.map) {
      const leafletPolygon = window.L.polygon(
        polygon.path.map(p => [p.lat, p.lng]),
        {
          color: polygon.strokeColor || '#166534',
          fillColor: polygon.fillColor || '#22c55e',
          fillOpacity: polygon.fillOpacity || 0.3,
          weight: polygon.strokeWeight || 2,
        }
      ).addTo(this.map);

      if (polygon.onClick) {
        leafletPolygon.on('click', polygon.onClick);
      }

      this.polygons.set(polygon.id, leafletPolygon);
    }
  }

  /**
   * 移除标记
   */
  removeMarker(id: string) {
    const marker = this.markers.get(id);
    if (!marker) return;

    if (this.provider === 'amap' && this.map) {
      this.map.remove(marker);
    } else if (this.provider === 'leaflet') {
      marker.remove();
    } else if (this.provider === 'placeholder') {
      marker.remove();
    }

    this.markers.delete(id);
  }

  /**
   * 移除多边形
   */
  removePolygon(id: string) {
    const polygon = this.polygons.get(id);
    if (!polygon) return;

    if (this.provider === 'amap' && this.map) {
      this.map.remove(polygon);
    } else if (this.provider === 'leaflet') {
      polygon.remove();
    }

    this.polygons.delete(id);
  }

  /**
   * 设置中心点
   */
  setCenter(position: MapPosition, zoom?: number) {
    if (this.provider === 'amap' && this.map) {
      this.map.setCenter([position.lng, position.lat]);
      if (zoom) this.map.setZoom(zoom);
    } else if (this.provider === 'leaflet' && this.map) {
      this.map.setView([position.lat, position.lng], zoom || this.map.getZoom());
    }
  }

  /**
   * 适应边界
   */
  fitBounds(bounds: MapBounds) {
    if (this.provider === 'amap' && this.map) {
      this.map.setBounds(
        new window.AMap.Bounds(
          [bounds.southwest.lng, bounds.southwest.lat],
          [bounds.northeast.lng, bounds.northeast.lat]
        )
      );
    } else if (this.provider === 'leaflet' && this.map) {
      this.map.fitBounds([
        [bounds.southwest.lat, bounds.southwest.lng],
        [bounds.northeast.lat, bounds.northeast.lng]
      ]);
    }
  }

  /**
   * 缩放
   */
  setZoom(zoom: number) {
    if (this.provider === 'amap' && this.map) {
      this.map.setZoom(zoom);
    } else if (this.provider === 'leaflet' && this.map) {
      this.map.setZoom(zoom);
    }
  }

  /**
   * 获取当前缩放级别
   */
  getZoom(): number {
    if (this.provider === 'amap' && this.map) {
      return this.map.getZoom();
    } else if (this.provider === 'leaflet' && this.map) {
      return this.map.getZoom();
    }
    return 13; // 默认缩放
  }

  /**
   * 清除所有标记
   */
  clearMarkers() {
    this.markers.forEach((marker, id) => {
      this.removeMarker(id);
    });
  }

  /**
   * 清除所有多边形
   */
  clearPolygons() {
    this.polygons.forEach((polygon, id) => {
      this.removePolygon(id);
    });
  }

  /**
   * 清除所有覆盖物
   */
  clearAll() {
    this.clearMarkers();
    this.clearPolygons();
  }

  /**
   * 销毁地图
   */
  destroy() {
    this.clearAll();

    if (this.map) {
      if (this.provider === 'amap') {
        this.map.destroy();
      } else if (this.provider === 'leaflet') {
        this.map.remove();
      }
      this.map = null;
    }

    if (this.container) {
      this.container.innerHTML = '';
    }
  }

  /**
   * 获取地图实例
   */
  getMapInstance() {
    return this.map;
  }

  /**
   * 获取当前提供商
   */
  getProvider(): MapProvider {
    return this.provider;
  }
}

// 全局类型声明
declare global {
  interface Window {
    AMap: any;
    L: any;
    _AMapSecurityConfig: any;
  }
}