import { Component, signal } from '@angular/core';
import { TestBed } from '@angular/core/testing';
import { provideRouter, Router } from '@angular/router';
import { provideHttpClient } from '@angular/common/http';
import { provideHttpClientTesting, HttpTestingController } from '@angular/common/http/testing';
import { MatDialog } from '@angular/material/dialog';
import { Subject } from 'rxjs';
import { AuthStore } from '../../../core/auth/auth-store';
import { HelpAccessService } from '../../../core/help/help-access';
import { MyTeamsStore } from '../../../core/team/my-teams-store';
import { TeamStore } from '../../../core/team/team-store';
import { environment } from '../../../../environments/environment';
import { More } from './more';

@Component({ template: '' })
class LoginStub {}

describe('More', () => {
  it('shows the feature links and logs the user out', async () => {
    const clearSession = vi.fn();
    await TestBed.configureTestingModule({
      imports: [More],
      providers: [
        provideHttpClient(),
        provideHttpClientTesting(),
        { provide: MatDialog, useValue: { open: vi.fn() } },
        provideRouter([{ path: 'auth/login', component: LoginStub }]),
        {
          provide: AuthStore,
          useValue: {
            currentUser: signal({ firstName: 'Alex', lastName: 'Muster', email: 'a@b.de' }),
            clearSession,
          },
        },
        { provide: HelpAccessService, useValue: { canOpenGuide: signal(true) } },
        { provide: TeamStore, useValue: { team: signal(null) } },
      ],
    }).compileComponents();
    const fixture = TestBed.createComponent(More);
    fixture.detectChanges();

    expect(fixture.nativeElement.textContent).toContain('Strafenkatalog');
    expect(fixture.nativeElement.textContent).toContain('Einladen');
    expect(fixture.nativeElement.textContent).toContain('Profil');
    expect(fixture.nativeElement.textContent).toContain('Öffentliche Freigabe');
    expect(fixture.nativeElement.textContent).toContain('Anleitung für Verantwortliche');

    expect(fixture.nativeElement.textContent).toContain('Benutzer');
    expect(fixture.nativeElement.querySelector('a[href="/users"]')).not.toBeNull();

    fixture.componentInstance['logout']();
    await fixture.whenStable();
    expect(clearSession).toHaveBeenCalled();
    expect(TestBed.inject(Router).url).toBe('/auth/login');
  });

  it('hides the guide link from regular players', async () => {
    await TestBed.configureTestingModule({
      imports: [More],
      providers: [
        provideHttpClient(),
        provideHttpClientTesting(),
        { provide: MatDialog, useValue: { open: vi.fn() } },
        provideRouter([]),
        {
          provide: AuthStore,
          useValue: {
            currentUser: signal({ firstName: 'Alex', lastName: 'Muster', email: 'a@b.de' }),
            clearSession: vi.fn(),
          },
        },
        { provide: HelpAccessService, useValue: { canOpenGuide: signal(false) } },
        { provide: TeamStore, useValue: { team: signal(null) } },
      ],
    }).compileComponents();
    const fixture = TestBed.createComponent(More);
    fixture.detectChanges();

    expect(fixture.nativeElement.textContent).not.toContain('Anleitung für Verantwortliche');
  });

  it('shows the permissions link only to a team manager', async () => {
    const managerTeam = {
      id: 5,
      name: 'Team A',
      alias: 'a',
      balance: 0,
      players: [
        {
          id: 1,
          firstName: 'Alex',
          lastName: 'Muster',
          balance: 0,
          active: true,
          teamRole: { id: 3 },
          user: { id: 42 },
        },
      ],
    };
    await TestBed.configureTestingModule({
      imports: [More],
      providers: [
        provideHttpClient(),
        provideHttpClientTesting(),
        { provide: MatDialog, useValue: { open: vi.fn() } },
        provideRouter([]),
        {
          provide: AuthStore,
          useValue: {
            currentUser: signal({
              id: 42,
              firstName: 'Alex',
              lastName: 'Muster',
              email: 'a@b.de',
              role: { id: 2 },
            }),
            clearSession: vi.fn(),
          },
        },
        { provide: HelpAccessService, useValue: { canOpenGuide: signal(false) } },
        { provide: TeamStore, useValue: { team: signal(managerTeam) } },
      ],
    }).compileComponents();
    const fixture = TestBed.createComponent(More);
    fixture.detectChanges();

    expect(fixture.nativeElement.textContent).toContain('Berechtigungen');
  });

  it('opens the create-team dialog and navigates into the newly created team on success', async () => {
    const dialogClosed = new Subject<
      { id: number; name: string; alias: string; balance: number } | undefined
    >();
    const dialog = { open: vi.fn(() => ({ afterClosed: () => dialogClosed.asObservable() })) };
    await TestBed.configureTestingModule({
      imports: [More],
      providers: [
        provideHttpClient(),
        provideHttpClientTesting(),
        provideRouter([]),
        {
          provide: AuthStore,
          useValue: {
            currentUser: signal({ id: 42, firstName: 'Alex', lastName: 'Muster', email: 'a@b.de' }),
            clearSession: vi.fn(),
          },
        },
        { provide: HelpAccessService, useValue: { canOpenGuide: signal(false) } },
        { provide: TeamStore, useValue: { team: signal(null) } },
        { provide: MatDialog, useValue: dialog },
      ],
    }).compileComponents();
    const router = TestBed.inject(Router);
    const navigateSpy = vi.spyOn(router, 'navigate');
    const myTeamsStore = TestBed.inject(MyTeamsStore);
    const refreshSpy = vi.spyOn(myTeamsStore, 'refresh');
    const fixture = TestBed.createComponent(More);
    fixture.detectChanges();

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

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

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

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