import {
  buildZoomRegistrantEmail,
  buildZoomUserRegistrantEmail,
  buildZoomPlaceholderRegistrantEmail,
  parseZoomRegistrantRegistrationId,
} from './zoom-registrant-email.util';

describe('buildZoomRegistrantEmail', () => {
  it('appends a +reg<id> tag to a plain address', () => {
    expect(buildZoomRegistrantEmail('madhuri.karedla@divami.com', 1234)).toBe(
      'madhuri.karedla+reg1234@divami.com',
    );
  });

  it('collapses an existing +tag so there is never a double tag', () => {
    expect(buildZoomRegistrantEmail('madhuri.karedla+1@divami.com', 2322)).toBe(
      'madhuri.karedla+reg2322@divami.com',
    );
  });

  it('collapses multiple existing + tags to the base', () => {
    expect(buildZoomRegistrantEmail('john+work+x@gmail.com', 7)).toBe('john+reg7@gmail.com');
  });

  it('produces distinct addresses for distinct registrations sharing one email', () => {
    const a = buildZoomRegistrantEmail('same@divami.com', 10);
    const b = buildZoomRegistrantEmail('same@divami.com', 11);
    expect(a).not.toBe(b);
    expect(a).toBe('same+reg10@divami.com');
    expect(b).toBe('same+reg11@divami.com');
  });

  it('is deterministic — same inputs always re-derive the same address', () => {
    expect(buildZoomRegistrantEmail('a.b@x.com', 99)).toBe(
      buildZoomRegistrantEmail('a.b@x.com', 99),
    );
  });

  it('trims surrounding whitespace before deriving', () => {
    expect(buildZoomRegistrantEmail('  user@x.com  ', 5)).toBe('user+reg5@x.com');
  });

  it('keeps the local part within the 64-char limit while preserving the unique tag', () => {
    const longLocal = 'a'.repeat(80);
    const result = buildZoomRegistrantEmail(`${longLocal}@x.com`, 123456);
    const local = result.slice(0, result.lastIndexOf('@'));
    expect(local.length).toBeLessThanOrEqual(64);
    expect(result.endsWith('+reg123456@x.com')).toBe(true);
  });

  it.each(['', '   ', 'not-an-email', '@nolocal.com', 'nodomain@'])(
    'leaves an unusable address (%p) untouched',
    (input) => {
      expect(buildZoomRegistrantEmail(input, 1)).toBe(input.trim());
    },
  );
});

describe('buildZoomUserRegistrantEmail', () => {
  it('appends a +gen<userId>p<programId> tag to a plain address', () => {
    expect(buildZoomUserRegistrantEmail('madhuri.karedla@divami.com', 42, 1473)).toBe(
      'madhuri.karedla+gen42p1473@divami.com',
    );
  });

  it('collapses an existing +tag so there is never a double tag', () => {
    expect(buildZoomUserRegistrantEmail('madhuri.karedla+1@divami.com', 42, 1473)).toBe(
      'madhuri.karedla+gen42p1473@divami.com',
    );
  });

  it('produces distinct addresses for distinct users sharing one email', () => {
    const a = buildZoomUserRegistrantEmail('same@divami.com', 1, 1473);
    const b = buildZoomUserRegistrantEmail('same@divami.com', 2, 1473);
    expect(a).not.toBe(b);
  });

  it('produces distinct addresses for the same user across different programs', () => {
    const a = buildZoomUserRegistrantEmail('same@divami.com', 1, 1473);
    const b = buildZoomUserRegistrantEmail('same@divami.com', 1, 1602);
    expect(a).not.toBe(b);
  });

  it('leaves an unusable address untouched', () => {
    expect(buildZoomUserRegistrantEmail('not-an-email', 1, 1473)).toBe('not-an-email');
  });
});

describe('buildZoomPlaceholderRegistrantEmail', () => {
  it('appends the same +gen<sequenceNumber>p<programId> tag scheme to the slug@domain base', () => {
    expect(buildZoomPlaceholderRegistrantEmail('staff', 'example.com', 1, 1473)).toBe(
      'staff+gen1p1473@example.com',
    );
  });

  it('produces distinct addresses for distinct sequence numbers in the same batch', () => {
    const a = buildZoomPlaceholderRegistrantEmail('staff', 'example.com', 1, 1473);
    const b = buildZoomPlaceholderRegistrantEmail('staff', 'example.com', 2, 1473);
    expect(a).not.toBe(b);
  });

  it('produces distinct addresses for the same slot across different programs', () => {
    const a = buildZoomPlaceholderRegistrantEmail('staff', 'example.com', 1, 1473);
    const b = buildZoomPlaceholderRegistrantEmail('staff', 'example.com', 1, 1602);
    expect(a).not.toBe(b);
  });
});

describe('parseZoomRegistrantRegistrationId', () => {
  it('extracts the registration id round-tripped through buildZoomRegistrantEmail', () => {
    const derived = buildZoomRegistrantEmail('sahithi.gundam@divami.com', 7600);
    expect(parseZoomRegistrantRegistrationId(derived)).toBe(7600);
  });

  it('extracts the id directly from a tagged address', () => {
    expect(parseZoomRegistrantRegistrationId('sahithi.gundam+reg7600@divami.com')).toBe(7600);
  });

  it.each([
    'plain@x.com',
    'plain+other@x.com',
    'plain+reg@x.com',
    'plain+regabc@x.com',
    '',
    undefined,
    null,
  ])('returns null for an untagged/unparseable address (%p)', (input) => {
    expect(parseZoomRegistrantRegistrationId(input as any)).toBeNull();
  });

  it('only matches the tag at the very end of the local part', () => {
    expect(parseZoomRegistrantRegistrationId('reg123@x.com')).toBeNull();
    expect(parseZoomRegistrantRegistrationId('plain+reg123extra@x.com')).toBeNull();
  });
});
