import { TestBed } from '@angular/core/testing';
import { provideHttpClient } from '@angular/common/http';
import { HttpTestingController, provideHttpClientTesting } from '@angular/common/http/testing';
import { provideRouter, Router } from '@angular/router';
import { Subject } from 'rxjs';
import { MatDialog } from '@angular/material/dialog';
import { TeamSelect } from './team-select';
import { environment } from '../../../environments/environment';
import { AuthStore } from '../../core/auth/auth-store';
import { Player } from '../../models/player.model';
import { Team } from '../../models/team.model';
import { MyTeamsStore } from '../../core/team/my-teams-store';
import { CreateTeamDialog } from './create-team-dialog/create-team-dialog';

describe('TeamSelect', () => {
  let httpMock: HttpTestingController;
  let router: Router;
  let authStore: AuthStore;
  let myTeamsStore: MyTeamsStore;
  let dialogClosed: Subject<Team | undefined>;
  let dialog: { open: ReturnType<typeof vi.fn> };

  beforeEach(async () => {
    localStorage.clear();
    dialogClosed = new Subject<Team | undefined>();
    dialog = { open: vi.fn(() => ({ afterClosed: () => dialogClosed.asObservable() })) };
    await TestBed.configureTestingModule({
      imports: [TeamSelect],
      providers: [
        provideHttpClient(),
        provideHttpClientTesting(),
        provideRouter([]),
        { provide: MatDialog, useValue: dialog },
      ],
    }).compileComponents();

    httpMock = TestBed.inject(HttpTestingController);
    router = TestBed.inject(Router);
    authStore = TestBed.inject(AuthStore);
    myTeamsStore = TestBed.inject(MyTeamsStore);
    authStore.setSession('token', { id: 42, email: 'a@b.de', firstName: 'A', lastName: 'B' });
  });

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

  it('renders one entry per team when the user has several', async () => {
    const players: Player[] = [
      {
        id: 1,
        firstName: 'A',
        lastName: 'B',
        balance: 0,
        active: true,
        team: { id: 5, name: 'Team A', alias: 'a', balance: 0 },
      },
      {
        id: 2,
        firstName: 'A',
        lastName: 'B',
        balance: 0,
        active: true,
        team: { id: 6, name: 'Team B', alias: 'b', balance: 0 },
      },
    ];

    const fixture = TestBed.createComponent(TeamSelect);
    fixture.detectChanges();

    httpMock.expectOne(`${environment.apiUrl}users/42/teams`).flush(players);
    await fixture.whenStable();
    fixture.detectChanges();

    const items = fixture.nativeElement.querySelectorAll('a[mat-list-item]');
    expect(items.length).toBe(2);
  });

  it('redirects automatically when the user has exactly one team', async () => {
    const players: Player[] = [
      {
        id: 1,
        firstName: 'A',
        lastName: 'B',
        balance: 0,
        active: true,
        team: { id: 5, name: 'Team A', alias: 'a', balance: 0 },
      },
    ];
    const navigateSpy = vi.spyOn(router, 'navigate');

    const fixture = TestBed.createComponent(TeamSelect);
    fixture.detectChanges();

    httpMock.expectOne(`${environment.apiUrl}users/42/teams`).flush(players);
    await fixture.whenStable();

    expect(navigateSpy).toHaveBeenCalledWith(['/team', 5, 'overview'], { replaceUrl: true });
  });

  it('shows an empty state when the user has no teams', async () => {
    const fixture = TestBed.createComponent(TeamSelect);
    fixture.detectChanges();

    httpMock.expectOne(`${environment.apiUrl}users/42/teams`).flush([]);
    await fixture.whenStable();
    fixture.detectChanges();

    expect(fixture.nativeElement.textContent).toContain('Du bist noch keinem Team zugeordnet.');
  });

  it('opens the create-team dialog and navigates into the newly created team on success', async () => {
    const navigateSpy = vi.spyOn(router, 'navigate');
    const refreshSpy = vi.spyOn(myTeamsStore, 'refresh');

    const fixture = TestBed.createComponent(TeamSelect);
    fixture.detectChanges();
    httpMock.expectOne(`${environment.apiUrl}users/42/teams`).flush([]);
    await fixture.whenStable();
    fixture.detectChanges();

    fixture.componentInstance['createTeam']();
    expect(dialog.open).toHaveBeenCalledWith(CreateTeamDialog);

    const created: Team = { id: 9, name: '1. Herren', alias: 'a', balance: 0 };
    dialogClosed.next(created);

    expect(refreshSpy).toHaveBeenCalledWith(42);
    expect(navigateSpy).toHaveBeenCalledWith(['/team', 9, 'overview']);

    httpMock.expectOne(`${environment.apiUrl}users/42/teams`).flush([]);
  });

  it('does not navigate when the create-team dialog is dismissed without a team', async () => {
    const navigateSpy = vi.spyOn(router, 'navigate');

    const fixture = TestBed.createComponent(TeamSelect);
    fixture.detectChanges();
    httpMock.expectOne(`${environment.apiUrl}users/42/teams`).flush([]);
    await fixture.whenStable();
    fixture.detectChanges();

    fixture.componentInstance['createTeam']();
    dialogClosed.next(undefined);

    expect(navigateSpy).not.toHaveBeenCalled();
  });
});
