import {
  INestApplication,
  UnauthorizedException,
  ValidationPipe,
  VersioningType,
} from '@nestjs/common';
import { AuthGuard } from '@nestjs/passport';
import { Test } from '@nestjs/testing';
import * as request from 'supertest';
import validationOptions from '../utils/validation-options';
import { CashboxExportController } from './cashbox-export.controller';
import { CashboxExportService } from './cashbox-export.service';

describe('cashbox export HTTP boundary', () => {
  let app: INestApplication;
  const service = {
    exportForUser: jest.fn(),
  };

  beforeAll(async () => {
    const module = await Test.createTestingModule({
      controllers: [CashboxExportController],
      providers: [{ provide: CashboxExportService, useValue: service }],
    })
      .overrideGuard(AuthGuard('jwt'))
      .useValue({
        canActivate(context) {
          const httpRequest = context.switchToHttp().getRequest();
          if (httpRequest.headers.authorization !== 'Bearer user') {
            throw new UnauthorizedException();
          }
          httpRequest.user = { id: 42, role: { id: 2 } };
          return true;
        },
      })
      .compile();
    app = module.createNestApplication();
    app.setGlobalPrefix('api');
    app.enableVersioning({ type: VersioningType.URI });
    app.useGlobalPipes(new ValidationPipe(validationOptions));
    await app.init();
  });

  afterAll(() => app.close());
  beforeEach(() => jest.clearAllMocks());

  it('requires authentication', async () => {
    await request(app.getHttpServer())
      .get('/api/v1/cashbox-export/5?from=2026-08-01&to=2026-08-31&format=csv')
      .expect(401);
  });

  it('rejects an invalid format', async () => {
    await request(app.getHttpServer())
      .get('/api/v1/cashbox-export/5?from=2026-08-01&to=2026-08-31&format=xls')
      .set('Authorization', 'Bearer user')
      .expect(422);
    expect(service.exportForUser).not.toHaveBeenCalled();
  });

  it('returns a CSV file with correct headers and content', async () => {
    const csvBuffer = Buffer.from('Datum;Typ;Wer;Notiz;Betrag;Periodensaldo', 'utf-8');
    service.exportForUser.mockResolvedValue({
      buffer: csvBuffer,
      contentType: 'text/csv; charset=utf-8',
      filename: 'kassenbuch_team-a_2026-08-01_2026-08-31.csv',
    });

    const response = await request(app.getHttpServer())
      .get('/api/v1/cashbox-export/5?from=2026-08-01&to=2026-08-31&format=csv')
      .set('Authorization', 'Bearer user')
      .expect(200);

    expect(response.headers['content-type']).toContain('text/csv');
    expect(response.headers['content-disposition']).toContain(
      'kassenbuch_team-a_2026-08-01_2026-08-31.csv',
    );
    expect(response.text).toBe(csvBuffer.toString('utf-8'));
    expect(service.exportForUser).toHaveBeenCalledWith(5, 42, '2026-08-01', '2026-08-31', 'csv');
  });

  it('returns a PDF file with correct headers and binary content', async () => {
    const pdfBuffer = Buffer.from('%PDF-1.4 fake content');
    service.exportForUser.mockResolvedValue({
      buffer: pdfBuffer,
      contentType: 'application/pdf',
      filename: 'kassenbuch_team-a_2026-08-01_2026-08-31.pdf',
    });

    const response = await request(app.getHttpServer())
      .get('/api/v1/cashbox-export/5?from=2026-08-01&to=2026-08-31&format=pdf')
      .set('Authorization', 'Bearer user')
      .expect(200);

    expect(response.headers['content-type']).toBe('application/pdf');
    expect(Buffer.from(response.body).equals(pdfBuffer)).toBe(true);
  });
});
