import { TRPCError } from '@trpc/server'
import bcrypt from 'bcrypt'
import { z } from 'zod'
import { auth } from '../../auth/lucia'
import client from '../../prisma/client'
import { protectedProcedure, publicProcedure, router } from '../router'

export const authRouter = router({
  register: publicProcedure
    .input(z.object({ username: z.string().min(1), password: z.string().min(6) }))
    .mutation(async ({ input, ctx }) => {
      const hashed = await bcrypt.hash(input.password, 10)
      const user = await client.user.create({
        data: {
          username: input.username,
          password: hashed,
          displayName: input.username,
        },
      })

      const session = await auth.createSession(user.id, {})
      const cookie = auth.createSessionCookie(session.id)

      ctx.res.setHeader('Set-Cookie', cookie.serialize())

      return { user }
    }),

  login: publicProcedure
    .input(z.object({ username: z.string().min(1), password: z.string() }))
    .mutation(async ({ input, ctx }) => {
      const user = await client.user.findFirst({
        where: {
          username: input.username,
        },
      })

      if (!user) {
        throw new TRPCError({
          code: 'NOT_FOUND',
          message: 'Incorrect username or password',
        })
      }

      const validPassword = await bcrypt.compare(input.password, user.password)

      if (!validPassword) {
        throw new TRPCError({
          code: 'NOT_FOUND',
          message: 'Incorrect username or password',
        })
      }

      const session = await auth.createSession(user.id, {})
      const cookie = auth.createSessionCookie(session.id)

      ctx.res.setHeader('Set-Cookie', cookie.serialize())

      return { user }
    }),

  me: protectedProcedure.query(({ ctx }) => {
    return ctx.user
  }),

  logout: publicProcedure.mutation(async ({ ctx }) => {
    if (ctx.session)
      await auth.invalidateSession(ctx.session.id)

    ctx.res.setHeader('Set-Cookie', auth.createBlankSessionCookie().serialize())

    return true
  }),
})
