'use client'

import { useState, useEffect, useRef, useCallback } from 'react'
import { GoogleMap, MarkerF, useJsApiLoader } from '@react-google-maps/api'

interface GeocodingResult {
  formatted_address: string
  geometry: {
    location: {
      lat: number
      lng: number
    }
  }
}

interface AddressPickerModalProps {
  isOpen: boolean
  onClose: () => void
  onConfirm: (address: string, lat: number, lng: number) => void
}

const libraries: ("places")[] = ["places"]

export default function AddressPickerModal({ isOpen, onClose, onConfirm }: AddressPickerModalProps) {
  const [searchQuery, setSearchQuery] = useState('')
  const [searchResults, setSearchResults] = useState<GeocodingResult[]>([])
  const [isSearching, setIsSearching] = useState(false)
  const [selectedPosition, setSelectedPosition] = useState<{ lat: number; lng: number } | null>(null)
  const [selectedAddress, setSelectedAddress] = useState('')
  const [isGettingLocation, setIsGettingLocation] = useState(false)
  const [locationError, setLocationError] = useState<string | null>(null)
  const [map, setMap] = useState<google.maps.Map | null>(null)

  const apiKey = process.env.NEXT_PUBLIC_GOOGLE_MAPS_API_KEY || ''
  const { isLoaded } = useJsApiLoader({
    id: 'google-map-script',
    googleMapsApiKey: apiKey,
    libraries: libraries,
  })

  // Fix: properly type the debounce to avoid TypeScript errors
  const searchTimeoutRef = useRef<NodeJS.Timeout | null>(null)

  // Cleanup debounce timeout on unmount
  useEffect(() => {
    return () => {
      if (searchTimeoutRef.current) {
        clearTimeout(searchTimeoutRef.current)
      }
    }
  }, [])

  const searchAddress = async (query: string) => {
    if (!query.trim()) {
      setSearchResults([])
      return
    }

    setIsSearching(true)
    try {
      // Use Google Geocoding API
      const response = await fetch(
        `https://maps.googleapis.com/maps/api/geocode/json?address=${encodeURIComponent(query)}&components=country:id&key=${apiKey}&limit=5`
      )
      const data = await response.json()
      setSearchResults(data.results || [])
    } catch (error) {
      console.error('Error searching address:', error)
      setSearchResults([])
    } finally {
      setIsSearching(false)
    }
  }

  const handleSearchInput = (value: string) => {
    setSearchQuery(value)

    // Debounce search to avoid too many API calls
    if (searchTimeoutRef.current) {
      clearTimeout(searchTimeoutRef.current)
    }

    searchTimeoutRef.current = setTimeout(() => {
      searchAddress(value)
    }, 500)
  }

  const handleSelectResult = (result: GeocodingResult) => {
    setSelectedPosition({
      lat: result.geometry.location.lat,
      lng: result.geometry.location.lng,
    })
    setSelectedAddress(result.formatted_address)
    setSearchResults([])
    setSearchQuery(result.formatted_address)
  }

  const handleMapClick = (e: google.maps.MapMouseEvent | undefined) => {
    if (e?.latLng) {
      const lat = e.latLng.lat()
      const lng = e.latLng.lng()
      setSelectedPosition({ lat, lng })
      // Reverse geocoding to get address from coordinates
      reverseGeocode(lat, lng)
    }
  }

  const reverseGeocode = async (lat: number, lng: number) => {
    try {
      const response = await fetch(
        `https://maps.googleapis.com/maps/api/geocode/json?latlng=${lat},${lng}&key=${apiKey}`
      )
      const data = await response.json()
      if (data.results && data.results.length > 0) {
        setSelectedAddress(data.results[0].formatted_address)
        setSearchQuery(data.results[0].formatted_address)
      } else {
        setSelectedAddress('Alamat tidak ditemukan')
        setSearchQuery('')
      }
    } catch (error) {
      console.error('Error reverse geocoding:', error)
      setSelectedAddress('Gagal mengambil alamat')
    }
  }

  const handleUseCurrentLocation = async () => {
    setIsGettingLocation(true)
    setLocationError(null)

    // First try: Use IP-based geolocation (fastest, works on desktop without permission)
    try {
      console.log('Attempting IP-based geolocation...')
      const location = await getLocationFromIP()

      setSelectedPosition({ lat: location.lat, lng: location.lng })
      reverseGeocode(location.lat, location.lng)
      setIsGettingLocation(false)
      setLocationError(null)
      return
    } catch (ipError: any) {
      console.error('IP-based geolocation failed:', ipError)
      // Continue to browser geolocation as fallback
    }

    // Check if browser supports geolocation
    if (!navigator.geolocation) {
      console.error('Geolocation not supported')
      setIsGettingLocation(false)
      setLocationError('Browser Anda tidak mendukung geolokasi.')
      return
    }

    // Fallback: Try browser geolocation with shorter timeout
    const tryGetLocation = (enableHighAccuracy: boolean): Promise<GeolocationPosition> => {
      return new Promise((resolve, reject) => {
        navigator.geolocation.getCurrentPosition(
          resolve,
          reject,
          {
            enableHighAccuracy,
            timeout: 5000,
            maximumAge: 60000, // Allow cached location up to 1 minute old
          }
        )
      })
    }

    try {
      // First attempt: low accuracy (faster)
      console.log('Attempting browser geolocation (low accuracy)...')
      const position = await tryGetLocation(false)

      const lat = position.coords.latitude
      const lng = position.coords.longitude
      setSelectedPosition({ lat, lng })
      reverseGeocode(lat, lng)
      setIsGettingLocation(false)
      setLocationError(null)
    } catch (error: any) {
      console.error('Browser geolocation failed (low accuracy):', error.message || error)

      // Try again with high accuracy as final fallback
      try {
        console.log('Attempting browser geolocation (high accuracy)...')
        const position = await tryGetLocation(true)

        const lat = position.coords.latitude
        const lng = position.coords.longitude
        setSelectedPosition({ lat, lng })
        reverseGeocode(lat, lng)
        setIsGettingLocation(false)
        setLocationError(null)
      } catch (highAccError: any) {
        console.error('Browser geolocation failed (high accuracy):', highAccError.message || highAccError)
        setIsGettingLocation(false)

        // Provide user-friendly error messages
        if (highAccError.code === 1) {
          setLocationError('Akses lokasi ditolak. Mohon izinkan akses lokasi di pengaturan browser.')
        } else if (highAccError.code === 2) {
          setLocationError('Informasi lokasi tidak tersedia. Pastikan GPS aktif atau coba gunakan WiFi.')
        } else if (highAccError.code === 3) {
          setLocationError('Permintaan lokasi timeout. Periksa koneksi internet Anda.')
        } else {
          setLocationError('Gagal mendapatkan lokasi. Silakan pilih lokasi secara manual di peta.')
        }
      }
    }
  }

  // Fallback: Get location from IP address using a free service
  const getLocationFromIP = async (): Promise<{ lat: number; lng: number }> => {
    try {
      // Try ipapi.co (free, no API key needed, 1000 requests/day)
      const response = await fetch('https://ipapi.co/json/')
      
      if (!response.ok) {
        throw new Error(`HTTP error! status: ${response.status}`)
      }
      
      const data = await response.json()
      
      if (data.latitude && data.longitude) {
        console.log('IP-based location found:', data.latitude, data.longitude)
        return {
          lat: data.latitude,
          lng: data.longitude,
        }
      }
      
      throw new Error('No coordinates in response')
    } catch (error) {
      console.error('ipapi.co failed, trying ipinfo.io...', error)
      
      // Fallback to ipinfo.io
      const response = await fetch('https://ipinfo.io/json?token=')
      
      if (!response.ok) {
        throw new Error(`HTTP error! status: ${response.status}`)
      }
      
      const data = await response.json()
      
      if (data.loc) {
        const [lat, lng] = data.loc.split(',').map(Number)
        if (!isNaN(lat) && !isNaN(lng)) {
          console.log('ipinfo.io location found:', lat, lng)
          return { lat, lng }
        }
      }
      
      throw new Error('All IP-based geolocation services failed')
    }
  }

  const handleConfirm = () => {
    if (selectedPosition && selectedAddress) {
      onConfirm(selectedAddress, selectedPosition.lat, selectedPosition.lng)
      // Reset state
      setSelectedPosition(null)
      setSelectedAddress('')
      setSearchQuery('')
      setSearchResults([])
    }
  }

  const handleClose = () => {
    setSelectedPosition(null)
    setSelectedAddress('')
    setSearchQuery('')
    setSearchResults([])
    setLocationError(null)
    onClose()
  }

  const onLoad = useCallback((map: google.maps.Map) => {
    setMap(map as any)
  }, [])

  if (!isOpen || !isLoaded) return null

  return (
    <div className="fixed inset-0 z-50 flex items-center justify-center p-4">
      {/* Backdrop */}
      <div className="absolute inset-0 bg-black/70" onClick={handleClose} />

      {/* Modal */}
      <div className="relative bg-gray-900 rounded-xl border border-gray-700 w-full max-w-2xl max-h-[90vh] flex flex-col shadow-2xl">
        {/* Header */}
        <div className="flex items-center justify-between px-4 py-3 border-b border-gray-700">
          <h2 className="text-lg font-bold text-white">Pilih Lokasi Pengantaran</h2>
          <button
            onClick={handleClose}
            className="text-gray-400 hover:text-white transition-colors text-2xl leading-none"
          >
            ×
          </button>
        </div>

        {/* Search Bar */}
        <div className="px-4 py-3 border-b border-gray-700">
          <div className="flex gap-2 mb-2">
            <button
              onClick={handleUseCurrentLocation}
              disabled={isGettingLocation}
              className="flex items-center gap-2 px-3 py-2 bg-green-600 hover:bg-green-700 disabled:bg-gray-700 disabled:text-gray-500 text-white rounded-lg transition-colors text-xs font-semibold"
              title="Gunakan lokasi terkini"
            >
              {isGettingLocation ? (
                <>
                  <div className="w-3 h-3 border-2 border-white border-t-transparent rounded-full animate-spin" />
                  <span>Mendeteksi lokasi...</span>
                </>
              ) : (
                <>
                  <svg className="w-3 h-3" 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>
                  <span>Gunakan Lokasi Terkini</span>
                </>
              )}
            </button>
          </div>
          <div className="relative">
            <input
              type="text"
              value={searchQuery}
              onChange={(e) => handleSearchInput(e.target.value)}
              placeholder="Ketik alamat untuk mencari..."
              className="w-full px-4 py-2.5 bg-gray-800 border border-gray-600 rounded-lg text-white text-sm focus:outline-none focus:border-blue-500 pr-10"
            />
            {isSearching && (
              <div className="absolute right-3 top-1/2 -translate-y-1/2">
                <div className="w-4 h-4 border-2 border-blue-500 border-t-transparent rounded-full animate-spin" />
              </div>
            )}
          </div>

          {/* Search Results Dropdown */}
          {searchResults.length > 0 && (
            <div className="absolute left-0 right-0 top-full mt-1 bg-gray-800 border border-gray-600 rounded-lg shadow-xl max-h-48 overflow-y-auto z-50">
              {searchResults.map((result, index) => (
                <button
                  key={index}
                  onClick={() => handleSelectResult(result)}
                  className="w-full text-left px-4 py-3 hover:bg-gray-700 border-b border-gray-700 last:border-b-0 transition-colors"
                >
                  <p className="text-sm text-white line-clamp-2">{result.formatted_address}</p>
                </button>
              ))}
            </div>
          )}

          {/* Location Error Message */}
          {locationError && (
            <div className="mt-2 p-2 bg-red-900/50 border border-red-500 rounded-lg text-red-300 text-xs">
              ⚠️ {locationError}
            </div>
          )}

          <p className="text-xs text-gray-500 mt-2">
            💡 Ketik alamat lalu pilih dari hasil, atau klik langsung di peta
          </p>
        </div>

        {/* Map */}
        <div className="flex-1 min-h-[400px] relative">
          <GoogleMap
            center={selectedPosition || { lat: -6.2088, lng: 106.8456 }}
            zoom={selectedPosition ? 16 : 13}
            mapContainerStyle={{ width: '100%', height: '100%', minHeight: '400px' }}
            onClick={handleMapClick}
            onLoad={onLoad}
            options={{
              styles: [
                { elementType: "geometry", stylers: [{ color: "#242f3e" }] },
                { elementType: "labels.text.stroke", stylers: [{ color: "#242f3e" }] },
                { elementType: "labels.text.fill", stylers: [{ color: "#746855" }] },
                {
                  featureType: "administrative.locality",
                  elementType: "labels.text.fill",
                  stylers: [{ color: "#d59563" }],
                },
                {
                  featureType: "poi",
                  elementType: "labels.text.fill",
                  stylers: [{ color: "#d59563" }],
                },
                {
                  featureType: "poi.park",
                  elementType: "geometry",
                  stylers: [{ color: "#263c3f" }],
                },
                {
                  featureType: "poi.park",
                  elementType: "labels.text.fill",
                  stylers: [{ color: "#6b9a76" }],
                },
                {
                  featureType: "road",
                  elementType: "geometry",
                  stylers: [{ color: "#38414e" }],
                },
                {
                  featureType: "road",
                  elementType: "geometry.stroke",
                  stylers: [{ color: "#212a37" }],
                },
                {
                  featureType: "road",
                  elementType: "labels.text.fill",
                  stylers: [{ color: "#9ca5b3" }],
                },
                {
                  featureType: "road.highway",
                  elementType: "geometry",
                  stylers: [{ color: "#746855" }],
                },
                {
                  featureType: "road.highway",
                  elementType: "geometry.stroke",
                  stylers: [{ color: "#1f2835" }],
                },
                {
                  featureType: "transit",
                  elementType: "geometry",
                  stylers: [{ color: "#2f3948" }],
                },
                {
                  featureType: "transit.station",
                  elementType: "labels.text.fill",
                  stylers: [{ color: "#d59563" }],
                },
                {
                  featureType: "water",
                  elementType: "geometry",
                  stylers: [{ color: "#17263c" }],
                },
                {
                  featureType: "water",
                  elementType: "labels.text.fill",
                  stylers: [{ color: "#515c6d" }],
                },
              ],
            }}
          >
            {selectedPosition && (
              <MarkerF position={{ lat: selectedPosition.lat, lng: selectedPosition.lng }} />
            )}
          </GoogleMap>
        </div>

        {/* Footer */}
        <div className="px-4 py-3 border-t border-gray-700 flex gap-2">
          <button
            onClick={handleClose}
            className="flex-1 px-4 py-2 bg-gray-800 hover:bg-gray-700 text-white rounded-lg transition-colors text-sm"
          >
            Batal
          </button>
          <button
            onClick={handleConfirm}
            disabled={!selectedPosition || !selectedAddress}
            className="flex-1 px-4 py-2 bg-blue-600 hover:bg-blue-700 disabled:bg-gray-700 disabled:text-gray-500 text-white rounded-lg transition-colors text-sm font-semibold"
          >
            Pilih Lokasi
          </button>
        </div>
      </div>
    </div>
  )
}
