import { provideHttpClient } from '@angular/common/http';
import { TestBed } from '@angular/core/testing';
import { provideRouter } from '@angular/router';
import { firstValueFrom } from 'rxjs';
import { AuthService } from '../auth/auth.service';
import { TokenStorageService } from '../auth/token-storage.service';
import { MenuService } from './menu.service';

describe('MenuService dependency and authorization', () => {
  let menuService: MenuService;
  let tokenStorage: TokenStorageService;

  beforeEach(() => {
    localStorage.clear();
    sessionStorage.clear();
    TestBed.configureTestingModule({
      providers: [provideHttpClient(), provideRouter([])],
    });
    menuService = TestBed.inject(MenuService);
    tokenStorage = TestBed.inject(TokenStorageService);
  });

  afterEach(() => {
    localStorage.clear();
    sessionStorage.clear();
  });

  it('constructs MenuService and AuthService without a circular dependency', () => {
    expect(menuService).toBeTruthy();
    expect(TestBed.inject(AuthService)).toBeTruthy();
  });

  it('hides the Users menu when the stored user is not a super administrator', async () => {
    tokenStorage.saveAuth(
      { accessToken: 'token', user: { id: '1', email: 'user@example.com', roles: ['admin'] } },
      false,
    );

    const context = await firstValueFrom(menuService.loadMenu());

    expect(hasPath(context.items, '/users')).toBe(false);
  });

  it('shows the Users menu when the stored user is a super administrator', async () => {
    tokenStorage.saveAuth(
      {
        accessToken: 'token',
        user: { id: '1', email: 'super@example.com', roles: ['super_admin'] },
      },
      false,
    );

    const context = await firstValueFrom(menuService.loadMenu());

    expect(hasPath(context.items, '/users')).toBe(true);
  });

  it('clears menu state during context cleanup', async () => {
    await firstValueFrom(menuService.loadMenu());

    menuService.clear();

    expect(menuService.menuContext()).toBeNull();
  });
});

function hasPath(items: ReturnType<MenuService['getNavigationMenu']>, path: string): boolean {
  return items.some(
    (item) =>
      item.path === path ||
      (item.children ? hasPath(item.children, path) : false) ||
      (item.children2 ? hasPath(item.children2, path) : false),
  );
}
