import {
	Armchair,
	BadgeEuro,
	Bath,
	BedDouble,
	Building2,
	Car,
	Clock,
	Copy,
	Edit,
	ExternalLink,
	Printer,
	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 Input from "~/components/custom_ui/input";
import FailedAnnuncioLoading from "~/components/failed-loading";
import { IconMatrix, type IconType } from "~/components/IconComponents";
import InformationBubble from "~/components/InformationBubble";
import { LoadingPage } from "~/components/loading";
import { MappaDialogFullscreen } from "~/components/MapDialog";
import { PricingComponent } 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 {
	Dialog,
	DialogContent,
	DialogDescription,
	DialogHeader,
	DialogTitle,
	DialogTrigger,
} from "~/components/ui/dialog";
import { Label } from "~/components/ui/label";
import { VideoPlayer } from "~/components/videoPlayer";
import { env } from "~/env";
import {
	type CaratteristicheFiltered,
	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 } from "~/lib/utils";
import { AnnuncioContext } from "~/providers/AnnuncioProvider";
import { useTranslation } from "~/providers/I18nProvider";
import { useSession } from "~/providers/SessionProvider";
import type { Annunci } from "~/schemas/public/Annunci";
import TipologiaPosizioneEnum from "~/schemas/public/TipologiaPosizioneEnum";
import type { VideosRefs } from "~/schemas/public/VideosRefs";
import { generateSSGHelper } from "~/server/utils/ssgHelper";
import { api } from "~/utils/api";

type AnnuncioProps = {
	cod: string;
	flag: string;
	meta: {
		ogImage: string;
		title: string;
		description: string;
		ogUrl: string;
	} | null;
};
const AnnuncioDettaglio: NextPage<AnnuncioProps> = ({
	cod,
	flag,
	meta,
}: AnnuncioProps) => {
	return (
		<main>
			<Head>
				<title>{`${cod} | ${meta?.title}`}</title>
				<meta content={meta?.description} property="description" />
				<meta content={meta?.ogUrl} property="og:url" />
				<meta content="website" property="og:type" />
				<meta content={`${cod} | ${meta?.title}`} property="og:title" />
				<meta content={meta?.description} property="og:description" />
				<meta content={meta?.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" />
			</Head>
			<AnnuncioView cod={cod} flag={flag} />
		</main>
	);
};

const AnnuncioView = ({ cod, flag }: Omit<AnnuncioProps, "meta">) => {
	const session = useSession();
	const { locale } = useTranslation();
	useStaleImageReload();

	const { data, isLoading } = api.annunci.getAnnuncio.useQuery(
		{
			cod: cod,
		},
		{ refetchOnMount: false },
	);

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

	if (isLoading || session.status === "pending") return <LoadingPage />;
	if (
		!data ||
		session.status === "error" ||
		(data && data.stato === "Sospeso")
	) {
		return <FailedAnnuncioLoading />;
	}

	const titolo = (locale === "it" ? data.titolo_it : data.titolo_en) || "";
	const description = (locale === "it" ? data.desc_it : data.desc_en) || "";

	const filteredCaratt = data.caratteristiche
		? filteredCaratteristiche(data.caratteristiche)
		: null;

	return (
		<AnnuncioContext.Provider value={data}>
			<TouchProvider>
				<div className="mx-auto w-full max-w-[100rem] px-2 sm:px-8">
					<CarouselAnnuncio
						immagini={data.images}
						updated_at={data.media_updated_at}
						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 data={data} />
								{session.user?.isAdmin ? (
									<>
										<Link
											className="w-full"
											href={`/area-riservata/admin/edit-annuncio/${data.id}`}
										>
											<Button className="w-full" type="button">
												<Edit /> Modifica annuncio
											</Button>
										</Link>
										<Link
											className="w-full"
											href={`/area-riservata/admin/scheda-annuncio-stampa/${data.id}`}
											target="_blank"
										>
											<Button
												className="w-full"
												type="button"
												variant="outline"
											>
												<Printer /> Scheda immobile
											</Button>
										</Link>
									</>
								) : (
									<AnnuncioInteractions
										disabled={flag === "true"}
										session={session}
									/>
								)}
								{data.tipo &&
									(data.tipo === "Transitorio" || data.tipo === "Stabile") && (
										<>
											<Pricing
												isDesktop={isDesktop}
												tipologia={
													data.tipo === "Transitorio"
														? TipologiaPosizioneEnum.Transitorio
														: TipologiaPosizioneEnum.Stabile
												}
											/>
										</>
									)}
							</div>
						</div>
						<div className="mx-2 md:w-2/3">
							<TestiAnnuncio
								description={description}
								filteredCaratt={filteredCaratt}
								titolo={titolo}
							/>
						</div>
					</div>
					<AnnuncioFooter
						comune={data.comune}
						consegna={data.consegna}
						external_videos={data.external_videos || []}
						tipo={data.tipo}
						updated_at={data.media_updated_at}
						videos={data.videos}
					/>
				</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 {
			notFound: true,
		};
	}
	await ssg.annunci.getAnnuncio.prefetch({ cod: cod });

	const meta = await ssg.annunci.getAnnuncioMeta.fetch({ cod: cod });

	const flag = await ssg.flags.GetFlagValue.fetch({
		id: "ANNUNCIO_INTERACTIONS_DISABLED",
	});
	return {
		props: {
			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,
	tipologia,
}: {
	isDesktop: boolean;
	tipologia: TipologiaPosizioneEnum;
}) => {
	const { t } = useTranslation();

	const { data: prezziario, isLoading } =
		api.prezziario.getPrezziPerTipologia.useQuery({
			tipologia,
		});

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

	const cta =
		tipologia === TipologiaPosizioneEnum.Transitorio
			? t.pricing_cmp.cta_breve
			: t.pricing_cmp.cta_stabile;
	const opzioni =
		tipologia === TipologiaPosizioneEnum.Transitorio
			? [
					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,
				]
			: [t.pricing_cmp.stabile_option1, t.pricing_cmp.stabile_option2];

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

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

	if (isDesktop) {
		return (
			<PricingComponent
				className={cn(
					style,
					"max-w-2xl sm:[&_#contratto-link]:h-8 xl:[&_#contratto-link]:h-9 [&_[data-role=amount]]:text-2xl xl:[&_[data-role=amount]]:text-3xl [&_[data-role=wrapper]]:flex-wrap lg:[&_[data-role=wrapper]]:flex-nowrap",
				)}
				cta={cta}
				opzioni={opzioni}
				pricingData={pricing}
				statico={true}
				tipo={tipologia}
				title={
					tipologia === TipologiaPosizioneEnum.Transitorio
						? t.prezzi.titolo_transitori
						: t.prezzi.titolo_stabile
				}
			/>
		);
	}
	return (
		<Accordion className="w-full" collapsible type="single">
			<AccordionItem value="item-1">
				<AccordionTrigger className="items-center">
					<div className="items-cernter flex justify-start gap-2 px-1 font-semibold text-xl">
						<BadgeEuro />
						<span>{t.pricing_cmp.cta_costo}</span>
					</div>
				</AccordionTrigger>
				<AccordionContent className="flex justify-center">
					<PricingComponent
						className={cn(style)}
						cta={cta}
						opzioni={opzioni}
						pricingData={pricing}
						statico={true}
						tipo={tipologia}
						title={
							tipologia === TipologiaPosizioneEnum.Transitorio
								? t.prezzi.titolo_transitori
								: t.prezzi.titolo_stabile
						}
					/>
				</AccordionContent>
			</AccordionItem>
		</Accordion>
	);
};

const TestiAnnuncio = ({
	titolo,
	description,
	filteredCaratt,
}: {
	titolo: string;
	description: string;
	filteredCaratt:
		| {
				text: string;
				icon: IconType;
				value: string | null;
		  }[]
		| null;
}) => {
	return (
		<>
			<h1 className="font-bold text-3xl uppercase">{titolo}</h1>
			<h1
				className="py-6"
				dangerouslySetInnerHTML={{
					__html: replaceWithBr(description),
				}}
			/>
			{filteredCaratt && (
				<CaratteristicheAccordion filteredCaratt={filteredCaratt} />
			)}
		</>
	);
};

const CaratteristicheAccordion = ({
	filteredCaratt,
}: {
	filteredCaratt: CaratteristicheFiltered;
}) => {
	return (
		<Accordion
			className="my-5"
			collapsible
			defaultValue="altre-caratt"
			type="single"
		>
			<AccordionItem value="altre-caratt">
				<AccordionTrigger>Altre caratteristiche</AccordionTrigger>
				<AccordionContent>
					{Object.entries(filteredCaratt).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 = ({ data }: { data: Annunci }) => {
	const { t } = useTranslation();

	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">
					Codice {data.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="rounded-md bg-primary-foreground p-2 text-center text-primary">
							{data.prezzo && (data.prezzo / 1e2).toFixed(2).replace(".", ",")}{" "}
							€/mese
						</div>
						{data.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">
										Prezzo al giorno
									</span>
									<div className="text-sm">
										{(data.prezzo / 1e2 / 30).toFixed(2).replace(".", ",")} €/gg
									</div>
								</div>
							</InformationBubble>
						)}
					</div>
					<div className="relative">
						<div
							className={cn(
								"rounded-md bg-primary-foreground p-2 text-center text-primary outline-2",
								data.tipo === "Transitorio" && "outline-transitorio",
								data.tipo === "Stabile" && "outline-stabile",
							)}
						>
							{data.tipo}
						</div>
						{data.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">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 />
							{(() => {
								if (!data.numero_camere) return "N/A";
								if (data.numero_camere > 1)
									return `${data.numero_camere} ${t.card.camere2}`;
								if (data.numero_camere === 1)
									return `${data.numero_camere} ${t.card.camere1}`;
							})()}
						</div>
						<div className="flex justify-center gap-2 rounded-md bg-primary-foreground p-2 text-primary">
							<Bath />
							<span>{data.numero_bagni} bagni</span>
						</div>
						<div className="flex justify-center gap-2 rounded-md bg-primary-foreground p-2 text-primary">
							<Armchair />
							{data.caratteristiche?.Scheda_Arredi || ""}
						</div>
						<div className="flex justify-center gap-2 rounded-md bg-primary-foreground p-2 text-primary">
							<Car />
							<span>{data.numero_postiauto} posti auto</span>
						</div>
					</div>
				</div>
				<div className="flex flex-col gap-2">
					<h3 className="px-2">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>
								{data.mq ? Number(data.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">
							<Building2 />
							<span>
								{(() => {
									if (data.piano === "0") return "piano terra";
									if (data.piano === "0.5") return "piano rialz.";
									if (data.piano) return `${data.piano}° piano`;
									return "";
								})()}
							</span>
						</div>
					</div>
				</div>

				<div className="text-center font-bold text-base">
					{data.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>Annuncio 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" />
							Disponibilità:{" "}
							<span className="text-red-500">
								{handleConsegna({
									aggiornamento: t.card.in_aggiornamento,
									consegna: data.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={data.lat_secondario}
						long={data.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>
					<Share2 className="size-5" />
				</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 = ({
	tipo,
	comune,
	consegna,
	videos,
	external_videos,
	updated_at,
}: {
	tipo: string | null;
	comune: string | null;
	consegna: number | null;
	videos: Pick<VideosRefs, "video" | "thumb">[];
	external_videos: string[];
	updated_at: Date | null;
}) => {
	return (
		<div className="flex flex-col gap-2">
			<p className="px-2 font-semibold text-lg">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: updated_at?.toISOString(), media: "image" },
							})}
							key={`videoplayer-${video.video}`} // Cache busting
							videoSrc={getStorageUrl({
								storageId: video.video,
								params: { cacheKey: updated_at?.toISOString(), 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={{
					pathname: "/annunci",
					query: {
						comune: comune,
						consegna: consegna,
						tipo: tipo,
					},
				}}
				target="_blank"
			>
				<Button className="my-10 w-full text-xl" variant="info">
					Cerca annunci simili <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;
	}
};
