import { signal } from '@angular/core';
import { TestBed } from '@angular/core/testing';
import { MatDialog } from '@angular/material/dialog';
import { MatSnackBar } from '@angular/material/snack-bar';
import { provideRouter } from '@angular/router';
import { of } from 'rxjs';
import { AuthStore } from '../../../../core/auth/auth-store';
import { PublicAccessApi } from '../../../../core/team/public-access-api';
import { TeamStore } from '../../../../core/team/team-store';
import { PublicAccess } from './public-access';

describe('PublicAccess', () => {
  async function setup(roleId = 3, enabled = true) {
    const status = { enabled, token: enabled ? 'a'.repeat(64) : null };
    const getStatus = vi.fn(() => of(status));
    const setEnabled = vi.fn((_teamId: number, next: boolean) =>
      of({ enabled: next, token: 'a'.repeat(64) }),
    );
    const rotate = vi.fn(() => of({ enabled: true, token: 'b'.repeat(64) }));
    const open = vi.fn(() => ({ afterClosed: () => of(true) }));
    const snackOpen = vi.fn();

    await TestBed.configureTestingModule({
      imports: [PublicAccess],
      providers: [
        provideRouter([]),
        {
          provide: AuthStore,
          useValue: {
            currentUser: signal({ id: 4, role: { id: 2 } }),
          },
        },
        {
          provide: TeamStore,
          useValue: {
            team: signal({
              id: 7,
              name: 'Team A',
              alias: 'team-a',
              balance: 0,
              players: [
                {
                  id: 3,
                  firstName: 'Ada',
                  lastName: 'Lovelace',
                  balance: 0,
                  active: true,
                  user: { id: 4 },
                  teamRole: { id: roleId },
                },
              ],
            }),
          },
        },
        { provide: PublicAccessApi, useValue: { getStatus, setEnabled, rotate } },
        { provide: MatDialog, useValue: { open } },
        { provide: MatSnackBar, useValue: { open: snackOpen } },
      ],
    }).compileComponents();

    const fixture = TestBed.createComponent(PublicAccess);
    fixture.detectChanges();
    await fixture.whenStable();
    fixture.detectChanges();
    return { fixture, getStatus, setEnabled, rotate, open, snackOpen };
  }

  it('shows an active link and QR code to every team member', async () => {
    const { fixture } = await setup(1);

    expect(fixture.nativeElement.textContent).toContain('Freigabe ist aktiv');
    expect(fixture.nativeElement.querySelector('[data-testid="public-link"]').value).toContain(
      `/t/${'a'.repeat(64)}`,
    );
    expect(fixture.nativeElement.querySelector('[data-testid="public-qr"]')).not.toBeNull();
    expect(fixture.nativeElement.querySelector('[data-testid="rotate-link"]')).toBeNull();
  });

  it('allows a captain to activate sharing', async () => {
    const { fixture, setEnabled } = await setup(3, false);

    expect(fixture.nativeElement.textContent).toContain('Öffentliche Freigabe bewusst nutzen');

    fixture.componentInstance['toggleAccess']();

    expect(setEnabled).toHaveBeenCalledWith(7, true);
    expect(fixture.componentInstance['status']()?.enabled).toBe(true);
  });

  it('confirms and rotates an active link for managers', async () => {
    const { fixture, open, rotate } = await setup(3);

    fixture.componentInstance['rotateLink']();

    expect(open).toHaveBeenCalled();
    expect(rotate).toHaveBeenCalledWith(7);
    expect(fixture.componentInstance['status']()?.token).toBe('b'.repeat(64));
  });

  it('falls back to copying when native sharing is unavailable', async () => {
    const clipboard = { writeText: vi.fn(() => Promise.resolve()) };
    Object.defineProperty(navigator, 'clipboard', { value: clipboard, configurable: true });
    Object.defineProperty(navigator, 'share', { value: undefined, configurable: true });
    const { fixture } = await setup(1);

    await fixture.componentInstance['shareLink']();

    expect(clipboard.writeText).toHaveBeenCalledWith(
      expect.stringContaining(`/t/${'a'.repeat(64)}`),
    );
  });
});
