import { ArrowRight, ExternalLink } from "lucide-react";
import type { GetServerSideProps } from "next";
import Link from "next/link";
import { useRouter } from "next/router";
import z from "zod";
import { AreaRiservataLayout } from "~/components/Layout";
import { Button } from "~/components/ui/button";
import {
	Card,
	CardContent,
	CardDescription,
	CardFooter,
	CardHeader,
	CardTitle,
} from "~/components/ui/card";
import { formatCurrency, redirectTo500 } from "~/lib/utils";
import type { NextPageWithLayout } from "~/pages/_app";
import { useTranslation } from "~/providers/I18nProvider";
import OrderTypeEnum from "~/schemas/public/OrderTypeEnum";
import type { Prezziario } from "~/schemas/public/Prezziario";
import type { PreparedPaymentData } from "~/server/controllers/pagamenti.controller";
import { TrpcAuthedFetchingIstance } from "~/server/utils/ssgHelper";
import { zRinnovoId, zServizioId } from "~/server/utils/zod_types";

type PreviewPurchaseProps = {
	stripeDisabled: boolean;
	data: PreparedPaymentData;
	saldoPreview: Prezziario | null;
};
/**
 * /servizio/pagamento?servizioId=<servizioId>|rinnovoId=<rinnovoId>&type=<OrderTypeEnum> \
 * Pagina di preparazione al pagamento.
 */
const PreviewPurchasePage: NextPageWithLayout<PreviewPurchaseProps> = ({
	stripeDisabled,
	data,
	saldoPreview,
}: PreviewPurchaseProps) => {
	const router = useRouter();
	const { t } = useTranslation();

	return (
		<div className="mt-1 flex w-full justify-center p-2 sm:mt-14">
			<Card className="h-fit">
				<CardHeader>
					<CardTitle className="text-3xl">{data.packName}</CardTitle>
					<CardDescription>Cod: &ldquo;{data.packid}&rdquo;</CardDescription>
				</CardHeader>
				<CardContent className="space-y-3">
					<p className="font-bold text-4xl">
						{formatCurrency(data.amount_cent / 100)}{" "}
						{data.sconto > 0 && (
							<span className="text-green-500">(Sconto: {data.sconto}%)</span>
						)}
					</p>
					<p>{data.packDesc}</p>
					<Link
						aria-label="Leggi le condizioni"
						className="block w-fit"
						href={`/servizio/condizioni/${data.condizioni}`}
						target="_blank"
					>
						<Button className="w-full text-sm">
							<span>{t.acquisto.leggi_condizioni}</span>
							<ExternalLink />
						</Button>
					</Link>

					{saldoPreview && (
						<div className="mt-6 space-y-4 rounded-md bg-muted/80 p-2">
							<h1 className="font-medium">{saldoPreview.nome_it}</h1>
							<div className="flex items-baseline gap-2">
								<p className="font-bold text-2xl text-muted-foreground line-through">
									{formatCurrency(saldoPreview.prezzo_cent / 100)}
								</p>
								<p className="font-bold text-4xl text-primary">
									{formatCurrency(0)}
								</p>
							</div>
							<span className="font-bold text-primary">
								Il Saldo non è dovuto in questo momento, ma al termine della
								ricerca.
							</span>
							<p className="text-muted-foreground text-sm">
								Il saldo verrà aggiornato in base ai parametri del servizio.
							</p>
						</div>
					)}
				</CardContent>
				<CardFooter>
					<Button
						className="w-full text-lg"
						onClick={async () =>
							await router.push(
								`/servizio/${stripeDisabled ? "bonifico-checkout" : "pagamento-checkout"}/${data.ordine_id}`,
							)
						}
						size="xl"
						variant="info"
					>
						<span>{t.acquisto.procedi_pagamento}</span> <ArrowRight />
					</Button>
				</CardFooter>
			</Card>
		</div>
	);
};

PreviewPurchasePage.getLayout = function getLayout(page) {
	return <AreaRiservataLayout noSidebar>{page}</AreaRiservataLayout>;
};

export default PreviewPurchasePage;

export const getServerSideProps = (async (context) => {
	const access_token = context.req.cookies.access_token;

	const helper = await TrpcAuthedFetchingIstance({ access_token });
	if (!helper) {
		return redirectTo500;
	}

	const flag = await helper.trpc.flags.GetFlagValue.fetch({
		id: "STRIPE_DISABLED",
	});
	const payment_type = context.query?.type;
	if (typeof payment_type !== "string") {
		console.error("Error: payment type is not a string");
		return redirectTo500;
	}
	const parsedType = z.enum(OrderTypeEnum).safeParse(payment_type);
	if (!parsedType.success) {
		console.error("Error parsing payment type", parsedType.error);
		return redirectTo500;
	}
	const type = parsedType.data;

	if (type === OrderTypeEnum.Rinnovo) {
		const id = context.query?.rinnovoId;
		if (typeof id !== "string") {
			console.error("Error: rinnovoId is not a string");
			return redirectTo500;
		}
		const parsedRinnovoId = zRinnovoId.safeParse(id);
		if (!parsedRinnovoId.success) {
			console.error("Error parsing rinnovoId", parsedRinnovoId.error);
			return redirectTo500;
		}
		const result = await helper.trpc.pagamenti.preparePaymentRinnovi.fetch({
			rinnovoId: parsedRinnovoId.data,
		});
		if (!result.ok) {
			// error type non usato prienamente per ora, logghiamo tutto con messaggio
			console.error("Error preparing payment", result.error.message);
			return redirectTo500;
		}
		return {
			props: {
				stripeDisabled: flag || false,
				data: result.value,
				saldoPreview: null,
			},
		};
	}
	// Non è un rinnovo, deve essere un servizio normale
	const id = context.query?.servizioId;
	if (typeof id !== "string") {
		console.error("Error: servizioId is not a string");
		return redirectTo500;
	}
	const parsedServizioId = zServizioId.safeParse(id);
	if (!parsedServizioId.success) {
		console.error("Error parsing servizioId", parsedServizioId.error);
		return redirectTo500;
	}
	const result = await helper.trpc.pagamenti.preparePayment.fetch({
		type,
		servizioId: parsedServizioId.data,
	});
	if (!result.ok) {
		// error type non usato prienamente per ora, logghiamo tutto con messaggio
		console.error("Error preparing payment", result.error.message);
		return redirectTo500;
	}
	let saldoPreview: Prezziario | null = null;
	if (type === OrderTypeEnum.Acconto) {
		const saldoResult = await helper.trpc.pagamenti.previewSaldo.fetch({
			servizioId: parsedServizioId.data,
		});
		if (saldoResult.success) {
			saldoPreview = saldoResult.pack;
		}
	}

	return {
		props: {
			stripeDisabled: flag || false,
			data: result.value,
			saldoPreview,
		},
	};
}) satisfies GetServerSideProps<PreviewPurchaseProps>;
