import { TRPCError } from "@trpc/server";
import { z } from "zod/v4";
import OrderTypeEnum from "~/schemas/public/OrderTypeEnum";
import { createTRPCRouter, protectedProcedure } from "~/server/api/trpc";
import {
	getPagamentoDataForCheckout,
	getRicevutaData,
	type PreparedPaymentData,
	type PreparePaymentError,
	preparePayment,
	previewSaldo,
} from "~/server/controllers/pagamenti.controller";

import { db } from "~/server/db";
import { TypstGenerate } from "~/server/services/typst.service";
import { zOrdineId, zRinnovoId, zServizioId } from "~/server/utils/zod_types";
import { zResult } from "~/utils/result";
// Create a new ratelimiter, that allows 10 requests per 10 seconds
/*
const ratelimit = new RateLimiterHandler({
  maxRequests: 10,
  windowSize: 60,
  analytics: false,
});
*/

export const pagamentiRouter = createTRPCRouter({
	getPaymentFromIntent: protectedProcedure
		.input(z.object({ pIntentId: z.string() }))
		.query(async ({ input }) => {
			try {
				const ordine = await db
					.selectFrom("ordini")
					.selectAll("ordini")
					.where("ordini.intent_id", "=", input.pIntentId)
					.executeTakeFirst();
				return ordine || null;
			} catch (error) {
				throw new TRPCError({
					code: "INTERNAL_SERVER_ERROR",
					message: `Errore durante il recupero del pagamento: ${(error as Error).message}`,
				});
			}
		}),
	preparePayment: protectedProcedure
		.input(
			z.object({
				servizioId: zServizioId,
				type: z.enum(OrderTypeEnum),
			}),
		)
		.output(zResult<PreparedPaymentData, PreparePaymentError>())
		.query(async ({ input }) => {
			if (input.type === OrderTypeEnum.Rinnovo) {
				return {
					ok: false,
					error: {
						_tag: "InvalidInput",
						message: "Use preparePaymentRinnovi for Rinnovo payments",
					},
				};
			}
			return await preparePayment({
				type: input.type,
				servizioId: input.servizioId,
			});
		}),
	previewSaldo: protectedProcedure
		.input(
			z.object({
				servizioId: zServizioId,
			}),
		)
		.query(async ({ input }) => {
			return await previewSaldo(input.servizioId);
		}),
	preparePaymentRinnovi: protectedProcedure
		.input(
			z.object({
				rinnovoId: zRinnovoId,
			}),
		)
		.output(zResult<PreparedPaymentData, PreparePaymentError>())
		.query(async ({ input }) => {
			return await preparePayment({
				type: OrderTypeEnum.Rinnovo,
				rinnovoId: input.rinnovoId,
			});
		}),

	getPagamentoDataForCheckout: protectedProcedure
		.input(z.object({ ordineId: zOrdineId }))
		.query(async ({ input }) => {
			return await getPagamentoDataForCheckout(input.ordineId);
		}),
	getRicevutaCortesiaPdf: protectedProcedure
		.input(z.object({ ordineId: zOrdineId }))
		.mutation(async ({ input }) => {
			try {
				const ricData = await getRicevutaData(input.ordineId);
				const pdf = await TypstGenerate({
					templateId: "receipt.typ",
					data: ricData.data,
				});
				return { title: ricData.title, pdf: pdf.toString("base64") };
			} catch (e) {
				throw new TRPCError({
					code: "INTERNAL_SERVER_ERROR",
					message: `Errore nella generazione della ricevuta di cortesia: ${(e as Error).message}`,
				});
			}
		}),
	getRicevutaCortesiaPdfQuery: protectedProcedure
		.input(z.object({ ordineId: zOrdineId }))
		.query(async ({ input }) => {
			try {
				const ricData = await getRicevutaData(input.ordineId);
				const pdf = await TypstGenerate({
					templateId: "receipt.typ",
					data: ricData.data,
				});
				return { title: ricData.title, pdf: pdf.toString("base64") };
			} catch (e) {
				throw new TRPCError({
					code: "INTERNAL_SERVER_ERROR",
					message: `Errore nella generazione della ricevuta di cortesia: ${(e as Error).message}`,
				});
			}
		}),
});
