import { type FC, useState, useEffect } from 'react'
import { MapContainer, TileLayer, Marker, useMapEvents, useMap } from 'react-leaflet'
import { Icon } from 'leaflet'
import type { LatLngTuple } from 'leaflet'

interface LocationPickerProps {
    initialPosition?: [number, number]
    onLocationSelect: (lat: number, lng: number) => void
}

interface NominatimSearchResult {
    place_id: number
    display_name: string
    lat: string
    lon: string
}

const ChangeView = ({ center, zoom }: { center: LatLngTuple; zoom: number }) => {
    const map = useMap()
    useEffect(() => {
        map.setView(center, zoom)
    }, [map, center, zoom])
    return null
}

const LocationPicker: FC<LocationPickerProps> = ({ initialPosition, onLocationSelect }) => {
    const [position, setPosition] = useState<LatLngTuple>(
        initialPosition || [35.6892, 51.3890] // تهران به عنوان پیش‌فرض
    )
    const [searchQuery, setSearchQuery] = useState('')
    const [searchResults, setSearchResults] = useState<NominatimSearchResult[]>([])
    const [isSearching, setIsSearching] = useState(false)
    const [searchError, setSearchError] = useState('')

    useEffect(() => {
        if (initialPosition) {
            setPosition(initialPosition)
        }
    }, [initialPosition])

    useEffect(() => {
        const query = searchQuery.trim()

        if (!query) {
            setSearchResults([])
            setSearchError('')
            setIsSearching(false)
            return
        }

        const controller = new AbortController()
        const timer = window.setTimeout(async () => {
            setIsSearching(true)
            setSearchError('')

            try {
                const params = new URLSearchParams({
                    q: query,
                    format: 'json',
                    addressdetails: '1',
                    limit: '5',
                })

                const response = await fetch(
                    `https://nominatim.openstreetmap.org/search?${params.toString()}`,
                    {
                        headers: {
                            Accept: 'application/json',
                        },
                        signal: controller.signal,
                    }
                )

                if (!response.ok) {
                    throw new Error('search request failed')
                }

                const data = (await response.json()) as NominatimSearchResult[]
                if (!data.length) {
                    setSearchResults([])
                    setSearchError('نتیجه‌ای پیدا نشد')
                    return
                }

                setSearchResults(data)
            } catch (error) {
                if ((error as DOMException).name === 'AbortError') {
                    return
                }
                setSearchResults([])
                setSearchError('خطا در جستجوی موقعیت')
            } finally {
                setIsSearching(false)
            }
        }, 500)

        return () => {
            controller.abort()
            window.clearTimeout(timer)
        }
    }, [searchQuery])

    const handleSelectSearchResult = (result: NominatimSearchResult) => {
        const lat = Number(result.lat)
        const lng = Number(result.lon)
        const newPosition: LatLngTuple = [lat, lng]
        setPosition(newPosition)
    }

    const LocationMarker = () => {
        useMapEvents({
            click(e) {
                const newPosition: LatLngTuple = [e.latlng.lat, e.latlng.lng]
                setPosition(newPosition)
                onLocationSelect(newPosition[0], newPosition[1])
            },
        })

        const customIcon = new Icon({
            iconUrl: 'https://unpkg.com/leaflet@1.9.4/dist/images/marker-icon.png',
            iconRetinaUrl: 'https://unpkg.com/leaflet@1.9.4/dist/images/marker-icon-2x.png',
            shadowUrl: 'https://unpkg.com/leaflet@1.9.4/dist/images/marker-shadow.png',
            iconSize: [25, 41],
            iconAnchor: [12, 41],
            popupAnchor: [1, -34],
            shadowSize: [41, 41],
        })

        return position ? <Marker position={position} icon={customIcon} /> : null
    }

    return (
        <div className='w-full'>
            <div className='mb-3'>
                <input
                    value={searchQuery}
                    onChange={(e) => setSearchQuery(e.target.value)}
                    placeholder='جستجوی آدرس یا مکان'
                    className='w-full h-10 border border-border rounded-xl px-3 text-sm outline-none focus:border-primary'
                />
            </div>

            {isSearching && <div className='text-xs text-description mb-2'>در حال جستجو...</div>}

            {searchError && <div className='text-xs text-red-500 mb-2'>{searchError}</div>}

            {searchResults.length > 0 && (
                <div className='mb-3 border border-border rounded-xl max-h-32 overflow-auto'>
                    {searchResults.map((result) => (
                        <button
                            key={result.place_id}
                            type='button'
                            onClick={() => handleSelectSearchResult(result)}
                            className='w-full text-right px-3 py-2 text-xs hover:bg-gray-50 border-b border-border last:border-b-0'
                        >
                            {result.display_name}
                        </button>
                    ))}
                </div>
            )}

            <div className='w-full h-[400px] rounded-xl overflow-hidden'>
            <MapContainer
                center={position}
                zoom={13}
                style={{ height: '100%', width: '100%' }}
                scrollWheelZoom={true}
            >
                <ChangeView center={position} zoom={13} />
                <TileLayer
                    attribution='&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
                    url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
                />
                <LocationMarker />
            </MapContainer>
            </div>
        </div>
    )
}

export default LocationPicker

