import { add, format, isAfter, isBefore } from "date-fns";
import {
	ArrowRight,
	BadgeCheck,
	CalendarClock,
	CircleCheck,
	CircleCheckBig,
	CircleHelp,
	CircleMinus,
	ClockFading,
	ExternalLink,
	type LucideIcon,
	MousePointerClick,
	PackageCheck,
	SearchX,
	Timer,
	Trash2,
} from "lucide-react";
import Link from "next/link";
import toast from "react-hot-toast";
import { DisclaimerInterruzioneServizio } from "~/components/servizio/interruzione";
import { cn } from "~/lib/utils";
import { useTranslation } from "~/providers/I18nProvider";
import {
	ServizioAnnuncioProvider,
	ServizioProvider,
	useServizio,
} from "~/providers/ServizioProvider";
import OrderTypeEnum from "~/schemas/public/OrderTypeEnum";
import type { Rinnovi } from "~/schemas/public/Rinnovi";
import type { UsersId } from "~/schemas/public/Users";
import type { ServizioData } from "~/server/controllers/servizio.controller";
import { api } from "~/utils/api";
import { DEFAULT_SERVIZIO_DURATION_DAYS } from "~/utils/config";
import { Confirm } from "../confirm";
import { AlarmClockSVG } from "../svgs";
import {
	AlertDialog,
	AlertDialogAction,
	AlertDialogCancel,
	AlertDialogContent,
	AlertDialogDescription,
	AlertDialogFooter,
	AlertDialogHeader,
	AlertDialogTitle,
	AlertDialogTrigger,
} from "../ui/alert-dialog";
import { Button } from "../ui/button";
import {
	Card,
	CardContent,
	CardDescription,
	CardHeader,
	CardTitle,
} from "../ui/card";
import { SaldoButton } from "./annuncio_actions";
import { AnnuncioCard, AnnuncioDisplay } from "./annuncio_card";
import { AnnunciCompatibili } from "./compatibili_dialog";
import { AdminServizioActions, ServizioInfos } from "./servizio_actions";

export const ServizioList = ({
	data,
	isAdmin,
	userId,
}: {
	data: (
		| { d: Date; type: "servizio"; data: ServizioData }
		| { d: Date; type: "rinnovo"; data: Rinnovi }
	)[];
	isAdmin: boolean;
	userId: UsersId;
}) => {
	const { t } = useTranslation();
	if (data.length === 0) {
		return (
			<div className="m-4 rounded-md bg-yellow-100 p-4 text-yellow-900">
				{t.servizio.nessun_servizio}
			</div>
		);
	}

	return (
		<div className="flex flex-col gap-4">
			{data.map(({ d: _d, type, data: s }) => {
				if (type === "rinnovo") {
					return (
						<RinnovoLinkCard
							data={s}
							isAdmin={isAdmin}
							key={s.id}
							userId={userId}
						/>
					);
				}
				return (
					<ServizioLinkCard
						isAdmin={isAdmin}
						key={s.servizio_id}
						servizio={s}
						userId={userId}
					/>
				);
			})}
		</div>
	);
};

const RinnovoLinkCard = ({
	data,
	isAdmin,
	userId,
}: {
	data: Rinnovi;
	isAdmin: boolean;
	userId: UsersId;
}) => {
	return (
		<Link
			className="group"
			href={
				isAdmin
					? `/area-riservata/admin/user-view/rinnovo/${userId}/${data.id}`
					: `/area-riservata/rinnovo/${data.id}`
			}
			key={data.id}
		>
			<Card
				className={cn("transition-shadow hover:bg-muted/15 hover:shadow-md")}
			>
				<CardHeader>
					<CardTitle className="text-xl group-hover:underline">
						Rinnovo {data.codice}
					</CardTitle>
					<CardDescription className="">
						Data rinnovo: {data.decorrenza.toLocaleDateString("it-IT")}
					</CardDescription>
				</CardHeader>
				<CardContent className="flex flex-col flex-wrap gap-4 sm:flex-row sm:justify-between">
					<div className="flex items-center gap-2 rounded-md text-muted-foreground group-hover:text-foreground">
						<span>Vai al rinnovo</span>
						<ArrowRight />
					</div>
				</CardContent>
			</Card>
		</Link>
	);
};

const ServizioLinkCard = ({
	servizio,
	isAdmin,
	userId,
}: {
	servizio: ServizioData;
	isAdmin: boolean;
	userId: UsersId;
}) => {
	const { t } = useTranslation();

	let status: keyof typeof t.servizio.status = "attivo";
	let StatusIcon: LucideIcon = CircleCheck;

	if (servizio.isInterrotto) {
		status = "interrotto";
		StatusIcon = SearchX;
	} else if (!servizio.isOkAcconto) {
		status = "in_attesa";
		StatusIcon = ClockFading;
	} else if (servizio.decorrenza) {
		const now = new Date();
		const decorrenza = new Date(servizio.decorrenza);
		if (
			now > add(decorrenza, { days: DEFAULT_SERVIZIO_DURATION_DAYS }) &&
			!servizio.isOkSaldo
		) {
			status = "scaduto";
			StatusIcon = CircleMinus;
		}
		if (servizio.isOkSaldo) {
			status = "completato";
			StatusIcon = CircleCheckBig;
		}
	}

	return (
		<Link
			className="group"
			href={
				isAdmin
					? `/area-riservata/admin/user-view/servizio/${userId}/${servizio.servizio_id}`
					: `/area-riservata/servizio/${servizio.servizio_id}`
			}
			key={servizio.servizio_id}
		>
			{status === "in_attesa" ? (
				<Card className="relative border-yellow-500 bg-yellow-500 text-white hover:bg-yellow-500/90 dark:bg-yellow-900 dark:hover:bg-yellow-900/90">
					<span className="absolute top-5 right-5 -mt-1 -mr-1 flex size-7 items-center justify-center">
						<span className="absolute inline-flex size-6 h-full w-full animate-ping rounded-full bg-white opacity-75" />
						<span className="relative inline-flex size-5 rounded-full bg-white"></span>
					</span>

					<CardHeader>
						<CardTitle className="text-xl group-hover:underline">
							{t.servizio.servizio_titolo} {servizio.tipologia}
						</CardTitle>
						<CardDescription className="text-white">
							{t.servizio.servizio_creato_il}{" "}
							{servizio.created_at.toLocaleDateString("it-IT")}
						</CardDescription>
					</CardHeader>
					<CardContent className="flex flex-col flex-wrap gap-4 sm:flex-row sm:justify-between">
						<div className="flex items-center gap-2">
							<StatusIcon className="size-5" />

							<span>{t.servizio.status[status]}</span>
						</div>
						<div className="flex items-center gap-2 rounded-md font-semibold text-white underline underline-offset-2">
							<span>{t.servizio.vai_al_servizio}</span>
							<MousePointerClick />
						</div>
					</CardContent>
				</Card>
			) : (
				<Card
					className={cn(
						status === "attivo" && "border-green-500",
						status === "interrotto" && "border-red-500",
						status === "scaduto" && "border-gray-500",
						status === "completato" && "border-blue-500",
						"transition-shadow hover:bg-muted/15 hover:shadow-md",
					)}
				>
					<CardHeader>
						<CardTitle className="text-xl group-hover:underline">
							{t.servizio.servizio_titolo} {servizio.tipologia}
						</CardTitle>
						<CardDescription className="">
							{t.servizio.servizio_creato_il}{" "}
							{servizio.created_at.toLocaleDateString("it-IT")}
						</CardDescription>
					</CardHeader>
					<CardContent className="flex flex-col flex-wrap gap-4 sm:flex-row sm:justify-between">
						<div
							className={cn(
								"flex items-center gap-2",
								status === "attivo" && "text-green-500",
								status === "interrotto" && "text-red-500",
								status === "scaduto" && "text-gray-500",
								status === "completato" && "text-blue-500",
							)}
						>
							<StatusIcon className="size-5" />

							<span>{t.servizio.status[status]}</span>
						</div>
						<div className="flex items-center gap-2 rounded-md font-semibold text-muted-foreground group-hover:text-foreground">
							<span>{t.servizio.vai_al_servizio}</span>
							<MousePointerClick />
						</div>
					</CardContent>
				</Card>
			)}
		</Link>
	);
};

export const Servizio = ({
	servizio,
	userId,
	isAdmin,
}: {
	servizio: ServizioData;
	userId: UsersId;
	isAdmin: boolean;
}) => {
	return (
		<ServizioProvider
			isAdmin={isAdmin}
			servizio={servizio}
			servizioId={servizio.servizio_id}
			userId={userId}
		>
			<Content />
		</ServizioProvider>
	);
};

const Content = () => {
	const { servizio } = useServizio();
	const { t } = useTranslation();
	const dec_txt = servizio.decorrenza
		? new Date(servizio.decorrenza).toLocaleDateString("it-IT")
		: "";
	const end_txt = servizio.decorrenza
		? new Date(
				add(servizio.decorrenza, { days: DEFAULT_SERVIZIO_DURATION_DAYS }),
			).toLocaleDateString("it-IT")
		: "";

	return (
		<div className="w-full space-y-4">
			<div className="flex flex-col flex-wrap items-start justify-between gap-4 sm:flex-row">
				<div className="flex flex-col gap-1">
					<h3 className="font-semibold text-2xl">
						{t.servizio.servizio_titolo} {servizio.tipologia}
					</h3>

					<div className="flex flex-wrap items-center gap-2 text-muted-foreground text-sm">
						<div className="flex items-center gap-2">
							<CalendarClock className="size-5" />
							<span>{t.servizio.durata_servizio}</span>
						</div>
						<span>
							{servizio.decorrenza !== null
								? `${dec_txt} - ${end_txt}`
								: "In attesa di attivazione"}
						</span>
					</div>
					{servizio.decorrenza && (
						<div className="flex items-center gap-2 text-muted-foreground text-sm">
							<Timer className="size-5" />
							<span>
								{t.servizio.interruzione.scadenza}{" "}
								{format(
									add(servizio.decorrenza, { days: servizio.interruzioneDays }),
									"dd/MM/yyyy",
								)}
							</span>
							<AlertDialog>
								<AlertDialogTrigger asChild>
									<Button className="px-1!" size="sm" variant="outline">
										<CircleHelp />
									</Button>
								</AlertDialogTrigger>
								<AlertDialogContent>
									<AlertDialogHeader>
										<AlertDialogTitle>
											{t.servizio.interruzione.info_title}
										</AlertDialogTitle>
										<AlertDialogDescription className="whitespace-pre-line">
											{t.servizio.interruzione.info_desc}
										</AlertDialogDescription>
									</AlertDialogHeader>
									<AlertDialogFooter>
										<AlertDialogCancel>Capito</AlertDialogCancel>
									</AlertDialogFooter>
								</AlertDialogContent>
							</AlertDialog>
						</div>
					)}
				</div>
				<AdminServizioActions />
			</div>
			<ServizioInfos />

			<Main />
		</div>
	);
};

const Main = () => {
	const { servizio, isAdmin, userId } = useServizio();
	const { t } = useTranslation();
	const utils = api.useUtils();
	const { mutate: attivazioneSenzaPagamento } =
		api.servizio.attivazioneSenzaPagamento.useMutation({
			onError: () => {
				toast.error("Errore durante l'attivazione del servizio");
			},
			onSuccess: async () => {
				toast.success("Servizio modificato con successo");
				await utils.servizio.invalidate();
			},
		});

	// se interrotto, mostra avvisos
	if (servizio.isInterrotto) {
		if (isAdmin) {
			return (
				<>
					<div className="flex w-full items-center justify-center rounded-md bg-red-100 p-2 text-red-900">
						<div className="flex items-center gap-2">
							<SearchX className="size-5 text-red-500" />
							<span>{t.servizio.servizio_interrotto}</span>
						</div>
					</div>
					<div className="@container grid grid-flow-row @sm:grid-cols-2 grid-cols-1 gap-4">
						{servizio.annunci.map((data) => {
							return (
								<ServizioAnnuncioProvider
									data={data}
									key={data.id}
									servizioId={servizio.servizio_id}
								>
									<AnnuncioCard />
								</ServizioAnnuncioProvider>
							);
						})}
						{servizio.annunci.length > 1 &&
							servizio.annunci.length % 2 === 1 && (
								<div className="@sm:block hidden size-full rounded-md border border-(--pattern-fg) bg-[repeating-linear-gradient(45deg,var(--pattern-fg)_0,var(--pattern-fg)_1px,transparent_0,transparent_50%)] bg-size-[10px_10px] bg-fixed opacity-10 [--pattern-fg:#696969] dark:[--pattern-fg:#e1e1e1]" />
							)}
					</div>
				</>
			);
		}
		return (
			<div className="flex w-full flex-col items-center justify-center gap-4 py-10 text-center">
				<div className="flex size-14 items-center justify-center rounded-full bg-red-100 dark:bg-red-500/10">
					<SearchX className="size-7 text-red-500 dark:text-red-400" />
				</div>
				<div className="flex flex-col gap-1">
					<p className="font-semibold text-xl">
						{t.servizio.servizio_interrotto}
					</p>
					<p className="max-w-sm text-muted-foreground text-sm">
						{t.servizio.servizio_interrotto_desc}
					</p>
				</div>
				<Link
					href={
						isAdmin
							? `/area-riservata/admin/user-view/ricerca/${userId}`
							: "/area-riservata/dashboard"
					}
				>
					<Button variant="secondary">Torna alla lista dei servizi</Button>
				</Link>
			</div>
		);
	}
	// mostra onboarding
	if (!servizio.onboardOk) {
		return (
			<div className="flex w-full flex-col items-center justify-center gap-8">
				<div className="flex w-full max-w-md flex-col items-center justify-center gap-4 text-center">
					<AlarmClockSVG className="size-46" />
					<h1 className="text-xl">{t.servizio.non_attivo}</h1>
					<Link
						aria-label="Attiva Servizio"
						className="w-full"
						href={
							isAdmin
								? `/area-riservata/admin/user-view/onboard/${servizio.servizio_id}`
								: `/servizio/onboard/${servizio.servizio_id}`
						}
					>
						<Button className="w-full text-lg" variant="success">
							<span>{t.servizio.attiva_cta}</span>
							<ArrowRight />
						</Button>
					</Link>
				</div>

				<AnnunciAnteprima />
				{isAdmin && <AnnunciCompatibili />}
			</div>
		);
	}
	// se non ok acconto, mostra invito a completare pagamento acconto o ad attivare se acconto già inserito
	if (!servizio.isOkAcconto || servizio.decorrenza === null) {
		const acconti = servizio.ordini.filter(
			(o) => o.type === OrderTypeEnum.Acconto,
		);

		const activeAcconto = acconti.find((a) => a.isActive);

		return (
			<div className="flex w-full flex-col items-center justify-center gap-8">
				<div className="flex w-full max-w-md flex-col items-center justify-center gap-4 text-center">
					<PackageCheck className="size-46 stroke-1" />
					<h1 className="text-xl">Parametri di ricerca salvati</h1>
					{activeAcconto ? (
						<AlertDialog>
							<AlertDialogTrigger asChild>
								<Button
									// se acconto inserito, attivato ma servizio non ancora attivo
									className="w-full text-lg"
									variant="info"
								>
									<span>Attiva il servizio</span>
									<ArrowRight />
								</Button>
							</AlertDialogTrigger>
							<AlertDialogContent className="sm:max-w-xl">
								<AlertDialogHeader>
									<div className="mb-4 flex size-9 items-center justify-center rounded-full bg-sky-600/10 sm:mx-0 dark:bg-sky-400/10">
										<BadgeCheck className="size-4.5 text-sky-600 dark:text-sky-400" />
									</div>
									<AlertDialogTitle className="text-xl">
										Attivazione del Servizio
									</AlertDialogTitle>
									<AlertDialogDescription>
										Procedendo all'attivazione del servizio, confermi che i
										parametri di ricerca salvati sono corretti e accetti di
										essere contattato per eventuali verifiche.
									</AlertDialogDescription>

									{activeAcconto?.testo_condizioni && (
										<div className="mt-4 w-full space-y-4">
											<Link
												aria-label="Leggi le condizioni"
												className="block w-fit"
												href={`/servizio/condizioni/${activeAcconto.testo_condizioni}`}
												target="_blank"
											>
												<Button className="w-full text-sm">
													<span>{t.acquisto.leggi_condizioni}</span>
													<ExternalLink />
												</Button>
											</Link>
											<p className="text-muted-foreground text-sm">
												Riceverai copia delle condizioni anche via email
											</p>
										</div>
									)}
								</AlertDialogHeader>
								<AlertDialogFooter>
									<AlertDialogCancel>{t.annulla}</AlertDialogCancel>
									<AlertDialogAction
										className="bg-sky-600 text-white hover:bg-sky-600 focus-visible:ring-sky-600 dark:bg-sky-400 dark:focus-visible:ring-sky-400 dark:hover:bg-sky-400"
										onClick={() => {
											attivazioneSenzaPagamento({
												ordineId: activeAcconto.ordine_id,
											});
										}}
									>
										<span>Attiva il servizio</span>
										<ArrowRight className="size-4" />
									</AlertDialogAction>
								</AlertDialogFooter>
							</AlertDialogContent>
						</AlertDialog>
					) : (
						<Link
							aria-label="Attiva Servizio"
							className="w-full"
							href={`/servizio/pagamento?servizioId=${servizio.servizio_id}&type=${OrderTypeEnum.Acconto}`}
						>
							<Button className="w-full text-lg" variant="info">
								<span>Procedi al pagamento</span>
								<ArrowRight />
							</Button>
						</Link>
					)}
				</div>

				<AnnunciAnteprima />
				{isAdmin && <AnnunciCompatibili />}
			</div>
		);
	}
	//servizio scaduto se decorrenza + 60 giorni è passato e non è ok saldo
	if (
		isBefore(
			add(servizio.decorrenza, { days: DEFAULT_SERVIZIO_DURATION_DAYS }),
			new Date(),
		) &&
		!servizio.isOkSaldo
	) {
		//todo capire come fare con saldo quando scade
		return (
			<>
				<p className="font-medium text-lg">{t.servizio.scaduto}</p>
				<p>{t.servizio.scaduto_desc}</p>
			</>
		);
	}

	const InConferma = servizio.annunci.filter((a) => a.status_conferma !== null);

	// in conferma, mostra solo annunci confermati
	if (servizio.isOkSaldo && InConferma.length > 0) {
		return (
			<>
				{InConferma.map((data) => {
					return (
						<ServizioAnnuncioProvider
							data={data}
							key={data.id}
							servizioId={servizio.servizio_id}
						>
							<AnnuncioCard className="max-w-full" />
						</ServizioAnnuncioProvider>
					);
				})}
				{isAdmin && (
					<div className="w-full space-y-2">
						<h4 className="text-lg">Altri annunci:</h4>
						<div className="@container grid grid-flow-row @sm:grid-cols-2 grid-cols-1 gap-4">
							{servizio.annunci
								.filter((a) => a.status_conferma === null)
								.map((data) => {
									return (
										<ServizioAnnuncioProvider
											data={data}
											key={data.id}
											servizioId={servizio.servizio_id}
										>
											<AnnuncioCard />
										</ServizioAnnuncioProvider>
									);
								})}
							{servizio.annunci.length > 1 &&
								servizio.annunci.length % 2 === 1 && (
									<div className="@sm:block hidden size-full rounded-md border border-(--pattern-fg) bg-[repeating-linear-gradient(45deg,var(--pattern-fg)_0,var(--pattern-fg)_1px,transparent_0,transparent_50%)] bg-size-[10px_10px] bg-fixed opacity-10 [--pattern-fg:#696969] dark:[--pattern-fg:#e1e1e1]" />
								)}
						</div>
					</div>
				)}
			</>
		);
	}

	// se superato periodo interruzione, ma non interrotto, non scaduto e non in conferma, mostra avviso
	if (
		!isAdmin &&
		!servizio.acceptedInterr &&
		isBefore(
			new Date(),
			add(servizio.decorrenza, { days: servizio.interruzioneDays }),
		) &&
		isAfter(
			new Date(),
			add(servizio.decorrenza, { days: servizio.interruzioneDays - 5 }),
		)
	) {
		return <DisclaimerInterruzioneServizio />;
	}

	// normal case
	return (
		<>
			{InConferma.length > 0 && (
				<div className="flex flex-col gap-2">
					<div className="flex items-center gap-2">
						<PackageCheck className="size-6 text-primary" />
						<span className="font-medium">{t.servizio.saldi_in_attesa}</span>
					</div>
					{InConferma.map((a) => (
						<div
							className="flex items-center gap-2 rounded-md bg-sky-400 p-2"
							key={a.annunci_id}
						>
							<h3 className="font-semibold text-white">{a.codice} </h3>
							<SaldoButton
								annuncioId={a.annunci_id}
								className="border-none"
								variant={"outline"}
							/>
						</div>
					))}
				</div>
			)}
			<div className="@container grid grid-flow-row @sm:grid-cols-2 grid-cols-1 gap-4">
				{servizio.annunci.map((data) => {
					return (
						<ServizioAnnuncioProvider
							data={data}
							key={data.id}
							servizioId={servizio.servizio_id}
						>
							<AnnuncioCard />
						</ServizioAnnuncioProvider>
					);
				})}
				{servizio.annunci.length > 1 && servizio.annunci.length % 2 === 1 && (
					<div className="@sm:block hidden size-full rounded-md border border-(--pattern-fg) bg-[repeating-linear-gradient(45deg,var(--pattern-fg)_0,var(--pattern-fg)_1px,transparent_0,transparent_50%)] bg-size-[10px_10px] bg-fixed opacity-10 [--pattern-fg:#696969] dark:[--pattern-fg:#e1e1e1]" />
				)}
			</div>
			<div className="flex flex-col items-center justify-center gap-4 py-4">
				{servizio.annunci.length === 0 && (
					<h2 className="font-medium text-lg">Cerca un annuncio ora!</h2>
				)}
				<AnnunciCompatibili />
			</div>
		</>
	);
};

const AnnunciAnteprima = () => {
	const { servizio, isAdmin } = useServizio();
	const { t } = useTranslation();
	const utils = api.useUtils();

	const { mutate: removeAnnuncioServizio } =
		api.servizio.removeAnnuncioServizio.useMutation({
			onError: () => {
				toast.error("Errore durante la rimozione dell'annuncio dal servizio");
			},
			onSuccess: async () => {
				await utils.servizio.invalidate();
				toast.success("Annuncio rimosso");
			},
		});

	if (servizio.annunci.length > 0) {
		return (
			<div className="w-full space-y-2">
				<p>
					{t.servizio.per_te_1} {servizio.annunci.length} {t.servizio.per_te_2}
				</p>
				<div className="grid gap-4 sm:grid-cols-2">
					{servizio.annunci.map((data) => (
						<div className="group relative" key={data.id}>
							<AnnuncioDisplay
								className="bg-[#e6e9ec]/50 dark:bg-card dark:outline dark:outline-foreground/10"
								data={{
									...data,
									modificato_il: data.modificato_il
										? new Date(data.modificato_il)
										: null,
									media_updated_at: data.media_updated_at
										? new Date(data.media_updated_at)
										: null,
								}}
							/>
							{isAdmin && (
								<Confirm
									description="Sei sicuro di voler rimuovere questo annuncio?"
									onConfirm={() => {
										removeAnnuncioServizio({
											annuncioId: data.annunci_id,
											servizioId: servizio.servizio_id,
										});
									}}
									title="Rimuovi Annuncio"
								>
									<Button
										aria-label="Rimuovi"
										className="absolute top-0 right-0 hidden group-hover:flex"
										size="sm"
										variant="destructive"
									>
										<Trash2 />
									</Button>
								</Confirm>
							)}
						</div>
					))}
					{servizio.annunci.length % 2 === 1 && (
						<div className="hidden size-full rounded-md border border-(--pattern-fg) bg-[repeating-linear-gradient(45deg,var(--pattern-fg)_0,var(--pattern-fg)_1px,transparent_0,transparent_50%)] bg-size-[10px_10px] bg-fixed opacity-10 [--pattern-fg:#696969] sm:block dark:[--pattern-fg:#e1e1e1]" />
					)}
				</div>
			</div>
		);
	}
	return null;
};
