import { add } from "date-fns";
import {
	Bug,
	ChevronDown,
	ClockAlert,
	Cog,
	Euro,
	ExternalLink,
	Plus,
	Search,
	SlidersHorizontal,
	Trash2,
} from "lucide-react";
import Link from "next/link";
import { useState } from "react";
import toast from "react-hot-toast";
import {
	Credenza,
	CredenzaBody,
	CredenzaContent,
	CredenzaDescription,
	CredenzaHeader,
	CredenzaTitle,
	CredenzaTrigger,
} from "~/components/custom_ui/credenza";
import { MultiSelect } from "~/components/custom_ui/multiselect";
import { LoadingPage } from "~/components/loading";
import {
	AlertDialog,
	AlertDialogAction,
	AlertDialogCancel,
	AlertDialogContent,
	AlertDialogDescription,
	AlertDialogFooter,
	AlertDialogHeader,
	AlertDialogTitle,
	AlertDialogTrigger,
} from "~/components/ui/alert-dialog";
import { Button } from "~/components/ui/button";
import {
	Collapsible,
	CollapsibleContent,
	CollapsibleTrigger,
} from "~/components/ui/collapsible";
import {
	Dialog,
	DialogContent,
	DialogDescription,
	DialogFooter,
	DialogHeader,
	DialogTitle,
	DialogTrigger,
} from "~/components/ui/dialog";
import {
	type FormValues as EditFormValues,
	FormEditServizio,
} from "~/forms/FormEditServizioAdmin";
import { FormNewServizio, type FormValues } from "~/forms/FormNewServizio";
import { cn, formatCurrency } from "~/lib/utils";
import { useTranslation } from "~/providers/I18nProvider";
import { useServizio } from "~/providers/ServizioProvider";
import type { AnnunciId } from "~/schemas/public/Annunci";
import type { ServizioServizioId } from "~/schemas/public/Servizio";
import TipologiaPosizioneEnum from "~/schemas/public/TipologiaPosizioneEnum";
import type { UsersId } from "~/schemas/public/Users";
import { api } from "~/utils/api";
import { Confirm } from "../confirm";

export const AdminActions = () => {
	const { servizio, isAdmin, userId } = useServizio();
	if (!isAdmin) return null;
	return (
		<div className="flex flex-wrap items-center gap-3">
			<AddAnnuncio servizioId={servizio.servizio_id} userId={userId} />
			<EditServizioAdmin />
			<Link
				href={`/area-riservata/admin/user-view/ordini/${userId}?servizioId=${servizio.servizio_id}`}
			>
				<Button variant="warning">
					<Search />
					<span>Ordini</span>
				</Button>
			</Link>
		</div>
	);
};

export const ServizioBasicActions = ({ className }: { className?: string }) => {
	const { servizio, isAdmin } = useServizio();

	const canUserEdit = servizio.isOkAcconto && servizio.decorrenza !== null;
	/*&&
		new Date() <= add(new Date(servizio.decorrenza), { days: 60 }) &&
		!servizio.annunci.some((a) => a.user_confirmed_at !== null) &&
		!servizio.isInterrotto &&
		!servizio.annunci.some((a) => a.user_confirmed_at !== null);*/

	if (isAdmin || canUserEdit) {
		return (
			<div className={cn("flex flex-wrap items-center gap-2", className)}>
				<EditParametri />
				<InterruzioneServizio />
			</div>
		);
	}
	return null;
};

export const ServizioPacksInfos = () => {
	const { servizio } = useServizio();
	const { t } = useTranslation();
	const { data: packs } = api.servizio.getPacksSolution.useQuery({
		servizioId: servizio.servizio_id,
	});
	if (!packs) return null;

	return (
		<Collapsible className="flex flex-col gap-2">
			<CollapsibleTrigger asChild>
				<Button
					className="h-fit w-full flex-wrap items-center justify-start py-1 sm:w-fit sm:justify-center"
					size="sm"
					variant="outline"
				>
					<Euro className="size-5" />

					<h3 className="font-semibold text-lg">{t.servizio.prezzi.title}</h3>

					<ChevronDown className="ml-auto size-4 sm:ml-0" />
				</Button>
			</CollapsibleTrigger>
			<CollapsibleContent className="flex flex-col gap-2">
				<span className="text-muted-foreground text-sm">
					{t.servizio.prezzi.sub}
				</span>
				<div className="flex w-full flex-col gap-4 md:flex-row">
					<div className="flex flex-1 flex-col gap-2 rounded-md bg-secondary/50 p-2">
						{packs.acconto.success ? (
							<>
								<span className="font-medium">
									{packs.acconto.pack.nome_it}
								</span>
								<span className="text-muted-foreground text-sm">
									{packs.acconto.pack.desc_it}
								</span>
								<span className="font-semibold text-lg">
									{formatCurrency(packs.acconto.pack.prezzo_cent / 100)}
								</span>
								<span className="text-muted-foreground text-sm">
									COD: {packs.acconto.pack.idprezziario}
								</span>
							</>
						) : (
							<span className="font-medium">{packs.acconto.message}</span>
						)}
					</div>

					<div className="flex flex-1 flex-col gap-2 rounded-md bg-secondary/50 p-2">
						{packs.saldo.success ? (
							<>
								<span className="font-medium">{packs.saldo.pack.nome_it}</span>
								<span className="text-muted-foreground text-sm">
									{packs.saldo.pack.desc_it}
								</span>
								<span className="font-semibold text-lg">
									{formatCurrency(packs.saldo.pack.prezzo_cent / 100)}
								</span>
								<span className="text-muted-foreground text-sm">
									COD: {packs.saldo.pack.idprezziario}
								</span>
							</>
						) : (
							<span className="font-medium">{packs.saldo.message}</span>
						)}
					</div>
					{servizio.tipologia === TipologiaPosizioneEnum.Stabile && (
						<div className="flex flex-1 flex-col gap-2 rounded-md bg-secondary/50 p-2">
							<>
								<span className="font-medium">
									{t.servizio.prezzi.consulenza}
								</span>
								<span className="text-muted-foreground text-sm">
									{t.servizio.prezzi.consulenza_desc}
								</span>
								<span className="font-semibold">
									<Link
										className="flex items-center gap-2 underline underline-offset-2"
										href={"/prezzi#contratti"}
										target="_blank"
									>
										<span>{t.servizio.prezzi.gotoprezzi}</span>
										<ExternalLink className="size-4 stroke-foreground" />
									</Link>
								</span>
							</>
						</div>
					)}
				</div>
			</CollapsibleContent>
		</Collapsible>
	);
};

const AddAnnuncio = ({
	servizioId,
	userId,
}: {
	servizioId: ServizioServizioId;
	userId: UsersId;
}) => {
	const { data: codici, isLoading: loading } =
		api.servizio.getAnnunciAvailableToAdd.useQuery({
			servizioId,
		});

	const [selectedAnnunci, setSelectedAnnunci] = useState<
		{ value: AnnunciId; label: string }[]
	>([]);

	const [openModal, setOpenModal] = useState(false);

	const utils = api.useUtils();
	const { mutate } = api.servizio.addServizioAnnunci.useMutation({
		onError: (error) => {
			console.error(error);
			toast.error("Errore durante l'aggiunta dell'annuncio");
		},
		onSuccess: async () => {
			await utils.servizio.getAllServizioAnnunci.invalidate({ userId });
			await utils.servizio.getServizioData.invalidate({ servizioId });
			await utils.servizio.getAnnunciAvailableToAdd.invalidate({
				servizioId,
			});
			await utils.servizio.getCompatibileAnnunci.invalidate({
				servizioId,
			});
			await utils.servizio.getUserServizi.invalidate({ userId });
			toast.success("Annuncio aggiunto");
			setOpenModal(false);
			setSelectedAnnunci([]);
		},
	});

	return (
		<Dialog onOpenChange={setOpenModal} open={openModal}>
			<DialogTrigger asChild>
				<Button
					aria-label="Add Annuncio"
					className=""
					onClick={() => {
						setSelectedAnnunci([]);
					}}
					variant="outline"
				>
					<Plus />
					Annuncio
				</Button>
			</DialogTrigger>
			<DialogContent
				className="sm:max-w-106.25"
				onInteractOutside={(e) => {
					if (selectedAnnunci.length !== 0) {
						e.preventDefault(); // Prevent closing the dialog if there are selected announcements
					}
				}}
			>
				<DialogHeader>
					<DialogTitle>Aggiungi annuncio</DialogTitle>
					<DialogDescription>
						Salva un annuncio nella ricerca dell&apos;utente
					</DialogDescription>
				</DialogHeader>
				<div className="grid gap-4 py-4">
					{loading ? (
						<LoadingPage />
					) : (
						<MultiSelect
							defaultValue={undefined}
							elementId="select-annuncio"
							elementName="annuncio"
							isMulti={true}
							onValueChange={(value) => {
								setSelectedAnnunci(
									value.map((v) => ({
										label: v.label,
										value: parseInt(v.value) as AnnunciId,
									})),
								);
							}}
							options={
								codici?.map((cod) => ({
									label: cod.codice,
									value: cod.id.toString(),
								})) || []
							}
							placeholder=""
						/>
					)}
				</div>
				<DialogFooter>
					<Button
						aria-label="Cancel Add Annuncio"
						disabled={!selectedAnnunci.length}
						onClick={() => {
							if (!selectedAnnunci.length) return;
							mutate({
								annunci: selectedAnnunci.map((annuncio) => annuncio.value),
								servizioId,
							});
						}}
						type="button"
					>
						Aggiungi
					</Button>
				</DialogFooter>
			</DialogContent>
		</Dialog>
	);
};

const InterruzioneServizio = () => {
	const { servizio, userId, isAdmin } = useServizio();
	const { t } = useTranslation();
	const beforeInterruzioneLimit =
		servizio.decorrenza != null &&
		new Date() <=
			add(servizio.decorrenza, {
				days: 14,
			});

	const utils = api.useUtils();
	const { mutate } = api.servizio.interruzioneServizio.useMutation({
		onError: (error) => {
			console.error(error);
			toast.error("Errore durante la richiesta di interruzione");
		},
		onSuccess: async () => {
			await utils.servizio.getAllServizioAnnunci.invalidate({ userId });
			await utils.servizio.getServizioData.invalidate({
				servizioId: servizio.servizio_id,
			});
			toast.success("Interruzione richiesta");
		},
	});

	return (
		<AlertDialog>
			<AlertDialogTrigger asChild>
				<Button
					aria-label="Request Interruzione"
					className=""
					disabled={
						!isAdmin &&
						(!beforeInterruzioneLimit ||
							servizio.isInterrotto ||
							servizio.annunci.some((a) => a.user_confirmed_at !== null))
					}
				>
					<ClockAlert /> <span>{t.servizio.interruzione.btn}</span>
				</Button>
			</AlertDialogTrigger>
			<AlertDialogContent>
				<AlertDialogHeader>
					<AlertDialogTitle>{t.servizio.interruzione.title}</AlertDialogTitle>
					<AlertDialogDescription>
						{t.servizio.interruzione.description}
					</AlertDialogDescription>
				</AlertDialogHeader>
				<AlertDialogFooter>
					<AlertDialogCancel>{t.annulla}</AlertDialogCancel>
					<AlertDialogAction
						aria-label="Confirm Interruzione"
						onClick={() => mutate({ servizioId: servizio.servizio_id })}
					>
						{t.conferma}
					</AlertDialogAction>
				</AlertDialogFooter>
			</AlertDialogContent>
		</AlertDialog>
	);
};

const EditParametri = () => {
	const { servizioId, userId, isAdmin, servizio } = useServizio();
	const { t } = useTranslation();
	const [openEditParametri, setOpenEditParametri] = useState(false);

	const utils = api.useUtils();

	const { mutate: update } = api.servizio.updateServizio.useMutation({
		onError: (error) => {
			toast.error(error.message);
		},
		onSuccess: async () => {
			toast.success("Servizio modificato con successo");
			await utils.servizio.getAllServizioAnnunci.invalidate({ userId });
			await utils.servizio.getServizioData.invalidate({ servizioId });

			await utils.servizio.getCompatibileAnnunci.invalidate({
				servizioId,
			});
			await utils.servizio.getPacksSolution.invalidate({ servizioId });
			setOpenEditParametri(false);
		},
	});

	function onSubmit(fields: FormValues) {
		update({
			data: {
				...fields,
			},
			servizioId,
		});
	}

	return (
		<Credenza onOpenChange={setOpenEditParametri} open={openEditParametri}>
			<CredenzaTrigger asChild>
				<Button
					aria-label="Parametri di ricerca"
					className=""
					disabled={
						!isAdmin &&
						(servizio.isInterrotto ||
							servizio.annunci.some((a) => a.hasConfermaAdmin))
					}
					variant="secondary"
				>
					<SlidersHorizontal />
					{t.servizio.parametri.btn}
				</Button>
			</CredenzaTrigger>
			<CredenzaContent className="max-h-[90vh] w-full sm:max-w-5xl">
				<CredenzaHeader>
					<CredenzaTitle>{t.servizio.parametri.title}</CredenzaTitle>
					<CredenzaDescription className="sr-only">
						{t.servizio.parametri.title}
					</CredenzaDescription>
				</CredenzaHeader>
				<CredenzaBody className="max-h-[80vh] w-full max-w-3xl overflow-y-auto pb-5 sm:max-w-5xl">
					<FormNewServizio
						initialData={servizio}
						isLimited={!isAdmin}
						onSubmit={onSubmit}
					/>
				</CredenzaBody>
			</CredenzaContent>
		</Credenza>
	);
};

const EditServizioAdmin = () => {
	const { servizioId, userId, servizio } = useServizio();
	const [open, setOpen] = useState(false);

	const utils = api.useUtils();

	const { mutate: update } = api.servizio.updateServizio.useMutation({
		onError: (error) => {
			toast.error(error.message);
		},
		onSuccess: async () => {
			toast.success("Servizio modificato con successo");
			await utils.servizio.getAllServizioAnnunci.invalidate({ userId });

			await utils.servizio.getServizioData.invalidate({ servizioId });
			await utils.servizio.getCompatibileAnnunci.invalidate({
				servizioId,
			});
			await utils.servizio.getPacksSolution.invalidate({ servizioId });
			setOpen(false);
		},
	});
	const { mutate: remove } = api.servizio.deleteServizio.useMutation({
		onError: (error) => {
			toast.error(error.message);
		},
		onSuccess: async () => {
			toast.success("Servizio rimosso con successo");
			await utils.servizio.getAllServizioAnnunci.invalidate({ userId });
			await utils.servizio.getServizioData.invalidate({ servizioId });
		},
	});

	function onSubmit(fields: EditFormValues) {
		update({
			data: {
				...fields,
			},
			servizioId,
		});
	}

	return (
		<Credenza onOpenChange={setOpen} open={open}>
			<CredenzaTrigger asChild>
				<Button aria-label="Modifica Servizio Admin">
					<Cog />
					Modifica
				</Button>
			</CredenzaTrigger>
			<CredenzaContent className="max-h-[90vh] w-full sm:max-w-5xl">
				<CredenzaHeader>
					<CredenzaTitle>Modifica Servizio Admin</CredenzaTitle>
					<CredenzaDescription className="sr-only">
						Modifica
					</CredenzaDescription>
				</CredenzaHeader>
				<CredenzaBody className="max-h-[80vh] w-full space-y-2 overflow-y-auto pb-5">
					<FormEditServizio initialData={servizio} onSubmit={onSubmit} />

					<Collapsible>
						<CollapsibleTrigger asChild>
							<Button variant="warning">
								<Bug /> Debug Info Servizio
							</Button>
						</CollapsibleTrigger>
						<CollapsibleContent>
							{(() => {
								const { annunci, ...rest } = servizio;
								return <pre>{JSON.stringify(rest, null, 2)}</pre>;
							})()}
						</CollapsibleContent>
					</Collapsible>
					<Confirm
						description="Sei sicuro di voler eliminare questo servizio? L'azione è irreversibile."
						onConfirm={() => {
							remove({ servizioId });
						}}
						title="Elimina servizio"
					>
						<Button aria-label="Elimina Servizio" variant="destructive">
							<Trash2 className="size-6" />
							Elimina Servizio
						</Button>
					</Confirm>
				</CredenzaBody>
			</CredenzaContent>
		</Credenza>
	);
};
