import { describe, it, expect } from 'vitest'
import { decodeJwtPayload, extractRoleFromJwt } from '../jwt'

/** 构造一个 fake JWT（header.payload.signature），payload 为给定对象 */
function fakeJwt(payload: Record<string, unknown>): string {
  const header = btoa(JSON.stringify({ alg: 'HS256', typ: 'JWT' }))
  const body = btoa(JSON.stringify(payload))
  return `${header}.${body}.fake-signature`
}

describe('decodeJwtPayload', () => {
  it('correctly decodes a standard JWT payload', () => {
    const payload = { uid: 1, role: 'administrator', exp: 9999999999 }
    const result = decodeJwtPayload(fakeJwt(payload))

    expect(result).toEqual(payload)
  })

  it('returns null for non-three-segment string', () => {
    expect(decodeJwtPayload('only-one-part')).toBeNull()
    expect(decodeJwtPayload('two.parts')).toBeNull()
    expect(decodeJwtPayload('')).toBeNull()
  })

  it('returns null for invalid base64 payload', () => {
    expect(decodeJwtPayload('a.!!!invalid!!!.c')).toBeNull()
  })

  it('returns null for non-JSON payload', () => {
    const nonJson = `a.${btoa('not json')}.c`
    expect(decodeJwtPayload(nonJson)).toBeNull()
  })

  it('handles base64url encoding (- and _ characters)', () => {
    // base64url uses - instead of + and _ instead of /
    const payload = { data: 'test+value/here' }
    const standard = btoa(JSON.stringify(payload))
    const urlSafe = standard.replace(/\+/g, '-').replace(/\//g, '_')
    const token = `header.${urlSafe}.sig`

    expect(decodeJwtPayload(token)).toEqual(payload)
  })
})

describe('extractRoleFromJwt', () => {
  it('extracts top-level role string', () => {
    expect(extractRoleFromJwt(fakeJwt({ role: 'administrator' }))).toBe('administrator')
    expect(extractRoleFromJwt(fakeJwt({ role: 'accessor' }))).toBe('accessor')
  })

  it('returns null when role field is missing', () => {
    expect(extractRoleFromJwt(fakeJwt({ uid: 1 }))).toBeNull()
  })

  it('returns null when role is not a string', () => {
    expect(extractRoleFromJwt(fakeJwt({ role: 123 }))).toBeNull()
    expect(extractRoleFromJwt(fakeJwt({ role: null }))).toBeNull()
    expect(extractRoleFromJwt(fakeJwt({ role: { name: 'admin' } }))).toBeNull()
  })

  it('returns null for invalid token', () => {
    expect(extractRoleFromJwt('garbage')).toBeNull()
    expect(extractRoleFromJwt('')).toBeNull()
  })
})
