import { describe, expect, it } from 'vitest';
import { currentSessionId } from './jwt';

/** Builds a JWT-shaped string whose payload is `claims`, base64url encoded. */
function token(claims: Record<string, unknown>): string {
  const payload = btoa(JSON.stringify(claims))
    .replace(/\+/g, '-')
    .replace(/\//g, '_')
    .replace(/=+$/, '');
  return `header.${payload}.signature`;
}

describe('currentSessionId', () => {
  it('reads the sessionId claim', () => {
    expect(currentSessionId(token({ sessionId: 'abc' }))).toBe('abc');
  });

  it('falls back to sid, then jti', () => {
    expect(currentSessionId(token({ sid: 'from-sid' }))).toBe('from-sid');
    expect(currentSessionId(token({ jti: 'from-jti' }))).toBe('from-jti');
  });

  it('decodes payloads containing base64url characters', () => {
    // '>' and '?' are what force '+' and '/' in standard base64.
    const id = 'a>b?c>d?e>f?';
    expect(currentSessionId(token({ sessionId: id }))).toBe(id);
  });

  it('returns undefined for a token with no session claim', () => {
    expect(currentSessionId(token({ sub: 'user-1' }))).toBeUndefined();
  });

  it('returns undefined rather than throwing on junk', () => {
    expect(currentSessionId(undefined)).toBeUndefined();
    expect(currentSessionId('')).toBeUndefined();
    expect(currentSessionId('opaque-token')).toBeUndefined();
    expect(currentSessionId('header.not-base64!!.sig')).toBeUndefined();
  });
});
