'use client';

import { useEffect, useState, useRef } from 'react';
import dynamic from 'next/dynamic';
import L from 'leaflet';

// Fix pour les icônes Leaflet avec Next.js
if (typeof window !== 'undefined') {
  delete (L.Icon.Default.prototype as any)._getIconUrl;
  L.Icon.Default.mergeOptions({
    iconRetinaUrl: 'https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.9.4/images/marker-icon-2x.png',
    iconUrl: 'https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.9.4/images/marker-icon.png',
    shadowUrl: 'https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.9.4/images/marker-shadow.png',
  });
}

// Import dynamique pour éviter les problèmes SSR avec Leaflet
const MapContainer = dynamic(() => import('react-leaflet').then((mod) => mod.MapContainer), { ssr: false });
const TileLayer = dynamic(() => import('react-leaflet').then((mod) => mod.TileLayer), { ssr: false });
const Marker = dynamic(() => import('react-leaflet').then((mod) => mod.Marker), { ssr: false });
const Popup = dynamic(() => import('react-leaflet').then((mod) => mod.Popup), { ssr: false });
const Polyline = dynamic(() => import('react-leaflet').then((mod) => mod.Polyline), { ssr: false });

interface TrajetMapProps {
  adresseDepart: string;
  adresseArrivee: string;
  adherentNom?: string;
}

interface Coordinates {
  lat: number;
  lng: number;
}

interface RouteInfo {
  distance: number; // en mètres
  duration: number; // en secondes
}

export default function TrajetMap({ adresseDepart, adresseArrivee, adherentNom }: TrajetMapProps) {
  const [departCoords, setDepartCoords] = useState<Coordinates | null>(null);
  const [arriveeCoords, setArriveeCoords] = useState<Coordinates | null>(null);
  const [routeInfo, setRouteInfo] = useState<RouteInfo | null>(null);
  const [loading, setLoading] = useState(false);
  const [error, setError] = useState<string | null>(null);
  // Cache simple pour éviter de regéocoder les mêmes adresses
  const geocodeCacheRef = useRef<Map<string, Coordinates>>(new Map());

  useEffect(() => {
    // Réinitialiser les coordonnées quand les adresses changent
    setDepartCoords(null);
    setArriveeCoords(null);
    setRouteInfo(null);
    setError(null);
    
    if (adresseDepart && adresseArrivee && adresseDepart.length >= 5 && adresseArrivee.length >= 5) {
      // Délai réduit pour une réponse plus rapide
      const timeoutId = setTimeout(() => {
        geocodeAddresses();
      }, 400);

      return () => clearTimeout(timeoutId);
    }
  }, [adresseDepart, adresseArrivee]);

  const geocodeAddresses = async () => {
    if (!adresseDepart || !adresseArrivee) {
      return;
    }

    // Vérifier que les adresses ont au moins 5 caractères
    if (adresseDepart.length < 5 || adresseArrivee.length < 5) {
      return;
    }

    setLoading(true);
    setError(null);

    try {
      // Géocoder les deux adresses en parallèle pour plus de rapidité
      // (l'API Nominatim permet généralement 1 req/sec, mais on peut essayer)
      const [departResult, arriveeResult] = await Promise.all([
        geocodeAddress(adresseDepart).catch(() => null),
        // Petit délai pour la deuxième requête pour respecter les limites
        new Promise(resolve => setTimeout(resolve, 1000)).then(() => 
          geocodeAddress(adresseArrivee).catch(() => null)
        ),
      ]);

      if (departResult && arriveeResult) {
        setDepartCoords(departResult);
        setArriveeCoords(arriveeResult);

        // Calculer la distance et le temps estimé
        const info = calculateRouteInfo(departResult, arriveeResult);
        setRouteInfo(info);
      } else if (!departResult) {
        setError(`Impossible de trouver l'adresse de départ: "${adresseDepart}"`);
      } else {
        setError(`Impossible de trouver l'adresse d'arrivée: "${adresseArrivee}"`);
      }
    } catch (err) {
      console.error('Erreur lors du géocodage:', err);
      setError('Erreur lors du chargement de la carte. Veuillez réessayer.');
    } finally {
      setLoading(false);
    }
  };

  const geocodeAddress = async (address: string): Promise<Coordinates | null> => {
    if (!address || address.length < 5) {
      return null;
    }

    try {
      // Nettoyer l'adresse pour améliorer les résultats
      const cleanAddress = address.trim().toLowerCase();
      
      // Vérifier le cache
      if (geocodeCacheRef.current.has(cleanAddress)) {
        return geocodeCacheRef.current.get(cleanAddress)!;
      }
      
      const response = await fetch(
        `https://nominatim.openstreetmap.org/search?format=json&q=${encodeURIComponent(address.trim())}&limit=1&addressdetails=1&countrycodes=fr`,
        {
          headers: {
            'User-Agent': 'MAD Platform',
            'Accept-Language': 'fr-FR,fr;q=0.9',
            'Referer': window.location.origin,
          },
        }
      );

      if (response.ok) {
        const data = await response.json();
        if (data && data.length > 0 && data[0].lat && data[0].lon) {
          const lat = parseFloat(data[0].lat);
          const lng = parseFloat(data[0].lon);
          
          // Vérifier que les coordonnées sont valides
          if (!isNaN(lat) && !isNaN(lng) && lat >= -90 && lat <= 90 && lng >= -180 && lng <= 180) {
            const coords = { lat, lng };
            // Mettre en cache (limiter à 50 entrées pour éviter la surconsommation mémoire)
            if (geocodeCacheRef.current.size < 50) {
              geocodeCacheRef.current.set(cleanAddress, coords);
            }
            return coords;
          }
        }
      } else {
        console.warn('Réponse non OK de Nominatim:', response.status);
      }
      return null;
    } catch (error) {
      console.error('Erreur de géocodage:', error);
      return null;
    }
  };

  const calculateRouteInfo = (depart: Coordinates, arrivee: Coordinates): RouteInfo => {
    // Calcul de la distance à vol d'oiseau (formule de Haversine)
    const R = 6371e3; // Rayon de la Terre en mètres
    const φ1 = (depart.lat * Math.PI) / 180;
    const φ2 = (arrivee.lat * Math.PI) / 180;
    const Δφ = ((arrivee.lat - depart.lat) * Math.PI) / 180;
    const Δλ = ((arrivee.lng - depart.lng) * Math.PI) / 180;

    const a =
      Math.sin(Δφ / 2) * Math.sin(Δφ / 2) +
      Math.cos(φ1) * Math.cos(φ2) * Math.sin(Δλ / 2) * Math.sin(Δλ / 2);
    const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));

    const distance = R * c; // Distance en mètres

    // Estimation du temps : vitesse moyenne de 50 km/h en ville
    // On multiplie la distance par 1.3 pour tenir compte des détours
    const distanceWithDetour = distance * 1.3;
    const vitesseMoyenne = 50; // km/h
    const duration = (distanceWithDetour / 1000 / vitesseMoyenne) * 3600; // en secondes

    return { distance: distanceWithDetour, duration };
  };

  const formatDistance = (meters: number): string => {
    if (meters < 1000) {
      return `${Math.round(meters)} m`;
    }
    return `${(meters / 1000).toFixed(1)} km`;
  };

  const formatDuration = (seconds: number): string => {
    const hours = Math.floor(seconds / 3600);
    const minutes = Math.floor((seconds % 3600) / 60);

    if (hours > 0) {
      return `${hours}h${minutes > 0 ? minutes : ''}`;
    }
    return `${minutes} min`;
  };

  if (!adresseDepart || !adresseArrivee) {
    return (
      <div className="h-full flex items-center justify-center text-gray-400">
        <div className="text-center">
          <svg className="w-16 h-16 mx-auto mb-4 opacity-50" fill="none" stroke="currentColor" viewBox="0 0 24 24">
            <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M9 20l-5.447-2.724A1 1 0 013 16.382V5.618a1 1 0 011.447-.894L9 7m0 13l6-3m-6 3V7m6 10l4.553 2.276A1 1 0 0021 18.382V7.618a1 1 0 00-.553-.894L15 4m0 13V4m0 0L9 7" />
          </svg>
          <p className="text-sm">Remplissez les adresses pour voir la carte</p>
        </div>
      </div>
    );
  }

  if (loading) {
    return (
      <div className="h-full flex items-center justify-center bg-white rounded-xl">
        <div className="text-center">
          <svg className="animate-spin h-12 w-12 text-lblue mx-auto mb-4" fill="none" viewBox="0 0 24 24">
            <circle className="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" strokeWidth="4"></circle>
            <path className="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path>
          </svg>
          <p className="text-sm font-medium text-gray-700 mb-1">Chargement de la carte...</p>
          <p className="text-xs text-gray-500">Géocodage des adresses en cours</p>
        </div>
      </div>
    );
  }

  if (error) {
    return (
      <div className="h-full flex items-center justify-center text-gray-400 bg-white rounded-xl p-8">
        <div className="text-center max-w-md">
          <svg className="w-20 h-20 mx-auto mb-4 opacity-50 text-orange-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
            <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z" />
          </svg>
          <p className="text-sm font-medium text-gray-700 mb-2">{error}</p>
          <p className="text-xs text-gray-500 mb-4">Vérifiez que les adresses sont correctes et complètes</p>
          <button
            onClick={geocodeAddresses}
            className="px-4 py-2 text-xs font-medium text-white bg-lblue rounded-lg hover:bg-dblue transition-colors"
          >
            Réessayer
          </button>
        </div>
      </div>
    );
  }

  if (!departCoords || !arriveeCoords) {
    return (
      <div className="h-full flex items-center justify-center text-gray-400">
        <div className="text-center">
          <svg className="w-16 h-16 mx-auto mb-4 opacity-50" fill="none" stroke="currentColor" viewBox="0 0 24 24">
            <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M9 20l-5.447-2.724A1 1 0 013 16.382V5.618a1 1 0 011.447-.894L9 7m0 13l6-3m-6 3V7m6 10l4.553 2.276A1 1 0 0021 18.382V7.618a1 1 0 00-.553-.894L15 4m0 13V4m0 0L9 7" />
          </svg>
          <p className="text-sm">Chargement de la carte...</p>
        </div>
      </div>
    );
  }

  // Calculer le centre et le zoom optimal pour afficher les deux points
  const centerLat = departCoords && arriveeCoords ? (departCoords.lat + arriveeCoords.lat) / 2 : 48.8566;
  const centerLng = departCoords && arriveeCoords ? (departCoords.lng + arriveeCoords.lng) / 2 : 2.3522;
  
  // Calculer le zoom optimal pour voir les deux points
  let optimalZoom = 12;
  if (departCoords && arriveeCoords) {
    const latDiff = Math.abs(departCoords.lat - arriveeCoords.lat);
    const lngDiff = Math.abs(departCoords.lng - arriveeCoords.lng);
    const maxDiff = Math.max(latDiff, lngDiff);
    
    if (maxDiff > 0.5) optimalZoom = 7;
    else if (maxDiff > 0.2) optimalZoom = 8;
    else if (maxDiff > 0.1) optimalZoom = 9;
    else if (maxDiff > 0.05) optimalZoom = 10;
    else if (maxDiff > 0.02) optimalZoom = 11;
    else optimalZoom = 12;
  }

  if (typeof window === 'undefined') {
    return null;
  }

  return (
    <div className="h-full flex flex-col min-h-[500px]">
      {/* Informations du trajet */}
      {routeInfo && (
        <div className="bg-white rounded-lg border border-gray-200 p-4 mb-4 shadow-sm">
          <div className="grid grid-cols-2 gap-6">
            <div className="flex items-center gap-3">
              <div className="w-10 h-10 rounded-lg bg-lgreen/10 flex items-center justify-center">
                <svg className="w-5 h-5 text-lgreen" fill="none" stroke="currentColor" viewBox="0 0 24 24">
                  <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M17.657 16.657L13.414 20.9a1.998 1.998 0 01-2.827 0l-4.244-4.243a8 8 0 1111.314 0z" />
                  <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M15 11a3 3 0 11-6 0 3 3 0 016 0z" />
                </svg>
              </div>
              <div>
                <div className="text-xs font-medium text-gray-500 uppercase tracking-wide mb-1">Distance</div>
                <div className="text-xl font-semibold text-gray-900">{formatDistance(routeInfo.distance)}</div>
              </div>
            </div>
            <div className="flex items-center gap-3 border-l border-gray-200 pl-6">
              <div className="w-10 h-10 rounded-lg bg-lblue/10 flex items-center justify-center">
                <svg className="w-5 h-5 text-lblue" fill="none" stroke="currentColor" viewBox="0 0 24 24">
                  <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z" />
                </svg>
              </div>
              <div>
                <div className="text-xs font-medium text-gray-500 uppercase tracking-wide mb-1">Temps estimé</div>
                <div className="text-xl font-semibold text-gray-900">{formatDuration(routeInfo.duration)}</div>
              </div>
            </div>
          </div>
        </div>
      )}

      {/* Carte */}
      <div className="flex-1 rounded-xl overflow-hidden border-2 border-gray-300 shadow-2xl" style={{ minHeight: '500px' }}>
        <MapContainer
          center={[centerLat, centerLng]}
          zoom={optimalZoom}
          style={{ height: '100%', width: '100%', zIndex: 0 }}
          zoomControl={true}
          scrollWheelZoom={true}
        >
          <TileLayer
            attribution='&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
            url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
          />
          <Marker
            position={[departCoords.lat, departCoords.lng]}
            icon={L.divIcon({
              className: 'custom-marker-depart',
              html: `
                <div style="
                  background: linear-gradient(135deg, #10b981 0%, #059669 100%);
                  width: 40px;
                  height: 40px;
                  border-radius: 50% 50% 50% 0;
                  transform: rotate(-45deg);
                  border: 4px solid white;
                  box-shadow: 0 4px 12px rgba(0,0,0,0.3);
                  display: flex;
                  align-items: center;
                  justify-content: center;
                ">
                  <div style="
                    transform: rotate(45deg);
                    color: white;
                    font-weight: bold;
                    font-size: 18px;
                  ">A</div>
                </div>
              `,
              iconSize: [40, 40],
              iconAnchor: [20, 40],
              popupAnchor: [0, -40],
            })}
          >
            <Popup className="custom-popup">
              <div className="text-sm p-2">
                <div className="font-bold text-lgreen mb-1 flex items-center gap-2">
                  <div className="w-3 h-3 rounded-full bg-lgreen"></div>
                  Départ
                </div>
                <div className="text-gray-700 font-medium">{adresseDepart}</div>
                {adherentNom && <div className="text-gray-500 mt-1 text-xs">{adherentNom}</div>}
              </div>
            </Popup>
          </Marker>
          <Marker
            position={[arriveeCoords.lat, arriveeCoords.lng]}
            icon={L.divIcon({
              className: 'custom-marker-arrivee',
              html: `
                <div style="
                  background: linear-gradient(135deg, #3b82f6 0%, #2563eb 100%);
                  width: 40px;
                  height: 40px;
                  border-radius: 50% 50% 50% 0;
                  transform: rotate(-45deg);
                  border: 4px solid white;
                  box-shadow: 0 4px 12px rgba(0,0,0,0.3);
                  display: flex;
                  align-items: center;
                  justify-content: center;
                ">
                  <div style="
                    transform: rotate(45deg);
                    color: white;
                    font-weight: bold;
                    font-size: 18px;
                  ">B</div>
                </div>
              `,
              iconSize: [40, 40],
              iconAnchor: [20, 40],
              popupAnchor: [0, -40],
            })}
          >
            <Popup className="custom-popup">
              <div className="text-sm p-2">
                <div className="font-bold text-lblue mb-1 flex items-center gap-2">
                  <div className="w-3 h-3 rounded-full bg-lblue"></div>
                  Arrivée
                </div>
                <div className="text-gray-700 font-medium">{adresseArrivee}</div>
              </div>
            </Popup>
          </Marker>
          <Polyline
            positions={[
              [departCoords.lat, departCoords.lng],
              [arriveeCoords.lat, arriveeCoords.lng],
            ]}
            pathOptions={{
              color: '#6B46C1',
              weight: 5,
              opacity: 0.8,
              dashArray: '10, 10',
            }}
          />
        </MapContainer>
      </div>
    </div>
  );
}
