import { describe, expect, it } from 'vitest';

import { setStartBitrate } from '../sdp';

describe('sdp - setStartBitrate', () => {
  it('adds x-google-start-bitrate for AV1/VP9/H264 fmtp lines (but not VP8)', () => {
    const offerSdp = `v=0
o=- 123 2 IN IP4 127.0.0.1
s=-
t=0 0
m=video 9 UDP/TLS/RTP/SAVPF 96 98 103 45
c=IN IP4 0.0.0.0
a=mid:0
a=rtpmap:96 VP8/90000
a=rtpmap:98 VP9/90000
a=fmtp:98 profile-id=0
a=rtpmap:103 H264/90000
a=fmtp:103 level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=42001f
a=rtpmap:45 AV1/90000
a=fmtp:45 level-idx=5;profile=0;tier=0
`;

    const result = setStartBitrate(offerSdp, 1500, 0.5, '0'); // 750kbps

    expect(result).toContain(
      'a=fmtp:98 profile-id=0;x-google-start-bitrate=750',
    );
    expect(result).toContain(
      'a=fmtp:103 level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=42001f;x-google-start-bitrate=750',
    );
    expect(result).toContain(
      'a=fmtp:45 level-idx=5;profile=0;tier=0;x-google-start-bitrate=750',
    );

    // VP8 is not a target codec
    expect(result).not.toContain('a=fmtp:96');
    expect(result).not.toContain(
      'a=rtpmap:96 VP8/90000;x-google-start-bitrate',
    );
  });

  it('does not add x-google-start-bitrate if already present', () => {
    const offerSdp = `v=0
o=- 123 2 IN IP4 127.0.0.1
s=-
t=0 0
m=video 9 UDP/TLS/RTP/SAVPF 103
c=IN IP4 0.0.0.0
a=mid:0
a=rtpmap:103 H264/90000
a=fmtp:103 level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=42001f;x-google-start-bitrate=500
`;

    const result = setStartBitrate(offerSdp, 1500, 0.9, '0');
    expect(result).toContain('x-google-start-bitrate=500');
    expect(result).not.toContain('x-google-start-bitrate=1350');

    // Ensure it's only present once
    expect(result.match(/x-google-start-bitrate/g)).toHaveLength(1);
  });

  it('clamps computed start bitrate to a minimum of 300kbps', () => {
    const offerSdp = `v=0
o=- 123 2 IN IP4 127.0.0.1
s=-
t=0 0
m=video 9 UDP/TLS/RTP/SAVPF 98
c=IN IP4 0.0.0.0
a=mid:0
a=rtpmap:98 VP9/90000
a=fmtp:98 profile-id=0
`;

    const result = setStartBitrate(offerSdp, 1500, 0.1, '0'); // 150 -> clamped to 300
    expect(result).toContain(
      'a=fmtp:98 profile-id=0;x-google-start-bitrate=300',
    );
  });

  it('can scope the change to a specific mid', () => {
    const offerSdp = `v=0
o=- 123 2 IN IP4 127.0.0.1
s=-
t=0 0
m=video 9 UDP/TLS/RTP/SAVPF 98
c=IN IP4 0.0.0.0
a=mid:0
a=rtpmap:98 VP9/90000
a=fmtp:98 profile-id=0
m=video 9 UDP/TLS/RTP/SAVPF 103
c=IN IP4 0.0.0.0
a=mid:1
a=rtpmap:103 H264/90000
a=fmtp:103 level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=42001f
`;

    const result = setStartBitrate(offerSdp, 1500, 0.7, '0'); // 1050kbps

    // mid:0 updated
    expect(result).toContain(
      'a=fmtp:98 profile-id=0;x-google-start-bitrate=1050',
    );

    // mid:1 untouched
    expect(result).toContain(
      'a=fmtp:103 level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=42001f',
    );
    expect(result).not.toContain(
      'a=fmtp:103 level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=42001f;x-google-start-bitrate=1050',
    );
  });

  it('clamps to 300kbps when factor is 0', () => {
    const offerSdp = `v=0
o=- 123 2 IN IP4 127.0.0.1
s=-
t=0 0
m=video 9 UDP/TLS/RTP/SAVPF 98
c=IN IP4 0.0.0.0
a=mid:0
a=rtpmap:98 VP9/90000
a=fmtp:98 profile-id=0
`;

    const result = setStartBitrate(offerSdp, 1500, 0, '0'); // 0 -> clamped to 300
    expect(result).toContain(
      'a=fmtp:98 profile-id=0;x-google-start-bitrate=300',
    );
  });

  it('uses max bitrate when factor is 1', () => {
    const offerSdp = `v=0
o=- 123 2 IN IP4 127.0.0.1
s=-
t=0 0
m=video 9 UDP/TLS/RTP/SAVPF 98
c=IN IP4 0.0.0.0
a=mid:0
a=rtpmap:98 VP9/90000
a=fmtp:98 profile-id=0
`;

    const result = setStartBitrate(offerSdp, 1500, 1, '0'); // should be 1500
    expect(result).toContain(
      'a=fmtp:98 profile-id=0;x-google-start-bitrate=1500',
    );
  });

  it('clamps to max bitrate when factor exceeds 1', () => {
    const offerSdp = `v=0
o=- 123 2 IN IP4 127.0.0.1
s=-
t=0 0
m=video 9 UDP/TLS/RTP/SAVPF 98
c=IN IP4 0.0.0.0
a=mid:0
a=rtpmap:98 VP9/90000
a=fmtp:98 profile-id=0
`;

    const result = setStartBitrate(offerSdp, 1500, 1.5, '0'); // 2250 -> clamped to 1500
    expect(result).toContain(
      'a=fmtp:98 profile-id=0;x-google-start-bitrate=1500',
    );
  });

  it('creates fmtp line when none exists for target codec', () => {
    const offerSdp = `v=0
o=- 123 2 IN IP4 127.0.0.1
s=-
t=0 0
m=video 9 UDP/TLS/RTP/SAVPF 98
c=IN IP4 0.0.0.0
a=mid:0
a=rtpmap:98 VP9/90000
`;

    const result = setStartBitrate(offerSdp, 1500, 0.5, '0'); // 750kbps
    expect(result).toContain('a=fmtp:98 x-google-start-bitrate=750');
  });

  it('creates fmtp lines for multiple codecs without existing fmtp', () => {
    const offerSdp = `v=0
o=- 123 2 IN IP4 127.0.0.1
s=-
t=0 0
m=video 9 UDP/TLS/RTP/SAVPF 98 103
c=IN IP4 0.0.0.0
a=mid:0
a=rtpmap:98 VP9/90000
a=rtpmap:103 H264/90000
`;

    const result = setStartBitrate(offerSdp, 1500, 0.5, '0'); // 750kbps
    expect(result).toContain('a=fmtp:98 x-google-start-bitrate=750');
    expect(result).toContain('a=fmtp:103 x-google-start-bitrate=750');
  });

  it('never exceeds maxBitrateKbps even when it is below 300', () => {
    const offerSdp = `v=0
o=- 123 2 IN IP4 127.0.0.1
s=-
t=0 0
m=video 9 UDP/TLS/RTP/SAVPF 98
c=IN IP4 0.0.0.0
a=mid:0
a=rtpmap:98 VP9/90000
a=fmtp:98 profile-id=0
`;

    // maxBitrateKbps (200) is less than minimum (300), should clamp to maxBitrateKbps
    const result = setStartBitrate(offerSdp, 200, 1, '0');
    expect(result).toContain(
      'a=fmtp:98 profile-id=0;x-google-start-bitrate=200',
    );
  });
});
