import { describe, it, expect } from 'vitest';
import { normalizeNsList, compareNsDelegation } from './route53-dns-delegation';

describe('normalizeNsList', () => {
  it('lowercases and strips trailing dots', () => {
    expect(normalizeNsList(['NS-123.AWSDNS-45.com.', 'ns-999.awsdns-01.org'])).toEqual([
      'ns-123.awsdns-45.com',
      'ns-999.awsdns-01.org',
    ]);
  });

  it('returns [] for null', () => {
    expect(normalizeNsList(null)).toEqual([]);
  });

  it('returns [] for undefined', () => {
    expect(normalizeNsList(undefined)).toEqual([]);
  });

  it('returns [] for a non-array input', () => {
    expect(normalizeNsList('not-an-array')).toEqual([]);
    expect(normalizeNsList(42)).toEqual([]);
    expect(normalizeNsList({})).toEqual([]);
  });

  it('de-duplicates and sorts so ordering differences never register as a mismatch', () => {
    expect(normalizeNsList(['ns-2.awsdns.com.', 'ns-1.awsdns.com', 'ns-1.awsdns.com.'])).toEqual([
      'ns-1.awsdns.com',
      'ns-2.awsdns.com',
    ]);
  });

  it('drops empty strings after trimming', () => {
    expect(normalizeNsList(['  ', 'ns-1.awsdns.com', ''])).toEqual(['ns-1.awsdns.com']);
  });
});

describe('compareNsDelegation', () => {
  it('returns mismatch: false with empty diffs when sets are identical', () => {
    const result = compareNsDelegation(
      ['ns-1.awsdns.com', 'ns-2.awsdns.com'],
      ['NS-1.AWSDNS.com.', 'ns-2.awsdns.com.'],
    );
    expect(result.mismatch).toBe(false);
    expect(result.missingFromLive).toEqual([]);
    expect(result.extraInLive).toEqual([]);
  });

  it('returns mismatch: true with populated missingFromLive when an authoritative NS is absent from the live answer', () => {
    const result = compareNsDelegation(
      ['ns-1.awsdns.com', 'ns-2.awsdns.com'],
      ['ns-1.awsdns.com'],
    );
    expect(result.mismatch).toBe(true);
    expect(result.missingFromLive).toEqual(['ns-2.awsdns.com']);
    expect(result.extraInLive).toEqual([]);
  });

  it('returns mismatch: true with populated extraInLive when the live answer contains an NS Route 53 does not consider authoritative', () => {
    const result = compareNsDelegation(
      ['ns-1.awsdns.com'],
      ['ns-1.awsdns.com', 'ns-rogue.example.com'],
    );
    expect(result.mismatch).toBe(true);
    expect(result.extraInLive).toEqual(['ns-rogue.example.com']);
    expect(result.missingFromLive).toEqual([]);
  });

  it('returns mismatch: true when live has no answer but authoritative is non-empty (delegation problem, not a pass)', () => {
    const result = compareNsDelegation(['ns1.example.com'], []);
    expect(result.mismatch).toBe(true);
  });

  it('returns mismatch: false when authoritative is empty (unjudgeable, must not false-alarm)', () => {
    const result = compareNsDelegation([], ['ns1.example.com']);
    expect(result.mismatch).toBe(false);
  });

  it('is case-insensitive and trailing-dot-insensitive on both sides', () => {
    const result = compareNsDelegation(['NS-1.AWSDNS.COM.'], ['ns-1.awsdns.com']);
    expect(result.mismatch).toBe(false);
  });

  it('handles null/undefined inputs on both sides without throwing', () => {
    expect(compareNsDelegation(null, undefined)).toMatchObject({ mismatch: false });
  });
});
