import {
	Bug,
	Check,
	Cog,
	Euro,
	ExternalLink,
	Logs,
	Plus,
	Search,
	Trash2,
} from "lucide-react";
import Link from "next/link";
import { useRouter } from "next/router";
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 { InterruzioneServizio } from "~/components/servizio/interruzione";
import { EditServizioModal } from "~/components/servizio/parametri_ricerca";
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 { FormNewOrder } from "~/forms/FormNewOrdine";
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 { Ordini } from "~/schemas/public/Ordini";
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";
import {
	Table,
	TableBody,
	TableCell,
	TableHead,
	TableHeader,
	TableRow,
} from "../ui/table";

export const ServizioInfos = () => {
	return (
		<div className="grid w-full grid-cols-2 gap-2 sm:grid-cols-4">
			<ServizioPrezzo />
			<UserActions />
			<ServizioOrders />
		</div>
	);
};

export const AdminServizioActions = () => {
	const { servizio, isAdmin, userId } = useServizio();
	if (!isAdmin) return null;
	return (
		<div className="flex flex-wrap items-center gap-3">
			<AdminActivationUfficio />
			<AddAnnuncio servizioId={servizio.servizio_id} userId={userId} />
			<EditServizioAdmin />
		</div>
	);
};

const UserActions = () => {
	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 (
			<>
				<EditServizioModal />
				<InterruzioneServizio />
			</>
		);
	}
	return null;
};

const ServizioPrezzo = () => {
	const { servizio } = useServizio();
	const { t } = useTranslation();
	const { data: packs } = api.servizio.getPacksSolution.useQuery({
		servizioId: servizio.servizio_id,
	});
	if (!packs) return null;
	return (
		<Dialog>
			<DialogTrigger asChild>
				<Button
					className={cn(
						"flex-1 text-white hover:text-white dark:text-white dark:hover:text-white",
						servizio.tipologia === TipologiaPosizioneEnum.Transitorio &&
							"border-transitorio bg-transitorio hover:border-transitorio/90 hover:bg-transitorio/90 dark:border-transitorio dark:bg-transitorio dark:hover:border-transitorio/90 dark:hover:bg-transitorio/90",
						servizio.tipologia === TipologiaPosizioneEnum.Stabile &&
							"border-stabile bg-stabile hover:border-stabile/90 hover:bg-stabile/90 dark:border-stabile dark:bg-stabile dark:hover:border-stabile/90 dark:hover:bg-stabile/90",
					)}
					variant="outline"
				>
					<Euro />
					<span>Costo Servizio</span>
				</Button>
			</DialogTrigger>
			<DialogContent className="sm:max-w-2xl">
				<DialogHeader>
					<DialogTitle>Costo Servizio</DialogTitle>
					<DialogDescription className="sr-only">
						Costo per questo servizio
					</DialogDescription>
				</DialogHeader>
				<div 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>
					{packs.acconto.success && (
						<Link
							aria-label="Leggi le condizioni"
							className="block w-fit"
							href={`/servizio/condizioni/${packs.acconto.pack.testo_condizioni}`}
							target="_blank"
						>
							<Button className="w-full text-sm">
								<span>{t.acquisto.leggi_condizioni}</span>
								<ExternalLink />
							</Button>
						</Link>
					)}
				</div>
			</DialogContent>
		</Dialog>
	);
};
const ServizioOrders = () => {
	const { isAdmin, servizio } = useServizio();
	return (
		<OrdersModal isAdmin={isAdmin} ordini={servizio.ordini}>
			<Button className="flex-1" variant="outline">
				<Logs />
				<span>Ordini</span>
			</Button>
		</OrdersModal>
	);
};

export const OrdersModal = ({
	children,
	isAdmin,
	ordini,
}: {
	children: React.ReactNode;
	isAdmin: boolean;
	ordini: Pick<
		Ordini,
		| "isActive"
		| "ordine_id"
		| "created_at"
		| "packid"
		| "amount_cent"
		| "userid"
		| "type"
	>[];
}) => {
	const [openOrders, setOpenOrders] = useState(false);
	const [openEdit, setOpenEdit] = useState(false);

	const swapToEdit = () => {
		setOpenOrders(false);
		setOpenEdit(true);
	};

	const swapToOrders = () => {
		setOpenEdit(false);
		setOpenOrders(true);
	};

	return (
		<>
			<Dialog onOpenChange={setOpenOrders} open={openOrders}>
				<DialogTrigger asChild>{children}</DialogTrigger>
				<DialogContent className="sm:max-w-2xl">
					<DialogHeader className="flex-row items-center gap-4">
						<DialogTitle>Ordini Servizio</DialogTitle>
						<DialogDescription className="sr-only">
							Ordini disponibili per questo servizio
						</DialogDescription>
						{isAdmin && (
							<Button
								className="w-fit"
								onClick={swapToEdit}
								size="sm"
								variant="outline"
							>
								<Plus />
							</Button>
						)}
					</DialogHeader>
					<div className="flex flex-col items-center gap-4 overflow-auto">
						<Table>
							<TableHeader>
								<TableRow>
									<TableHead>Data</TableHead>
									<TableHead>ID</TableHead>
									<TableHead>Importo</TableHead>
									<TableHead>Status</TableHead>
									<TableHead></TableHead>
								</TableRow>
							</TableHeader>
							<TableBody>
								{ordini.length === 0 && (
									<tr>
										<td className="py-4 text-center" colSpan={4}>
											<span>Nessun ordine disponibile</span>
										</td>
									</tr>
								)}
								{ordini.map((ordine) => (
									<TableRow key={ordine.ordine_id}>
										<TableCell>
											{ordine.created_at.toLocaleDateString("it-IT")}
										</TableCell>
										<TableCell className="font-medium">
											{ordine.packid}
										</TableCell>
										<TableCell>
											{formatCurrency(ordine.amount_cent / 100)}
										</TableCell>
										<TableCell>
											{ordine.isActive ? "Attivo" : "Non attivo"}
										</TableCell>
										<TableCell>
											<Link
												href={`/area-riservata/${isAdmin ? "admin/user-view/" : ""}ordini${isAdmin ? `/${ordine.userid}` : ""}?ordineId=${ordine.ordine_id}`}
												target="_blank"
											>
												<Button size="sm" variant="outline">
													<Search />
												</Button>
											</Link>
										</TableCell>
									</TableRow>
								))}
							</TableBody>
						</Table>
					</div>
				</DialogContent>
			</Dialog>
			<Dialog onOpenChange={setOpenEdit} open={openEdit}>
				<DialogContent>
					<DialogHeader>
						<DialogTitle>Nuovo Ordine</DialogTitle>
						<DialogDescription className="sr-only">nuovo</DialogDescription>
					</DialogHeader>
					<AddOrderDialogContent swapBack={swapToOrders} />
				</DialogContent>
			</Dialog>
		</>
	);
};

const AddOrderDialogContent = ({ swapBack }: { swapBack: () => void }) => {
	const { servizioId, userId } = useServizio();
	const { data, isLoading } = api.prezziario.getPrezziario.useQuery();

	if (isLoading) return <LoadingPage />;

	if (!data)
		return (
			<>
				<span>Errore nel caricamento del prezziario.</span>
			</>
		);

	return (
		<FormNewOrder
			prezziario={data}
			servizioId={servizioId}
			setOpen={swapBack}
			userId={userId}
		/>
	);
};

const AdminActivationUfficio = () => {
	const { servizio } = useServizio();
	const utils = api.useUtils();

	const { mutate } = api.servizio.AdminAttivaServizio_Ufficio.useMutation({
		onError: (error) => {
			toast.error(error.message);
		},
		onSuccess: async () => {
			toast.success("Servizio attivato con successo");
			await utils.servizio.invalidate();
		},
	});
	if (servizio.onboardOk) return null;
	if (!servizio.ordini.some((o) => o.isActive)) return null;
	return (
		<Confirm
			description="Sei sicuro di voler attivare il servizio manualmente?"
			onConfirm={() => mutate({ servizioId: servizio.servizio_id })}
			title="Attivazione Servizio"
		>
			<Button variant="destructive">
				<Check />
				<span>Attivazione Ufficio</span>
			</Button>
		</Confirm>
	);
};

const AddAnnuncio = ({
	servizioId,
}: {
	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.invalidate();
			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-2xl"
				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} - ${cod.titolo_it}`,
									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 EditServizioAdmin = () => {
	const { servizioId, userId, servizio } = useServizio();
	const [open, setOpen] = useState(false);
	const utils = api.useUtils();
	const router = useRouter();
	const { mutate: update } = api.servizio.updateServizio.useMutation({
		onError: (error) => {
			toast.error(error.message);
		},
		onSuccess: async () => {
			toast.success("Servizio modificato con successo");
			await utils.servizio.invalidate();
			setOpen(false);
		},
	});
	const { mutate: remove } = api.servizio.deleteServizio.useMutation({
		onError: (error) => {
			toast.error(error.message);
		},
		onMutate: async () => {
			await router.push(`/area-riservata/admin/user-view/ricerca/${userId}`);
		},

		onSuccess: async () => {
			toast.success("Servizio rimosso con successo");

			await utils.servizio.invalidate();
		},
	});

	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>
	);
};
