import { afterAll, beforeAll, describe, expect, test } from 'bun:test';

const ORIGINAL_ENV = { ...process.env };

const decodeTokenPayload = (token: string) => {
  const [encodedPayload] = token.split('.');
  return JSON.parse(Buffer.from(encodedPayload, 'base64url').toString('utf8')) as Record<string, unknown>;
};

let MockMediaProvider: typeof import('../media/providers/mock').MockMediaProvider;

beforeAll(async () => {
  process.env.BETTER_AUTH_SECRET = 'mock-provider-secret';
  process.env.MEDIA_MOCK_BASE_URL = 'http://media.example.test';
  ({ MockMediaProvider } = await import('../media/providers/mock'));
});

afterAll(() => {
  process.env = { ...ORIGINAL_ENV };
});

describe('mock media provider', () => {
  test('creates deterministic publish and subscribe endpoints for a session', async () => {
    const provider = new MockMediaProvider();

    const session = await provider.createSession({
      streamSessionId: 'stream-1',
      ownerUserId: 'user-1',
      cameraDeviceId: 'camera-1',
      requesterDeviceId: 'client-1',
    });

    expect(session.provider).toBe('mock');
    expect(session.mediaSessionId).toBe('mock_stream-1');
    expect(session.publishUrl).toBe('http://media.example.test/media/mock/publish/mock_stream-1');
    expect(session.subscribeUrl).toBe('http://media.example.test/media/mock/subscribe/mock_stream-1');
  });

  test('issues publish credentials with a signed token payload', async () => {
    const provider = new MockMediaProvider();

    const credentials = await provider.issuePublishCredentials({
      mediaSessionId: 'mock_stream-1',
      cameraDeviceId: 'camera-1',
      ownerUserId: 'user-1',
    });

    const payload = decodeTokenPayload(credentials.publishToken);
    expect(credentials.provider).toBe('mock');
    expect(credentials.publishUrl).toBe('http://media.example.test/media/mock/publish/mock_stream-1');
    expect(credentials.expiresInSeconds).toBe(600);
    expect(payload.typ).toBe('publish');
    expect(payload.mediaSessionId).toBe('mock_stream-1');
    expect(payload.cameraDeviceId).toBe('camera-1');
  });

  test('issues subscribe credentials with a signed token payload', async () => {
    const provider = new MockMediaProvider();

    const credentials = await provider.issueSubscribeCredentials({
      mediaSessionId: 'mock_stream-1',
      viewerDeviceId: 'client-1',
      ownerUserId: 'user-1',
    });

    const payload = decodeTokenPayload(credentials.subscribeToken);
    expect(credentials.provider).toBe('mock');
    expect(credentials.subscribeUrl).toBe('http://media.example.test/media/mock/subscribe/mock_stream-1');
    expect(credentials.expiresInSeconds).toBe(600);
    expect(payload.typ).toBe('subscribe');
    expect(payload.mediaSessionId).toBe('mock_stream-1');
    expect(payload.viewerDeviceId).toBe('client-1');
  });
});
