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 { UserScopesService, type UserScope, type UserScopesPayload } from './user-scopes.service';

const BFF_BASE = 'http://bff.test/api';

const SCOPE: UserScope = {
  id: 'scope-1',
  kind: 'etablissement',
  value: '0330800013',
  source: 'seed',
  createdAt: '2026-05-26T10:00:00.000Z',
  expiresAt: null,
};

const PAGE: UserScopesPayload = {
  user: {
    oid: 'target-oid',
    userId: 'user-uuid-1',
    displayName: 'Jane Doe',
    email: 'jane@apf.example',
  },
  scopes: [SCOPE],
};

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

describe('UserScopesService.list', () => {
  it('GETs /admin/users/:oid/scopes and returns the page', async () => {
    const { service, http } = setup();
    const promise = firstValueFrom(service.list('target-oid'));
    const req = http.expectOne(`${BFF_BASE}/admin/users/target-oid/scopes`);
    expect(req.request.method).toBe('GET');
    req.flush(PAGE);
    await expect(promise).resolves.toEqual(PAGE);
  });

  it('URL-encodes the oid', async () => {
    const { service, http } = setup();
    void firstValueFrom(service.list('weird/oid'));
    const req = http.expectOne(`${BFF_BASE}/admin/users/weird%2Foid/scopes`);
    req.flush(PAGE);
  });
});

describe('UserScopesService.grant', () => {
  it('POSTs the input body and returns the created scope', async () => {
    const { service, http } = setup();
    const promise = firstValueFrom(
      service.grant('target-oid', {
        kind: 'etablissement',
        value: '0330800013',
        expiresAt: '2026-12-31T23:59:59.000Z',
      }),
    );
    const req = http.expectOne(`${BFF_BASE}/admin/users/target-oid/scopes`);
    expect(req.request.method).toBe('POST');
    expect(req.request.body).toEqual({
      kind: 'etablissement',
      value: '0330800013',
      expiresAt: '2026-12-31T23:59:59.000Z',
    });
    req.flush(SCOPE);
    await expect(promise).resolves.toEqual(SCOPE);
  });
});

describe('UserScopesService.revoke', () => {
  it('DELETEs the scope by id', async () => {
    const { service, http } = setup();
    const promise = firstValueFrom(service.revoke('target-oid', 'scope-1'));
    const req = http.expectOne(`${BFF_BASE}/admin/users/target-oid/scopes/scope-1`);
    expect(req.request.method).toBe('DELETE');
    req.flush(null);
    await expect(promise).resolves.toBeNull();
  });
});
