import { OidcDiscoveryService } from './oidc-discovery.service';
import type { AppEnvironment } from '../../configuration/src';

describe('OidcDiscoveryService', () => {
  const environment: AppEnvironment = {
    databaseUrl: 'postgresql://u:p@postgres:5432/db',
    redisUrl: 'redis://redis:6379',
    oidcIssuer: 'https://idp.example.test',
    oidcAudience: 'client-1',
    oidcClientId: 'client-1',
    oidcClientSecret: 'secret-1',
    appVersion: 'dev',
    teamCityBuildNumber: 'local',
    sourceRevision: 'local',
  };

  it('fetches the discovery document once and exposes the token endpoint', async () => {
    const fetchMock = jest.fn().mockResolvedValue({
      ok: true,
      json: () =>
        Promise.resolve({
          jwks_uri: 'https://idp.example.test/oidc/jwks',
          token_endpoint: 'https://idp.example.test/oidc/token',
        }),
    });
    (globalThis as { fetch: typeof fetch }).fetch = fetchMock as never;

    const service = new OidcDiscoveryService(environment);
    await service.onModuleInit();

    expect(fetchMock).toHaveBeenCalledWith(
      'https://idp.example.test/.well-known/openid-configuration',
    );
    expect(service.getTokenEndpoint()).toBe(
      'https://idp.example.test/oidc/token',
    );
    expect(service.getIssuer()).toBe('https://idp.example.test');
    expect(service.getAudience()).toBe('client-1');
  });

  it('throws when asked for the token endpoint before discovery has completed', () => {
    const service = new OidcDiscoveryService(environment);
    expect(() => service.getTokenEndpoint()).toThrow(
      'OIDC discovery has not completed yet',
    );
  });
});
