'use client'

import { useCallback, useEffect, useRef, type ReactNode } from 'react'
import Map, { type ViewStateChangeEvent } from 'react-map-gl/maplibre'
import { ExternalLink, RotateCcw } from 'lucide-react'
import { cn } from '@djangocfg/ui-core/lib'
import 'maplibre-gl/dist/maplibre-gl.css'

import { MapProvider, useMapContext } from '../context'
import { MAP_STYLES } from '../styles'
import type { MapViewport, MapStyleKey } from '../types'

export interface MapContainerProps {
  children?: ReactNode
  initialViewport?: Partial<MapViewport>
  mapStyle?: MapStyleKey | string
  interactiveLayerIds?: string[]
  className?: string
  style?: React.CSSProperties
  cursor?: string
  attributionControl?: boolean
  reuseMaps?: boolean
  /** URL to open in external maps app (shows "Open in Maps" button if provided) */
  openInMapsUrl?: string
  /** Label for the open in maps button */
  openInMapsLabel?: string
  /** Auto-reset to initial viewport after N ms of inactivity (0 = disabled) */
  autoResetDelay?: number
  /** Show reset button */
  showResetButton?: boolean
}

interface MapInnerProps extends Omit<MapContainerProps, 'initialViewport'> {}

function MapInner({
  children,
  mapStyle = 'light',
  interactiveLayerIds,
  style,
  cursor,
  attributionControl = true,
  reuseMaps = true,
  openInMapsUrl,
  openInMapsLabel = 'Open in Maps',
  autoResetDelay = 0,
  showResetButton = false,
}: MapInnerProps) {
  const { mapRef, viewport, setViewport, setIsLoaded, resetToInitial, initialViewport } = useMapContext()
  const resetTimerRef = useRef<NodeJS.Timeout | null>(null)
  const isInteractingRef = useRef(false)

  // Check if viewport has changed from initial
  const hasViewportChanged =
    Math.abs(viewport.longitude - initialViewport.longitude) > 0.0001 ||
    Math.abs(viewport.latitude - initialViewport.latitude) > 0.0001 ||
    Math.abs(viewport.zoom - initialViewport.zoom) > 0.1

  const handleMove = useCallback(
    (evt: ViewStateChangeEvent) => {
      setViewport({
        longitude: evt.viewState.longitude,
        latitude: evt.viewState.latitude,
        zoom: evt.viewState.zoom,
        bearing: evt.viewState.bearing,
        pitch: evt.viewState.pitch,
      })
    },
    [setViewport]
  )

  const handleMoveStart = useCallback(() => {
    isInteractingRef.current = true
    // Clear any pending reset timer
    if (resetTimerRef.current) {
      clearTimeout(resetTimerRef.current)
      resetTimerRef.current = null
    }
  }, [])

  const handleMoveEnd = useCallback(() => {
    isInteractingRef.current = false
    // Start auto-reset timer if enabled
    if (autoResetDelay > 0) {
      resetTimerRef.current = setTimeout(() => {
        if (!isInteractingRef.current) {
          resetToInitial()
        }
      }, autoResetDelay)
    }
  }, [autoResetDelay, resetToInitial])

  const handleLoad = useCallback(() => {
    setIsLoaded(true)
  }, [setIsLoaded])

  // Cleanup timer on unmount
  useEffect(() => {
    return () => {
      if (resetTimerRef.current) {
        clearTimeout(resetTimerRef.current)
      }
    }
  }, [])

  const resolvedStyle = mapStyle in MAP_STYLES
    ? MAP_STYLES[mapStyle as MapStyleKey]
    : mapStyle

  return (
    <>
      <Map
        ref={mapRef}
        {...viewport}
        onMove={handleMove}
        onMoveStart={handleMoveStart}
        onMoveEnd={handleMoveEnd}
        onLoad={handleLoad}
        mapStyle={resolvedStyle}
        interactiveLayerIds={interactiveLayerIds}
        attributionControl={attributionControl ? {} : false}
        reuseMaps={reuseMaps}
        style={{
          width: '100%',
          height: '100%',
          ...style,
        }}
        cursor={cursor}
      >
        {children}
      </Map>

      {/* Map overlay buttons */}
      <div className="absolute bottom-3 right-3 flex items-center gap-2">
        {/* Reset button */}
        {showResetButton && hasViewportChanged && (
          <button
            type="button"
            onClick={resetToInitial}
            className={cn(
              'inline-flex items-center gap-2 px-3 py-2 rounded-lg',
              'bg-background/95 backdrop-blur-sm text-foreground text-sm font-medium',
              'hover:bg-background transition-colors shadow-sm border border-border'
            )}
          >
            <RotateCcw className="w-4 h-4" />
            Reset
          </button>
        )}

        {/* Open in Maps button */}
        {openInMapsUrl && (
          <a
            href={openInMapsUrl}
            target="_blank"
            rel="noopener noreferrer"
            className={cn(
              'inline-flex items-center gap-2 px-4 py-2 rounded-lg',
              'bg-background/95 backdrop-blur-sm text-foreground text-sm font-medium',
              'hover:bg-background transition-colors shadow-sm border border-border'
            )}
          >
            <ExternalLink className="w-4 h-4" />
            {openInMapsLabel}
          </a>
        )}
      </div>
    </>
  )
}

export function MapContainer({
  children,
  initialViewport,
  className,
  ...props
}: MapContainerProps) {
  return (
    <div className={className} style={{ width: '100%', height: '100%', position: 'relative' }}>
      <MapProvider initialViewport={initialViewport}>
        <MapInner {...props}>{children}</MapInner>
      </MapProvider>
    </div>
  )
}

/**
 * Use this when you need the map inside an existing MapProvider
 */
export function MapView(props: Omit<MapContainerProps, 'initialViewport'>) {
  return <MapInner {...props} />
}
