import { BadRequestException, NotFoundException } from '@nestjs/common';
import { MarcacionesService } from './marcaciones.service';

describe('MarcacionesService.ajustarLimpia', () => {
  function createService() {
    const tx = {
      rrhh_marcaciones_limpias: {
        update: jest.fn(),
      },
      rrhh_marcaciones_ajustes_manuales: {
        createMany: jest.fn().mockResolvedValue({ count: 1 }),
      },
    };

    const prisma = {
      rrhh_marcaciones_limpias: {
        findFirst: jest.fn(),
      },
      rrhh_turnos: {
        findFirst: jest.fn(),
      },
      $transaction: jest.fn(async (cb: any) => cb(tx)),
    };

    const parser = {} as any;
    const dedup = {} as any;
    const relojClient = {} as any;
    const hikvisionClient = {} as any;
    const service = new MarcacionesService(
      prisma as any,
      parser,
      dedup,
      relojClient,
      hikvisionClient,
    );
    return { service, prisma, tx };
  }

  it('ajusta hora/turno, marca procesado_novedades=false y deja auditoría', async () => {
    const { service, prisma, tx } = createService();
    prisma.rrhh_marcaciones_limpias.findFirst.mockResolvedValue({
      id: 'limpia-1',
      empresa_id: 'emp-1',
      turno_id: 'turno-1',
      hora_entrada: new Date('1970-01-01T08:00:00Z'),
      hora_salida: new Date('1970-01-01T17:00:00Z'),
    });
    prisma.rrhh_turnos.findFirst.mockResolvedValue({ id: 'turno-2' });
    tx.rrhh_marcaciones_limpias.update.mockResolvedValue({ id: 'limpia-1' });

    const out = await service.ajustarLimpia(
      'limpia-1',
      'emp-1',
      {
        hora_entrada: '08:10',
        turno_id: 'turno-2',
        motivo: 'Corrección manual',
      },
      'user-1',
    );

    expect(tx.rrhh_marcaciones_limpias.update).toHaveBeenCalledWith(
      expect.objectContaining({
        where: { id: 'limpia-1' },
        data: expect.objectContaining({
          procesado_novedades: false,
          turno_id: 'turno-2',
        }),
      }),
    );
    expect(tx.rrhh_marcaciones_ajustes_manuales.createMany).toHaveBeenCalled();
    expect(out.ajustes_creados).toBeGreaterThan(0);
  });

  it('falla cuando no recibe campos a ajustar', async () => {
    const { service } = createService();
    await expect(
      service.ajustarLimpia('limpia-1', 'emp-1', { motivo: 'x' }, 'user-1'),
    ).rejects.toThrow(BadRequestException);
  });

  it('falla cuando la marcación no existe para la empresa', async () => {
    const { service, prisma } = createService();
    prisma.rrhh_marcaciones_limpias.findFirst.mockResolvedValue(null);
    await expect(
      service.ajustarLimpia(
        'limpia-1',
        'emp-1',
        { hora_entrada: '08:00', motivo: 'x' },
        'user-1',
      ),
    ).rejects.toThrow(NotFoundException);
  });

  it('falla cuando el turno no pertenece a la empresa', async () => {
    const { service, prisma } = createService();
    prisma.rrhh_marcaciones_limpias.findFirst.mockResolvedValue({
      id: 'limpia-1',
      empresa_id: 'emp-1',
      turno_id: null,
      hora_entrada: new Date('1970-01-01T08:00:00Z'),
      hora_salida: new Date('1970-01-01T17:00:00Z'),
    });
    prisma.rrhh_turnos.findFirst.mockResolvedValue(null);

    await expect(
      service.ajustarLimpia(
        'limpia-1',
        'emp-1',
        { turno_id: 'turno-x', motivo: 'x' },
        'user-1',
      ),
    ).rejects.toThrow(BadRequestException);
  });
});
