import { provideHttpClient } from '@angular/common/http';
import { TestBed } from '@angular/core/testing';
import { HttpTestingController, provideHttpClientTesting } from '@angular/common/http/testing';
import { environment } from '../../../environments/environment';
import { AdminUsersApi } from './admin-users-api';
import { AdminUserProfileRequest } from '../../models/user-directory.model';
import { UsersApi } from './users-api';

describe('UsersApi', () => {
  let service: UsersApi;
  let httpMock: HttpTestingController;

  beforeEach(() => {
    TestBed.configureTestingModule({ providers: [provideHttpClient(), provideHttpClientTesting()] });
    service = TestBed.inject(UsersApi);
    httpMock = TestBed.inject(HttpTestingController);
  });

  afterEach(() => httpMock.verify());

  it('loads the safe user directory with supplied pagination and search filters', () => {
    service.loadDirectory({ page: 2, limit: 10, search: 'Alex Muster' }).subscribe();

    const request = httpMock.expectOne(
      `${environment.apiUrl}users/directory?page=2&limit=10&search=Alex%20Muster`,
    );
    expect(request.request.method).toBe('GET');
    request.flush({ data: [], page: 2, limit: 10, total: 0, hasNextPage: false });
  });
});

describe('AdminUsersApi', () => {
  let service: AdminUsersApi;
  let httpMock: HttpTestingController;

  it('accepts profile requests with omitted or string names only', () => {
    const omitted: AdminUserProfileRequest = {};
    const names: AdminUserProfileRequest = {
      firstName: 'Ada',
      lastName: 'Admin',
    };

    // @ts-expect-error Profile names cannot be explicitly cleared to null.
    const nullName: AdminUserProfileRequest = { firstName: null };

    expect(omitted).toEqual({});
    expect(names).toEqual({ firstName: 'Ada', lastName: 'Admin' });
    expect(nullName).toEqual({ firstName: null });
  });

  beforeEach(() => {
    TestBed.configureTestingModule({ providers: [provideHttpClient(), provideHttpClientTesting()] });
    service = TestBed.inject(AdminUsersApi);
    httpMock = TestBed.inject(HttpTestingController);
  });

  afterEach(() => httpMock.verify());

  it('uses the dedicated admin profile endpoint and payload', () => {
    service.updateProfile(7, { firstName: 'Alex' }).subscribe();
    const request = httpMock.expectOne(`${environment.apiUrl}admin/users/7/profile`);
    expect(request.request.method).toBe('PATCH');
    expect(request.request.body).toEqual({ firstName: 'Alex' });
    request.flush({});
  });

  it('uses the dedicated admin role endpoint and payload', () => {
    service.updateRole(7, { role: 1 }).subscribe();
    const request = httpMock.expectOne(`${environment.apiUrl}admin/users/7/role`);
    expect(request.request.method).toBe('PATCH');
    expect(request.request.body).toEqual({ role: 1 });
    request.flush({});
  });

  it('uses the dedicated admin status endpoint and payload', () => {
    service.updateStatus(7, { status: 2 }).subscribe();
    const request = httpMock.expectOne(`${environment.apiUrl}admin/users/7/status`);
    expect(request.request.method).toBe('PATCH');
    expect(request.request.body).toEqual({ status: 2 });
    request.flush({});
  });

  it('loads players with the admin filters', () => {
    service.loadPlayers({ search: 'Alex', teamId: 5, assignment: 'unassigned', page: 2, limit: 10 }).subscribe();
    const request = httpMock.expectOne(
      `${environment.apiUrl}admin/users/players?search=Alex&teamId=5&assignment=unassigned&page=2&limit=10`,
    );
    expect(request.request.method).toBe('GET');
    request.flush({ data: [], page: 2, limit: 10, total: 0, hasNextPage: false });
  });

  it('assigns a player through the dedicated admin endpoint', () => {
    service.assignPlayer(7, 9).subscribe();
    const request = httpMock.expectOne(`${environment.apiUrl}admin/users/7/players/9`);
    expect(request.request.method).toBe('PUT');
    expect(request.request.body).toBeNull();
    request.flush({});
  });

  it('unlinks a player through the dedicated admin endpoint', () => {
    service.unlinkPlayer(7, 9).subscribe();
    const request = httpMock.expectOne(`${environment.apiUrl}admin/users/7/players/9`);
    expect(request.request.method).toBe('DELETE');
    request.flush({});
  });
});
