import { provideHttpClient } from '@angular/common/http';
import { HttpTestingController, provideHttpClientTesting } from '@angular/common/http/testing';
import { TestBed } from '@angular/core/testing';
import { firstValueFrom } from 'rxjs';
import { AUTH_BFF_BASE_URL } from 'feature-auth';
import { AuditEventsService, type AdminAuditPage } from './audit-events.service';

const BFF_BASE = 'http://bff.test/api';
const AUDIT_URL = `${BFF_BASE}/admin/audit`;

const PAGE: AdminAuditPage = {
  items: [
    {
      id: '11111111-1111-1111-1111-111111111111',
      createdAt: '2026-05-13T10:30:00.000Z',
      eventType: 'auth.sign_in',
      audience: 'workforce',
      actorIdHash: 'hash(jane)',
      traceId: 'trace-abc',
      subject: 'session:sid-1',
      outcome: 'success',
      payload: { amr: ['pwd', 'mfa'] },
    },
  ],
  total: 1,
  limit: 50,
  offset: 0,
};

function setup() {
  TestBed.configureTestingModule({
    providers: [
      provideHttpClient(),
      provideHttpClientTesting(),
      { provide: AUTH_BFF_BASE_URL, useValue: BFF_BASE },
    ],
  });
  return {
    service: TestBed.inject(AuditEventsService),
    http: TestBed.inject(HttpTestingController),
  };
}

describe('AuditEventsService.query', () => {
  it('GETs /admin/audit with the populated filter fields as URL params', async () => {
    const { service, http } = setup();
    const promise = firstValueFrom(
      service.query({
        eventType: 'auth.sign_in',
        audience: 'workforce',
        outcome: 'success',
        limit: 25,
        offset: 50,
      }),
    );
    const req = http.expectOne((r) => r.url === AUDIT_URL);
    expect(req.request.method).toBe('GET');
    expect(req.request.params.get('eventType')).toBe('auth.sign_in');
    expect(req.request.params.get('audience')).toBe('workforce');
    expect(req.request.params.get('outcome')).toBe('success');
    expect(req.request.params.get('limit')).toBe('25');
    expect(req.request.params.get('offset')).toBe('50');
    req.flush(PAGE);
    await expect(promise).resolves.toEqual(PAGE);
  });

  it('omits filter fields that are empty strings (BFF rejects `?foo=` as invalid)', async () => {
    const { service, http } = setup();
    void firstValueFrom(
      service.query({
        eventType: '',
        subjectPrefix: '',
        limit: 50,
      }),
    );
    const req = http.expectOne((r) => r.url === AUDIT_URL);
    expect(req.request.params.has('eventType')).toBe(false);
    expect(req.request.params.has('subjectPrefix')).toBe(false);
    expect(req.request.params.get('limit')).toBe('50');
    req.flush(PAGE);
  });

  it('omits undefined filter fields', async () => {
    const { service, http } = setup();
    void firstValueFrom(service.query({}));
    const req = http.expectOne((r) => r.url === AUDIT_URL);
    expect(req.request.params.keys().length).toBe(0);
    req.flush(PAGE);
  });
});
