import request from 'supertest';
import express from 'express';
import { createRouter } from '../routes';

// EN: Mock external dependencies for E2E tests
// VI: Mock dependencies bên ngoài cho E2E tests
jest.mock('../config/database.config', () => ({
  connectDatabase: jest.fn().mockResolvedValue(undefined),
  prisma: {
    $queryRaw: jest.fn().mockResolvedValue([{ '1': 1 }]),
    $disconnect: jest.fn().mockResolvedValue(undefined),
  },
}));

jest.mock('../config/redis.config', () => ({
  getRedisClient: jest.fn().mockReturnValue({
    call: jest.fn(),
  }),
}));

jest.mock('../config/app.config', () => ({
  appConfig: {
    port: 3001,
    nodeEnv: 'test',
    corsOrigin: '*',
  },
}));

jest.mock('@goodgo/logger', () => ({
  logger: {
    info: jest.fn(),
    error: jest.fn(),
  },
}));

jest.mock('@goodgo/auth-sdk', () => ({
  verifyToken: jest.fn(),
  decodeToken: jest.fn(),
  createToken: jest.fn(),
  extractTokenFromHeader: jest.fn(),
  isTokenExpired: jest.fn(),
}));

jest.mock('@goodgo/tracing', () => ({
  initTracing: jest.fn(),
}));

jest.mock('prom-client', () => ({
  register: {
    contentType: 'text/plain; version=0.0.4; charset=utf-8',
    getMetricsAsJSON: jest.fn().mockReturnValue({}),
    metrics: jest.fn().mockReturnValue('# Test metrics'),
  },
}));

describe('Health Endpoints E2E', () => {
  let app: express.Application;

  beforeAll(() => {
    // EN: Set up test environment
    // VI: Thiết lập môi trường test
    process.env.NODE_ENV = 'test';
    process.env.API_VERSION = 'v1';

    app = express();
    app.use(express.json());
    app.use(createRouter());
  });

  describe('GET /health', () => {
    it('should return healthy status', async () => {
      // EN: Act
      // VI: Thực hiện
      const response = await request(app)
        .get('/health')
        .expect(200);

      // EN: Assert
      // VI: Kiểm tra
      expect(response.body).toMatchObject({
        success: true,
        data: {
          status: 'ok',
        },
      });
      expect(response.body.timestamp).toBeDefined();
      expect(response.body.data.timestamp).toBeDefined();
    });
  });

  describe('GET /health/ready', () => {
    it('should return ready status when database is connected', async () => {
      // EN: Act
      // VI: Thực hiện
      const response = await request(app)
        .get('/health/ready')
        .expect(200);

      // EN: Assert
      // VI: Kiểm tra
      expect(response.body).toMatchObject({
        success: true,
        data: {
          status: 'ready',
        },
      });
      expect(response.body.timestamp).toBeDefined();
    });

    // EN: Note: Database error testing requires more complex mocking
    // VI: Lưu ý: Test lỗi database cần mocking phức tạp hơn
    // EN: This test is skipped in E2E context as the mock setup is complex
    // VI: Test này bị bỏ qua trong context E2E vì setup mock phức tạp
  });

  describe('GET /health/live', () => {
    it('should return live status', async () => {
      // EN: Act
      // VI: Thực hiện
      const response = await request(app)
        .get('/health/live')
        .expect(200);

      // EN: Assert
      // VI: Kiểm tra
      expect(response.body).toMatchObject({
        success: true,
        data: {
          status: 'live',
        },
      });
      expect(response.body.timestamp).toBeDefined();
    });
  });

  describe('GET /metrics', () => {
    it('should return metrics in Prometheus format', async () => {
      // EN: Act
      // VI: Thực hiện
      const response = await request(app)
        .get('/metrics')
        .expect(200);

      // EN: Assert
      // VI: Kiểm tra
      expect(response.text).toBeDefined();
      expect(response.headers['content-type']).toContain('text/plain');
    });
  });
});