import { useState, useMemo } from 'react';
import { defineStory, useSelect, useNumber, useBoolean } from '@djangocfg/playground';
import { MapContainer, MapMarker, MapPopup, MapProvider, MapView, MapCluster, useMapControl } from './index';
import { offsetOverlappingMarkers } from './utils/spiderfy';

export default defineStory({
  title: 'Tools/Map',
  component: MapContainer,
  description: 'Interactive map component using MapLibre GL.',
});

// Sample property locations
const PROPERTIES = {
  dubai: {
    id: 'dubai-marina',
    latitude: 25.0805,
    longitude: 55.1403,
    name: 'Dubai Marina Tower',
    address: 'Dubai Marina, Dubai, UAE',
    price: '$2,500,000',
  },
  london: {
    id: 'london-chelsea',
    latitude: 51.4875,
    longitude: -0.1687,
    name: 'Chelsea Townhouse',
    address: 'Chelsea, London, UK',
    price: '£3,200,000',
  },
  nyc: {
    id: 'nyc-manhattan',
    latitude: 40.7580,
    longitude: -73.9855,
    name: 'Manhattan Penthouse',
    address: 'Midtown, New York, USA',
    price: '$5,800,000',
  },
  paris: {
    id: 'paris-marais',
    latitude: 48.8566,
    longitude: 2.3522,
    name: 'Le Marais Apartment',
    address: 'Le Marais, Paris, France',
    price: '€1,900,000',
  },
  tokyo: {
    id: 'tokyo-shibuya',
    latitude: 35.6595,
    longitude: 139.7004,
    name: 'Shibuya Residence',
    address: 'Shibuya, Tokyo, Japan',
    price: '¥180,000,000',
  },
};

export const Interactive = () => {
  const [property] = useSelect('property', {
    options: ['dubai', 'london', 'nyc', 'paris', 'tokyo'] as const,
    defaultValue: 'dubai',
    label: 'Property',
    description: 'Select property location',
  });

  const [mapStyle] = useSelect('mapStyle', {
    options: ['light', 'dark', 'streets', 'satellite'] as const,
    defaultValue: 'light',
    label: 'Map Style',
    description: 'Map visual style',
  });

  const [zoom] = useNumber('zoom', {
    defaultValue: 14,
    min: 1,
    max: 18,
    label: 'Zoom Level',
    description: 'Map zoom level',
  });

  const [showMarker] = useBoolean('showMarker', {
    defaultValue: true,
    label: 'Show Marker',
    description: 'Display property marker',
  });

  const [showResetButton] = useBoolean('showResetButton', {
    defaultValue: true,
    label: 'Reset Button',
    description: 'Show reset view button',
  });

  const loc = PROPERTIES[property];
  const googleMapsUrl = `https://www.google.com/maps?q=${loc.latitude},${loc.longitude}`;

  return (
    <div className="space-y-4">
      {/* Property info */}
      <div className="p-4 rounded-lg border border-border bg-card">
        <h3 className="font-semibold text-foreground">{loc.name}</h3>
        <p className="text-sm text-muted-foreground">{loc.address}</p>
        <p className="text-lg font-bold text-primary mt-2">{loc.price}</p>
      </div>

      {/* Map */}
      <div className="h-80 rounded-xl overflow-hidden border border-border" key={`${property}-${zoom}-${mapStyle}`}>
        <MapContainer
          initialViewport={{
            latitude: loc.latitude,
            longitude: loc.longitude,
            zoom,
          }}
          mapStyle={mapStyle}
          openInMapsUrl={googleMapsUrl}
          showResetButton={showResetButton}
          autoResetDelay={5000}
        >
          {showMarker && (
            <MapMarker marker={loc} color="#10b981" size={32} />
          )}
        </MapContainer>
      </div>
    </div>
  );
};

export const PropertyCard = () => {
  const loc = PROPERTIES.dubai;
  const googleMapsUrl = `https://www.google.com/maps?q=${loc.latitude},${loc.longitude}`;

  return (
    <div className="max-w-md rounded-xl border border-border bg-card overflow-hidden">
      {/* Map */}
      <div className="aspect-[2/1]">
        <MapContainer
          initialViewport={{
            latitude: loc.latitude,
            longitude: loc.longitude,
            zoom: 14,
          }}
          mapStyle="light"
          attributionControl={false}
          openInMapsUrl={googleMapsUrl}
          autoResetDelay={5000}
        >
          <MapMarker marker={loc} color="#10b981" size={32} />
        </MapContainer>
      </div>

      {/* Property info */}
      <div className="p-4">
        <h3 className="font-semibold text-foreground">{loc.name}</h3>
        <p className="text-sm text-muted-foreground">{loc.address}</p>
        <p className="text-lg font-bold text-primary mt-2">{loc.price}</p>
      </div>
    </div>
  );
};

export const DarkStyle = () => {
  const loc = PROPERTIES.tokyo;

  return (
    <div className="h-96 rounded-xl overflow-hidden border border-border">
      <MapContainer
        initialViewport={{
          latitude: loc.latitude,
          longitude: loc.longitude,
          zoom: 13,
        }}
        mapStyle="dark"
      >
        <MapMarker marker={loc} color="#f97316" size={28} />
      </MapContainer>
    </div>
  );
};

export const MultipleMarkers = () => (
  <div className="h-96 rounded-xl overflow-hidden border border-border">
    <MapContainer
      initialViewport={{
        latitude: 40,
        longitude: 0,
        zoom: 2,
      }}
      mapStyle="light"
      showResetButton
    >
      {Object.values(PROPERTIES).map((prop) => (
        <MapMarker key={prop.id} marker={prop} color="#3b82f6" size={24} />
      ))}
    </MapContainer>
  </div>
);

export const WithAutoReset = () => {
  const loc = PROPERTIES.london;

  return (
    <div className="space-y-2">
      <p className="text-sm text-muted-foreground">
        Pan/zoom the map — it will reset after 3 seconds of inactivity
      </p>
      <div className="h-80 rounded-xl overflow-hidden border border-border">
        <MapContainer
          initialViewport={{
            latitude: loc.latitude,
            longitude: loc.longitude,
            zoom: 15,
          }}
          mapStyle="streets"
          autoResetDelay={3000}
          showResetButton
        >
          <MapMarker marker={loc} color="#ec4899" size={32} />
        </MapContainer>
      </div>
    </div>
  );
};

type PropertyKey = keyof typeof PROPERTIES;

// Inner component that uses useMapControl (must be inside MapProvider)
function MapWithPopupInner({
  selectedId,
  setSelectedId,
}: {
  selectedId: PropertyKey | null;
  setSelectedId: (id: PropertyKey | null) => void;
}) {
  const { flyTo } = useMapControl();
  const selectedProperty = selectedId ? PROPERTIES[selectedId] : null;

  const handleMarkerClick = (key: PropertyKey) => {
    const prop = PROPERTIES[key];
    setSelectedId(key);
    // Fly to the selected marker with animation
    flyTo([prop.longitude, prop.latitude], 12, { duration: 1500 });
  };

  return (
    <MapView mapStyle="light" showResetButton>
      {(Object.entries(PROPERTIES) as [PropertyKey, typeof PROPERTIES[PropertyKey]][]).map(([key, prop]) => (
        <MapMarker
          key={prop.id}
          marker={prop}
          color={selectedId === key ? '#10b981' : '#3b82f6'}
          size={selectedId === key ? 36 : 28}
          onClick={() => handleMarkerClick(key)}
        />
      ))}

      {selectedProperty && (
        <MapPopup
          longitude={selectedProperty.longitude}
          latitude={selectedProperty.latitude}
          onClose={() => setSelectedId(null)}
          anchor="bottom"
          offset={20}
        >
          <div className="p-3 min-w-48">
            <h3 className="font-semibold text-foreground text-sm">{selectedProperty.name}</h3>
            <p className="text-xs text-muted-foreground mt-1">{selectedProperty.address}</p>
            <p className="text-base font-bold text-primary mt-2">{selectedProperty.price}</p>
            <a
              href={`https://www.google.com/maps?q=${selectedProperty.latitude},${selectedProperty.longitude}`}
              target="_blank"
              rel="noopener noreferrer"
              className="mt-3 block w-full text-center text-xs px-3 py-1.5 bg-primary text-primary-foreground rounded-md hover:bg-primary/90 transition-colors"
            >
              View on Google Maps
            </a>
          </div>
        </MapPopup>
      )}
    </MapView>
  );
}

export const WithPopup = () => {
  const [selectedId, setSelectedId] = useState<PropertyKey | null>(null);

  return (
    <div className="space-y-2">
      <p className="text-sm text-muted-foreground">
        Click on markers to fly to property and see details
      </p>
      <div className="h-96 rounded-xl overflow-hidden border border-border">
        <MapProvider
          initialViewport={{
            latitude: 40,
            longitude: 0,
            zoom: 2,
          }}
        >
          <MapWithPopupInner selectedId={selectedId} setSelectedId={setSelectedId} />
        </MapProvider>
      </div>
    </div>
  );
};

// =============================================================================
// Spiderfy Demo - Overlapping Markers
// =============================================================================

// Generate multiple points at the same location (simulating overlapping markers)
const SPIDERFY_POINTS: GeoJSON.FeatureCollection = {
  type: 'FeatureCollection',
  features: [
    // Group 1: 5 apartments at same building in Paris
    ...Array.from({ length: 5 }, (_, i) => ({
      type: 'Feature' as const,
      properties: {
        id: `paris-apt-${i + 1}`,
        name: `Paris Apartment ${i + 1}`,
        floor: i + 1,
        price: `€${(800 + i * 50).toLocaleString()},000`,
      },
      geometry: {
        type: 'Point' as const,
        coordinates: [2.3522, 48.8566], // Exact same location
      },
    })),
    // Group 2: 3 offices at same building in London
    ...Array.from({ length: 3 }, (_, i) => ({
      type: 'Feature' as const,
      properties: {
        id: `london-office-${i + 1}`,
        name: `London Office ${i + 1}`,
        floor: i * 2 + 1,
        price: `£${(1200 + i * 100).toLocaleString()},000`,
      },
      geometry: {
        type: 'Point' as const,
        coordinates: [-0.1276, 51.5074], // Same location
      },
    })),
    // Group 3: 8 units in NYC building
    ...Array.from({ length: 8 }, (_, i) => ({
      type: 'Feature' as const,
      properties: {
        id: `nyc-unit-${i + 1}`,
        name: `NYC Unit ${i + 1}`,
        floor: i + 1,
        price: `$${(500 + i * 75).toLocaleString()},000`,
      },
      geometry: {
        type: 'Point' as const,
        coordinates: [-73.9857, 40.7484], // Same location (Empire State)
      },
    })),
    // Single point in Tokyo (no overlap)
    {
      type: 'Feature' as const,
      properties: {
        id: 'tokyo-single',
        name: 'Tokyo Tower View',
        floor: 1,
        price: '¥95,000,000',
      },
      geometry: {
        type: 'Point' as const,
        coordinates: [139.7454, 35.6586],
      },
    },
  ],
};

export const SpiderfyCluster = () => {
  const [selectedFeature, setSelectedFeature] = useState<GeoJSON.Feature | null>(null);

  // Pre-process data: offset overlapping points so they're visible when unclustered
  const processedData = useMemo(() => {
    // Convert GeoJSON features to MarkerData format for offsetting
    const markers = SPIDERFY_POINTS.features.map((f, i) => ({
      id: f.properties?.id || `point-${i}`,
      longitude: (f.geometry as GeoJSON.Point).coordinates[0],
      latitude: (f.geometry as GeoJSON.Point).coordinates[1],
      data: f.properties,
    }));

    // Apply offset to overlapping markers
    const offsetMarkers = offsetOverlappingMarkers(markers, {
      spiralRadius: 0.0003, // ~30m spread
    });

    // Convert back to GeoJSON
    return {
      type: 'FeatureCollection' as const,
      features: offsetMarkers.map((m) => ({
        type: 'Feature' as const,
        properties: m.data,
        geometry: {
          type: 'Point' as const,
          coordinates: [m.longitude, m.latitude],
        },
      })),
    };
  }, []);

  return (
    <div className="space-y-2">
      <p className="text-sm text-muted-foreground">
        Overlapping points are automatically offset so they're visible at high zoom.
        <br />
        <span className="text-xs">Paris: 5 apartments • London: 3 offices • NYC: 8 units • Tokyo: 1 property</span>
      </p>
      <div className="h-[500px] rounded-xl overflow-hidden border border-border">
        <MapContainer
          initialViewport={{
            latitude: 45,
            longitude: -20,
            zoom: 2,
          }}
          mapStyle="light"
          showResetButton
        >
          <MapCluster
            sourceId="spiderfy-demo"
            data={processedData}
            clusterRadius={60}
            clusterMaxZoom={14}
            colors={['#3b82f6', '#8b5cf6', '#ec4899']}
            onPointClick={(feature) => setSelectedFeature(feature)}
            renderPopup={(feature, onClose) => (
              <div className="p-3 min-w-48 bg-card rounded-lg shadow-lg border">
                <h3 className="font-semibold text-foreground text-sm">
                  {feature.properties?.name}
                </h3>
                <p className="text-xs text-muted-foreground mt-1">
                  Floor {feature.properties?.floor}
                </p>
                <p className="text-base font-bold text-primary mt-2">
                  {feature.properties?.price}
                </p>
                <button
                  onClick={onClose}
                  className="mt-3 w-full text-xs px-3 py-1.5 bg-muted text-muted-foreground rounded-md hover:bg-muted/80 transition-colors"
                >
                  Close
                </button>
              </div>
            )}
            popupAnchor="bottom"
            popupOffset={15}
          />
        </MapContainer>
      </div>
      {selectedFeature && (
        <div className="p-3 rounded-lg border border-border bg-card text-sm">
          <span className="text-muted-foreground">Last clicked: </span>
          <span className="font-medium">{selectedFeature.properties?.name}</span>
        </div>
      )}
    </div>
  );
};
