import { Test } from '@nestjs/testing';
import { ConfigModule } from '@nestjs/config';
import type { INestApplication } from '@nestjs/common';
import { PinoLogger } from 'nestjs-pino';
import { AssemblyMonitoringSpRepository } from './assembly-monitoring.sp.repository';
import { MssqlService } from 'src/infra/mssql/mssql.service';
import { assemblyRepositoryFixtures } from '@test-fixtures/monitoring/assembly/repository.fixture';

jest.setTimeout(30000);

const createStubLogger = (): PinoLogger =>
  ({
    setContext: jest.fn(),
    debug: jest.fn(),
    error: jest.fn(),
    info: jest.fn(),
    warn: jest.fn(),
  }) as unknown as PinoLogger;

const assertProcColumns = (row: Record<string, unknown>) => {
  const hasProcColumn = Object.keys(row).some((key) =>
    assemblyRepositoryFixtures.procColumnPattern.test(key),
  );
  expect(hasProcColumn).toBe(true);
};

describe('AssemblyMonitoringSpRepository (int)', () => {
  let app: INestApplication | null = null;
  let repository: AssemblyMonitoringSpRepository;

  beforeAll(async () => {
    const moduleRef = await Test.createTestingModule({
      imports: [
        ConfigModule.forRoot({
          isGlobal: true,
          envFilePath: '.env',
        }),
      ],
      providers: [
        MssqlService,
        AssemblyMonitoringSpRepository,
        { provide: PinoLogger, useValue: createStubLogger() },
      ],
    }).compile();

    app = moduleRef.createNestApplication();
    await app.init();

    repository = moduleRef.get(AssemblyMonitoringSpRepository);
  });

  afterAll(async () => {
    if (app) {
      await app.close();
    }
  });

  it('executes realtime SP and returns PROC_* columns', async () => {
    const result = await repository.findRealtimeData(
      assemblyRepositoryFixtures.realtimeQuery,
    );

    expect(Array.isArray(result.rows)).toBe(true);
    if (result.rows.length > 0) {
      assertProcColumns(result.rows[0] as unknown as Record<string, unknown>);
    }
    expect(Array.isArray(result.inactiveWorkers)).toBe(true);
  });

  it('executes daily SP and returns PROC_* columns', async () => {
    const rows = await repository.findDailyData(
      assemblyRepositoryFixtures.createDailyQuery(),
    );

    expect(Array.isArray(rows)).toBe(true);
    if (rows.length > 0) {
      assertProcColumns(rows[0] as unknown as Record<string, unknown>);
    }
  });

  it('executes process status SP and returns expected columns', async () => {
    const rows = await repository.findProcesses(
      assemblyRepositoryFixtures.processesQuery,
    );

    expect(Array.isArray(rows)).toBe(true);
    if (rows.length > 0) {
      const row = rows[0] as unknown as Record<string, unknown>;
      expect(row).toHaveProperty(
        assemblyRepositoryFixtures.processRowKeys.procTypeName,
      );
      expect(row).toHaveProperty(
        assemblyRepositoryFixtures.processRowKeys.modelSerialList,
      );
      expect(row).toHaveProperty(
        assemblyRepositoryFixtures.processRowKeys.startDt,
      );
    }
  });
});
