import { describe, test, expect } from 'bun:test';
import { SubtleCryptoProvider } from '@shade/crypto-web';
import { ValidationError } from '@shade/core';
import {
  generateStreamId,
  generateStreamSecret,
  streamIdToString,
  streamIdFromString,
  STREAM_ID_BYTES,
  STREAM_SECRET_BYTES,
} from '../src/index.js';

const crypto = new SubtleCryptoProvider();

describe('streamId / streamSecret generators', () => {
  test('streamId is 16 bytes', () => {
    expect(generateStreamId(crypto).length).toBe(STREAM_ID_BYTES);
  });

  test('streamSecret is 32 bytes', () => {
    expect(generateStreamSecret(crypto).length).toBe(STREAM_SECRET_BYTES);
  });

  test('successive generations are not equal (high-entropy)', () => {
    const a = generateStreamId(crypto);
    const b = generateStreamId(crypto);
    expect(a).not.toEqual(b);
  });
});

describe('base64url encode/decode roundtrip', () => {
  test('roundtrips arbitrary 16-byte streamIds', () => {
    for (let i = 0; i < 50; i++) {
      const id = generateStreamId(crypto);
      const s = streamIdToString(id);
      expect(streamIdFromString(s)).toEqual(id);
    }
  });

  test('emits URL-safe alphabet (no +, /, =)', () => {
    for (let i = 0; i < 50; i++) {
      const s = streamIdToString(generateStreamId(crypto));
      expect(s).not.toMatch(/[+/=]/);
    }
  });

  test('rejects wrong-length streamId on encode', () => {
    expect(() => streamIdToString(new Uint8Array(15))).toThrow(ValidationError);
    expect(() => streamIdToString(new Uint8Array(17))).toThrow(ValidationError);
  });

  test('rejects strings that decode to wrong length', () => {
    expect(() => streamIdFromString('AAAA')).toThrow(ValidationError);
  });
});
