'use client';

/* eslint-disable import-x/no-named-as-default-member */
import mapboxgl from 'mapbox-gl';
import * as React from 'react';
import 'mapbox-gl/dist/mapbox-gl.css';
import { ComponentErrorBoundary } from '@/components/error-boundary';
import type { ListingDetail } from '@/lib/listings-api';
import { useMapboxStyle } from '@/lib/mapbox-style';

function formatPrice(priceVND: string): string {
  const num = Number(priceVND);
  if (num >= 1_000_000_000) return `${(num / 1_000_000_000).toFixed(1)} tỷ`;
  if (num >= 1_000_000) return `${(num / 1_000_000).toFixed(0)} tr`;
  return num.toLocaleString('vi-VN');
}

interface ListingMapProps {
  listings: ListingDetail[];
  onMarkerClick?: (listing: ListingDetail) => void;
  selectedListingId?: string;
  className?: string;
}

interface MapMarker {
  listing: ListingDetail;
  lat: number;
  lng: number;
}

const CITY_COORDS: Record<string, [number, number]> = {
  'Hồ Chí Minh': [10.8231, 106.6297],
  'Hà Nội': [21.0285, 105.8542],
  'Đà Nẵng': [16.0544, 108.2022],
  'Nha Trang': [12.2388, 109.1967],
  'Cần Thơ': [10.0452, 105.7469],
};

const DEFAULT_CENTER: [number, number] = [106.6297, 10.8231]; // HCMC [lng, lat]
const DEFAULT_ZOOM = 12;

function getMarkerCoords(listing: ListingDetail, index: number): { lat: number; lng: number } {
  if (listing.property.latitude != null && listing.property.longitude != null) {
    return { lat: listing.property.latitude, lng: listing.property.longitude };
  }
  const base = CITY_COORDS[listing.property.city] || [10.8231, 106.6297];
  const seed = listing.id.charCodeAt(0) + index;
  return {
    lat: base[0] + ((seed % 100) - 50) * 0.001,
    lng: base[1] + ((seed % 73) - 36) * 0.001,
  };
}

export function ListingMap(props: ListingMapProps) {
  return (
    <ComponentErrorBoundary label="bản đồ">
      <ListingMapInner {...props} />
    </ComponentErrorBoundary>
  );
}

function ListingMapInner({ listings, onMarkerClick, selectedListingId, className }: ListingMapProps) {
  const mapContainerRef = React.useRef<HTMLDivElement>(null);
  const mapRef = React.useRef<mapboxgl.Map | null>(null);
  const markersRef = React.useRef<mapboxgl.Marker[]>([]);
  const popupRef = React.useRef<mapboxgl.Popup | null>(null);
  const mapStyle = useMapboxStyle();

  const markers: MapMarker[] = React.useMemo(
    () => listings.map((listing, index) => ({ listing, ...getMarkerCoords(listing, index) })),
    [listings],
  );

  // Initialize map
  React.useEffect(() => {
    if (!mapContainerRef.current) return;

    const token = process.env['NEXT_PUBLIC_MAPBOX_TOKEN'];
    if (!token) {
      console.warn('NEXT_PUBLIC_MAPBOX_TOKEN is not set. Map will not render.');
      return;
    }

    mapboxgl.accessToken = token;

    const map = new mapboxgl.Map({
      container: mapContainerRef.current,
      style: mapStyle,
      center: DEFAULT_CENTER,
      zoom: DEFAULT_ZOOM,
      attributionControl: false,
    });

    map.addControl(new mapboxgl.NavigationControl(), 'top-right');
    map.addControl(new mapboxgl.AttributionControl({ compact: true }), 'bottom-right');

    mapRef.current = map;

    return () => {
      map.remove();
      mapRef.current = null;
    };
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, []);

  // Sync style changes with theme
  React.useEffect(() => {
    const map = mapRef.current;
    if (!map) return;
    map.setStyle(mapStyle);
  }, [mapStyle]);

  // Update markers when listings change
  React.useEffect(() => {
    const map = mapRef.current;
    if (!map) return;

    // Clear existing markers
    markersRef.current.forEach((m) => m.remove());
    markersRef.current = [];

    if (markers.length === 0) return;

    const bounds = new mapboxgl.LngLatBounds();

    markers.forEach((marker) => {
      const el = document.createElement('button');
      el.className = 'mapbox-price-marker';
      const isSelected = selectedListingId === marker.listing.id;
      const span = document.createElement('span');
      if (isSelected) span.className = 'selected';
      span.textContent = formatPrice(marker.listing.priceVND);
      el.appendChild(span);
      el.style.cssText = 'border:none;cursor:pointer;background:none;padding:0;';

      el.addEventListener('click', (e) => {
        e.stopPropagation();
        onMarkerClick?.(marker.listing);
        showPopup(map, marker);
      });

      const mbMarker = new mapboxgl.Marker({ element: el, anchor: 'bottom' })
        .setLngLat([marker.lng, marker.lat])
        .addTo(map);

      markersRef.current.push(mbMarker);
      bounds.extend([marker.lng, marker.lat]);
    });

    // Fit bounds with padding
    if (markers.length > 1) {
      map.fitBounds(bounds, { padding: 60, maxZoom: 15 });
    } else {
      map.flyTo({ center: [markers[0]!.lng, markers[0]!.lat], zoom: 14 });
    }
  }, [markers, selectedListingId, onMarkerClick]);

  function buildPopupContent(listing: ListingDetail): HTMLDivElement {
    const container = document.createElement('div');
    container.style.cssText = 'font-family:system-ui,sans-serif;background:hsl(var(--card));color:hsl(var(--card-foreground));padding:8px;border-radius:6px;';

    if ((listing.property.media?.length ?? 0) > 0) {
      const img = document.createElement('img');
      img.src = listing.property.media![0]!.url;
      img.alt = listing.property.title;
      img.style.cssText = 'width:100%;height:96px;object-fit:cover;border-radius:6px;margin-bottom:8px;';
      container.appendChild(img);
    }

    const price = document.createElement('p');
    price.style.cssText = 'font-weight:700;color:hsl(var(--primary));font-size:14px;margin:0 0 4px;';
    price.textContent = `${formatPrice(listing.priceVND)} VND`;
    container.appendChild(price);

    const title = document.createElement('p');
    title.style.cssText = 'font-size:13px;font-weight:500;margin:0 0 2px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;';
    title.textContent = listing.property.title;
    container.appendChild(title);

    const location = document.createElement('p');
    location.style.cssText = 'font-size:12px;color:hsl(var(--muted-foreground));margin:0 0 8px;';
    location.textContent = `${listing.property.district}, ${listing.property.city}`;
    container.appendChild(location);

    const details = document.createElement('div');
    details.style.cssText = 'display:flex;gap:4px;font-size:11px;margin-bottom:8px;';
    const tagStyle = 'background:hsl(var(--secondary));color:hsl(var(--secondary-foreground));padding:2px 6px;border-radius:4px;';

    const areaTag = document.createElement('span');
    areaTag.style.cssText = tagStyle;
    areaTag.textContent = `${listing.property.areaM2} m\u00B2`;
    details.appendChild(areaTag);

    if (listing.property.bedrooms != null) {
      const bedTag = document.createElement('span');
      bedTag.style.cssText = tagStyle;
      bedTag.textContent = `${listing.property.bedrooms} PN`;
      details.appendChild(bedTag);
    }
    if (listing.property.bathrooms != null) {
      const bathTag = document.createElement('span');
      bathTag.style.cssText = tagStyle;
      bathTag.textContent = `${listing.property.bathrooms} WC`;
      details.appendChild(bathTag);
    }
    container.appendChild(details);

    const link = document.createElement('a');
    link.href = `/listings/${listing.id}`;
    link.style.cssText = 'display:block;text-align:center;font-size:12px;font-weight:500;color:hsl(var(--primary));text-decoration:none;';
    link.textContent = 'Xem chi ti\u1EBFt \u2192';
    container.appendChild(link);

    return container;
  }

  function showPopup(map: mapboxgl.Map, marker: MapMarker) {
    popupRef.current?.remove();

    const popup = new mapboxgl.Popup({ offset: 25, maxWidth: 'min(260px, 85vw)', closeButton: true })
      .setLngLat([marker.lng, marker.lat])
      .setDOMContent(buildPopupContent(marker.listing))
      .addTo(map);

    popupRef.current = popup;
  }

  const hasToken = typeof process !== 'undefined' && process.env['NEXT_PUBLIC_MAPBOX_TOKEN'];

  return (
    <div className={`relative overflow-hidden rounded-lg border ${className || 'h-[300px] md:h-[500px]'}`}>
      <div ref={mapContainerRef} className="h-full w-full" />

      {/* Fallback when no Mapbox token */}
      {!hasToken && (
        <div className="absolute inset-0 flex items-center justify-center bg-gradient-to-b from-blue-50 to-green-50">
          <div className="text-center">
            <svg className="mx-auto mb-2 h-10 w-10 text-muted-foreground" fill="none" stroke="currentColor" viewBox="0 0 24 24">
              <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={1.5} 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 text-muted-foreground">
              Thiết lập NEXT_PUBLIC_MAPBOX_TOKEN để hiển thị bản đồ
            </p>
          </div>
        </div>
      )}

      {/* Listing count overlay */}
      <div className="absolute bottom-3 left-3 rounded bg-white/90 px-2 py-1 text-xs text-muted-foreground shadow">
        {markers.length} bất động sản trên bản đồ
      </div>

      {/* Empty state */}
      {markers.length === 0 && hasToken && (
        <div className="absolute inset-0 flex items-center justify-center bg-white/60">
          <p className="text-muted-foreground">Không có bất động sản để hiển thị trên bản đồ</p>
        </div>
      )}

      <style jsx global>{`
        .mapbox-price-marker span {
          display: block;
          background: hsl(var(--card));
          color: hsl(var(--card-foreground));
          border-radius: 9999px;
          padding: 4px 8px;
          font-size: 12px;
          font-weight: 700;
          box-shadow: 0 1px 4px rgba(0,0,0,0.3);
          white-space: nowrap;
          transition: all 0.15s;
        }
        .mapbox-price-marker:hover span,
        .mapbox-price-marker span.selected {
          background: hsl(var(--primary));
          color: hsl(var(--primary-foreground));
          transform: scale(1.1);
        }
        .mapboxgl-popup-content {
          border-radius: 8px !important;
          padding: 12px !important;
          box-shadow: 0 4px 12px rgba(0,0,0,0.3) !important;
        }
      `}</style>
    </div>
  );
}
