import { useEffect, useRef, useState } from "preact/hooks";
import type { Trip } from "../../lib/types";
import type { UserLocation } from "../../lib/use-location";
import { getCategory, CATEGORIES } from "../../lib/categories";

declare const L: any;

function cssVar(name: string): string {
  return getComputedStyle(document.documentElement).getPropertyValue(name).trim();
}

const LEAFLET_CSS = "https://unpkg.com/leaflet@1.9.4/dist/leaflet.css";
const LEAFLET_JS = "https://unpkg.com/leaflet@1.9.4/dist/leaflet.js";

function loadLeaflet(): Promise<void> {
  if (typeof L !== "undefined") return Promise.resolve();

  return new Promise((resolve, reject) => {
    if (!document.querySelector(`link[href="${LEAFLET_CSS}"]`)) {
      const link = document.createElement("link");
      link.rel = "stylesheet";
      link.href = LEAFLET_CSS;
      document.head.appendChild(link);
    }

    if (document.querySelector(`script[src="${LEAFLET_JS}"]`)) {
      const check = setInterval(() => {
        if (typeof L !== "undefined") { clearInterval(check); resolve(); }
      }, 50);
      return;
    }

    const script = document.createElement("script");
    script.src = LEAFLET_JS;
    script.onload = () => resolve();
    script.onerror = () => reject(new Error("Failed to load Leaflet"));
    document.head.appendChild(script);
  });
}

export function MapTab({ trip, location }: { trip: Trip; location: UserLocation | null }) {
  const mapRef = useRef<HTMLDivElement>(null);
  const mapInstance = useRef<any>(null);
  const userMarker = useRef<any>(null);
  const accuracyCircle = useRef<any>(null);
  const [ready, setReady] = useState(false);
  const [error, setError] = useState<string | null>(null);
  const [following, setFollowing] = useState(false);
  const followingRef = useRef(false);

  useEffect(() => {
    loadLeaflet()
      .then(() => setReady(true))
      .catch(e => setError(e.message));
  }, []);

  useEffect(() => {
    if (!ready || !mapRef.current || mapInstance.current) return;

    const map = L.map(mapRef.current, {
      zoomControl: true,
      scrollWheelZoom: true,
    });

    map.on("dragstart", () => {
      followingRef.current = false;
      setFollowing(false);
    });

    L.tileLayer("https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png", {
      attribution: '&copy; <a href="https://openstreetmap.org/copyright">OpenStreetMap</a>',
      maxZoom: 18,
    }).addTo(map);

    const bounds: [number, number][] = [];

    trip.places.forEach(place => {
      const cat = getCategory(place.category);
      const marker = L.circleMarker([place.lat, place.lng], {
        radius: 7,
        fillColor: cat.color,
        color: "#fff",
        weight: 2,
        opacity: 1,
        fillOpacity: 0.85,
      }).addTo(map);

      const popupContent = [
        `<strong>${place.name}</strong>`,
        `<span style="color:${cat.color}">${cat.icon} ${cat.label}</span>`,
        place.description ? `<p style="margin:4px 0 0;font-size:12px;color:var(--text-mid)">${place.description}</p>` : "",
        place.phone ? `<p style="margin:4px 0 0"><a href="tel:${place.phone}" style="color:var(--gold)">${place.phone}</a></p>` : "",
      ].filter(Boolean).join("<br>");

      marker.bindPopup(popupContent, {
        maxWidth: 220,
        className: "map-popup",
      });

      bounds.push([place.lat, place.lng]);
    });

    trip.days.forEach(day => {
      day.drives.forEach(drive => {
        if (drive.route && drive.route.length >= 2) {
          L.polyline(drive.route, {
            color: cssVar("--gold"),
            weight: 3,
            opacity: 0.6,
            dashArray: "8, 6",
          }).addTo(map);

          drive.route.forEach(pt => bounds.push(pt));
        }
      });
    });

    if (bounds.length > 0) {
      map.fitBounds(L.latLngBounds(bounds), { padding: [30, 30] });
    } else {
      map.setView([35.5, -120.5], 9);
    }

    mapInstance.current = map;

    return () => {
      map.remove();
      mapInstance.current = null;
    };
  }, [ready, trip]);

  useEffect(() => {
    if (!mapInstance.current || !location) return;
    const map = mapInstance.current;
    const latlng = [location.lat, location.lng] as [number, number];

    if (!userMarker.current) {
      const infoColor = cssVar("--info");
      userMarker.current = L.circleMarker(latlng, {
        radius: 8,
        fillColor: infoColor,
        color: "#fff",
        weight: 3,
        opacity: 1,
        fillOpacity: 1,
        className: "user-location-marker",
      }).addTo(map);

      accuracyCircle.current = L.circle(latlng, {
        radius: location.accuracy,
        fillColor: infoColor,
        fillOpacity: 0.1,
        color: infoColor,
        weight: 1,
        opacity: 0.3,
      }).addTo(map);
    } else {
      userMarker.current.setLatLng(latlng);
      accuracyCircle.current.setLatLng(latlng);
      accuracyCircle.current.setRadius(location.accuracy);
    }

    if (followingRef.current) {
      map.setView(latlng, Math.max(map.getZoom(), 12));
    }
  }, [location]);

  const recenter = () => {
    if (!mapInstance.current || !location) return;
    followingRef.current = true;
    setFollowing(true);
    mapInstance.current.setView([location.lat, location.lng], 14);
  };

  const fitAll = () => {
    if (!mapInstance.current) return;
    setFollowing(false);
    const bounds: [number, number][] = [];
    trip.places.forEach(p => bounds.push([p.lat, p.lng]));
    if (location) bounds.push([location.lat, location.lng]);
    if (bounds.length > 0) {
      mapInstance.current.fitBounds(L.latLngBounds(bounds), { padding: [30, 30] });
    }
  };

  if (error) return <div class="map-error">Failed to load map: {error}</div>;

  return (
    <div class="map-tab">
      <div class="map-container" ref={mapRef}>
        {!ready && <div class="map-loading">Loading map...</div>}
      </div>

      <div class="map-controls">
        {location && (
          <button class="map-btn" onClick={recenter} title="Center on me">
            <span class="map-btn-dot" />My Location
          </button>
        )}
        <button class="map-btn" onClick={fitAll} title="Show all">
          All Places
        </button>
      </div>

      <div class="map-legend">
        {location && (
          <div class="legend-item">
            <span class="legend-dot" style={{ background: "var(--info)" }} />
            <span class="legend-label">You</span>
          </div>
        )}
        {Object.values(CATEGORIES).map(cat => (
          <div key={cat.id} class="legend-item">
            <span
              class="legend-dot"
              style={{ background: cat.color }}
            />
            <span class="legend-label">{cat.icon} {cat.label}</span>
          </div>
        ))}
      </div>
    </div>
  );
}
