import {vi, describe, it, beforeEach, expect} from "vitest"
import resetPassword from "./resetPassword"
import db from "db"
import {hash256} from "@blitzjs/auth"
import {SecurePassword} from "@blitzjs/auth/secure-password"

beforeEach(async () => {
  await db.$reset()
})

const mockCtx: any = {
  session: {
    $create: vi.fn(),
  },
}

describe("resetPassword mutation", () => {
  it("works correctly", async () => {
    expect(true).toBe(true)

    // Create test user
    const goodToken = "randomPasswordResetToken"
    const expiredToken = "expiredRandomPasswordResetToken"
    const future = new Date()
    future.setHours(future.getHours() + 4)
    const past = new Date()
    past.setHours(past.getHours() - 4)

    const user = await db.user.create({
      data: {
        email: "user@example.com",
        tokens: {
          // Create old token to ensure it's deleted
          create: [
            {
              type: "RESET_PASSWORD",
              hashedToken: hash256(expiredToken),
              expiresAt: past,
              sentTo: "user@example.com",
            },
            {
              type: "RESET_PASSWORD",
              hashedToken: hash256(goodToken),
              expiresAt: future,
              sentTo: "user@example.com",
            },
          ],
        },
      },
      include: {tokens: true},
    })

    const newPassword = "newPassword"

    // Non-existent token
    await expect(
      resetPassword({token: "no-token", password: "", passwordConfirmation: ""}, mockCtx),
    ).rejects.toThrowError()

    // Expired token
    await expect(
      resetPassword(
        {token: expiredToken, password: newPassword, passwordConfirmation: newPassword},
        mockCtx,
      ),
    ).rejects.toThrowError()

    // Good token
    await resetPassword(
      {token: goodToken, password: newPassword, passwordConfirmation: newPassword},
      mockCtx,
    )

    // Delete's the token
    const numberOfTokens = await db.token.count({where: {userId: user.id}})
    expect(numberOfTokens).toBe(0)

    // Updates user's password
    const updatedUser = await db.user.findFirst({where: {id: user.id}})
    expect(await SecurePassword.verify(updatedUser!.hashedPassword, newPassword)).toBe(
      SecurePassword.VALID,
    )
  })
})
