import { Test } from '@nestjs/testing';
import { ValidationPipe } from '@nestjs/common';
import type { INestApplication } from '@nestjs/common';
import request from 'supertest';
import { AssemblyMonitoringController } from './assembly-monitoring.controller';
import { AssemblyMonitoringService } from './assembly-monitoring.service';
import { ResponseInterceptor } from 'src/common/interceptors/response.interceptor';
import { GlobalExceptionFilter } from 'src/common/filters/global-exception.filter';
import { Logger, PinoLogger } from 'nestjs-pino';
import type { Server } from 'http';
import { assemblyControllerFixtures } from '@test-fixtures/monitoring/assembly/scenario.fixture';

describe('AssemblyMonitoringController (integration)', () => {
  let app: INestApplication;
  const monitoringService = {
    findRealtimeData: jest.fn(),
    findDailyData: jest.fn(),
    findProcesses: jest.fn(),
    findWaitingProcesses: jest.fn(),
    findUnitList: jest.fn(),
    findUnitDetail: jest.fn(),
  };

  const loggerStub = {
    setContext: jest.fn(),
    info: jest.fn(),
    debug: jest.fn(),
    warn: jest.fn(),
    error: jest.fn(),
  };

  beforeAll(async () => {
    const moduleRef = await Test.createTestingModule({
      controllers: [AssemblyMonitoringController],
      providers: [
        ResponseInterceptor,
        { provide: AssemblyMonitoringService, useValue: monitoringService },
        { provide: PinoLogger, useValue: loggerStub },
        { provide: Logger, useValue: loggerStub },
      ],
    }).compile();

    app = moduleRef.createNestApplication();
    app.useGlobalPipes(new ValidationPipe({ transform: true }));
    app.useGlobalFilters(
      new GlobalExceptionFilter(loggerStub as unknown as Logger),
    );
    app.useGlobalInterceptors(app.get(ResponseInterceptor));
    await app.init();
  });

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

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

  it('wraps successful responses with standard format', async () => {
    monitoringService.findRealtimeData.mockResolvedValue(
      assemblyControllerFixtures.realtimeResponse,
    );

    const server = app.getHttpServer() as Server;
    const response = await request(server)
      .get(assemblyControllerFixtures.realtimePath)
      .expect(assemblyControllerFixtures.okStatusCode);

    expect(response.body.success).toBe(true);
    expect(response.body.data).toEqual(
      assemblyControllerFixtures.realtimeResponse,
    );
    expect(response.body.meta).toEqual(
      expect.objectContaining(assemblyControllerFixtures.realtimeMeta),
    );
  });

  it('returns standard error format on validation errors', async () => {
    const server = app.getHttpServer() as Server;
    const response = await request(server)
      .get(assemblyControllerFixtures.dailyPath)
      .expect(assemblyControllerFixtures.badRequestStatusCode);

    expect(monitoringService.findDailyData).not.toHaveBeenCalled();

    expect(response.body.success).toBe(false);

    expect(response.body.error).toEqual(
      expect.objectContaining(assemblyControllerFixtures.badRequestError),
    );

    expect(String(response.body.error.message)).toContain(
      assemblyControllerFixtures.dailyValidationKey,
    );

    expect(response.body.meta).toEqual(
      expect.objectContaining(assemblyControllerFixtures.dailyMeta),
    );
  });
});
