import { AnimatePresence, motion } from "framer-motion";
import dynamic from "next/dynamic";
import Image from "next/image";
import {
	type Dispatch,
	Fragment,
	memo,
	type SetStateAction,
	useState,
} from "react";
import { LoadingPage } from "~/components/loading";
import { Status500 } from "~/components/status-page";
import { handleConsegna } from "~/lib/annuncio_details";
import { formatCurrency } from "~/lib/utils";
import { useTranslation } from "~/providers/I18nProvider";
import { useRicerca } from "~/providers/RicercaProvider";
import type { AnnuncioRicercaWPosition } from "~/server/controllers/annunci.controller";
import { api } from "~/utils/api";

const MapComp = dynamic(() => import("~/components/map/Map"), {
	ssr: false,
});

export const MapSection = () => {
	const { comune, consegna, tipo } = useRicerca();
	const [selected, setSelected] = useState<AnnuncioRicercaWPosition | null>(
		null,
	);

	return (
		<div className="relative z-50 flex h-[60vh] w-full items-center justify-center sm:h-[65vh]">
			<MapDisplay
				selectComune={comune}
				selectConsegna={consegna}
				selectTipo={tipo}
				setSelected={setSelected}
			/>
			<SelectedComp selected={selected} />
		</div>
	);
};

const MapDisplay = memo(
	({
		selectTipo,
		selectComune,
		selectConsegna,
		setSelected,
	}: {
		selectTipo: string;
		selectComune: string;
		selectConsegna: number | null;
		setSelected: Dispatch<SetStateAction<AnnuncioRicercaWPosition | null>>;
	}) => {
		const { data, isLoading } = api.annunci.getMapping.useQuery({
			comune: selectComune,
			consegna: selectConsegna || undefined,
			tipologia: selectTipo,
		});

		if (isLoading) return <LoadingPage />;
		if (!data) return <Status500 />;

		const posizioni = data
			.map((a) => {
				if (a.lat_secondario && a.lon_secondario) {
					return {
						markerTxt: `€ ${a.prezzo / 1e2}`,
						onClick: () => setSelected(a),
						pos: {
							lat: parseFloat(a.lat_secondario),
							lng: parseFloat(a.lon_secondario),
						},
					};
				}
				return undefined;
			})
			.filter((a) => a !== undefined);

		return (
			<MapComp
				groupData={posizioni}
				height="100%"
				isGroup
				markerType="price"
				onMapClick={() => setSelected(null)}
				posix={{ pos: { lat: 45.764718, lng: 11.73067 } }}
				scrollWheelZoom
				width="100%"
				zoom={13}
			/>
		);
	},
);

MapDisplay.displayName = "MapDisplay";

const SelectedComp = memo(
	({ selected }: { selected: AnnuncioRicercaWPosition | null }) => {
		const { t } = useTranslation();

		return (
			<Fragment>
				<AnimatePresence initial={false}>
					{selected && (
						<motion.a
							animate={{ opacity: 1, scale: 1 }}
							aria-label="Visualizza Dettagli Annuncio"
							className="group absolute right-0 bottom-0 left-0 z-20 mx-2 mb-2 flex flex-col gap-2 rounded-md bg-white p-4 ring-neutral-500 hover:ring-1"
							exit={{ opacity: 0, scale: 0 }}
							href={`/annuncio/${selected.codice}`}
							initial={{ opacity: 0, scale: 0 }}
							key={selected.id}
							target="_blank"
							transition={{
								duration: 0.1,
								scale: { bounce: 0.2, type: "spring", visualDuration: 0.1 },
							}}
						>
							<div className="flex gap-2">
								{selected.url_immagini?.[0] ? (
									<Image
										alt="a"
										className="size-24 rounded-md object-cover sm:size-40"
										height={500}
										src={selected.url_immagini[0]}
										width={500}
									/>
								) : (
									<div className="size-20 bg-gray-200 sm:size-40" />
								)}
								<div className="flex flex-col sm:gap-2 sm:text-lg">
									<h6 className="font-semibold underline-offset-2 group-hover:underline">
										{selected.codice}
									</h6>
									<h3 className="text-sm sm:text-base">{selected.titolo_it}</h3>
									<div className="flex gap-2">
										<h3 className="font-semibold">
											{formatCurrency(selected.prezzo / 1e2)}
										</h3>
										<h3>{selected.mq}mq</h3>
									</div>
									<p>
										{handleConsegna({
											aggiornamento: t.card.in_aggiornamento,
											consegna: selected.consegna,
											consegna_da: t.card.consegna_da,
											mesi: t.preferenze.mesi,
											subito: t.card.consegna_subito,
										})}
									</p>
								</div>
							</div>
						</motion.a>
					)}
				</AnimatePresence>
			</Fragment>
		);
	},
);
SelectedComp.displayName = "SelectedComp";
