import { signal } from '@angular/core';
import { TestBed } from '@angular/core/testing';
import { of } from 'rxjs';
import { MatDialog } from '@angular/material/dialog';
import { AuthStore } from '../../../core/auth/auth-store';
import { TeamStore } from '../../../core/team/team-store';
import { TransactionsApi } from '../../../core/team/transactions-api';
import { Cashbox } from './cashbox';

describe('Cashbox', () => {
  const team = {
    id: 5,
    name: 'Team A',
    alias: 'team-a',
    balance: 120,
    players: [
      {
        id: 1,
        firstName: 'Alex',
        lastName: 'Muster',
        balance: -12,
        active: true,
        teamRole: { id: 2, name: 'scnd_treasurer' },
        user: { id: 42, email: 'alex@example.com', firstName: 'Alex', lastName: 'Muster' },
      },
      {
        id: 2,
        firstName: 'Bea',
        lastName: 'Test',
        balance: 5,
        active: true,
        teamRole: { id: 1, name: 'player' },
      },
      {
        id: 3,
        firstName: 'Chris',
        lastName: 'Drittel',
        balance: 0,
        active: true,
        teamRole: { id: 1, name: 'player' },
      },
    ],
  };

  const activities = [
    {
      id: 9,
      date: '2026-07-31T10:00:00.000Z',
      amount: 12,
      type: 'fine',
      note: 'Training',
      playerName: 'Bea Test',
      isTeamWalletTransaction: false,
    },
  ];

  async function setup(roleId = 2, confirm = true) {
    const createPlayerTransactions = vi.fn(() => of([]));
    const createTeamWalletTransaction = vi.fn(() => of(activities[0]));
    const reverseTransaction = vi.fn(() => of(activities[0]));
    const loadTeamTransactions = vi.fn(() => of(activities));
    const refreshTeam = vi.fn();
    const dialog = {
      open: vi.fn(() => ({ afterClosed: () => of(confirm) })),
    };

    await TestBed.configureTestingModule({
      imports: [Cashbox],
      providers: [
        {
          provide: AuthStore,
          useValue: {
            currentUser: signal({
              id: 42,
              email: 'alex@example.com',
              firstName: 'Alex',
              lastName: 'Muster',
              role: { id: roleId === 99 ? 1 : 2 },
            }),
          },
        },
        {
          provide: TeamStore,
          useValue: { team: signal(team), loading: signal(false), refreshTeam },
        },
        {
          provide: TransactionsApi,
          useValue: {
            loadTeamTransactions,
            createPlayerTransactions,
            createTeamWalletTransaction,
            reverseTransaction,
          },
        },
        { provide: MatDialog, useValue: dialog },
      ],
    }).compileComponents();

    if (roleId === 1) {
      team.players[0].teamRole.id = 1;
    } else {
      team.players[0].teamRole.id = 2;
    }

    const fixture = TestBed.createComponent(Cashbox);
    fixture.detectChanges();
    return {
      fixture,
      component: fixture.componentInstance,
      createPlayerTransactions,
      reverseTransaction,
      dialog,
      refreshTeam,
    };
  }

  it('shows the activity feed and booking controls to a treasurer', async () => {
    const { fixture } = await setup();

    expect(fixture.nativeElement.textContent).toContain('Bea Test');
    expect(fixture.nativeElement.textContent).toContain('-12,00');
    expect(fixture.nativeElement.querySelector('[data-testid="player-booking"]')).not.toBeNull();
  });

  it('submits cent-preserving split transactions for selected players', async () => {
    const { component, createPlayerTransactions, refreshTeam } = await setup();
    component['playerForm'].setValue({
      playerIds: [1, 2, 3],
      amount: 10,
      type: 11,
      note: 'Training',
      date: '2026-07-31',
      total: true,
    });

    component['submitPlayerBooking']();

    expect(createPlayerTransactions).toHaveBeenCalledWith([
      expect.objectContaining({ playerId: 1, amount: 3.34, type: 11 }),
      expect.objectContaining({ playerId: 2, amount: 3.33, type: 11 }),
      expect.objectContaining({ playerId: 3, amount: 3.33, type: 11 }),
    ]);
    expect(refreshTeam).toHaveBeenCalled();
  });

  it('asks for confirmation before booking a high amount', async () => {
    const { component, createPlayerTransactions, dialog } = await setup(2, false);
    component['playerForm'].setValue({
      playerIds: [1],
      amount: 300,
      type: 11,
      note: '',
      date: '2026-07-31',
      total: false,
    });

    component['submitPlayerBooking']();

    expect(dialog.open).toHaveBeenCalled();
    expect(createPlayerTransactions).not.toHaveBeenCalled();
  });

  it('does not show mutation controls to a regular member', async () => {
    const { fixture } = await setup(1);

    expect(fixture.nativeElement.querySelector('[data-testid="player-booking"]')).toBeNull();
    expect(fixture.nativeElement.querySelector('[data-testid="reverse-booking"]')).toBeNull();
  });
});
