import { Test, TestingModule } from '@nestjs/testing';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { EventsGateway } from './events.gateway';

// Mock chokidar
jest.mock('chokidar', () => ({
  watch: jest.fn(),
}));

describe('AppController', () => {
  let controller: AppController;
  let appService: jest.Mocked<AppService>;
  let eventsGateway: jest.Mocked<EventsGateway>;

  beforeEach(async () => {
    const mockAppService = {
      getSettings: jest.fn(),
      setSettings: jest.fn(),
      deleteSetting: jest.fn(),
    };

    const mockEventsGateway = {
      emitTaskUpdate: jest.fn(),
      emitSettingsUpdate: jest.fn(),
      emitMaintenanceUpdate: jest.fn(),
    };

    const module: TestingModule = await Test.createTestingModule({
      controllers: [AppController],
      providers: [
        {
          provide: AppService,
          useValue: mockAppService,
        },
        {
          provide: EventsGateway,
          useValue: mockEventsGateway,
        },
      ],
    }).compile();

    controller = module.get<AppController>(AppController);
    appService = module.get(AppService);
    eventsGateway = module.get(EventsGateway);
  });

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

  describe('getRoot', () => {
    it('should return app info', () => {
      const result = controller.getRoot();
      expect(result).toHaveProperty('status', 'ok');
      expect(result).toHaveProperty('message');
      expect(result).toHaveProperty('datetime');
      expect(result).toHaveProperty('uptime');
    });
  });

  describe('getReady', () => {
    it('should return ready status', () => {
      const result = controller.getReady();
      expect(result).toHaveProperty('status', 'ready');
      expect(result).toHaveProperty('datetime');
    });
  });

  describe('getHealth', () => {
    it('should return healthy status', () => {
      const result = controller.getHealth();
      expect(result).toHaveProperty('status', 'healthy');
      expect(result).toHaveProperty('datetime');
    });
  });

  describe('getSettings', () => {
    it('should return all settings', () => {
      const mockSettings = { key: 'value' };
      appService.getSettings.mockReturnValue(mockSettings);

      const result = controller.getSettings();

      expect(appService.getSettings).toHaveBeenCalledWith(undefined, undefined);
      expect(result).toEqual(mockSettings);
    });

    it('should return specific setting', () => {
      const mockSetting = 'value';
      appService.getSettings.mockReturnValue(mockSetting);

      const result = controller.getSettings('testKey');

      expect(appService.getSettings).toHaveBeenCalledWith('testKey', undefined);
      expect(result).toEqual(mockSetting);
    });
  });

  describe('setSettings', () => {
    it('should set settings', () => {
      const settings = { key: 'value' };
      const mockResult = true;
      appService.setSettings.mockReturnValue(mockResult);

      const result = controller.setSettings(settings);

      expect(appService.setSettings).toHaveBeenCalledWith(settings);
      expect(result).toEqual(mockResult);
    });
  });

  describe('deleteSetting', () => {
    it('should delete setting', () => {
      const mockResult = true;
      appService.deleteSetting.mockReturnValue(mockResult);

      const result = controller.deleteSetting('testKey');

      expect(appService.deleteSetting).toHaveBeenCalledWith('testKey');
      expect(result).toEqual(mockResult);
    });
  });

  // Add more tests for other endpoints as needed
  // For brevity, focusing on settings-related endpoints
});
