import { Test, TestingModule } from '@nestjs/testing';
import { Server, Socket } from 'socket.io';
import { EventsGateway } from './events.gateway';

describe('EventsGateway', () => {
  let gateway: EventsGateway;
  let mockServer: jest.Mocked<Server>;

  beforeEach(async () => {
    mockServer = {
      emit: jest.fn(),
    } as any;

    const module: TestingModule = await Test.createTestingModule({
      providers: [EventsGateway],
    }).compile();

    gateway = module.get<EventsGateway>(EventsGateway);
    // Mock the server
    (gateway as any).server = mockServer;
  });

  it('should be defined', () => {
    expect(gateway).toBeDefined();
  });

  describe('handleJoin', () => {
    it('should add client to room', () => {
      const mockClient = {
        id: 'testId',
        join: jest.fn(),
        emit: jest.fn(),
      } as jest.Mocked<Socket>;

      const result = gateway.handleJoin({ room: 'testRoom' }, mockClient);

      expect(mockClient.join).toHaveBeenCalledWith('testRoom');
      expect(result).toEqual({ event: 'joined', data: { room: 'testRoom' } });
    });
  });

  describe('handleLeave', () => {
    it('should remove client from room', () => {
      const mockClient = {
        id: 'testId',
        leave: jest.fn(),
        emit: jest.fn(),
      } as jest.Mocked<Socket>;

      const result = gateway.handleLeave({ room: 'testRoom' }, mockClient);

      expect(mockClient.leave).toHaveBeenCalledWith('testRoom');
      expect(result).toEqual({ event: 'left', data: { room: 'testRoom' } });
    });
  });

  describe('emitTaskUpdate', () => {
    it('should emit taskUpdate event', () => {
      const taskData = { type: 'settings', task: 'update' };

      gateway.emitTaskUpdate(taskData);

      expect(mockServer.emit).toHaveBeenCalledWith('taskUpdate', taskData);
    });
  });

  describe('emitFileUpdate', () => {
    it('should emit fileUpdate event', () => {
      const fileData = { file: 'test.mp4' };

      gateway.emitFileUpdate(fileData);

      expect(mockServer.emit).toHaveBeenCalledWith('fileUpdate', fileData);
    });
  });

  describe('emitMaintenanceUpdate', () => {
    it('should emit maintenanceUpdate event', () => {
      const maintenanceData = { type: 'cleanup', dirs: ['/tmp'] };

      gateway.emitMaintenanceUpdate(maintenanceData);

      expect(mockServer.emit).toHaveBeenCalledWith(
        'maintenanceUpdate',
        maintenanceData,
      );
    });
  });

  describe('emitWatcherUpdate', () => {
    it('should emit watcherUpdate event', () => {
      const watcherData = { status: 'running' };

      gateway.emitWatcherUpdate(watcherData);

      expect(mockServer.emit).toHaveBeenCalledWith(
        'watcherUpdate',
        watcherData,
      );
    });
  });
});
