'use client'

import { useEffect, useRef, useState, useCallback } from 'react'
import { GeoJSONPolygon } from '@/app/geo-lernwelt/types'

// MapLibre GL JS types (imported dynamically)
type MapInstance = {
  on: (event: string, callback: (...args: unknown[]) => void) => void
  addSource: (id: string, source: object) => void
  addLayer: (layer: object) => void
  getSource: (id: string) => { setData: (data: object) => void } | undefined
  removeLayer: (id: string) => void
  removeSource: (id: string) => void
  getCanvas: () => { style: { cursor: string } }
  remove: () => void
  fitBounds: (bounds: [[number, number], [number, number]], options?: object) => void
}

interface AOISelectorProps {
  onPolygonDrawn: (polygon: GeoJSONPolygon) => void
  initialPolygon?: GeoJSONPolygon | null
  maxAreaKm2?: number
  geoServiceUrl: string
}

// Germany bounds
const GERMANY_BOUNDS: [[number, number], [number, number]] = [
  [5.87, 47.27],
  [15.04, 55.06],
]

// Default center (Germany)
const DEFAULT_CENTER: [number, number] = [10.45, 51.16]
const DEFAULT_ZOOM = 6

export default function AOISelector({
  onPolygonDrawn,
  initialPolygon,
  maxAreaKm2 = 4,
  geoServiceUrl,
}: AOISelectorProps) {
  const mapContainerRef = useRef<HTMLDivElement>(null)
  const mapRef = useRef<MapInstance | null>(null)
  const [isDrawing, setIsDrawing] = useState(false)
  const [drawPoints, setDrawPoints] = useState<[number, number][]>([])
  const [mapReady, setMapReady] = useState(false)
  const [areaKm2, setAreaKm2] = useState<number | null>(null)
  const [validationError, setValidationError] = useState<string | null>(null)

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

    const initMap = async () => {
      const maplibregl = await import('maplibre-gl')
      // CSS is loaded via CDN in head to avoid Next.js dynamic import issues
      if (!document.querySelector('link[href*="maplibre-gl.css"]')) {
        const link = document.createElement('link')
        link.rel = 'stylesheet'
        link.href = 'https://unpkg.com/maplibre-gl@5.0.1/dist/maplibre-gl.css'
        document.head.appendChild(link)
      }

      const map = new maplibregl.Map({
        container: mapContainerRef.current!,
        style: {
          version: 8,
          name: 'GeoEdu Map',
          sources: {
            osm: {
              type: 'raster',
              tiles: ['https://tile.openstreetmap.org/{z}/{x}/{y}.png'],
              tileSize: 256,
              attribution: '© OpenStreetMap contributors',
            },
          },
          layers: [
            {
              id: 'osm-tiles',
              type: 'raster',
              source: 'osm',
              minzoom: 0,
              maxzoom: 19,
            },
          ],
        },
        center: DEFAULT_CENTER,
        zoom: DEFAULT_ZOOM,
        maxBounds: [
          [GERMANY_BOUNDS[0][0] - 1, GERMANY_BOUNDS[0][1] - 1],
          [GERMANY_BOUNDS[1][0] + 1, GERMANY_BOUNDS[1][1] + 1],
        ],
      }) as unknown as MapInstance

      map.on('load', () => {
        // Add drawing layer sources
        map.addSource('draw-polygon', {
          type: 'geojson',
          data: {
            type: 'FeatureCollection',
            features: [],
          },
        })

        map.addSource('draw-points', {
          type: 'geojson',
          data: {
            type: 'FeatureCollection',
            features: [],
          },
        })

        // Add polygon fill layer
        map.addLayer({
          id: 'draw-polygon-fill',
          type: 'fill',
          source: 'draw-polygon',
          paint: {
            'fill-color': '#3b82f6',
            'fill-opacity': 0.3,
          },
        })

        // Add polygon outline layer
        map.addLayer({
          id: 'draw-polygon-outline',
          type: 'line',
          source: 'draw-polygon',
          paint: {
            'line-color': '#3b82f6',
            'line-width': 2,
          },
        })

        // Add points layer
        map.addLayer({
          id: 'draw-points-layer',
          type: 'circle',
          source: 'draw-points',
          paint: {
            'circle-radius': 6,
            'circle-color': '#3b82f6',
            'circle-stroke-color': '#ffffff',
            'circle-stroke-width': 2,
          },
        })

        mapRef.current = map
        setMapReady(true)

        // Load initial polygon if provided
        if (initialPolygon) {
          loadPolygon(map, initialPolygon)
        }
      })
    }

    initMap()

    return () => {
      if (mapRef.current) {
        mapRef.current.remove()
      }
    }
  }, [])

  // Update polygon when initialPolygon changes
  useEffect(() => {
    if (mapReady && mapRef.current && initialPolygon) {
      loadPolygon(mapRef.current, initialPolygon)
    }
  }, [initialPolygon, mapReady])

  const loadPolygon = (map: MapInstance, polygon: GeoJSONPolygon) => {
    const source = map.getSource('draw-polygon')
    if (source) {
      source.setData({
        type: 'Feature',
        geometry: polygon,
        properties: {},
      })
    }

    // Calculate and validate area
    validatePolygon(polygon)

    // Fit bounds to polygon
    const coords = polygon.coordinates[0]
    const bounds = coords.reduce<[[number, number], [number, number]]>(
      (acc, coord) => [
        [Math.min(acc[0][0], coord[0]), Math.min(acc[0][1], coord[1])],
        [Math.max(acc[1][0], coord[0]), Math.max(acc[1][1], coord[1])],
      ],
      [
        [Infinity, Infinity],
        [-Infinity, -Infinity],
      ]
    )

    map.fitBounds(bounds, { padding: 50 })
  }

  const validatePolygon = async (polygon: GeoJSONPolygon) => {
    try {
      const res = await fetch(`${geoServiceUrl}/api/v1/aoi/validate`, {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify(polygon),
      })

      if (res.ok) {
        const data = await res.json()
        setAreaKm2(data.area_km2)

        if (!data.valid) {
          setValidationError(data.error || 'Ungueltiges Polygon')
        } else if (!data.within_germany) {
          setValidationError('Gebiet muss innerhalb Deutschlands liegen')
        } else if (!data.within_size_limit) {
          setValidationError(`Gebiet zu gross (max. ${maxAreaKm2} km²)`)
        } else {
          setValidationError(null)
        }
      }
    } catch (e) {
      // Fallback to client-side calculation
      console.error('Validation error:', e)
    }
  }

  const handleMapClick = useCallback(
    (e: { lngLat: { lng: number; lat: number } }) => {
      if (!isDrawing || !mapRef.current) return

      const newPoint: [number, number] = [e.lngLat.lng, e.lngLat.lat]
      const newPoints = [...drawPoints, newPoint]
      setDrawPoints(newPoints)

      // Update points layer
      const pointsSource = mapRef.current.getSource('draw-points')
      if (pointsSource) {
        pointsSource.setData({
          type: 'FeatureCollection',
          features: newPoints.map((pt) => ({
            type: 'Feature',
            geometry: { type: 'Point', coordinates: pt },
            properties: {},
          })),
        })
      }

      // Update polygon preview if we have at least 3 points
      if (newPoints.length >= 3) {
        const polygonCoords = [...newPoints, newPoints[0]]
        const polygonSource = mapRef.current.getSource('draw-polygon')
        if (polygonSource) {
          polygonSource.setData({
            type: 'Feature',
            geometry: {
              type: 'Polygon',
              coordinates: [polygonCoords],
            },
            properties: {},
          })
        }
      }
    },
    [isDrawing, drawPoints]
  )

  // Attach click handler when drawing
  useEffect(() => {
    if (!mapReady || !mapRef.current) return

    const map = mapRef.current

    if (isDrawing) {
      map.getCanvas().style.cursor = 'crosshair'
      map.on('click', handleMapClick as (...args: unknown[]) => void)
    } else {
      map.getCanvas().style.cursor = ''
    }

    return () => {
      // Note: maplibre doesn't have off() in the same way, handled by cleanup
    }
  }, [isDrawing, mapReady, handleMapClick])

  const startDrawing = () => {
    setIsDrawing(true)
    setDrawPoints([])
    setAreaKm2(null)
    setValidationError(null)

    // Clear existing polygon
    if (mapRef.current) {
      const polygonSource = mapRef.current.getSource('draw-polygon')
      const pointsSource = mapRef.current.getSource('draw-points')
      if (polygonSource) {
        polygonSource.setData({ type: 'FeatureCollection', features: [] })
      }
      if (pointsSource) {
        pointsSource.setData({ type: 'FeatureCollection', features: [] })
      }
    }
  }

  const finishDrawing = () => {
    if (drawPoints.length < 3) {
      setValidationError('Mindestens 3 Punkte erforderlich')
      return
    }

    setIsDrawing(false)

    // Close the polygon
    const closedCoords = [...drawPoints, drawPoints[0]]
    const polygon: GeoJSONPolygon = {
      type: 'Polygon',
      coordinates: [closedCoords],
    }

    // Clear points layer
    if (mapRef.current) {
      const pointsSource = mapRef.current.getSource('draw-points')
      if (pointsSource) {
        pointsSource.setData({ type: 'FeatureCollection', features: [] })
      }
    }

    // Validate and callback
    validatePolygon(polygon)
    onPolygonDrawn(polygon)
  }

  const cancelDrawing = () => {
    setIsDrawing(false)
    setDrawPoints([])

    // Clear layers
    if (mapRef.current) {
      const polygonSource = mapRef.current.getSource('draw-polygon')
      const pointsSource = mapRef.current.getSource('draw-points')
      if (polygonSource) {
        polygonSource.setData({ type: 'FeatureCollection', features: [] })
      }
      if (pointsSource) {
        pointsSource.setData({ type: 'FeatureCollection', features: [] })
      }
    }
  }

  return (
    <div className="relative w-full h-full">
      {/* Map Container */}
      <div ref={mapContainerRef} className="w-full h-full" />

      {/* Drawing Toolbar */}
      <div className="absolute top-4 left-4 flex gap-2">
        {!isDrawing ? (
          <button
            onClick={startDrawing}
            className="px-4 py-2 bg-blue-500 hover:bg-blue-600 text-white rounded-lg shadow-lg transition-colors flex items-center gap-2"
          >
            <svg
              className="w-4 h-4"
              fill="none"
              stroke="currentColor"
              viewBox="0 0 24 24"
            >
              <path
                strokeLinecap="round"
                strokeLinejoin="round"
                strokeWidth={2}
                d="M15.232 5.232l3.536 3.536m-2.036-5.036a2.5 2.5 0 113.536 3.536L6.5 21.036H3v-3.572L16.732 3.732z"
              />
            </svg>
            Gebiet zeichnen
          </button>
        ) : (
          <>
            <button
              onClick={finishDrawing}
              disabled={drawPoints.length < 3}
              className="px-4 py-2 bg-green-500 hover:bg-green-600 disabled:bg-gray-500 text-white rounded-lg shadow-lg transition-colors"
            >
              ✓ Fertig ({drawPoints.length} Punkte)
            </button>
            <button
              onClick={cancelDrawing}
              className="px-4 py-2 bg-red-500 hover:bg-red-600 text-white rounded-lg shadow-lg transition-colors"
            >
              ✕ Abbrechen
            </button>
          </>
        )}
      </div>

      {/* Drawing Instructions */}
      {isDrawing && (
        <div className="absolute top-4 right-4 bg-black/70 text-white px-4 py-2 rounded-lg text-sm max-w-xs">
          <p>Klicke auf die Karte um Punkte zu setzen.</p>
          <p className="text-white/60 mt-1">Mindestens 3 Punkte erforderlich.</p>
        </div>
      )}

      {/* Area Info */}
      {areaKm2 !== null && (
        <div className="absolute bottom-4 left-4 bg-black/70 text-white px-4 py-2 rounded-lg">
          <div className="text-sm">
            <span className="text-white/60">Flaeche: </span>
            <span className={areaKm2 > maxAreaKm2 ? 'text-red-400' : 'text-green-400'}>
              {areaKm2.toFixed(2)} km²
            </span>
            <span className="text-white/40"> / {maxAreaKm2} km² max</span>
          </div>
        </div>
      )}

      {/* Validation Error */}
      {validationError && (
        <div className="absolute bottom-4 right-4 bg-red-500/90 text-white px-4 py-2 rounded-lg text-sm max-w-xs">
          {validationError}
        </div>
      )}

      {/* Loading Overlay */}
      {!mapReady && (
        <div className="absolute inset-0 bg-slate-800 flex items-center justify-center">
          <div className="text-white/60 flex flex-col items-center gap-2">
            <div className="w-8 h-8 border-2 border-white/30 border-t-white rounded-full animate-spin" />
            <span>Karte wird geladen...</span>
          </div>
        </div>
      )}
    </div>
  )
}
