import { describe, it, expect } from "vitest"
import { signToken, verifyToken } from "@/lib/jwt"

process.env.JWT_SECRET = "test-secret-that-is-at-least-32-chars-long-for-security"

describe("JWT", () => {
  it("signs and verifies a valid token", async () => {
    const token = await signToken({ userId: "user-1", role: "admin" })
    expect(token).toBeTruthy()
    expect(typeof token).toBe("string")

    const payload = await verifyToken(token)
    expect(payload).not.toBeNull()
    expect(payload!.userId).toBe("user-1")
    expect(payload!.role).toBe("admin")
  })

  it("rejects a tampered token", async () => {
    const token = await signToken({ userId: "user-1", role: "admin" })
    const tampered = token.slice(0, -5) + "XXXXX"
    const payload = await verifyToken(tampered)
    expect(payload).toBeNull()
  })

  it("rejects an expired token", async () => {
    const { SignJWT } = await import("jose")
    const { getJWTSecret } = await import("@/lib/jwt")
    const expiredToken = await new SignJWT({ userId: "user-1", role: "admin" })
      .setProtectedHeader({ alg: "HS256" })
      .setExpirationTime("0s")
      .sign(getJWTSecret())
    const payload = await verifyToken(expiredToken)
    expect(payload).toBeNull()
  })

  it("rejects a token with invalid signature", async () => {
    const { SignJWT } = await import("jose")
    const wrongSecret = new TextEncoder().encode("different-secret-key-for-signing-purposes-only")
    const token = await new SignJWT({ userId: "user-1", role: "admin" })
      .setProtectedHeader({ alg: "HS256" })
      .setExpirationTime("24h")
      .setIssuedAt()
      .sign(wrongSecret)
    const payload = await verifyToken(token)
    expect(payload).toBeNull()
  })

  it("returns null for empty token", async () => {
    const payload = await verifyToken("")
    expect(payload).toBeNull()
  })

  it("returns null for garbage token", async () => {
    const payload = await verifyToken("this.is.not.a.jwt")
    expect(payload).toBeNull()
  })
})
