import { TestBed } from '@angular/core/testing';
import { provideRouter, Router } from '@angular/router';
import { provideHttpClient } from '@angular/common/http';
import { provideHttpClientTesting } from '@angular/common/http/testing';
import { routes } from './app.routes';
import { AuthStore } from './core/auth/auth-store';

describe('app routing', () => {
  let router: Router;
  let authStore: AuthStore;

  beforeEach(() => {
    localStorage.clear();
    TestBed.configureTestingModule({
      providers: [provideRouter(routes), provideHttpClient(), provideHttpClientTesting()],
    });
    router = TestBed.inject(Router);
    authStore = TestBed.inject(AuthStore);
  });

  it('redirects the root path to login when logged out', async () => {
    await router.navigateByUrl('/');
    expect(router.url).toBe('/auth/login');
  });

  it('redirects a protected team route to login when logged out', async () => {
    await router.navigateByUrl('/team/1/overview');
    expect(router.url).toBe('/auth/login');
  });

  it('redirects the protected users route to login when logged out', async () => {
    await router.navigateByUrl('/users');
    expect(router.url).toBe('/auth/login');
  });

  it('allows an authenticated user to open the users route', async () => {
    authStore.setSession('token', { id: 1, email: 'a@b.de', firstName: 'A', lastName: 'B' });
    await router.navigateByUrl('/users');
    expect(router.url).toBe('/users');
  });

  it('redirects the root path to team-select when logged in', async () => {
    authStore.setSession('token', { id: 1, email: 'a@b.de', firstName: 'A', lastName: 'B' });
    await router.navigateByUrl('/');
    expect(router.url).toBe('/team-select');
  });

  it('redirects the bare team route to its overview child', async () => {
    authStore.setSession('token', { id: 1, email: 'a@b.de', firstName: 'A', lastName: 'B' });
    await router.navigateByUrl('/team/1');
    expect(router.url).toBe('/team/1/overview');
  });

  it('falls back to the not-found route for unknown paths', async () => {
    await router.navigateByUrl('/does-not-exist');
    expect(router.url).toBe('/does-not-exist');
  });

  it('allows public team routes without a session', async () => {
    await router.navigateByUrl('/t/team-a');
    expect(router.url).toBe('/t/team-a');
  });

  it('registers public access management below the protected team shell', () => {
    const teamRoute = routes.find((route) => route.path === 'team/:id');
    expect(teamRoute?.children?.some((route) => route.path === 'more/public-access')).toBe(true);
  });

  it('registers the guide below the protected team shell', () => {
    const teamRoute = routes.find((route) => route.path === 'team/:id');
    expect(teamRoute?.children?.some((route) => route.path === 'more/guide')).toBe(true);
  });

  it('accepts the password reset URL generated by the backend', async () => {
    expect(routes.some((route) => route.path === 'password-change/:hash')).toBe(true);
    await router.navigateByUrl('/password-change/reset-hash');
    expect(router.url).toBe('/password-change/reset-hash');
  });
});
