import { Test } from '@nestjs/testing';
import type { INestApplication } from '@nestjs/common';
import { ValidationPipe } from '@nestjs/common';
import request from 'supertest';
import { AppModule } from '../src/app.module';
import { ResponseInterceptor } from '../src/common/interceptors/response.interceptor';
import { GlobalExceptionFilter } from '../src/common/filters/global-exception.filter';
import { Logger } from 'nestjs-pino';
import type { Server } from 'http';
import { monitoringE2eFixtures } from '@test-fixtures/monitoring/e2e.fixture';

describe('Monitoring API (e2e)', () => {
  let app: INestApplication;

  beforeAll(async () => {
    const moduleRef = await Test.createTestingModule({
      imports: [AppModule],
    }).compile();

    app = moduleRef.createNestApplication();
    const appLogger = app.get(Logger);

    app.useLogger(appLogger);
    app.useGlobalPipes(new ValidationPipe({ transform: true }));
    app.useGlobalFilters(new GlobalExceptionFilter(appLogger));
    app.useGlobalInterceptors(app.get(ResponseInterceptor));

    await app.init();
  });

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

  it('GET /api/monitoring/cp/assembly/realtime returns standard success response', async () => {
    const server = app.getHttpServer() as Server;
    const response = await request(server)
      .get(monitoringE2eFixtures.assemblyRealtimePath)
      .expect(monitoringE2eFixtures.okStatusCode);

    const body = response.body as {
      success: boolean;
      data: {
        processes: {
          driveUnitAssembly: unknown[];
          mainAssembly: unknown[];
        };
        inactiveWorkers: unknown[];
      };
      meta: {
        path: string;
        method: string;
        statusCode: number;
      };
    };

    expect(body.success).toBe(true);
    expect(Array.isArray(body.data.processes.driveUnitAssembly)).toBe(true);
    expect(Array.isArray(body.data.processes.mainAssembly)).toBe(true);
    expect(Array.isArray(body.data.inactiveWorkers)).toBe(true);
    expect(body.meta).toEqual(
      expect.objectContaining(monitoringE2eFixtures.assemblyRealtimeMeta),
    );
  });

  it('GET /api/monitoring/cp/inventory returns grouped inventory list', async () => {
    const server = app.getHttpServer() as Server;
    const response = await request(server)
      .get(monitoringE2eFixtures.inventoryListPath)
      .expect(monitoringE2eFixtures.okStatusCode);

    const body = response.body as {
      success: boolean;
      data: {
        cp: unknown[];
        lp: unknown[];
        tp: unknown[];
        pb: unknown[];
        other: unknown[];
      };
      meta: {
        path: string;
        method: string;
        statusCode: number;
      };
    };

    expect(body.success).toBe(true);
    expect(Array.isArray(body.data.cp)).toBe(true);
    expect(Array.isArray(body.data.lp)).toBe(true);
    expect(Array.isArray(body.data.tp)).toBe(true);
    expect(Array.isArray(body.data.pb)).toBe(true);
    expect(Array.isArray(body.data.other)).toBe(true);
    expect(body.meta).toEqual(
      expect.objectContaining(monitoringE2eFixtures.inventoryListMeta),
    );
  });

  it('GET /api/monitoring/cp/inventory returns 400 on validation error', async () => {
    const server = app.getHttpServer() as Server;
    const response = await request(server)
      .get(monitoringE2eFixtures.inventoryMissingToPath)
      .expect(monitoringE2eFixtures.badRequestStatusCode);

    const body = response.body as {
      success: boolean;
      error: {
        code: string;
        message: string;
      };
      meta: {
        path: string;
        method: string;
        statusCode: number;
      };
    };

    expect(body.success).toBe(false);
    expect(body.error).toEqual(
      expect.objectContaining(monitoringE2eFixtures.badRequestError),
    );
    expect(String(body.error.message)).toContain(
      monitoringE2eFixtures.missingToKey,
    );
    expect(body.meta).toEqual(
      expect.objectContaining(monitoringE2eFixtures.inventoryMissingToMeta),
    );
  });
});
