import { useCallback, useEffect, useRef, useState } from 'react';
import Map, { Layer, Marker, NavigationControl, Source } from 'react-map-gl/maplibre';
import 'maplibre-gl/dist/maplibre-gl.css';
import { api } from '../../api/client';

const INITIAL_VIEW = { longitude: -61.2, latitude: 15.5, zoom: 7 };

// Styles des couches selon le type (observation vs prédiction)
const layerStyles = (isPrediction) => ({
  fill: {
    id:     isPrediction ? 'forecasts-fill'  : 'observations-fill',
    type:   'fill',
    source: isPrediction ? 'forecasts'       : 'observations',
    paint:  {
      'fill-color':   isPrediction ? '#818cf8' : '#f59e0b',
      'fill-opacity': isPrediction ? 0.25      : 0.35,
    },
  },
  line: {
    id:     isPrediction ? 'forecasts-line'  : 'observations-line',
    type:   'line',
    source: isPrediction ? 'forecasts'       : 'observations',
    paint:  {
      'line-color':      isPrediction ? '#6366f1' : '#d97706',
      'line-width':      2,
      'line-dasharray':  isPrediction ? [4, 3]    : [1],
    },
  },
});

const OBS_STYLES  = layerStyles(false);
const FORE_STYLES = layerStyles(true);

const horizonToInt = (h) => parseInt(h.replace('h', ''), 10);

export default function SargassesMap({ onSpotSelect, selectedSpotId, activeStep }) {
  const mapRef = useRef(null);
  const [spots,         setSpots]         = useState([]);
  const [obsGeoJSON,    setObsGeoJSON]    = useState(null);
  const [foreGeoJSON,   setForeGeoJSON]   = useState(null);
  const [viewState,     setViewState]     = useState(INITIAL_VIEW);

  // Spots côtiers : chargement unique
  useEffect(() => {
    api.spots.list()
      .then(data => setSpots(Array.isArray(data) ? data : (data['hydra:member'] ?? data.member ?? [])))
      .catch(console.error);
  }, []);

  const loadLayers = useCallback(() => {
    const map = mapRef.current?.getMap();
    if (!map) return;

    const b    = map.getBounds();
    const bbox = [b.getWest(), b.getSouth(), b.getEast(), b.getNorth()]
      .map(v => v.toFixed(4)).join(',');

    if (activeStep === 'now') {
      // Observations réelles
      api.observations.list(bbox)
        .then(data => setObsGeoJSON(toFeatureCollection(data.items)))
        .catch(console.error);
      setForeGeoJSON(null);
    } else {
      // Forecasts pour cet horizon
      const horizon = horizonToInt(activeStep);
      api.forecasts.list(bbox, horizon)
        .then(data => {
          setForeGeoJSON(toFeatureCollection(data.items));
          setObsGeoJSON(null);
        })
        .catch(console.error);
    }
  }, [activeStep]);

  useEffect(() => { loadLayers(); }, [loadLayers]);

  const toFeatureCollection = (items = []) => {
    const features = (items ?? [])
      .filter(i => i.geometry)
      .map(i => ({ type: 'Feature', geometry: i.geometry, properties: {} }));
    return features.length ? { type: 'FeatureCollection', features } : null;
  };

  const getCoords = (spot) => {
    if (spot.longitude != null && spot.latitude != null) {
      return { lng: spot.longitude, lat: spot.latitude };
    }
    return null;
  };

  return (
    <Map
      ref={mapRef}
      {...viewState}
      onMove={e => setViewState(e.viewState)}
      onMoveEnd={loadLayers}
      onLoad={loadLayers}
      mapStyle="https://basemaps.cartocdn.com/gl/dark-matter-gl-style/style.json"
      style={{ width: '100%', height: '100vh' }}
    >
      <NavigationControl position="top-right" />

      {/* Couche observations (now) */}
      {obsGeoJSON && (
        <Source id="observations" type="geojson" data={obsGeoJSON}>
          <Layer {...OBS_STYLES.fill} />
          <Layer {...OBS_STYLES.line} />
        </Source>
      )}

      {/* Couche prédictions (H+6/12/24/48) */}
      {foreGeoJSON && (
        <Source id="forecasts" type="geojson" data={foreGeoJSON}>
          <Layer {...FORE_STYLES.fill} />
          <Layer {...FORE_STYLES.line} />
        </Source>
      )}

      {/* Marqueurs spots */}
      {spots.map(spot => {
        const coords    = getCoords(spot);
        if (!coords) return null;
        const isSelected = spot.id === selectedSpotId;

        return (
          <Marker
            key={spot.id}
            longitude={coords.lng}
            latitude={coords.lat}
            anchor="center"
            onClick={() => onSpotSelect(spot)}
          >
            <div
              title={spot.name}
              style={{
                width:        isSelected ? 16 : 10,
                height:       isSelected ? 16 : 10,
                borderRadius: '50%',
                background:   isSelected ? '#38bdf8' : '#fff',
                border:       `2px solid ${isSelected ? '#0ea5e9' : '#94a3b8'}`,
                cursor:       'pointer',
                transition:   'all .15s',
              }}
            />
          </Marker>
        );
      })}
    </Map>
  );
}
