"use client";

import * as React from "react";
import { useForm } from "react-hook-form";
import { zodResolver } from "@hookform/resolvers/zod";
import * as z from "zod";
import {
	Form,
	FormControl,
	FormField,
	FormItem,
	FormLabel,
	FormMessage,
} from "@/components/ui/form";
import { Input } from "@/components/ui/input";
import {
	Command,
	CommandEmpty,
	CommandGroup,
	CommandInput,
	CommandItem,
	CommandList,
} from "@/components/ui/command";
import useDebounce from "@/hooks/use-debounce";
import { OpenStreetMapLocation } from "@/types/types";
import getOsmEmbedUrl from "@/lib/osmEmbed";
import { Location } from "@/types/types";

// Zod schema for validation
const locationFormSchema = z.object({
	id: z.number().optional(),
	street: z.string().min(1, "Street is required"),
	city: z.string().min(1, "City is required"),
	postalCode: z.string().min(1, "Postal code is required"),
	latitude: z.number().optional(),
	longitude: z.number().optional(),
});

export type LocationFormValues = z.infer<typeof locationFormSchema>;

export const LocationForm: React.FC<{
	location?: Location;
	setForm: React.Dispatch<
		React.SetStateAction<
			ReturnType<typeof useForm<LocationFormValues>> | undefined
		>
	>;
}> = ({ location, setForm }) => {
	const [osmQuery, setOsmQuery] = React.useState("");
	const [suggestions, setSuggestions] = React.useState<
		OpenStreetMapLocation[]
	>([]);
	const [isLoading, setIsLoading] = React.useState(false);

	const form = useForm<LocationFormValues>({
		resolver: zodResolver(locationFormSchema),
		defaultValues: location || {
			street: "",
			city: "",
			postalCode: "",
		},
	});

	React.useEffect(() => {
		setForm(form);
	}, [form, setForm]);

	// Fetch suggestions from OpenStreetMap Nominatim API
	const fetchSuggestions = async (query: string) => {
		if (!query || query.length < 3) {
			setSuggestions([]);
			return;
		}

		setIsLoading(true);
		try {
			const url = new URL("https://nominatim.openstreetmap.org/search");
			url.searchParams.append("q", query);
			url.searchParams.append("format", "json");
			url.searchParams.append("addressdetails", "1");
			url.searchParams.append("limit", "5");

			const response = await fetch(url);
			if (!response.ok) {
				throw new Error(`HTTP error! status: ${response.status}`);
			}
			const data: OpenStreetMapLocation[] = await response.json();
			setSuggestions(data);
		} catch (error) {
			console.error("Error fetching OSM suggestions:", error);
			setSuggestions([]);
		} finally {
			setIsLoading(false);
		}
	};

	const debouncedFetchSuggestions = useDebounce(fetchSuggestions, 300);

	// Handle form submission
	const onSubmit = (data: LocationFormValues) => {
		console.log("New Location:", data);
		// Here you can send the data to your backend (e.g., via API call)
	};

	const longitude = form.watch("longitude");
	const latitude = form.watch("latitude");

	// Helper function to construct street from OSM address
	const getStreetFromAddress = (
		address: OpenStreetMapLocation["address"],
	): string => {
		const houseNumber = address.house_number || "";
		const road = address.road || "";
		return (
			[houseNumber, road].filter(Boolean).join(" ").trim() ||
			"Unknown Street"
		);
	};

	return (
		<Form {...form}>
			<form onSubmit={form.handleSubmit(onSubmit)}>
				{/* Autocomplete Input */}
				<Command className="rounded-lg border shadow-md h-40">
					<CommandInput
						placeholder="Écrivez pour trouver une adresse..."
						value={osmQuery}
						onValueChange={(value) => {
							setOsmQuery(value);
							debouncedFetchSuggestions(value);
						}}
					/>
					<CommandList>
						{isLoading && <CommandEmpty>Loading...</CommandEmpty>}
						{!isLoading &&
							suggestions.length === 0 &&
							osmQuery.length < 1 && (
								<CommandEmpty>No results found.</CommandEmpty>
							)}
						{!isLoading && suggestions.length > 0 && (
							<CommandGroup heading="Suggestions">
								{suggestions.map((suggestion) => (
									<CommandItem
										key={suggestion.place_id}
										onSelect={() => {
											const address = suggestion.address;
											form.setValue(
												"street",
												getStreetFromAddress(address),
											);
											form.setValue(
												"city",
												address.city ||
													address.town ||
													address.village ||
													"",
											);
											form.setValue(
												"postalCode",
												address.postcode || "",
											);

											form.setValue(
												"latitude",
												parseFloat(suggestion.lat),
											);
											form.setValue(
												"longitude",
												parseFloat(suggestion.lon),
											);
										}}
									>
										{suggestion.display_name}
									</CommandItem>
								))}
							</CommandGroup>
						)}
					</CommandList>
				</Command>

				{/* Editable Fields */}
				<FormField
					control={form.control}
					name="street"
					render={({ field }) => (
						<FormItem>
							<FormLabel>Rue</FormLabel>
							<FormControl>
								<Input
									placeholder="Entrer une rue"
									{...field}
								/>
							</FormControl>
							<FormMessage />
						</FormItem>
					)}
				/>

				<FormField
					control={form.control}
					name="city"
					render={({ field }) => (
						<FormItem>
							<FormLabel>Ville</FormLabel>
							<FormControl>
								<Input
									placeholder="Entrer une ville"
									{...field}
								/>
							</FormControl>
							<FormMessage />
						</FormItem>
					)}
				/>

				<FormField
					control={form.control}
					name="postalCode"
					render={({ field }) => (
						<FormItem>
							<FormLabel>Code postal</FormLabel>
							<FormControl>
								<Input
									placeholder="Entrer un code postal"
									{...field}
								/>
							</FormControl>
							<FormMessage />
						</FormItem>
					)}
				/>

				{/* OSM Embed Map Preview */}
				{latitude && longitude && (
					<div className="mt-6">
						<h3 className="text-lg font-semibold mb-2">
							Prévisualisation
						</h3>
						<div className="h-[300px] w-full rounded-lg border overflow-hidden">
							<iframe
								width="100%"
								height="100%"
								src={getOsmEmbedUrl(latitude, longitude)}
								title="OpenStreetMap Preview"
							/>
						</div>
					</div>
				)}
			</form>
		</Form>
	);
};
