import {
	Armchair,
	ArrowUp01,
	BadgeEuro,
	Bath,
	BedDouble,
	Car,
	Clock,
	Copy,
	ExternalLink,
	Ruler,
	Share2,
	TrafficCone,
} from "lucide-react";
import type { GetStaticPaths, GetStaticPropsContext, NextPage } from "next";
import Head from "next/head";
import Link from "next/link";
import { useEffect, useState } from "react";
import toast from "react-hot-toast";
import { CarouselAnnuncio } from "~/components/annuncio_card";
import { AnnuncioInteractions } from "~/components/annuncio-interactions/annuncio_interactions";
import { TouchProvider } from "~/components/custom_ui/HybridTooltip";
import { ComeFunziona } from "~/components/expand_guida";
import FailedAnnuncioLoading from "~/components/failed-loading";
import { IconMatrix } from "~/components/IconComponents";
import InformationBubble from "~/components/InformationBubble";
import { LoadingPage } from "~/components/loading";
import { MappaDialogFullscreen } from "~/components/MapDialog";
import { PricingComponent, type PricingData } from "~/components/prezzi";
import {
	Accordion,
	AccordionContent,
	AccordionItem,
	AccordionTrigger,
} from "~/components/ui/accordion";
import { Button } from "~/components/ui/button";
import { Card, CardContent, CardHeader, CardTitle } from "~/components/ui/card";
import {
	Collapsible,
	CollapsibleContent,
	CollapsibleTrigger,
} from "~/components/ui/collapsible";
import {
	Dialog,
	DialogContent,
	DialogDescription,
	DialogHeader,
	DialogTitle,
	DialogTrigger,
} from "~/components/ui/dialog";
import Input from "~/components/ui/input";
import { Label } from "~/components/ui/label";
import { VideoPlayer } from "~/components/videoPlayer";
import { env } from "~/env";
import { filteredCaratteristiche } from "~/hooks/schedaAnnuncioUtils";
import { useStaleImageReload } from "~/hooks/staleImage";
import { useMediaQuery } from "~/hooks/use-media-query";
import { handleConsegna } from "~/lib/annuncio_details";
import { replaceWithBr } from "~/lib/newlineToBr";
import { getStorageUrl } from "~/lib/storage_utils";
import { cn, redirectTo500 } from "~/lib/utils";
import { AnnuncioContext, useAnnuncio } from "~/providers/AnnuncioProvider";
import { useTranslation } from "~/providers/I18nProvider";
import { buildRicercaUrl } from "~/providers/RicercaProvider";
import TipologiaPosizioneEnum from "~/schemas/public/TipologiaPosizioneEnum";
import type { AnnuncioData } from "~/server/controllers/annunci.controller";
import { generateSSGHelper } from "~/server/utils/ssgHelper";
import { api } from "~/utils/api";

type AnnuncioProps = {
	data: AnnuncioData;
	flag: string;
};

/**
 * Pagina di dettaglio annuncio: /annuncio/[cod]
 * Questa pagina mostra i dettagli di un annuncio specifico, identificato dal codice (cod) passato come parametro. Utilizza getStaticProps per prefetchare i dati dell'annuncio e le relative informazioni meta per SEO e condivisione sui social media. Se l'annuncio è in stato "Sospeso" o se si verifica un errore durante il caricamento, viene mostrata una pagina di errore.
 */
const AnnuncioDettaglio: NextPage<AnnuncioProps> = ({
	data,
	flag,
}: AnnuncioProps) => {
	return (
		<main>
			<Head>
				<title>{`${data.codice} | ${data.titolo_it}`}</title>
				<meta content={data.desc_it || ""} property="description" />
				<meta content={data.ogUrl} property="og:url" />
				<meta content="website" property="og:type" />
				<meta
					content={`${data.codice} | ${data.titolo_it}`}
					property="og:title"
				/>
				<meta content={data.desc_it || ""} property="og:description" />
				<meta content={data.ogImage} property="og:image" />
				<meta content="1200" property="og:image:width" />
				<meta content="630" property="og:image:height" />
				<meta
					content={`${env.NEXT_PUBLIC_BASE_URL}/Infoalloggi.png`}
					property="og:logo"
				/>
				<meta content="Infoalloggi.it" property="og:site_name" />
				<link href={data.ogUrl || ""} rel="canonical" />
				<link
					href={`${env.NEXT_PUBLIC_BASE_URL}/annuncio/${data.codice}`}
					hrefLang="it"
					rel="alternate"
				/>
				<link
					href={`${env.NEXT_PUBLIC_BASE_URL}/en/annuncio/${data.codice}`}
					hrefLang="en"
					rel="alternate"
				/>
			</Head>
			<AnnuncioView data={data} flag={flag} />
		</main>
	);
};

const AnnuncioView = ({ data, flag }: AnnuncioProps) => {
	useStaleImageReload();

	const isDesktop = useMediaQuery("(min-width: 768px)");

	if (!data || (data && data.stato === "Sospeso")) {
		return <FailedAnnuncioLoading />;
	}

	return (
		<AnnuncioContext.Provider value={data}>
			<TouchProvider>
				<div className="mx-auto w-full max-w-400 px-2 sm:px-8">
					<CarouselAnnuncio
						immagini={data.images}
						updated_at={
							data.media_updated_at ? new Date(data.media_updated_at) : null
						}
						videos={data.videos}
					/>

					<div className="flex flex-col sm:py-8 md:flex-row-reverse md:gap-2">
						<div className="mb-6 flex flex-col md:mb-0 md:w-1/3">
							<div className="flex w-full flex-col flex-nowrap items-center justify-center gap-6">
								<CardInfos />
								<AnnuncioInteractions disabled={flag === "true"} />
								<ComeFunziona />
								{data.tipo &&
									(data.tipo === "Transitorio" || data.tipo === "Stabile") && (
										<>
											<Pricing isDesktop={isDesktop} />
										</>
									)}
							</div>
						</div>
						<div className="mx-2 md:w-2/3">
							<TestiAnnuncio />
						</div>
					</div>
					<AnnuncioFooter />
				</div>
			</TouchProvider>
		</AnnuncioContext.Provider>
	);
};

export async function getStaticProps(
	context: GetStaticPropsContext<{ cod: string }>,
) {
	const ssg = generateSSGHelper();
	const cod = context.params?.cod;
	if (typeof cod !== "string") {
		return {
			redirect: {
				destination: "/annuncio-non-trovato",
				permanent: false,
			},
		};
	}
	const result = await ssg.annunci.getAnnuncioData.fetch({ cod: cod });

	if (!result.ok) {
		if (result.error._tag === "InternalError") {
			return redirectTo500;
		}

		return {
			redirect: {
				destination: "/annuncio-non-trovato",
				permanent: false,
			},
		};
	}
	if (result.value.stato === "Sospeso") {
		return {
			redirect: {
				destination: "/annuncio-non-trovato",
				permanent: false,
			},
		};
	}

	const flag = await ssg.flags.GetFlagValue.fetch({
		id: "ANNUNCIO_INTERACTIONS_DISABLED",
	});
	return {
		props: {
			data: result.value,
			//cod,
			flag,
			//meta,
			trpcState: ssg.dehydrate(),
		},
		revalidate: 21600, // 6 hours - ensures fresh data 4x per day
	};
}

export const getStaticPaths: GetStaticPaths = async () => {
	return {
		fallback: "blocking",
		paths: [],
	};
};

export default AnnuncioDettaglio;

const Pricing = ({ isDesktop }: { isDesktop: boolean }) => {
	const { t } = useTranslation();
	const { prezzo, tipo } = useAnnuncio();
	const tipologia =
		tipo === "Transitorio"
			? TipologiaPosizioneEnum.Transitorio
			: TipologiaPosizioneEnum.Stabile;
	const { data: prezziario, isLoading } =
		api.prezziario.getPrezziPerTipologia.useQuery({
			tipologia,
		});

	if (isLoading) return <LoadingPage />;
	if (!prezziario) return null;

	const opzioniT = [
		t.pricing_cmp.breve_option1,
		t.pricing_cmp.breve_option2,
		t.pricing_cmp.breve_option3,
		t.pricing_cmp.breve_option4,
		t.pricing_cmp.breve_option5,
	];
	const opzioniS = [
		t.pricing_cmp.stabile_option1,
		t.pricing_cmp.stabile_option2,
		t.pricing_cmp.stabile_option3,
	];

	const cta =
		tipologia === TipologiaPosizioneEnum.Transitorio
			? t.pricing_cmp.cta_breve
			: t.pricing_cmp.cta_stabile;

	const pricing = prezziario.saldi.map((s) => ({
		downPayment: prezziario.acconto.prezzo_cent / 100,
		secondPayment: s.prezzo_cent / 100,
	}));

	let opzioni: string[] = [];
	let pricingData: PricingData = [];

	if (tipologia === TipologiaPosizioneEnum.Stabile) {
		//se stabile, mostra il prezzo basato sul canone in default
		const idx = prezzo > 70000 ? 2 : prezzo > 50000 ? 1 : 0;
		const opzione = opzioniS[idx];
		const pricingS = pricing[idx];
		if (opzione && pricingS) {
			opzioni = [opzione];
			pricingData = [pricingS];
		} else {
			opzioni = opzioniS;
			pricingData = pricing;
		}
	} else {
		opzioni = opzioniT;
		pricingData = pricing;
	}

	const style =
		tipologia === TipologiaPosizioneEnum.Transitorio
			? "border-transitorio bg-transitorio"
			: "border-stabile bg-stabile";

	const title =
		tipologia === TipologiaPosizioneEnum.Transitorio
			? t.prezzi.titolo_transitori
			: t.prezzi.titolo_stabile;

	if (isDesktop) {
		return (
			<PricingComponent
				className={cn(
					style,
					"max-w-2xl **:data-[role=wrapper]:flex-wrap **:data-[role=amount]:text-2xl lg:**:data-[role=wrapper]:flex-nowrap xl:**:data-[role=amount]:text-3xl sm:[&_#contratto-link]:h-8 xl:[&_#contratto-link]:h-9",
				)}
				cta={cta}
				opzioni={opzioni}
				pricingData={pricingData}
				statico={true}
				tipo={tipologia}
				title={title}
			/>
		);
	}
	return (
		<Collapsible className="w-full">
			<CollapsibleTrigger asChild>
				<Button
					className={cn(
						"w-full text-white",
						tipologia === TipologiaPosizioneEnum.Transitorio
							? "bg-transitorio"
							: "bg-stabile",
					)}
					data-umami-event={`pricing_mobile_cta_click`}
				>
					<div className="flex items-center gap-2">
						<BadgeEuro className="size-5" />
						<span>{t.pricing_cmp.cta_costo}</span>
					</div>
				</Button>
			</CollapsibleTrigger>
			<CollapsibleContent className="mt-2">
				<PricingComponent
					className={cn(style, "max-w-full")}
					cta={cta}
					opzioni={opzioni}
					pricingData={pricingData}
					statico={true}
					tipo={tipologia}
					title={title}
				/>
			</CollapsibleContent>
		</Collapsible>
	);
};

const TestiAnnuncio = () => {
	const { locale } = useTranslation();
	const { titolo_it, titolo_en, desc_it, desc_en } = useAnnuncio();

	return (
		<>
			<h1 className="font-bold text-3xl uppercase">
				{locale === "it" ? titolo_it : titolo_en}
			</h1>
			<h1
				className="py-6"
				dangerouslySetInnerHTML={{
					__html: replaceWithBr((locale === "it" ? desc_it : desc_en) || ""),
				}}
			/>

			<CaratteristicheAccordion />
		</>
	);
};

const CaratteristicheAccordion = () => {
	const { caratteristiche } = useAnnuncio();
	if (!caratteristiche) return null;
	return (
		<Accordion
			className="my-5"
			collapsible
			defaultValue="altre-caratt"
			type="single"
		>
			<AccordionItem
				className="border-b dark:border-muted-foreground/50"
				value="altre-caratt"
			>
				<AccordionTrigger>Altre caratteristiche</AccordionTrigger>
				<AccordionContent>
					{Object.entries(filteredCaratteristiche(caratteristiche)).map(
						([key, scheda_value]) => {
							const { text, icon, value } = scheda_value;
							if (value === null) return null;
							return (
								<div
									className="flex flex-row items-center gap-2 text-base"
									key={key}
								>
									<IconMatrix className="size-4" type={icon} />
									{text}: {value}
								</div>
							);
						},
					)}
				</AccordionContent>
			</AccordionItem>
		</Accordion>
	);
};

const CardInfos = () => {
	const { t } = useTranslation();
	const {
		codice,
		prezzo,
		tipo,
		numero_camere,
		numero_bagni,
		caratteristiche,
		numero_postiauto,
		mq,
		piano,
		stato,
		consegna,
		lat_secondario,
		lon_secondario,
	} = useAnnuncio();
	return (
		<Card className="relative w-full bg-secondary text-secondary-foreground outline outline-secondary-foreground">
			<CardHeader>
				<CardTitle className="text-center font-bold text-3xl md:pl-8 lg:pl-0">
					{t.annunci.codice} {codice}
				</CardTitle>
			</CardHeader>
			<CardContent className="flex flex-col gap-4 p-4 py-0">
				<div className="grid grid-cols-2 gap-3 font-semibold">
					<div className="relative">
						<div className="flex h-10 items-center justify-center rounded-md bg-primary-foreground text-center text-primary">
							{prezzo && (prezzo / 1e2).toFixed(2).replace(".", ",")}{" "}
							{t.annunci.euro_mese}
						</div>
						{prezzo && (
							<InformationBubble
								icon="euro"
								iconClassName="h-[19.5px] w-[19.5px] bg-orange-500 text-white rounded-full"
							>
								<div className="text-fxd-foreground">
									<span className="font-semibold text-sm">
										{t.annunci.prezzo_giorno}
									</span>
									<div className="text-sm">
										{(prezzo / 1e2 / 30).toFixed(2).replace(".", ",")}{" "}
										{t.annunci.euro_giorno}
									</div>
								</div>
							</InformationBubble>
						)}
					</div>
					<div className="relative">
						<div
							className={cn(
								"h-10 rounded-md bg-primary-foreground p-2 text-center text-primary outline-2",
								tipo === "Transitorio" && "outline-transitorio",
								tipo === "Stabile" && "outline-stabile",
							)}
						>
							{tipo}
						</div>
						{tipo === "Transitorio" && (
							<InformationBubble
								href="/guida#faq-transitori"
								target="_blank"
								txt="Più informazioni sugli affitti transitori"
							/>
						)}
					</div>
				</div>
				<div className="flex flex-col gap-2">
					<h3 className="px-2">{t.annunci.fornitura}:</h3>
					<div className="grid grid-cols-2 gap-3">
						<div className="flex justify-center gap-2 rounded-md bg-primary-foreground p-2 text-primary">
							<BedDouble />
							<span className="line-clamp-1 break-all">
								{(() => {
									if (!numero_camere) return "N/A";
									if (numero_camere > 1)
										return `${numero_camere} ${t.card.camere2}`;
									if (numero_camere === 1)
										return `${numero_camere} ${t.card.camere1}`;
								})()}
							</span>
						</div>
						<div className="flex justify-center gap-2 rounded-md bg-primary-foreground p-2 text-primary">
							<Bath />
							<span className="line-clamp-1 break-all">
								{numero_bagni || 0} {t.annunci.bagni}
							</span>
						</div>
						<div className="flex justify-center gap-2 rounded-md bg-primary-foreground p-2 text-primary">
							<Armchair />
							<span className="line-clamp-1 break-all">
								{caratteristiche?.Scheda_Arredi || ""}
							</span>
						</div>
						<div className="flex justify-center gap-2 rounded-md bg-primary-foreground p-2 text-primary">
							<Car />
							<span className="line-clamp-1 break-all">
								{numero_postiauto || 0} {t.annunci.posti_auto}
							</span>
						</div>
					</div>
				</div>
				<div className="flex flex-col gap-2">
					<h3 className="px-2">{t.annunci.dati_immobile}:</h3>
					<div className="grid grid-cols-2 gap-3">
						<div className="flex justify-center gap-2 rounded-md bg-primary-foreground p-2 text-primary">
							<Ruler />
							<span className="line-clamp-1 break-all">
								{mq ? Number(mq).toLocaleString("it-IT") : "--"} m<sup>2</sup>
							</span>
						</div>

						<div className="flex justify-center gap-2 rounded-md bg-primary-foreground p-2 text-primary">
							{piano !== null && piano !== "" && (
								<>
									<ArrowUp01 />
									<span className="line-clamp-1 break-all">
										{(() => {
											if (piano === "0") return t.annunci.p_terra;
											if (piano === "0.5") return t.annunci.p_rialzato;
											if (piano) return `${piano}° ${t.annunci.piano}`;
											return "--";
										})()}
									</span>
								</>
							)}
						</div>
					</div>
				</div>

				<div className="text-center font-bold text-base">
					{stato === "Trattativa" ? (
						<div className="flex items-center justify-center gap-1 rounded-md py-1.5 text-trattativa outline-2 outline-trattativa dark:bg-secondary-foreground">
							<TrafficCone className="inline-block size-5" />
							<span>{t.annunci.in_aggiornamento}</span>
						</div>
					) : (
						<div className="flex items-center justify-center gap-1 rounded-md py-1.5 outline-2 outline-secondary-foreground">
							<Clock className="inline-block size-5" />
							{t.annunci.disponibile}:{" "}
							<span className="text-red-500">
								{handleConsegna({
									aggiornamento: t.card.in_aggiornamento,
									consegna: consegna,
									consegna_da: t.card.consegna_da,
									mesi: t.parametri.mesi,
									subito: t.card.consegna_subito,
								})}
							</span>
						</div>
					)}
				</div>
				<div className="flex flex-row justify-around gap-3">
					<MappaDialogFullscreen lat={lat_secondario} long={lon_secondario} />

					<ShareComponent />
				</div>
			</CardContent>
		</Card>
	);
};

const ShareComponent = () => {
	const { t } = useTranslation();

	const [link, setLink] = useState("");

	useEffect(() => {
		if (typeof window !== "undefined") {
			setLink(window.location.href);
		}
	}, []);
	const handleCopyLink = async () => {
		if (navigator.clipboard?.writeText) {
			try {
				await navigator.clipboard.writeText(link);
				toast(t.share.copiato, { icon: "📋" });
			} catch (err) {
				console.error("Failed to copy: ", err);
			}
		} else {
			// Fallback for browsers that do not support navigator.clipboard.writeText
			const textArea = document.createElement("textarea");
			textArea.value = link;
			document.body.appendChild(textArea);
			textArea.select();
			try {
				document.execCommand("copy");
				toast(t.share.copiato, { icon: "📋" });
			} catch (err) {
				console.error("Failed to copy: ", err);
			}
			document.body.removeChild(textArea);
		}
	};

	return (
		<Dialog>
			<DialogTrigger asChild>
				<Button data-umami-event="share_button_click">
					<Share2 />
				</Button>
			</DialogTrigger>
			<DialogContent className="sm:max-w-md">
				<DialogHeader>
					<DialogTitle>{t.share.condividi}</DialogTitle>
					<DialogDescription>{t.share.descrizione}</DialogDescription>
				</DialogHeader>
				<div className="flex items-center space-x-2">
					<div className="grid flex-1 gap-2">
						<Label className="sr-only" htmlFor="link">
							Link
						</Label>
						<Input defaultValue={link} id="link" readOnly />
					</div>
					<Button
						className="px-3"
						onClick={async () => await handleCopyLink()}
						size="sm"
						type="submit"
					>
						<span className="sr-only">Copy</span>
						<Copy />
					</Button>
				</div>
			</DialogContent>
		</Dialog>
	);
};

const AnnuncioFooter = () => {
	const { tipo, comune, consegna, videos, external_videos, media_updated_at } =
		useAnnuncio();
	const { t } = useTranslation();
	return (
		<div className="flex flex-col gap-2">
			<p
				className={cn(
					"px-2 font-semibold text-lg",
					videos.length === 0 && external_videos?.length === 0 && "hidden",
				)}
			>
				Video:
			</p>
			<div className="flex flex-col flex-wrap gap-4 sm:flex-row sm:gap-2 sm:px-2">
				{videos.map((video) => {
					return (
						<VideoPlayer
							className="h-96 max-w-96"
							coverImage={getStorageUrl({
								storageId: video.thumb,
								params: {
									cacheKey: media_updated_at || undefined,
									media: "image",
								},
							})}
							key={`videoplayer-${video.video}`} // Cache busting
							videoSrc={getStorageUrl({
								storageId: video.video,
								params: {
									cacheKey: media_updated_at || undefined,
									media: "video",
								},
							})}
						/>
					);
				})}
				{external_videos?.map((videoUrl) => {
					const embedUrl = getYouTubeEmbedUrl(videoUrl);
					if (!embedUrl) return null;
					return (
						<iframe
							allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share"
							allowFullScreen
							className="h-96 max-w-96 rounded-lg"
							key={`external-videoplayer-${videoUrl}`}
							loading="lazy"
							referrerPolicy="strict-origin-when-cross-origin"
							src={embedUrl}
							title="YouTube video player"
						/>
					);
				})}
			</div>

			<Link
				href={buildRicercaUrl({
					comune: comune || undefined,
					consegna: consegna ? [consegna] : undefined,
					tipo:
						tipo in ["Transitorio", "Stabile"]
							? (tipo as "Transitorio" | "Stabile")
							: undefined,
				})}
				target="_blank"
			>
				<Button
					className="my-10 w-full text-xl"
					data-umami-event="similar_listings_click"
					variant="secondary"
				>
					{t.annunci.find_similar} <ExternalLink className="size-6" />
				</Button>
			</Link>
		</div>
	);
};

export const getYouTubeEmbedUrl = (url: string): string | null => {
	try {
		const urlObj = new URL(url);
		let videoId: string | null = null;

		// youtube.com/watch?v=VIDEO_ID
		if (
			urlObj.hostname.includes("youtube.com") &&
			urlObj.pathname === "/watch"
		) {
			videoId = urlObj.searchParams.get("v");
		}

		// youtu.be/VIDEO_ID
		if (urlObj.hostname === "youtu.be") {
			videoId = urlObj.pathname.slice(1);
		}

		// youtube.com/embed/VIDEO_ID (already embed format)
		if (
			urlObj.hostname.includes("youtube.com") &&
			urlObj.pathname.startsWith("/embed/")
		) {
			videoId = urlObj.pathname.split("/embed/")[1]?.split("?")[0] || null;
		}

		if (!videoId) return null;

		// Use youtube-nocookie.com domain (privacy-enhanced mode)
		// Add parameters to reduce ads and suggestions
		const params = new URLSearchParams({
			rel: "0", // Don't show related videos from other channels
			modestbranding: "1", // Minimal YouTube branding
			controls: "1", // Show player controls
			showinfo: "0", // Don't show video info before playing
			fs: "1", // Allow fullscreen
			iv_load_policy: "3", // Hide video annotations
			disablekb: "0", // Enable keyboard controls
			autoplay: "0", // Don't autoplay
			// cc_load_policy: "1", // Show closed captions (optional)
		});

		return `https://www.youtube-nocookie.com/embed/${videoId}?${params.toString()}`;
	} catch {
		return null;
	}
};
