"use client";

import { useState, useRef, useEffect } from "react";
import { MapPin, Search, X } from "lucide-react";

import { useCallback } from "react";

// Helper function moved outside component to be stable
const extractLocationDetails = (result: GeocoderResult): LocationDetails => {
    const details: LocationDetails = {};
    if (result.address_components) {
        result.address_components.forEach((component: GeocoderAddressComponent) => {
            const types = component.types || [];
            if (types.includes('administrative_area_level_1')) details.state = component.long_name;
            if (types.includes('locality') || types.includes('sublocality')) details.locality = component.long_name;
            if (types.includes('administrative_area_level_2')) details.city = component.long_name;
            if (types.includes('postal_code')) details.pincode = component.long_name;
        });
    }
    if (result.formatted_address) details.address = result.formatted_address;
    return details;
};

// Declare Google Maps types
// eslint-disable-next-line @typescript-eslint/no-explicit-any
type GoogleAny = any;

declare global {
    interface Window {
        google: GoogleAny;
        gm_authFailure?: () => void;
    }
}

// Type definitions for Google Maps Geocoder
interface GeocoderAddressComponent {
    long_name: string;
    short_name: string;
    types: string[];
}

interface GeocoderResult {
    formatted_address: string;
    geometry: {
        location: {
            lat: () => number;
            lng: () => number;
        };
    };
    address_components?: GeocoderAddressComponent[];
    [key: string]: unknown;
}

type GeocoderStatus = 'OK' | 'ZERO_RESULTS' | 'OVER_QUERY_LIMIT' | 'REQUEST_DENIED' | 'INVALID_REQUEST' | 'UNKNOWN_ERROR';

export interface LocationDetails {
    address?: string;
    state?: string;
    city?: string;
    locality?: string;
    pincode?: string;
    landmark?: string;
}

interface GoogleMapLocationPickerProps {
    value: string;
    onChange: (location: string, lat?: number, lng?: number, details?: LocationDetails) => void;
    placeholder?: string;
    height?: string;
}

export default function GoogleMapLocationPicker({
    value,
    onChange,
    placeholder = "Search location or click on map",
    height = "400px",
}: GoogleMapLocationPickerProps) {
    // Helper to keep onChange stable for effects
    const onChangeRef = useRef(onChange);
    useEffect(() => {
        onChangeRef.current = onChange;
    }, [onChange]);

    const [searchQuery, setSearchQuery] = useState("");
    const [showMap, setShowMap] = useState(false);
    const [selectedLocation, setSelectedLocation] = useState<{ lat: number; lng: number; address: string } | null>(null);
    const [mapLoaded, setMapLoaded] = useState(false);
    const mapRef = useRef<HTMLDivElement>(null);
    const mapInstanceRef = useRef<GoogleAny>(null);
    const markerRef = useRef<GoogleAny>(null);
    const autocompleteRef = useRef<GoogleAny>(null);
    const searchInputRef = useRef<HTMLInputElement>(null);



    const reverseGeocode = useCallback((lat: number, lng: number) => {
        if (!window.google || !window.google.maps) return;

        const geocoder = new window.google.maps.Geocoder();
        geocoder.geocode({ location: { lat, lng } }, (results: GeocoderResult[] | null, status: GeocoderStatus) => {
            if (status === "OK" && results && results[0]) {
                const result = results[0];
                const address = result.formatted_address;
                const details = extractLocationDetails(result);

                setSelectedLocation({ lat, lng, address });
                const locationString = `${address} (${lat}, ${lng})`;
                onChangeRef.current(locationString, lat, lng, details);
                setSearchQuery(address);
            } else {
                const locationString = `${lat}, ${lng}`;
                setSelectedLocation({ lat, lng, address: locationString });
                onChangeRef.current(locationString, lat, lng, {});
                setSearchQuery(`${lat}, ${lng}`);
            }
        });
    }, []);

    const placeMarker = useCallback((lat: number, lng: number, map: unknown) => {
        if (!window.google || !window.google.maps) return;

        if (markerRef.current) {
            markerRef.current.setMap(null);
        }

        const marker = new window.google.maps.Marker({
            position: { lat, lng },
            map: map,
            draggable: true,
            animation: window.google.maps.Animation.DROP,
        });

        markerRef.current = marker;

        marker.addListener("dragend", () => {
            const position = marker.getPosition();
            if (position) {
                const newLat = position.lat();
                const newLng = position.lng();
                reverseGeocode(newLat, newLng);
            }
        });
    }, [reverseGeocode]);

    const initializeMap = useCallback(() => {
        if (!mapRef.current) return;
        if (!window.google || !window.google.maps) return;

        try {
            // Initialize map centered on India
            const map = new window.google.maps.Map(mapRef.current, {
                center: { lat: 20.5937, lng: 78.9629 }, // India center
                zoom: 6,
                mapTypeControl: true,
                streetViewControl: false,
            });

            mapInstanceRef.current = map;

            // Add click listener to place marker
            map.addListener("click", (e: GoogleAny) => {
                if (e.latLng) {
                    const lat = e.latLng.lat();
                    const lng = e.latLng.lng();
                    placeMarker(lat, lng, map);
                    reverseGeocode(lat, lng);
                }
            });

            // Initialize Autocomplete for search
            if (searchInputRef.current && window.google.maps.places) {
                try {
                    const autocomplete = new window.google.maps.places.Autocomplete(searchInputRef.current, {
                        types: ["geocode", "establishment"],
                        componentRestrictions: { country: "in" }, // Restrict to India
                    });

                    autocompleteRef.current = autocomplete;

                    autocomplete.addListener("place_changed", () => {
                        const place = autocomplete.getPlace();
                        if (place.geometry?.location) {
                            const lat = place.geometry.location.lat();
                            const lng = place.geometry.location.lng();
                            const address = place.formatted_address || place.name || "";
                            const details = extractLocationDetails(place as unknown as GeocoderResult);

                            setSelectedLocation({ lat, lng, address });
                            placeMarker(lat, lng, map);
                            map.setCenter({ lat, lng });
                            map.setZoom(15);

                            const locationString = `${address} (${lat}, ${lng})`;
                            onChangeRef.current(locationString, lat, lng, details);
                            setSearchQuery(address);
                        }
                    });
                } catch (autocompleteError) {
                    console.error("Error initializing Autocomplete:", autocompleteError);
                }
            }
        } catch (error) {
            console.error("Error initializing map:", error);
            setMapLoaded(false);
        }
    }, [placeMarker, reverseGeocode]);

    const useCurrentLocation = () => {
        if (navigator.geolocation) {
            navigator.geolocation.getCurrentPosition(
                (position) => {
                    const lat = position.coords.latitude;
                    const lng = position.coords.longitude;
                    if (mapInstanceRef.current) {
                        placeMarker(lat, lng, mapInstanceRef.current);
                        mapInstanceRef.current.setCenter({ lat, lng });
                        mapInstanceRef.current.setZoom(15);
                        reverseGeocode(lat, lng);
                    }
                },
                (error) => {
                    console.error("Error getting current location:", error);
                    alert("Unable to get your current location.");
                }
            );
        } else {
            alert("Geolocation is not supported by your browser.");
        }
    };

    const handleSearch = () => {
        if (searchQuery.trim()) {
            if (!window.google || !window.google.maps) return;

            const geocoder = new window.google.maps.Geocoder();
            geocoder.geocode({ address: searchQuery }, (results: GeocoderResult[] | null, status: GeocoderStatus) => {
                if (status === "OK" && results && results[0] && mapInstanceRef.current) {
                    const result = results[0];
                    const location = result.geometry.location;
                    const lat = location.lat();
                    const lng = location.lng();
                    const address = result.formatted_address;
                    const details = extractLocationDetails(result);

                    setSelectedLocation({ lat, lng, address });
                    placeMarker(lat, lng, mapInstanceRef.current);
                    mapInstanceRef.current.setCenter({ lat, lng });
                    mapInstanceRef.current.setZoom(15);

                    const locationString = `${address} (${lat}, ${lng})`;
                    onChange(locationString, lat, lng, details);
                } else {
                    alert("Location not found.");
                }
            });
        }
    };

    const handleSaveLocation = () => {
        if (selectedLocation) {
            onChange(selectedLocation.address, selectedLocation.lat, selectedLocation.lng);
            setShowMap(false);
        }
    };

    // Load Google Maps script
    useEffect(() => {
        if (showMap && !mapLoaded) {
            const apiKey = process.env.NEXT_PUBLIC_GOOGLE_MAPS_API_KEY;

            if (!apiKey) {
                console.error("Google Maps API key is missing");
                return;
            }

            // Check if script already exists
            const existingScript = document.querySelector(`script[src*="maps.googleapis.com"]`);
            if (existingScript) {
                if (window.google && window.google.maps) {
                    setTimeout(() => {
                        setMapLoaded(true);
                    }, 0);
                }
                return;
            }

            const script = document.createElement("script");
            const cleanApiKey = apiKey.trim();
            const scriptUrl = `https://maps.googleapis.com/maps/api/js?key=${cleanApiKey}&libraries=places`;
            script.src = scriptUrl;
            script.async = true;
            script.defer = true;

            script.onload = () => {
                if (window.google && window.google.maps) {
                    setMapLoaded(true);
                    setTimeout(() => {
                        try {
                            initializeMap();
                        } catch (error) {
                            console.error("Map initialization error:", error);
                            setMapLoaded(false);
                        }
                    }, 100);
                } else {
                    console.error("Google Maps script loaded but API not available");
                    setMapLoaded(false);
                }
            };

            script.onerror = (error) => {
                console.error("Failed to load Google Maps script:", error);
                setShowMap(false);
                setMapLoaded(false);
            };

            document.head.appendChild(script);
        } else if (showMap && mapLoaded && window.google && window.google.maps) {
            setTimeout(() => {
                try {
                    initializeMap();
                } catch (error) {
                    console.error("Map initialization error:", error);
                }
            }, 100);
        }
    }, [showMap, mapLoaded, initializeMap]);

    return (
        <div className="w-full">
            <div className="flex gap-2 mb-2">
                <div className="flex-1 relative">
                    <input
                        type="text"
                        value={value || searchQuery}
                        onChange={(e) => {
                            setSearchQuery(e.target.value);
                            onChange(e.target.value);
                        }}
                        placeholder={placeholder}
                        className="w-full px-4 py-3 pr-10 rounded-xl bg-theme-input border border-primary-500/20 text-theme-primary focus:border-primary-500 focus:outline-none transition-colors"
                    />
                    <Search className="absolute right-3 top-1/2 -translate-y-1/2 w-5 h-5 text-gray-400" />
                </div>
                <button
                    type="button"
                    onClick={() => {
                        if (!showMap && !process.env.NEXT_PUBLIC_GOOGLE_MAPS_API_KEY) {
                            alert("Google Maps API key is not configured.\n\nPlease add NEXT_PUBLIC_GOOGLE_MAPS_API_KEY to your .env.local file.");
                            return;
                        }
                        setShowMap(!showMap);
                    }}
                    className="px-4 py-3 bg-primary-500 text-white rounded-xl hover:bg-primary-600 transition-colors flex items-center gap-2 whitespace-nowrap"
                >
                    <MapPin className="w-4 h-4" />
                    {showMap ? "Hide Map" : "Pick Location"}
                </button>
            </div>

            {showMap && (
                <div className="mt-4 border border-primary-500/20 rounded-xl overflow-hidden">
                    <div className="bg-gray-50 p-4 border-b border-primary-500/20">
                        <div className="flex items-center justify-between mb-3">
                            <p className="text-sm font-medium text-theme-secondary">
                                Click on the map to set location or search above
                            </p>
                            <button
                                type="button"
                                onClick={() => setShowMap(false)}
                                className="text-gray-500 hover:text-gray-700"
                            >
                                <X className="w-5 h-5" />
                            </button>
                        </div>
                        <div className="flex gap-2">
                            <input
                                ref={searchInputRef}
                                type="text"
                                value={searchQuery}
                                onChange={(e) => setSearchQuery(e.target.value)}
                                placeholder="Search for a place..."
                                className="flex-1 px-4 py-2 rounded-lg bg-white border border-gray-300 text-gray-900 focus:border-primary-500 focus:outline-none"
                                disabled={!mapLoaded}
                            />
                            <button
                                type="button"
                                onClick={handleSearch}
                                disabled={!mapLoaded}
                                className="px-4 py-2 bg-primary-500 text-white rounded-lg hover:bg-primary-600 transition-colors disabled:opacity-50"
                            >
                                Search
                            </button>
                            <button
                                type="button"
                                onClick={useCurrentLocation}
                                disabled={!mapLoaded}
                                className="px-4 py-2 bg-blue-500 text-white rounded-lg hover:bg-blue-600 transition-colors disabled:opacity-50 flex items-center gap-2"
                            >
                                <MapPin className="w-4 h-4" />
                                Current
                            </button>
                        </div>
                    </div>
                    {mapLoaded ? (
                        <div
                            ref={mapRef}
                            className="w-full bg-gray-200 rounded-b-xl"
                            style={{ height, minHeight: "300px" }}
                        />
                    ) : (
                        <div className="w-full bg-gray-200 flex items-center justify-center rounded-b-xl" style={{ height, minHeight: "300px" }}>
                            <div className="text-center">
                                <div className="inline-block animate-spin rounded-full h-12 w-12 border-b-2 border-primary-500 mb-4"></div>
                                <p className="text-gray-600">Loading map...</p>
                            </div>
                        </div>
                    )}
                    {selectedLocation && (
                        <div className="bg-gray-50 p-4 border-t border-primary-500/20">
                            <div className="flex items-center justify-between">
                                <div>
                                    <p className="text-sm font-medium text-gray-700">Selected Location:</p>
                                    <p className="text-sm text-gray-600 mt-1">{selectedLocation.address}</p>
                                </div>
                                <button
                                    type="button"
                                    onClick={handleSaveLocation}
                                    className="px-4 py-2 bg-green-600 text-white rounded-lg hover:bg-green-700 transition-colors"
                                >
                                    Save Location
                                </button>
                            </div>
                        </div>
                    )}
                </div>
            )}
        </div>
    );
}
