import { GUARDS_METADATA, PATH_METADATA } from '@nestjs/common/constants';
import { validate } from 'class-validator';
import { plainToInstance } from 'class-transformer';
import { RoleEnum } from '../../roles/roles.enum';
import { RolesGuard } from '../../roles/roles.guard';
import { AdminLogQueryDto } from './dto/admin-log-query.dto';
import { LogsController } from './logs.controller';

describe('LogsController', () => {
  const service = { findLogs: jest.fn() };
  const controller = new LogsController(service as any);

  beforeEach(() => jest.clearAllMocks());

  it('uses a separate versioned admin/logs controller guarded by the global admin role', () => {
    expect(Reflect.getMetadata(PATH_METADATA, LogsController)).toBe('admin/logs');
    expect(Reflect.getMetadata('roles', LogsController)).toEqual([RoleEnum.admin]);
    expect(Reflect.getMetadata(GUARDS_METADATA, LogsController)).toContain(RolesGuard);
  });

  it('passes the query straight through to the service', async () => {
    const query = { page: 2, limit: 50, level: 'ERROR' as const };

    await controller.findLogs(query as any);

    expect(service.findLogs).toHaveBeenCalledWith(query);
  });
});

describe('AdminLogQueryDto', () => {
  it('defaults page and limit when omitted', async () => {
    const dto = plainToInstance(AdminLogQueryDto, {});

    expect(await validate(dto)).toEqual([]);
    expect(dto).toMatchObject({ page: 1, limit: 50 });
  });

  it('accepts valid level, event, and date-range filters', async () => {
    const dto = plainToInstance(AdminLogQueryDto, {
      level: 'ERROR',
      event: 'cashbox_export_subscription_run_fail',
      from: '2026-01-01',
      to: '2026-01-31',
      search: 'teamId=5',
      page: '2',
      limit: '100',
    });

    expect(await validate(dto)).toEqual([]);
    expect(dto).toMatchObject({ page: 2, limit: 100 });
  });

  it('rejects an unknown level or event value', async () => {
    const level = plainToInstance(AdminLogQueryDto, { level: 'NOPE' });
    const event = plainToInstance(AdminLogQueryDto, { event: 'not_a_real_event' });

    expect(await validate(level)).not.toEqual([]);
    expect(await validate(event)).not.toEqual([]);
  });

  it('rejects a limit above the maximum', async () => {
    const dto = plainToInstance(AdminLogQueryDto, { limit: 500 });

    expect(await validate(dto)).not.toEqual([]);
  });
});
