"use client"

import { useRef, useEffect, useState } from "react"
import { cn } from "@/lib/utils"

export interface AddressComponents {
  street_number?: string
  route?: string
  locality?: string
  sublocality_level_1?: string
  administrative_area_level_1?: string
  postal_code?: string
  country?: string
}

export interface AddressResult {
  address: string
  city: string
  state: string
  zipCode: string
  coordinates?: {
    lat: number
    lng: number
  }
}

interface AddressAutocompleteProps {
  value?: string
  onChange?: (result: AddressResult) => void
  onAddressChange?: (address: string) => void
  placeholder?: string
  className?: string
  disabled?: boolean
}

const AddressAutocomplete: React.FC<AddressAutocompleteProps> = ({
  value,
  onChange,
  onAddressChange,
  placeholder = "123 Main Street, City, State",
  className,
  disabled
}) => {
  const containerRef = useRef<HTMLDivElement>(null)
  const autocompleteElementRef = useRef<any>(null)
  const onChangeRef = useRef(onChange)
  const [isLoaded, setIsLoaded] = useState(false)
  const [inputValue, setInputValue] = useState(value || "")
  const [isScriptLoading, setIsScriptLoading] = useState(false)
  const [useLegacyAPI, setUseLegacyAPI] = useState(false)
  const inputRef = useRef<HTMLInputElement>(null)
  const legacyAutocompleteRef = useRef<any>(null)
  const listenerRef = useRef<any>(null)

  // Keep onChange ref up to date
  useEffect(() => {
    onChangeRef.current = onChange
  }, [onChange])

  useEffect(() => {
    setInputValue(value || "")
  }, [value])

  useEffect(() => {
    const loadGoogleMapsScript = async () => {
      console.log('🚀 AddressAutocomplete - Starting to load Google Maps')
      
      const apiKey = process.env.NEXT_PUBLIC_GOOGLE_MAPS_API_KEY
      if (!apiKey) {
        console.warn("⚠️ AddressAutocomplete - Google Maps API key not found")
        return
      }

      // Check if already loaded
      if (window.google && window.google.maps) {
        console.log('✅ Google Maps already loaded')
        await initializeNewAutocomplete()
        return
      }

      if (isScriptLoading) {
        console.log('⏳ Script already loading...')
        return
      }

      setIsScriptLoading(true)

      // Check if script already exists
      const existingScript = document.querySelector('script[src*="maps.googleapis.com"]')
      if (existingScript) {
        console.log('📜 Script element exists, waiting for load...')
        const checkLoaded = async () => {
          if (window.google && window.google.maps) {
            console.log('✅ Google Maps loaded')
            setIsScriptLoading(false)
            await initializeNewAutocomplete()
          } else {
            setTimeout(checkLoaded, 100)
          }
        }
        checkLoaded()
        return
      }

      // Load new API with async loading
      const script = document.createElement('script')
      script.src = `https://maps.googleapis.com/maps/api/js?key=${apiKey}&loading=async&libraries=places`
      script.async = true
      script.defer = true
      
      script.onload = async () => {
        console.log('✅ Google Maps script loaded')
        setIsScriptLoading(false)
        await initializeNewAutocomplete()
      }
      
      script.onerror = () => {
        console.error("❌ Failed to load Google Maps API")
        setIsScriptLoading(false)
      }

      console.log('📥 Loading Google Maps script...')
      document.head.appendChild(script)
    }

    const initializeNewAutocomplete = async () => {
      if (!containerRef.current) {
        console.warn('⚠️ Container ref not available')
        return
      }
      
      if (!window.google || !window.google.maps) {
        console.warn('⚠️ Google Maps not available')
        return
      }

      try {
        // Try to use new PlaceAutocompleteElement API (when available)
        console.log('🆕 Attempting to use new PlaceAutocompleteElement API...')

        // Import the places library only if importLibrary exists on this runtime
        if (typeof window.google.maps.importLibrary === 'function') {
          await window.google.maps.importLibrary('places')
        }

        // Check if PlaceAutocompleteElement is available
        if (window.google.maps.places && window.google.maps.places.PlaceAutocompleteElement) {
          console.log('✅ Using NEW PlaceAutocompleteElement API')
          setupNewAPI()
        } else {
          throw new Error('PlaceAutocompleteElement not available')
        }
      } catch (error) {
        console.warn('⚠️ New API not available, falling back to legacy Autocomplete:', error)
        setUseLegacyAPI(true)
        // Attempt legacy setup directly; the script URL already includes libraries=places
        setupLegacyAPI()
      }
    }

    const setupNewAPI = () => {
      try {
        // Create the new autocomplete element
        const autocompleteElement = document.createElement('gmp-place-autocomplete') as any
        autocompleteElement.setAttribute('placeholder', placeholder)
        
        // Set options
        autocompleteElement.componentRestrictions = { country: 'us' }
        autocompleteElement.types = ['address']
        
        // Style the element
        const style = document.createElement('style')
        style.textContent = `
          gmp-place-autocomplete {
            width: 100%;
          }
          gmp-place-autocomplete input {
            width: 100%;
            height: 2.5rem;
            border-radius: 0.375rem;
            border: 1px solid hsl(var(--input));
            background-color: hsl(var(--background));
            padding: 0.5rem 0.75rem;
            font-size: 0.875rem;
            line-height: 1.25rem;
          }
          gmp-place-autocomplete input:focus {
            outline: none;
            ring: 2px;
            ring-color: hsl(var(--ring));
            ring-offset: 2px;
          }
          gmp-place-autocomplete input:disabled {
            cursor: not-allowed;
            opacity: 0.5;
          }
        `
        document.head.appendChild(style)
        
        // Clear container and add element
        if (containerRef.current) {
          containerRef.current.innerHTML = ''
          containerRef.current.appendChild(autocompleteElement)
        }
        
        autocompleteElementRef.current = autocompleteElement
        
        // Listen to place selection
        autocompleteElement.addEventListener('gmp-placeselect', async (event: any) => {
          console.log('🎯 NEW API - Place selected event triggered')
          
          const place = event.place
          
          if (!place) {
            console.warn('⚠️ No place data in event')
            return
          }
          
          // Fetch place details
          await place.fetchFields({
            fields: ['addressComponents', 'formattedAddress', 'location']
          })
          
          console.log('📍 Place details:', place)
          
          if (!place.addressComponents) {
            console.warn('⚠️ No address components')
            return
          }
          
          const components: AddressComponents = {}
          let stateShortName = ''
          let zipCode = ''
          
          // Parse address components
          place.addressComponents.forEach((component: any) => {
            const types = component.types || []
            const type = types[0]
            
            if (type === 'street_number') components.street_number = component.longText
            if (type === 'route') components.route = component.longText
            if (type === 'locality') components.locality = component.longText
            if (type === 'sublocality_level_1') components.locality = components.locality || component.longText
            if (type === 'administrative_area_level_1') {
              components.administrative_area_level_1 = component.longText
              stateShortName = component.shortText
            }
            if (type === 'postal_code') {
              zipCode = component.longText
            }
            if (type === 'postal_code_suffix' && zipCode) {
              zipCode += '-' + component.longText
            }
          })
          
          console.log('✅ Parsed components:', components)
          console.log('✅ State:', stateShortName)
          console.log('✅ ZIP Code:', zipCode)
          
          const street = [components.street_number, components.route]
            .filter(Boolean)
            .join(' ')
          
          const result: AddressResult = {
            address: street || place.formattedAddress || '',
            city: components.locality || '',
            state: stateShortName || components.administrative_area_level_1 || '',
            zipCode: zipCode || '',
            coordinates: place.location ? {
              lat: place.location.lat(),
              lng: place.location.lng()
            } : undefined
          }
          
          console.log('🚀 Final result:', result)
          
          setInputValue(result.address)
          
          if (onChangeRef.current) {
            console.log('📤 Calling onChange callback')
            onChangeRef.current(result)
          }
        })
        
        setIsLoaded(true)
        console.log('✅ NEW API setup complete')
      } catch (error) {
        console.error('❌ Error setting up new API:', error)
        setUseLegacyAPI(true)
        setupLegacyAPI()
      }
    }

    const setupLegacyAPI = () => {
      // Wait a bit for input to be rendered
      setTimeout(() => {
        if (!inputRef.current) {
          console.warn('⚠️ Input ref not available, retrying...')
          // Retry once after a short delay
          setTimeout(() => {
            if (!inputRef.current) {
              console.error('❌ Input ref still not available, giving up')
              return
            }
            initLegacyAutocomplete()
          }, 100)
          return
        }
        initLegacyAutocomplete()
      }, 50)
    }
    
    const initLegacyAutocomplete = () => {
      if (!inputRef.current) {
        console.error('❌ Cannot initialize: input ref not available')
        return
      }
      
      // Check if Google Maps and places library are available
      if (!window.google || !window.google.maps || !window.google.maps.places || !window.google.maps.places.Autocomplete) {
        console.warn('⚠️ Google Maps places library not yet available, retrying shortly...')
        setTimeout(() => {
          if (window.google && window.google.maps && window.google.maps.places && window.google.maps.places.Autocomplete) {
            initLegacyAutocomplete()
          } else {
            console.error('❌ Google Maps places library still not available. Available objects:', {
              google: !!window.google,
              maps: !!(window.google && window.google.maps),
              places: !!(window.google && window.google.maps && window.google.maps.places),
              Autocomplete: !!(window.google && window.google.maps && window.google.maps.places && window.google.maps.places.Autocomplete)
            })
          }
        }, 200)
        return
      }
      
      try {
        console.log('🔄 Setting up LEGACY Autocomplete API')
        setIsLoaded(true)

        legacyAutocompleteRef.current = new window.google.maps.places.Autocomplete(
          inputRef.current,
          {
            types: ['address'],
            componentRestrictions: { country: 'us' },
            fields: ['address_components', 'formatted_address', 'geometry', 'place_id']
          }
        )

        const handlePlaceSelect = () => {
          console.log('🎯 LEGACY API - Place changed')
          
          setTimeout(() => {
            const place = legacyAutocompleteRef.current?.getPlace()
            
            if (!place || !place.address_components) {
              console.warn('⚠️ No address components')
              return
            }

            const components: AddressComponents = {}
            let stateShortName = ''
            let zipCode = ''
            
            place.address_components.forEach((component: any) => {
              const type = component.types[0]
              components[type as keyof AddressComponents] = component.long_name
              
              if (type === 'administrative_area_level_1') {
                stateShortName = component.short_name
              }
              
              if (type === 'postal_code') {
                zipCode = component.long_name
              } else if (type === 'postal_code_suffix' && zipCode) {
                zipCode += '-' + component.long_name
              }
            })

            console.log('✅ Parsed components:', components)
            console.log('✅ ZIP Code:', zipCode)

            const street = [components.street_number, components.route]
              .filter(Boolean)
              .join(' ')

            const result: AddressResult = {
              address: street || place.formatted_address || '',
              city: components.locality || components.sublocality_level_1 || '',
              state: stateShortName || components.administrative_area_level_1 || '',
              zipCode: zipCode || components.postal_code || '',
              coordinates: place.geometry?.location ? {
                lat: place.geometry.location.lat(),
                lng: place.geometry.location.lng()
              } : undefined
            }

            console.log('🚀 Final result:', result)

            setInputValue(result.address)
            
            if (onChangeRef.current) {
              console.log('📤 Calling onChange callback')
              onChangeRef.current(result)
            }
          }, 0)
        }

        if (listenerRef.current && window.google) {
          try {
            window.google.maps.event.removeListener(listenerRef.current)
          } catch (e) {
            // Ignore
          }
        }

        listenerRef.current = legacyAutocompleteRef.current.addListener('place_changed', handlePlaceSelect)

        console.log('✅ LEGACY API setup complete')
      } catch (error) {
        console.error('❌ Error setting up legacy API:', error)
      }
    }

    loadGoogleMapsScript()

    return () => {
      // Cleanup
      if (listenerRef.current && window.google) {
        try {
          window.google.maps.event.removeListener(listenerRef.current)
        } catch (error) {
          // Ignore
        }
      }
      if (legacyAutocompleteRef.current && window.google) {
        try {
          window.google.maps.event.clearInstanceListeners(legacyAutocompleteRef.current)
        } catch (error) {
          // Ignore
        }
      }
    }
  }, [placeholder])

  const handleInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {
    const newValue = e.target.value
    setInputValue(newValue)
    if (onAddressChange) {
      onAddressChange(newValue)
    }
  }

  // Always render both containers (hidden based on state)
  return (
    <div className="relative">
      {/* New API Container (hidden if using legacy) */}
      {!useLegacyAPI && (
        <div ref={containerRef} className={cn("w-full", className)} />
      )}
      
      {/* Legacy API Input (hidden if using new) */}
      {useLegacyAPI && (
        <input
          ref={inputRef}
          type="text"
          value={inputValue}
          onChange={handleInputChange}
          placeholder={placeholder}
          className={cn(
            "flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50",
            className
          )}
          disabled={disabled || isScriptLoading}
          autoComplete="off"
        />
      )}
      
      {isScriptLoading && (
        <div className="absolute right-3 top-3">
          <div className="w-4 h-4 border-2 border-gray-300 border-t-blue-600 rounded-full animate-spin"></div>
        </div>
      )}
    </div>
  )
}

export default AddressAutocomplete