import { TRPCError } from "@trpc/server";
import { z } from "zod";
import { env } from "~/env";
import {
	adminProcedure,
	createTRPCRouter,
	publicProcedure,
} from "~/server/api/trpc";
import {
	createInviteToken,
	InviteAcceptance,
	InviteVerification,
	sendInvitoEmail,
} from "~/server/controllers/invites.controller";
import { db } from "~/server/db";
import { findUser_byEmail, getUser } from "~/server/services/user.service";
import { zUserId } from "~/server/utils/zod_types";

export const inviteRouter = createTRPCRouter({
	// Admin sends invite
	sendInvite: adminProcedure
		.input(
			z.object({
				id: zUserId,
			}),
		)
		.mutation(async ({ input }) => {
			try {
				const user = await getUser({ userId: input.id, db });

				const token = await createInviteToken(user.email);

				const inviteUrl = `${env.BASE_URL}/auth/accetta-invito/${token}?e=${btoa(user.email)}`;

				await sendInvitoEmail({
					userId: input.id,
					email: user.email,
					nome: user.nome,
					//password: user.password,
					inviteUrl,
				});

				return { success: true };
			} catch (e) {
				console.error("Error in sendInvite:", e);
				throw new TRPCError({
					code: "INTERNAL_SERVER_ERROR",
					message:
						"Errore durante l'invio dell'invito: " +
						(e instanceof Error ? e.message : "Unknown error"),
				});
			}
		}),

	requestNewInvite: publicProcedure
		.input(z.object({ email: z.email() }))
		.mutation(async ({ input }) => {
			try {
				const user = await findUser_byEmail({ email: input.email });
				if (!user) {
					// For security, we don't reveal whether the email exists or not
					return { success: true };
				}

				const token = await createInviteToken(user.email);
				const inviteUrl = `${env.BASE_URL}/auth/accetta-invito/${token}?e=${btoa(user.email)}`;

				await sendInvitoEmail({
					userId: user.id,
					email: user.email,
					nome: user.nome,
					//password: user.password,
					inviteUrl,
				});
				return { success: true };
			} catch (e) {
				console.error("Error in requestNewInvite:", e);
				throw new TRPCError({
					code: "INTERNAL_SERVER_ERROR",
					message:
						"Errore durante la richiesta di un nuovo invito: " +
						(e instanceof Error ? e.message : "Unknown error"),
				});
			}
		}),

	// Verify invite token (public - user clicking the link)
	verifyInvite: publicProcedure
		.input(z.object({ token: z.string(), email: z.string().nullable() }))
		.query(async ({ input }) => {
			return await InviteVerification(input.token, input.email);
		}),

	// Accept invite and set password
	acceptInvite: publicProcedure
		.input(
			z.object({
				email: z.email(),
				token: z.string(),
				password: z.string().min(8),
			}),
		)
		.mutation(async ({ input, ctx }) => {
			return await InviteAcceptance(
				ctx,
				input.token,
				input.email,
				input.password,
			);
		}),
});
