import { z } from "zod";
import {
  adminProcedure,
  createTRPCRouter,
  protectedProcedure,
  publicProcedure,
} from "~/server/api/trpc";
import {
  createUserAdmin,
  logIn,
  logOut,
  passwordChange,
  swapAuth,
} from "~/server/controllers/auth.controller";
import { zUserId } from "~/server/utils/zod_types";
import {
  genPasswordResetToken,
  isTokenValid,
  passwordOverrideHandler,
  pwResetSendLinkHandler,
  pwResetTokenFromMailHandler,
  resetPasswordFromTokenHandler,
} from "~/server/services/auth.service";
import { zStrongPassword } from "~/hooks/useStrongPassword";

// Create a new ratelimiter, that allows 10 requests per 10 seconds
/*
const ratelimit = new RateLimiterHandler({
  windowSize: 10,
  maxRequests: 10,
  analytics: true,
});
*/

export const authRouter = createTRPCRouter({
  loginUser: publicProcedure
    .input(
      z.object({
        email: z.string().email("Inserisci una email valida"),
        password: z.string(),
      }),
    )
    .mutation(async ({ input, ctx }) => {
      return await logIn({
        ...input,
        ctx: ctx,
      });
    }),
  swapUser: adminProcedure
    .input(
      z.object({
        id: zUserId,
      }),
    )
    .mutation(async ({ ctx, input }) => {
      return await swapAuth({ ctx, userId: input.id });
    }),

  logoutUser: protectedProcedure.mutation(async ({ ctx }) => {
    await logOut({ ctx: ctx });
    return "logout success";
  }),

  getSession: publicProcedure.query(async ({ ctx }) => {
    if (!ctx.session) return null;
    return ctx.session;
  }),
  addUserAdmin: adminProcedure
    .input(
      z.object({
        email: z.string().email("Inserisci una email valida"),
        password: zStrongPassword,
        nome: z.string().nonempty("Inserisci un nome valido"),
        cognome: z.string().nonempty("Inserisci un cognome valido"),
        telefono: z.string().nonempty("Inserisci un numero di telefono"),
      }),
    )
    .mutation(async ({ input }) => {
      return await createUserAdmin({ ...input });
    }),

  genPswResetToken: adminProcedure
    .input(z.object({ id: zUserId }))
    .mutation(async ({ input }) => {
      return await genPasswordResetToken({ id: input.id });
    }),
  resetPasswordFromToken: publicProcedure
    .input(
      z.object({
        newpassword: z.string(),
        resetToken: z.string(),
      }),
    )
    .mutation(async ({ input }) => {
      return await resetPasswordFromTokenHandler({
        newpassword: input.newpassword,
        token: input.resetToken,
      });
    }),
  pwResetGenTokenMail: publicProcedure
    .input(z.object({ email: z.string() }))
    .mutation(async ({ input }) => {
      return await pwResetTokenFromMailHandler({
        email: input.email,
      });
    }),
  checkTokenValidity: publicProcedure
    .input(z.object({ token: z.string() }))
    .query(async ({ input }) => {
      return await isTokenValid({ token: input.token });
    }),
  sendResetLink: publicProcedure
    .input(z.object({ email: z.string() }))
    .mutation(async ({ input }) => {
      return await pwResetSendLinkHandler({
        email: input.email,
      });
    }),

  OverridePassword: adminProcedure
    .input(
      z.object({
        id: zUserId,
        password: z.string(),
      }),
    )
    .mutation(async ({ input }) => {
      return await passwordOverrideHandler({ input });
    }),
  UpdatePasswordAndLogin: publicProcedure
    .input(
      z.object({
        id: zUserId,
        password: z.string(),
      }),
    )
    .mutation(async ({ input, ctx }) => {
      await passwordOverrideHandler({ input });
      await swapAuth({
        ctx: ctx,
        userId: input.id,
      });
      return true;
    }),
  ChangePassword: protectedProcedure
    .input(
      z.object({
        oldpassword: z.string(),
        newpassword: z.string(),
      }),
    )
    .mutation(async ({ ctx, input }) => {
      return await passwordChange({
        userId: ctx.session.id,
        ...input,
      });
    }),
});
