import { SignJWT } from 'jose';
import { describe, expect, it } from 'vitest';
import { JWT_AUDIENCE, JWT_ISSUER } from '@pintrush/protocol';
import { signHostToken, signTvToken } from '../server/tokens';
import { firstParam, verifyTvToken } from './token';

const room = { roomId: '0b3f3c2a-6d55-4f0e-9a43-2b8d7d7c9c11', venueId: '7e0f2d55-1c4b-4c0e-8a39-5f2a8f3d1e22', v: 2 };

describe('verifyTvToken', () => {
  it('accepts a TV token minted by the web app', async () => {
    expect(await verifyTvToken(await signTvToken(room))).toEqual({ scope: 'tv', ...room });
  });

  it('rejects missing, garbage and wrongly-signed tokens', async () => {
    expect(await verifyTvToken(null)).toBeNull();
    expect(await verifyTvToken('')).toBeNull();
    expect(await verifyTvToken('not-a-jwt')).toBeNull();
    expect(await verifyTvToken(await signTvToken(room), 'some-other-secret-that-is-long-enough')).toBeNull();
  });

  it('rejects host tokens: a host link is not a TV link', async () => {
    const host = await signHostToken({ sub: '5a1d2c3b-0000-4000-8000-000000000001', venueId: room.venueId, role: 'OWNER' });
    expect(await verifyTvToken(host)).toBeNull();
  });

  it('rejects tokens for another audience', async () => {
    const key = new TextEncoder().encode(process.env.AUTH_SECRET || 'dev-only-insecure-secret-change-me-0123456789');
    const foreign = await new SignJWT({ ...room, scope: 'tv' }).setProtectedHeader({ alg: 'HS256' }).setIssuer(JWT_ISSUER).setAudience('someone-else').sign(key);
    expect(await verifyTvToken(foreign)).toBeNull();
    const ok = await new SignJWT({ ...room, scope: 'tv' }).setProtectedHeader({ alg: 'HS256' }).setIssuer(JWT_ISSUER).setAudience(JWT_AUDIENCE).sign(key);
    expect(await verifyTvToken(ok)).not.toBeNull();
  });
});

describe('firstParam', () => {
  it('takes the first value of a repeated search param', () => {
    expect(firstParam('abc')).toBe('abc');
    expect(firstParam(['x', 'y'])).toBe('x');
    expect(firstParam(undefined)).toBeNull();
    expect(firstParam([])).toBeNull();
  });
});
