import { ForbiddenException, NotFoundException } from '@nestjs/common';
import { TeamRolesEnum } from '../team-roles/team-roles.enum';
import { CashboxExportService } from './cashbox-export.service';

describe('CashboxExportService', () => {
  const teamRepository = { findOne: jest.fn() };
  const access = { assertAtLeast: jest.fn() };
  let service: CashboxExportService;
  let callOrder: string[];

  const team = {
    id: 5,
    name: 'Team A',
    alias: 'team-a',
    transactions: [
      { date: '2026-08-05T00:00:00.000Z', amount: 10, note: 'Sponsoring', type: { name: 'credit' } },
    ],
    players: [],
  };

  beforeEach(() => {
    jest.clearAllMocks();
    callOrder = [];

    access.assertAtLeast.mockImplementation(async () => {
      callOrder.push('assertAtLeast');
    });

    teamRepository.findOne.mockImplementation(async () => {
      callOrder.push('findOne');
      return team;
    });

    service = new CashboxExportService(teamRepository as any, access as any);
  });

  it('checks permission before loading data', async () => {
    await service.exportForUser(5, 42, '2026-08-01', '2026-08-31', 'csv');

    expect(access.assertAtLeast).toHaveBeenCalledWith(
      42,
      5,
      'transaction_create_min_role',
      TeamRolesEnum.scnd_treasurer,
    );
  });

  it('calls assertAtLeast before findOne to enforce permission check ordering', async () => {
    await service.exportForUser(5, 42, '2026-08-01', '2026-08-31', 'csv');

    expect(callOrder).toEqual(['assertAtLeast', 'findOne']);
  });

  it('skips team lookup when permission check rejects', async () => {
    access.assertAtLeast.mockRejectedValueOnce(new ForbiddenException('Insufficient permissions'));

    await expect(
      service.exportForUser(5, 42, '2026-08-01', '2026-08-31', 'csv'),
    ).rejects.toBeInstanceOf(ForbiddenException);

    expect(teamRepository.findOne).not.toHaveBeenCalled();
  });

  it('throws NotFoundException for an unknown team', async () => {
    teamRepository.findOne.mockResolvedValueOnce(null);

    await expect(
      service.exportForUser(999, 42, '2026-08-01', '2026-08-31', 'csv'),
    ).rejects.toBeInstanceOf(NotFoundException);
  });

  it('builds a CSV buffer with the correct content type and filename', async () => {
    const result = await service.exportForUser(5, 42, '2026-08-01', '2026-08-31', 'csv');

    expect(result.contentType).toBe('text/csv; charset=utf-8');
    expect(result.filename).toBe('kassenbuch_team-a_2026-08-01_2026-08-31.csv');
    expect(result.buffer.toString('utf-8')).toContain('Sponsoring');
  });

  it('builds a PDF buffer with the correct content type and filename', async () => {
    const result = await service.exportForUser(5, 42, '2026-08-01', '2026-08-31', 'pdf');

    expect(result.contentType).toBe('application/pdf');
    expect(result.filename).toBe('kassenbuch_team-a_2026-08-01_2026-08-31.pdf');
    expect(result.buffer.subarray(0, 5).toString('utf-8')).toBe('%PDF-');
  });
});
