import { Test, TestingModule } from '@nestjs/testing';
import { HealthController } from '../../../src/api/controllers/health.controller';
import { PrismaService } from '../../../src/infrastructure/persistence/prisma/prisma.service';

describe('HealthController', () => {
  let controller: HealthController;
  let mockPrisma: { $queryRaw: jest.Mock };

  beforeEach(async () => {
    mockPrisma = {
      $queryRaw: jest.fn(),
    };

    const module: TestingModule = await Test.createTestingModule({
      controllers: [HealthController],
      providers: [{ provide: PrismaService, useValue: mockPrisma }],
    }).compile();

    controller = module.get<HealthController>(HealthController);
  });

  describe('check', () => {
    it('should return ok status', async () => {
      const result = await controller.check();

      expect(result.status).toBe('ok');
      expect(result.service).toBe('backup-service');
      expect(result.timestamp).toBeDefined();
    });

    it('should return valid timestamp', async () => {
      const result = await controller.check();

      const timestamp = new Date(result.timestamp);
      expect(timestamp.getTime()).not.toBeNaN();
      expect(timestamp.getTime()).toBeLessThanOrEqual(Date.now());
    });
  });

  describe('readiness', () => {
    it('should return ready when database is connected', async () => {
      mockPrisma.$queryRaw.mockResolvedValue([{ 1: 1 }]);

      const result = await controller.readiness();

      expect(result.status).toBe('ready');
      expect(result.database).toBe('connected');
      expect(result.timestamp).toBeDefined();
    });

    it('should return not ready when database is disconnected', async () => {
      mockPrisma.$queryRaw.mockRejectedValue(new Error('Connection refused'));

      const result = await controller.readiness();

      expect(result.status).toBe('not ready');
      expect(result.database).toBe('disconnected');
      expect(result.error).toBe('Connection refused');
    });

    it('should handle timeout errors', async () => {
      mockPrisma.$queryRaw.mockRejectedValue(new Error('Query timeout'));

      const result = await controller.readiness();

      expect(result.status).toBe('not ready');
      expect(result.error).toBe('Query timeout');
    });
  });

  describe('liveness', () => {
    it('should return alive status', async () => {
      const result = await controller.liveness();

      expect(result.status).toBe('alive');
      expect(result.timestamp).toBeDefined();
    });

    it('should always succeed regardless of database state', async () => {
      // Even if database check would fail, liveness should succeed
      mockPrisma.$queryRaw.mockRejectedValue(new Error('DB Error'));

      const result = await controller.liveness();

      expect(result.status).toBe('alive');
    });
  });
});
