/**
 * MapShapeUtil - Mapus-inspired collaborative map shape for tldraw
 *
 * Inspired by https://github.com/alyssaxuu/mapus
 *
 * Features:
 * - Real-time collaboration with user cursors/presence
 * - Find Nearby places (restaurants, hotels, etc.)
 * - Drawing tools (markers, lines, areas)
 * - Annotations list with visibility toggle
 * - Color picker for annotations
 * - Search and routing (Nominatim + OSRM)
 * - GPS location sharing
 * - "Observe" mode to follow other users
 */

import { BaseBoxShapeUtil, TLBaseShape, HTMLContainer, TLResizeInfo, resizeBox, T } from 'tldraw';
import { useRef, useEffect, useState, useCallback } from 'react';
import maplibregl from 'maplibre-gl';
import 'maplibre-gl/dist/maplibre-gl.css';
import { StandardizedToolWrapper } from '../components/StandardizedToolWrapper';
import { usePinnedToView } from '../hooks/usePinnedToView';
import { useMaximize } from '../hooks/useMaximize';

// =============================================================================
// Types
// =============================================================================

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

export interface MapViewport {
  center: Coordinate;
  zoom: number;
  bearing: number;
  pitch: number;
}

export interface Annotation {
  id: string;
  type: 'marker' | 'line' | 'area';
  name: string;
  color: string;
  visible: boolean;
  coordinates: Coordinate[]; // Single for marker, multiple for line/area
  createdBy?: string;
  createdAt: number;
}

export interface RouteInfo {
  distance: number;
  duration: number;
  geometry: GeoJSON.LineString;
}

export interface CollaboratorPresence {
  id: string;
  name: string;
  color: string;
  cursor?: Coordinate;
  location?: Coordinate;
  isObserving?: string; // ID of user being observed
  lastSeen: number;
}

export type IMapShape = TLBaseShape<
  'Map',
  {
    w: number;
    h: number;
    viewport: MapViewport;
    styleKey: string;
    title: string;
    description: string;
    annotations: Annotation[];
    route: RouteInfo | null;
    waypoints: Coordinate[];
    collaborators: CollaboratorPresence[];
    showSidebar: boolean;
    pinnedToView: boolean;
    tags: string[];
    isMinimized: boolean;
    // Legacy compatibility properties
    interactive: boolean;
    showGPS: boolean;
    showSearch: boolean;
    showDirections: boolean;
    sharingLocation: boolean;
    gpsUsers: CollaboratorPresence[];
  }
>;

// =============================================================================
// Constants
// =============================================================================

const DEFAULT_VIEWPORT: MapViewport = {
  center: { lat: 40.7128, lng: -74.006 },
  zoom: 12,
  bearing: 0,
  pitch: 0,
};

const OSRM_BASE_URL = 'https://routing.jeffemmett.com';

// Mapus color palette
const COLORS = [
  '#E15F59', // Red
  '#F29F51', // Orange
  '#F9D458', // Yellow
  '#5EBE86', // Green
  '#4890E8', // Blue
  '#634FF1', // Purple
  '#A564D2', // Violet
  '#222222', // Black
];

// Find Nearby categories (inspired by Mapus)
const NEARBY_CATEGORIES = [
  { key: 'restaurant', label: 'Food', icon: '🍽️', color: '#4890E8', types: 'restaurant,cafe,fast_food,food_court' },
  { key: 'bar', label: 'Drinks', icon: '🍺', color: '#F9D458', types: 'bar,pub,cafe,wine_bar' },
  { key: 'supermarket', label: 'Groceries', icon: '🛒', color: '#5EBE86', types: 'supermarket,convenience,grocery' },
  { key: 'hotel', label: 'Hotels', icon: '🏨', color: '#AC6C48', types: 'hotel,hostel,motel,guest_house' },
  { key: 'hospital', label: 'Health', icon: '🏥', color: '#E15F59', types: 'hospital,pharmacy,clinic,doctors' },
  { key: 'bank', label: 'Services', icon: '🏦', color: '#634FF1', types: 'bank,atm,post_office' },
  { key: 'shopping', label: 'Shopping', icon: '🛍️', color: '#A564D2', types: 'mall,department_store,clothes' },
  { key: 'transport', label: 'Transport', icon: '🚉', color: '#718390', types: 'bus_station,train_station,subway' },
];

// Map styles
const MAP_STYLES = {
  voyager: {
    name: 'Voyager',
    url: 'https://basemaps.cartocdn.com/gl/voyager-gl-style/style.json',
    icon: '🗺️',
  },
  positron: {
    name: 'Light',
    url: 'https://basemaps.cartocdn.com/gl/positron-gl-style/style.json',
    icon: '☀️',
  },
  darkMatter: {
    name: 'Dark',
    url: 'https://basemaps.cartocdn.com/gl/dark-matter-gl-style/style.json',
    icon: '🌙',
  },
  satellite: {
    name: 'Satellite',
    url: {
      version: 8,
      sources: {
        'esri-satellite': {
          type: 'raster',
          tiles: ['https://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}'],
          tileSize: 256,
          attribution: '&copy; Esri',
          maxzoom: 19,
        },
      },
      layers: [{ id: 'satellite-layer', type: 'raster', source: 'esri-satellite' }],
    } as maplibregl.StyleSpecification,
    icon: '🛰️',
  },
} as const;

type StyleKey = keyof typeof MAP_STYLES;

// =============================================================================
// Shape Definition
// =============================================================================

export class MapShape extends BaseBoxShapeUtil<IMapShape> {
  static override type = 'Map' as const;

  // Map theme color: Blue (consistent with mapping/navigation)
  static readonly PRIMARY_COLOR = '#4890E8';

  static override props = {
    w: T.number,
    h: T.number,
    viewport: T.any,
    styleKey: T.string,
    title: T.string,
    description: T.string,
    annotations: T.any,
    route: T.any,
    waypoints: T.any,
    collaborators: T.any,
    showSidebar: T.boolean,
    pinnedToView: T.boolean,
    tags: T.any,
    isMinimized: T.boolean,
    // Legacy compatibility properties
    interactive: T.boolean,
    showGPS: T.boolean,
    showSearch: T.boolean,
    showDirections: T.boolean,
    sharingLocation: T.boolean,
    gpsUsers: T.any,
  };

  getDefaultProps(): IMapShape['props'] {
    return {
      w: 800,
      h: 550,
      viewport: DEFAULT_VIEWPORT,
      styleKey: 'voyager',
      title: 'Collaborative Map',
      description: 'Click to explore together',
      annotations: [],
      route: null,
      waypoints: [],
      collaborators: [],
      showSidebar: true,
      pinnedToView: false,
      tags: ['map'],
      isMinimized: false,
      // Legacy compatibility defaults
      interactive: true,
      showGPS: false,
      showSearch: false,
      showDirections: false,
      sharingLocation: false,
      gpsUsers: [],
    };
  }

  override canResize() { return true; }
  override canEdit() { return false; }

  override onResize(shape: IMapShape, info: TLResizeInfo<IMapShape>) {
    return resizeBox(shape, info);
  }

  indicator(shape: IMapShape) {
    const height = shape.props.isMinimized ? 40 : shape.props.h + 40;
    return <rect x={0} y={0} width={shape.props.w} height={height} fill="none" rx={8} />;
  }

  component(shape: IMapShape) {
    const isSelected = this.editor.getSelectedShapeIds().includes(shape.id);
    return <MapComponent shape={shape} editor={this.editor} isSelected={isSelected} />;
  }
}

// =============================================================================
// Styles
// =============================================================================

const styles = {
  sidebar: {
    width: 280,
    background: '#fff',
    borderRight: '1px solid #E8E8E8',
    height: '100%',
    overflowY: 'auto' as const,
    fontSize: 13,
    zIndex: 10,
    position: 'relative' as const,
  },
  section: {
    padding: '14px 16px',
    borderBottom: '1px solid #E8E8E8',
  },
  sectionTitle: {
    fontWeight: 600,
    fontSize: 13,
    color: '#222',
    marginBottom: 10,
  },
  button: {
    border: 'none',
    borderRadius: 6,
    background: '#fff',
    cursor: 'pointer',
    transition: 'background 0.15s',
    pointerEvents: 'auto' as const,
  },
  toolbar: {
    position: 'absolute' as const,
    bottom: 20,
    left: '50%',
    transform: 'translateX(-50%)',
    background: '#fff',
    borderRadius: 12,
    boxShadow: '0 4px 20px rgba(0,0,0,0.15)',
    display: 'flex',
    padding: 6,
    gap: 4,
    zIndex: 10000,
    pointerEvents: 'auto' as const,
  },
  toolButton: {
    width: 42,
    height: 42,
    border: 'none',
    borderRadius: 8,
    background: 'transparent',
    cursor: 'pointer',
    display: 'flex',
    alignItems: 'center',
    justifyContent: 'center',
    fontSize: 18,
    transition: 'background 0.15s',
    pointerEvents: 'auto' as const,
  },
  activeToolButton: {
    background: '#222',
    color: '#fff',
  },
  mapButton: {
    pointerEvents: 'auto' as const,
    zIndex: 10000,
  },
};

// =============================================================================
// Map Component
// =============================================================================

function MapComponent({ shape, editor, isSelected }: { shape: IMapShape; editor: MapShape['editor']; isSelected: boolean }) {
  const containerRef = useRef<HTMLDivElement>(null);
  const mapRef = useRef<maplibregl.Map | null>(null);
  const markersRef = useRef<Map<string, maplibregl.Marker>>(new Map());
  const isMountedRef = useRef(true); // Track if component is still mounted

  const [isLoaded, setIsLoaded] = useState(false);
  const [activeTool, setActiveTool] = useState<'cursor' | 'marker' | 'line' | 'area' | 'eraser'>('cursor');
  const activeToolRef = useRef(activeTool); // Ref to track current tool in event handlers
  const [selectedColor, setSelectedColor] = useState(COLORS[4]);

  // Keep ref in sync with state
  useEffect(() => {
    activeToolRef.current = activeTool;
  }, [activeTool]);
  const [showColorPicker, setShowColorPicker] = useState(false);
  const [searchQuery, setSearchQuery] = useState('');
  const [searchResults, setSearchResults] = useState<any[]>([]);
  const [_nearbyPlaces, setNearbyPlaces] = useState<any[]>([]);
  const [isSearching, setIsSearching] = useState(false);
  const [isFetchingNearby, setIsFetchingNearby] = useState(false);
  const [observingUser, setObservingUser] = useState<string | null>(null);

  const styleKey = (shape.props.styleKey || 'voyager') as StyleKey;
  const currentStyle = MAP_STYLES[styleKey] || MAP_STYLES.voyager;

  // Use the pinning hook to keep the shape fixed to viewport when pinned
  usePinnedToView(editor, shape.id, shape.props.pinnedToView);

  // Use the maximize hook for fullscreen functionality
  const { isMaximized, toggleMaximize } = useMaximize({
    editor: editor,
    shapeId: shape.id,
    currentW: shape.props.w,
    currentH: shape.props.h,
    shapeType: 'Map',
  });

  // Track mounted state for cleanup
  useEffect(() => {
    isMountedRef.current = true;
    return () => {
      isMountedRef.current = false;
    };
  }, []);

  // ==========================================================================
  // Map Initialization
  // ==========================================================================

  useEffect(() => {
    if (!containerRef.current) return;

    const map = new maplibregl.Map({
      container: containerRef.current,
      style: typeof currentStyle.url === 'string' ? currentStyle.url : currentStyle.url,
      center: [shape.props.viewport.center.lng, shape.props.viewport.center.lat],
      zoom: shape.props.viewport.zoom,
      bearing: shape.props.viewport.bearing,
      pitch: shape.props.viewport.pitch,
      attributionControl: false,
    });

    mapRef.current = map;

    const handleLoad = () => {
      if (isMountedRef.current) {
        setIsLoaded(true);
      }
    };

    // Save viewport changes with null checks
    const handleMoveEnd = () => {
      if (!isMountedRef.current || !mapRef.current) return;
      try {
        const center = mapRef.current.getCenter();
        editor.updateShape<IMapShape>({
          id: shape.id,
          type: 'Map',
          props: {
            viewport: {
              center: { lat: center.lat, lng: center.lng },
              zoom: mapRef.current.getZoom(),
              bearing: mapRef.current.getBearing(),
              pitch: mapRef.current.getPitch(),
            },
          },
        });
      } catch (err) {
        // Map may have been destroyed, ignore
      }
    };

    // Handle map clicks based on active tool
    const handleClick = (e: maplibregl.MapMouseEvent) => {
      if (!isMountedRef.current) return;
      const coord = { lat: e.lngLat.lat, lng: e.lngLat.lng };
      const currentTool = activeToolRef.current;

      console.log('Map click with tool:', currentTool, 'at', coord);

      if (currentTool === 'marker') {
        addAnnotation('marker', [coord]);
      }
      // TODO: Implement line and area drawing
    };

    map.on('load', handleLoad);
    map.on('moveend', handleMoveEnd);
    map.on('click', handleClick);

    return () => {
      // Remove event listeners before destroying map
      map.off('load', handleLoad);
      map.off('moveend', handleMoveEnd);
      map.off('click', handleClick);

      // Clear all markers
      markersRef.current.forEach((marker) => {
        try {
          marker.remove();
        } catch (err) {
          // Marker may already be removed
        }
      });
      markersRef.current.clear();

      // Destroy the map
      try {
        map.remove();
      } catch (err) {
        // Map may already be destroyed
      }
      mapRef.current = null;
      setIsLoaded(false);
    };
  }, [containerRef.current]);

  // Style changes
  useEffect(() => {
    if (!mapRef.current || !isLoaded || !isMountedRef.current) return;
    try {
      mapRef.current.setStyle(typeof currentStyle.url === 'string' ? currentStyle.url : currentStyle.url);
    } catch (err) {
      // Map may have been destroyed
    }
  }, [styleKey, isLoaded]);

  // Resize
  useEffect(() => {
    if (!mapRef.current || !isLoaded || !isMountedRef.current) return;
    const resizeTimeout = setTimeout(() => {
      if (mapRef.current && isMountedRef.current) {
        try {
          mapRef.current.resize();
        } catch (err) {
          // Map may have been destroyed
        }
      }
    }, 0);
    return () => clearTimeout(resizeTimeout);
  }, [shape.props.w, shape.props.h, isLoaded, shape.props.showSidebar]);

  // ==========================================================================
  // Annotations
  // ==========================================================================

  useEffect(() => {
    if (!mapRef.current || !isLoaded || !isMountedRef.current) return;

    const map = mapRef.current;
    const currentIds = new Set(shape.props.annotations.map((a: Annotation) => a.id));

    // Remove old markers
    markersRef.current.forEach((marker, id) => {
      if (!currentIds.has(id)) {
        try {
          marker.remove();
        } catch (err) {
          // Marker may already be removed
        }
        markersRef.current.delete(id);
      }
    });

    // Add/update markers
    shape.props.annotations.forEach((ann: Annotation) => {
      if (!isMountedRef.current || !mapRef.current) return;
      if (ann.type !== 'marker' || !ann.visible) return;

      let marker = markersRef.current.get(ann.id);
      const coord = ann.coordinates[0];

      if (!marker && coord) {
        try {
          const el = document.createElement('div');
          el.className = 'map-annotation-marker';
          el.style.cssText = `
            width: 32px;
            height: 32px;
            background: ${ann.color};
            border: 3px solid white;
            border-radius: 50%;
            box-shadow: 0 2px 8px rgba(0,0,0,0.3);
            cursor: pointer;
            display: flex;
            align-items: center;
            justify-content: center;
            font-size: 14px;
          `;
          el.textContent = '📍';
          el.title = ann.name;

          const popup = new maplibregl.Popup({ offset: 20 })
            .setHTML(`<div style="padding: 8px; font-size: 13px;"><strong>${ann.name}</strong></div>`);

          marker = new maplibregl.Marker({ element: el, draggable: true })
            .setLngLat([coord.lng, coord.lat])
            .setPopup(popup)
            .addTo(map);

          marker.on('dragend', () => {
            if (!isMountedRef.current || !marker) return;
            try {
              const lngLat = marker.getLngLat();
              updateAnnotationPosition(ann.id, [{ lat: lngLat.lat, lng: lngLat.lng }]);
            } catch (err) {
              // Marker may have been removed
            }
          });

          markersRef.current.set(ann.id, marker);
        } catch (err) {
          // Map may have been destroyed
        }
      } else if (marker && coord) {
        try {
          marker.setLngLat([coord.lng, coord.lat]);
        } catch (err) {
          // Marker may have been removed
        }
      }
    });

    // Hide markers for invisible annotations
    markersRef.current.forEach((marker, id) => {
      const ann = shape.props.annotations.find((a: Annotation) => a.id === id);
      if (ann && !ann.visible) {
        try {
          marker.remove();
        } catch (err) {
          // Marker may already be removed
        }
        markersRef.current.delete(id);
      }
    });
  }, [shape.props.annotations, isLoaded]);

  // ==========================================================================
  // Collaborator presence (cursors/locations)
  // ==========================================================================

  useEffect(() => {
    if (!mapRef.current || !isLoaded || !isMountedRef.current) return;

    // TODO: Render collaborator cursors on map
    // This would be integrated with tldraw's presence system
  }, [shape.props.collaborators, isLoaded]);

  // ==========================================================================
  // Actions
  // ==========================================================================

  const addAnnotation = useCallback((type: Annotation['type'], coordinates: Coordinate[], options?: { name?: string; color?: string }) => {
    const newAnnotation: Annotation = {
      id: `ann-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`,
      type,
      name: options?.name || `${type.charAt(0).toUpperCase() + type.slice(1)} ${shape.props.annotations.length + 1}`,
      color: options?.color || selectedColor,
      visible: true,
      coordinates,
      createdAt: Date.now(),
    };

    editor.updateShape<IMapShape>({
      id: shape.id,
      type: 'Map',
      props: { annotations: [...shape.props.annotations, newAnnotation] },
    });
  }, [shape.props.annotations, selectedColor, shape.id, editor]);

  const updateAnnotationPosition = useCallback((annotationId: string, coordinates: Coordinate[]) => {
    const updated = shape.props.annotations.map((ann: Annotation) =>
      ann.id === annotationId ? { ...ann, coordinates } : ann
    );
    editor.updateShape<IMapShape>({
      id: shape.id,
      type: 'Map',
      props: { annotations: updated },
    });
  }, [shape.props.annotations, shape.id, editor]);

  const toggleAnnotationVisibility = useCallback((annotationId: string) => {
    const updated = shape.props.annotations.map((ann: Annotation) =>
      ann.id === annotationId ? { ...ann, visible: !ann.visible } : ann
    );
    editor.updateShape<IMapShape>({
      id: shape.id,
      type: 'Map',
      props: { annotations: updated },
    });
  }, [shape.props.annotations, shape.id, editor]);

  const removeAnnotation = useCallback((annotationId: string) => {
    const updated = shape.props.annotations.filter((ann: Annotation) => ann.id !== annotationId);
    editor.updateShape<IMapShape>({
      id: shape.id,
      type: 'Map',
      props: { annotations: updated },
    });
  }, [shape.props.annotations, shape.id, editor]);

  const hideAllAnnotations = useCallback(() => {
    const updated = shape.props.annotations.map((ann: Annotation) => ({ ...ann, visible: false }));
    editor.updateShape<IMapShape>({
      id: shape.id,
      type: 'Map',
      props: { annotations: updated },
    });
  }, [shape.props.annotations, shape.id, editor]);

  // ==========================================================================
  // Search
  // ==========================================================================

  const searchPlaces = useCallback(async () => {
    if (!searchQuery.trim()) return;
    setIsSearching(true);
    try {
      const response = await fetch(
        `https://nominatim.openstreetmap.org/search?format=json&q=${encodeURIComponent(searchQuery)}&limit=6`,
        { headers: { 'User-Agent': 'CanvasWebsite/1.0' } }
      );
      const data = await response.json() as { display_name: string; lat: string; lon: string }[];
      setSearchResults(data.map((r) => ({
        name: r.display_name,
        lat: parseFloat(r.lat),
        lng: parseFloat(r.lon),
      })));
    } catch (err) {
      console.error('Search error:', err);
    } finally {
      setIsSearching(false);
    }
  }, [searchQuery]);

  const selectSearchResult = useCallback((result: { lat: number; lng: number; name: string }) => {
    if (mapRef.current && isMountedRef.current) {
      try {
        mapRef.current.flyTo({ center: [result.lng, result.lat], zoom: 15, duration: 1000 });
      } catch (err) {
        // Map may have been destroyed
      }
    }
    setSearchQuery('');
    setSearchResults([]);
  }, []);

  // ==========================================================================
  // Find Nearby
  // ==========================================================================

  const findNearby = useCallback(async (category: typeof NEARBY_CATEGORIES[0]) => {
    if (!mapRef.current || !isMountedRef.current) return;

    console.log('🗺️ findNearby called for category:', category.label);
    setIsFetchingNearby(true);

    let bounds;
    try {
      bounds = mapRef.current.getBounds();
      console.log('🗺️ Map bounds:', bounds.toString());
    } catch (err) {
      console.error('🗺️ Error getting bounds:', err);
      setIsFetchingNearby(false);
      return;
    }

    try {
      const query = `
        [out:json][timeout:10];
        (
          node["amenity"~"${category.types.replace(/,/g, '|')}"](${bounds.getSouth()},${bounds.getWest()},${bounds.getNorth()},${bounds.getEast()});
        );
        out body 10;
      `;
      console.log('🗺️ Overpass query:', query);

      const response = await fetch('https://overpass-api.de/api/interpreter', {
        method: 'POST',
        body: query,
      });

      if (!isMountedRef.current) {
        setIsFetchingNearby(false);
        return;
      }

      console.log('🗺️ Overpass response status:', response.status);
      const data = await response.json() as { elements: { id: number; lat: number; lon: number; tags?: { name?: string; amenity?: string } }[] };
      console.log('🗺️ Found', data.elements.length, 'places');

      const places = data.elements.slice(0, 10).map((el) => ({
        id: el.id,
        name: el.tags?.name || category.label,
        lat: el.lat,
        lng: el.lon,
        type: el.tags?.amenity || category.key,
        color: category.color,
      }));

      if (!isMountedRef.current) {
        setIsFetchingNearby(false);
        return;
      }
      setNearbyPlaces(places);

      // Add markers for nearby places
      console.log('🗺️ Adding', places.length, 'markers');
      places.forEach((place: any) => {
        if (isMountedRef.current) {
          addAnnotation('marker', [{ lat: place.lat, lng: place.lng }], {
            name: place.name,
            color: place.color,
          });
        }
      });
      setIsFetchingNearby(false);
    } catch (err) {
      console.error('🗺️ Find nearby error:', err);
      setIsFetchingNearby(false);
    }
  }, [addAnnotation]);

  // ==========================================================================
  // Observe User
  // ==========================================================================

  const observeUser = useCallback((userId: string | null) => {
    setObservingUser(userId);
    if (userId && mapRef.current && isMountedRef.current) {
      const collaborator = shape.props.collaborators.find((c: CollaboratorPresence) => c.id === userId);
      if (collaborator?.location) {
        try {
          mapRef.current.flyTo({
            center: [collaborator.location.lng, collaborator.location.lat],
            zoom: 15,
            duration: 1000,
          });
        } catch (err) {
          // Map may have been destroyed
        }
      }
    }
  }, [shape.props.collaborators]);

  // ==========================================================================
  // Title/Description
  // ==========================================================================

  const updateTitle = useCallback((title: string) => {
    editor.updateShape<IMapShape>({
      id: shape.id,
      type: 'Map',
      props: { title },
    });
  }, [shape.id, editor]);

  const updateDescription = useCallback((description: string) => {
    editor.updateShape<IMapShape>({
      id: shape.id,
      type: 'Map',
      props: { description },
    });
  }, [shape.id, editor]);

  // ==========================================================================
  // Toggle Sidebar
  // ==========================================================================

  const toggleSidebar = useCallback(() => {
    editor.updateShape<IMapShape>({
      id: shape.id,
      type: 'Map',
      props: { showSidebar: !shape.props.showSidebar },
    });
  }, [shape.id, shape.props.showSidebar, editor]);

  // ==========================================================================
  // Style Change
  // ==========================================================================

  const changeStyle = useCallback((key: StyleKey) => {
    editor.updateShape<IMapShape>({
      id: shape.id,
      type: 'Map',
      props: { styleKey: key },
    });
  }, [shape.id, editor]);

  // ==========================================================================
  // Event Handlers
  // ==========================================================================

  const stopPropagation = useCallback((e: { stopPropagation: () => void }) => {
    e.stopPropagation();
  }, []);

  // Handle wheel events on map container - attach native listener for proper capture
  useEffect(() => {
    const mapContainer = containerRef.current?.parentElement;
    if (!mapContainer) return;

    const handleWheel = (e: WheelEvent) => {
      // Stop propagation to prevent tldraw from capturing the wheel event
      e.stopPropagation();
      // Let maplibre handle the wheel event natively for zooming
      // Don't prevent default - let the map's scrollZoom handle it
    };

    // Capture wheel events before they bubble up to tldraw
    mapContainer.addEventListener('wheel', handleWheel, { passive: true });

    return () => {
      mapContainer.removeEventListener('wheel', handleWheel);
    };
  }, [isLoaded]);

  // Close handler for StandardizedToolWrapper
  const handleClose = useCallback(() => {
    editor.deleteShape(shape.id);
  }, [editor, shape.id]);

  // Minimize handler
  const handleMinimize = useCallback(() => {
    editor.updateShape<IMapShape>({
      id: shape.id,
      type: 'Map',
      props: { isMinimized: !shape.props.isMinimized },
    });
  }, [editor, shape.id, shape.props.isMinimized]);

  // Pin handler
  const handlePinToggle = useCallback(() => {
    editor.updateShape<IMapShape>({
      id: shape.id,
      type: 'Map',
      props: { pinnedToView: !shape.props.pinnedToView },
    });
  }, [editor, shape.id, shape.props.pinnedToView]);

  // Tags handler
  const handleTagsChange = useCallback((newTags: string[]) => {
    editor.updateShape<IMapShape>({
      id: shape.id,
      type: 'Map',
      props: { tags: newTags },
    });
  }, [editor, shape.id]);

  // ==========================================================================
  // Render
  // ==========================================================================

  const contentHeight = shape.props.h;

  return (
    <HTMLContainer style={{ width: shape.props.w, height: contentHeight + 40 }}>
      <style>{`
        .mapus-sidebar::-webkit-scrollbar { width: 6px; }
        .mapus-sidebar::-webkit-scrollbar-thumb { background: #ddd; border-radius: 3px; }
        .mapus-btn:hover { background: #f7f7f7 !important; }
        .mapus-btn:active { transform: scale(0.97); }
        .mapus-category:hover { background: #f7f7f7 !important; }
        .mapus-annotation:hover { background: #f7f7f7; }
        .mapus-result:hover { background: #f3f4f6 !important; }
        .mapus-tool:hover { background: #f7f7f7; }
        .mapus-tool.active { background: #222 !important; color: #fff !important; }
        .mapus-color:hover { transform: scale(1.15); }
        .mapus-color.selected { transform: scale(1.2); box-shadow: 0 0 0 2px #222; }
        @keyframes pulse { 0%, 100% { opacity: 1; } 50% { opacity: 0.5; } }
      `}</style>

      <StandardizedToolWrapper
        title={shape.props.title || 'Collaborative Map'}
        primaryColor={MapShape.PRIMARY_COLOR}
        isSelected={isSelected}
        width={shape.props.w}
        height={contentHeight + 40}
        onClose={handleClose}
        onMinimize={handleMinimize}
        isMinimized={shape.props.isMinimized}
        onMaximize={toggleMaximize}
        isMaximized={isMaximized}
        editor={editor}
        shapeId={shape.id}
        isPinnedToView={shape.props.pinnedToView}
        onPinToggle={handlePinToggle}
        tags={shape.props.tags || ['map']}
        onTagsChange={handleTagsChange}
        tagsEditable={true}
      >
        <div
          style={{
            width: '100%',
            height: '100%',
            display: 'flex',
            position: 'relative',
            fontFamily: 'Inter, -apple-system, BlinkMacSystemFont, sans-serif',
          }}
        >
          {/* Left Sidebar */}
          {shape.props.showSidebar && (
            <div
              className="mapus-sidebar"
              style={styles.sidebar}
              onPointerDown={stopPropagation}
            >
              {/* Search */}
              <div style={styles.section}>
                <div style={{ display: 'flex', gap: 6 }}>
                  <input
                    type="text"
                    value={searchQuery}
                    onChange={(e) => setSearchQuery(e.target.value)}
                    onKeyDown={(e) => {
                      e.stopPropagation();
                      if (e.key === 'Enter') searchPlaces();
                    }}
                    onPointerDown={stopPropagation}
                    placeholder="Search for a place..."
                    style={{
                      flex: 1,
                      padding: '10px 12px',
                      border: '1px solid #E8E8E8',
                      borderRadius: 6,
                      fontSize: 13,
                      outline: 'none',
                    }}
                  />
                  <button
                    onClick={searchPlaces}
                    onPointerDown={stopPropagation}
                    className="mapus-btn"
                    style={{
                      ...styles.button,
                      padding: '10px 14px',
                      border: '1px solid #E8E8E8',
                    }}
                  >
                    {isSearching ? '⏳' : '🔍'}
                  </button>
                </div>

                {/* Search Results */}
                {searchResults.length > 0 && (
                  <div style={{ marginTop: 8, maxHeight: 200, overflowY: 'auto' }}>
                    {searchResults.map((result, i) => (
                      <div
                        key={i}
                        className="mapus-result"
                        onClick={() => selectSearchResult(result)}
                        onPointerDown={stopPropagation}
                        style={{
                          padding: '10px 8px',
                          cursor: 'pointer',
                          fontSize: 12,
                          borderRadius: 4,
                        }}
                      >
                        📍 {result.name.slice(0, 50)}...
                      </div>
                    ))}
                  </div>
                )}
              </div>

              {/* Find Nearby */}
              <div style={styles.section}>
                <div style={styles.sectionTitle}>
                  Find nearby {isFetchingNearby && <span style={{ marginLeft: 8, fontSize: 12 }}>⏳</span>}
                </div>
                <div style={{ display: 'grid', gridTemplateColumns: 'repeat(4, 1fr)', gap: 4, opacity: isFetchingNearby ? 0.5 : 1 }}>
                  {NEARBY_CATEGORIES.map((cat) => (
                    <div
                      key={cat.key}
                      className="mapus-category"
                      onClick={() => !isFetchingNearby && findNearby(cat)}
                      onPointerDown={stopPropagation}
                      style={{
                        textAlign: 'center',
                        padding: '10px 4px',
                        borderRadius: 6,
                        cursor: isFetchingNearby ? 'wait' : 'pointer',
                        fontSize: 11,
                        color: '#626C72',
                      }}
                    >
                      <div style={{ fontSize: 22, marginBottom: 4 }}>{cat.icon}</div>
                      {cat.label}
                    </div>
                  ))}
                </div>
              </div>

              {/* Collaborators */}
              {shape.props.collaborators.length > 0 && (
                <div style={styles.section}>
                  <div style={styles.sectionTitle}>People ({shape.props.collaborators.length})</div>
                  {shape.props.collaborators.map((collab: CollaboratorPresence) => (
                    <div
                      key={collab.id}
                      className="mapus-annotation"
                      onClick={() => observeUser(observingUser === collab.id ? null : collab.id)}
                      onPointerDown={stopPropagation}
                      style={{
                        display: 'flex',
                        alignItems: 'center',
                        gap: 10,
                        padding: '8px 6px',
                        borderRadius: 6,
                        cursor: 'pointer',
                        background: observingUser === collab.id ? '#f0fdf4' : 'transparent',
                      }}
                    >
                      <div style={{
                        width: 28,
                        height: 28,
                        borderRadius: '50%',
                        background: collab.color,
                        display: 'flex',
                        alignItems: 'center',
                        justifyContent: 'center',
                        fontSize: 12,
                        color: 'white',
                        fontWeight: 600,
                      }}>
                        {collab.name[0].toUpperCase()}
                      </div>
                      <div style={{ flex: 1 }}>
                        <div style={{ fontSize: 13, fontWeight: 500 }}>{collab.name}</div>
                        {observingUser === collab.id && (
                          <div style={{ fontSize: 11, color: '#22c55e' }}>👁️ Observing</div>
                        )}
                      </div>
                    </div>
                  ))}
                </div>
              )}

              {/* Annotations */}
              <div style={styles.section}>
                <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: 10 }}>
                  <div style={styles.sectionTitle}>Annotations</div>
                  <button
                    onClick={hideAllAnnotations}
                    onPointerDown={stopPropagation}
                    className="mapus-btn"
                    style={{ ...styles.button, fontSize: 12, padding: '4px 8px', color: '#626C72' }}
                  >
                    Hide all
                  </button>
                </div>

                {shape.props.annotations.length === 0 ? (
                  <div style={{ fontSize: 12, color: '#9ca3af', textAlign: 'center', padding: 16 }}>
                    No annotations yet.<br />Use the tools below to add some!
                  </div>
                ) : (
                  <div style={{ maxHeight: 200, overflowY: 'auto' }}>
                    {shape.props.annotations.map((ann: Annotation) => (
                      <div
                        key={ann.id}
                        className="mapus-annotation"
                        onPointerDown={stopPropagation}
                        style={{
                          display: 'flex',
                          alignItems: 'center',
                          gap: 8,
                          padding: '8px 6px',
                          borderRadius: 6,
                          cursor: 'pointer',
                          opacity: ann.visible ? 1 : 0.5,
                        }}
                      >
                        <div style={{
                          width: 12,
                          height: 12,
                          borderRadius: '50%',
                          background: ann.color,
                        }} />
                        <div style={{ flex: 1, fontSize: 13, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>
                          {ann.name}
                        </div>
                        <button
                          onClick={(e) => { e.stopPropagation(); toggleAnnotationVisibility(ann.id); }}
                          onPointerDown={stopPropagation}
                          className="mapus-btn"
                          style={{ ...styles.button, padding: 4, fontSize: 14 }}
                        >
                          {ann.visible ? '👁️' : '👁️‍🗨️'}
                        </button>
                        <button
                          onClick={(e) => { e.stopPropagation(); removeAnnotation(ann.id); }}
                          onPointerDown={stopPropagation}
                          className="mapus-btn"
                          style={{ ...styles.button, padding: 4, fontSize: 14, color: '#E15F59' }}
                        >
                          ✕
                        </button>
                      </div>
                    ))}
                  </div>
                )}
              </div>

              {/* Attribution */}
              <div style={{ ...styles.section, borderBottom: 'none', fontSize: 11, color: '#9ca3af' }}>
                © <a href="https://www.openstreetmap.org/copyright" target="_blank" rel="noopener" style={{ color: '#9ca3af' }}>OpenStreetMap</a>
              </div>
            </div>
          )}

          {/* Map Container */}
          <div
            style={{ flex: 1, position: 'relative', pointerEvents: 'auto' }}
            onPointerDown={stopPropagation}
          >
            <div ref={containerRef} style={{ width: '100%', height: '100%', pointerEvents: 'auto' }} />

            {/* Sidebar Toggle */}
            <button
              onClick={toggleSidebar}
              onPointerDown={stopPropagation}
              className="mapus-btn"
              style={{
                position: 'absolute',
                top: 10,
                left: 10,
                width: 36,
                height: 36,
                borderRadius: 8,
                background: '#fff',
                border: 'none',
                boxShadow: '0 2px 8px rgba(0,0,0,0.15)',
                cursor: 'pointer',
                display: 'flex',
                alignItems: 'center',
                justifyContent: 'center',
                fontSize: 18,
                zIndex: 10,
              }}
            >
              {shape.props.showSidebar ? '◀' : '▶'}
            </button>

            {/* Style Picker */}
            <div style={{ position: 'absolute', top: 10, right: 10, zIndex: 10 }}>
              <select
                value={styleKey}
                onChange={(e) => changeStyle(e.target.value as StyleKey)}
                onPointerDown={stopPropagation}
                style={{
                  padding: '8px 12px',
                  borderRadius: 6,
                  border: 'none',
                  background: '#fff',
                  boxShadow: '0 2px 8px rgba(0,0,0,0.15)',
                  fontSize: 13,
                  cursor: 'pointer',
                }}
              >
                {Object.entries(MAP_STYLES).map(([key, style]) => (
                  <option key={key} value={key}>{style.icon} {style.name}</option>
                ))}
              </select>
            </div>

            {/* Zoom Controls */}
            <div style={{ position: 'absolute', bottom: 80, right: 10, display: 'flex', flexDirection: 'column', gap: 4, zIndex: 10 }}>
              <button
                onClick={() => mapRef.current?.zoomIn()}
                onPointerDown={stopPropagation}
                className="mapus-btn"
                style={{
                  width: 36,
                  height: 36,
                  borderRadius: 8,
                  background: '#fff',
                  border: 'none',
                  boxShadow: '0 2px 8px rgba(0,0,0,0.15)',
                  cursor: 'pointer',
                  fontSize: 18,
                }}
              >
                +
              </button>
              <button
                onClick={() => mapRef.current?.zoomOut()}
                onPointerDown={stopPropagation}
                className="mapus-btn"
                style={{
                  width: 36,
                  height: 36,
                  borderRadius: 8,
                  background: '#fff',
                  border: 'none',
                  boxShadow: '0 2px 8px rgba(0,0,0,0.15)',
                  cursor: 'pointer',
                  fontSize: 18,
                }}
              >
                −
              </button>
              <button
                onClick={() => {
                  navigator.geolocation?.getCurrentPosition((pos) => {
                    mapRef.current?.flyTo({
                      center: [pos.coords.longitude, pos.coords.latitude],
                      zoom: 15,
                      duration: 1000,
                    });
                  });
                }}
                onPointerDown={stopPropagation}
                className="mapus-btn"
                style={{
                  width: 36,
                  height: 36,
                  borderRadius: 8,
                  background: '#fff',
                  border: 'none',
                  boxShadow: '0 2px 8px rgba(0,0,0,0.15)',
                  cursor: 'pointer',
                  fontSize: 16,
                  marginTop: 4,
                }}
                title="My location"
              >
                ⊙
              </button>
            </div>

            {/* Drawing Toolbar (Mapus-style) */}
            <div style={styles.toolbar} onPointerDown={stopPropagation}>
              {/* Cursor Tool */}
              <button
                onClick={() => setActiveTool('cursor')}
                className={`mapus-tool ${activeTool === 'cursor' ? 'active' : ''}`}
                style={styles.toolButton}
                title="Select"
              >
                ↖️
              </button>

              {/* Marker Tool */}
              <button
                onClick={() => setActiveTool('marker')}
                className={`mapus-tool ${activeTool === 'marker' ? 'active' : ''}`}
                style={styles.toolButton}
                title="Add marker"
              >
                📍
              </button>

              {/* Line Tool */}
              <button
                onClick={() => setActiveTool('line')}
                className={`mapus-tool ${activeTool === 'line' ? 'active' : ''}`}
                style={styles.toolButton}
                title="Draw line"
              >
                📏
              </button>

              {/* Area Tool */}
              <button
                onClick={() => setActiveTool('area')}
                className={`mapus-tool ${activeTool === 'area' ? 'active' : ''}`}
                style={styles.toolButton}
                title="Draw area"
              >
                ⬡
              </button>

              {/* Eraser */}
              <button
                onClick={() => setActiveTool('eraser')}
                className={`mapus-tool ${activeTool === 'eraser' ? 'active' : ''}`}
                style={styles.toolButton}
                title="Eraser"
              >
                🧹
              </button>

              {/* Divider */}
              <div style={{ width: 1, background: '#E8E8E8', margin: '4px 6px' }} />

              {/* Color Picker */}
              <div style={{ position: 'relative' }}>
                <button
                  onClick={() => setShowColorPicker(!showColorPicker)}
                  style={{
                    ...styles.toolButton,
                    background: 'transparent',
                    border: 'none',
                    cursor: 'pointer',
                  }}
                  title="Color"
                >
                  <div style={{
                    width: 24,
                    height: 24,
                    borderRadius: '50%',
                    background: selectedColor,
                    border: '2px solid #fff',
                    boxShadow: '0 1px 4px rgba(0,0,0,0.2)',
                  }} />
                </button>

                {showColorPicker && (
                  <div style={{
                    position: 'absolute',
                    bottom: '100%',
                    left: '50%',
                    transform: 'translateX(-50%)',
                    marginBottom: 8,
                    background: '#fff',
                    borderRadius: 8,
                    boxShadow: '0 4px 16px rgba(0,0,0,0.2)',
                    padding: 8,
                    display: 'flex',
                    gap: 6,
                  }}>
                    {COLORS.map((color) => (
                      <div
                        key={color}
                        className={`mapus-color ${selectedColor === color ? 'selected' : ''}`}
                        onClick={() => { setSelectedColor(color); setShowColorPicker(false); }}
                        style={{
                          width: 28,
                          height: 28,
                          borderRadius: '50%',
                          background: color,
                          cursor: 'pointer',
                          transition: 'transform 0.15s',
                        }}
                      />
                    ))}
                  </div>
                )}
              </div>
            </div>

            {/* Observing Indicator */}
            {observingUser && (
              <div style={{
                position: 'absolute',
                top: 8,
                left: 8,
                right: 8,
                bottom: 8,
                pointerEvents: 'none',
                border: `3px solid ${shape.props.collaborators.find((c: CollaboratorPresence) => c.id === observingUser)?.color || '#3b82f6'}`,
                borderRadius: 8,
              }}>
                <div style={{
                  position: 'absolute',
                  top: -30,
                  left: 10,
                  background: shape.props.collaborators.find((c: CollaboratorPresence) => c.id === observingUser)?.color || '#3b82f6',
                  color: '#fff',
                  padding: '4px 10px',
                  borderRadius: 4,
                  fontSize: 12,
                  fontWeight: 500,
                }}>
                  👁️ Observing {shape.props.collaborators.find((c: CollaboratorPresence) => c.id === observingUser)?.name}
                </div>
              </div>
            )}
          </div>
        </div>
      </StandardizedToolWrapper>
    </HTMLContainer>
  );
}

export default MapShape;
