import { jest } from '@jest/globals';

// EN: Extend global types for test utilities
// VI: Mở rộng global types cho test utilities
declare global {
  var testUtils: {
    createMockReq: (overrides?: any) => any;
    createMockRes: () => any;
    createMockNext: () => jest.Mock;
  };
}

// EN: Mock environment variables for tests
// VI: Mock biến môi trường cho tests
process.env.NODE_ENV = 'test';
process.env.DATABASE_URL = 'postgresql://test:test@localhost:5432/test_db';
process.env.REDIS_URL = 'redis://localhost:6379/1';
process.env.PORT = '3001';
process.env.SERVICE_NAME = 'test-service';
process.env.API_VERSION = 'v1';

// EN: Mock external services to avoid real network calls
// VI: Mock các service bên ngoài để tránh gọi mạng thật
jest.mock('@goodgo/logger', () => ({
  logger: {
    info: jest.fn(),
    error: jest.fn(),
    warn: jest.fn(),
    debug: jest.fn(),
  },
}));

// EN: Auth SDK mocking is handled in individual test files
// VI: Auth SDK mocking được xử lý trong từng test file riêng biệt

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

// EN: Mock database client to avoid real DB connections in unit tests
// VI: Mock database client để tránh kết nối DB thật trong unit tests
jest.mock('../config/database.config', () => ({
  connectDatabase: jest.fn(),
  prisma: {
    $queryRaw: jest.fn(),
    $disconnect: jest.fn(),
    $connect: jest.fn(),
    feature: {
      create: jest.fn(),
      findMany: jest.fn(),
      findUnique: jest.fn(),
      update: jest.fn(),
      delete: jest.fn(),
    },
  },
}));

// EN: Set up default mock implementations
// VI: Thiết lập implementations mock mặc định
const { prisma } = require('../config/database.config');

// EN: Mock successful feature creation
// VI: Mock việc tạo feature thành công
prisma.feature.create.mockResolvedValue({
  id: 'test-feature-id',
  name: 'test-feature',
  title: 'Test Feature',
  description: 'Test description',
  config: {},
  enabled: true,
  version: '1.0.0',
  tags: [],
  createdAt: new Date(),
  updatedAt: new Date(),
});

// EN: Mock successful feature queries
// VI: Mock việc query feature thành công
prisma.feature.findMany.mockResolvedValue([]);
prisma.feature.findUnique.mockResolvedValue(null);
prisma.feature.update.mockResolvedValue({
  id: 'test-feature-id',
  name: 'test-feature',
  title: 'Updated Feature',
  description: 'Updated description',
  config: {},
  enabled: true,
  version: '1.0.0',
  tags: [],
  createdAt: new Date(),
  updatedAt: new Date(),
});
prisma.feature.delete.mockResolvedValue({});

// EN: Mock Redis client to avoid real Redis connections
// VI: Mock Redis client để tránh kết nối Redis thật
jest.mock('../config/redis.config', () => ({
  getRedisClient: jest.fn().mockReturnValue({
    call: jest.fn(),
    connect: jest.fn(),
    disconnect: jest.fn(),
  }),
}));

// EN: Mock Prometheus registry to avoid global state issues in tests
// VI: Mock Prometheus registry để tránh vấn đề global state trong tests
jest.mock('prom-client', () => {
  const mockRegistry = {
    registerMetric: jest.fn(),
    getMetricsAsJSON: jest.fn().mockReturnValue({}),
    metrics: jest.fn().mockReturnValue(''),
  };

  return {
    Registry: jest.fn().mockImplementation(() => mockRegistry),
    register: mockRegistry,
    collectDefaultMetrics: jest.fn(),
    Gauge: jest.fn().mockImplementation(() => ({
      set: jest.fn(),
      inc: jest.fn(),
      dec: jest.fn(),
    })),
    Counter: jest.fn().mockImplementation(() => ({
      inc: jest.fn(),
      add: jest.fn(),
    })),
    Histogram: jest.fn().mockImplementation(() => ({
      observe: jest.fn(),
      startTimer: jest.fn().mockReturnValue(jest.fn()),
    })),
  };
});

// EN: Global test utilities
// VI: Utilities test toàn cục
global.testUtils = {
  // EN: Helper to create mock request/response objects
  // VI: Helper để tạo mock request/response objects
  createMockReq: (overrides = {}) => ({
    body: {},
    params: {},
    query: {},
    headers: {},
    ...overrides,
  }),

  createMockRes: () => {
    const res: any = {};
    res.status = jest.fn().mockReturnValue(res);
    res.json = jest.fn().mockReturnValue(res);
    res.send = jest.fn().mockReturnValue(res);
    return res;
  },

  // EN: Helper to create mock next function
  // VI: Helper để tạo mock next function
  createMockNext: () => jest.fn(),
};