import { z } from "zod/v4";
import type { AnnunciUpdate } from "~/schemas/public/Annunci";
import {
	adminProcedure,
	apiProcedure,
	createTRPCRouter,
	protectedProcedure,
	publicProcedure,
} from "~/server/api/trpc";
import {
	editAnnuncioHandler,
	get_AnnunciPositionsHandler,
	getAnnunciById_rawImgUrls,
	getAnnunciListHandler,
	getAnnuncioData,
	getAnnunciRicerca,
	getAnnunciSchedaData,
	getCodici_AnnunciHandler,
	getOptions_AnnunciHandler,
	getProprietarioDataHandler,
	type ImgToRemove,
	removeAnnuncioMedia,
	type VideoToRemove,
} from "~/server/controllers/annunci.controller";
import { getIncrociAnnuncio } from "~/server/controllers/servizio.controller";
import { db } from "~/server/db";
import {
	invalidateCache,
	SCHEDA_ANNUNCIO_CACHE_PREFIX,
} from "~/server/services/cache.service";
import { NewMail } from "~/server/services/mailer";
import { TypstGenerate } from "~/server/services/typst.service";
import { zAnnuncioId, zServizioId } from "~/server/utils/zod_types";

export const annunciRouter = createTRPCRouter({
	editAnnuncio: adminProcedure
		.input(
			z.object({ annuncioId: zAnnuncioId, data: z.custom<AnnunciUpdate>() }),
		)
		.mutation(async ({ input }) => {
			await invalidateCache(
				`${SCHEDA_ANNUNCIO_CACHE_PREFIX}${input.annuncioId}`,
			);

			return await editAnnuncioHandler({
				...input,
			});
		}),
	getAnnunciList: publicProcedure.query(async () => {
		return await getAnnunciListHandler();
	}),
	getAnnunciOptions: publicProcedure.query(async () => {
		return await getOptions_AnnunciHandler();
	}),
	getAnnuncioData: publicProcedure
		.input(
			z.object({
				cod: z.string(),
			}),
		)

		.query(async ({ input }) => {
			return await getAnnuncioData({ ...input });
		}),
	getAnnuncioFull: adminProcedure
		.input(
			z.object({
				id: zAnnuncioId,
			}),
		)
		.query(async ({ input }) => {
			return await db
				.selectFrom("annunci")
				.selectAll()
				.where("id", "=", input.id)
				.executeTakeFirst();
		}),
	getAnnuncioById_rawImgUrls: publicProcedure
		.input(
			z.object({
				id: zAnnuncioId,
			}),
		)
		.query(async ({ input }) => {
			return await getAnnunciById_rawImgUrls({ ...input });
		}),
	getSchedaAnnuncioData: adminProcedure
		.input(
			z.object({
				id: zAnnuncioId,
			}),
		)
		.query(async ({ input }) => {
			return await getAnnunciSchedaData(input.id);
		}),
	getSchedaAnnuncioPdf: adminProcedure
		.input(
			z.object({
				id: zAnnuncioId,
			}),
		)
		.mutation(async ({ input }) => {
			const data = await getAnnunciSchedaData(input.id);
			const pdfBuffer = await TypstGenerate({
				templateId: "annuncio.typ",
				data,
			});
			return {
				pdf: pdfBuffer.toString("base64"),
				title: `scheda-annuncio-${data.codice}.pdf`,
			};
		}),
	getCodici: publicProcedure.query(async () => {
		return await getCodici_AnnunciHandler();
	}),
	getMapping: publicProcedure
		.input(
			z.object({
				comune: z.string().optional(),
				consegna: z.number().array().optional(),
				tipologia: z.string().optional(),
				minBudget: z.number().optional(),
				maxBudget: z.number().optional(),
			}),
		)
		.query(async ({ input }) => {
			return await get_AnnunciPositionsHandler({
				...input,
			});
		}),

	getProprietarioData: protectedProcedure
		.input(z.object({ annuncioId: zAnnuncioId, servizioId: zServizioId }))
		.query(async ({ input }) => {
			return await getProprietarioDataHandler({
				annuncioId: input.annuncioId,
				servizioId: input.servizioId,
			});
		}),

	annunciRicerca: publicProcedure
		.input(
			z.object({
				comune: z.string().optional(),
				consegna: z.number().array().optional(),
				sort: z.enum(["Recenti", "Prezzo", "Consegna", "Mq"]).optional(),
				tipologia: z.string().optional(),
				minBudget: z.number().optional(),
				maxBudget: z.number().optional(),
			}),
		)
		.query(async ({ input }) => {
			return await getAnnunciRicerca({
				...input,
			});
		}),
	/**Used for cron job */
	checkAnnunci: apiProcedure.query(async () => {
		const hasAnnunci = await db
			.selectFrom("annunci")
			.select("id")
			.where("stato", "=", "Attivo")
			.where("web", "is", true)
			.execute();
		if (hasAnnunci.length === 0) {
			await NewMail({
				template: {
					mailType: "generic",
					props: {
						title: "Attenzione: Nessun annuncio attivo!",
						testo:
							"Nel sistema non è presente nessun annuncio con stato Attivo e visibile sul web.",
					},
				},
				mail: {
					subject: "Attenzione: Nessun annuncio attivo!",
					to: "m.pedone98@gmail.com",
				},
			});

			return { status: "no_annunci", timestamp: Date.now() };
		}
		return { status: "ok", timestamp: Date.now() };
	}),
	removeAnnuncioMedia: adminProcedure
		.input(z.custom<ImgToRemove | VideoToRemove>())
		.mutation(async ({ input }) => {
			return await removeAnnuncioMedia({
				...input,
			});
		}),
	getIncrociAnnuncio: protectedProcedure
		.input(
			z.object({
				annuncioId: zAnnuncioId,
			}),
		)
		.query(async ({ input }) => {
			return await getIncrociAnnuncio(input.annuncioId);
		}),
});
