/**
 * Jest Test Setup
 *
 * This file runs before each test file.
 * It sets up the test environment, mocks, and global utilities.
 */

import dotenv from 'dotenv';
import { initTestDatabase, closeTestDatabase } from './helpers/database';

// Load test environment variables
dotenv.config({ path: '.env.test' });

// Set test environment
process.env.NODE_ENV = 'test';
process.env.JWT_SECRET = 'test-jwt-secret-key-for-unit-tests-only';
process.env.JWT_REFRESH_SECRET = 'test-jwt-refresh-secret-key-for-unit-tests-only';
process.env.TOKEN_ENCRYPTION_KEY = 'test-token-encryption-key-32chars!!';
process.env.BCRYPT_ROUNDS = '4'; // Lower rounds for faster tests

// Mock console methods in test environment
const originalConsoleError = console.error;
const originalConsoleWarn = console.warn;
const originalConsoleLog = console.log;

// Global test setup
beforeAll(async () => {
	// Initialize test database connection
	await initTestDatabase();
});

afterAll(async () => {
	// Close test database connection
	await closeTestDatabase();
});

beforeEach(() => {
	// Clear all mocks before each test
	jest.clearAllMocks();

	// Reset console mocks
	console.error = jest.fn();
	console.warn = jest.fn();
	console.log = jest.fn();
});

afterEach(() => {
	// Restore console methods
	console.error = originalConsoleError;
	console.warn = originalConsoleWarn;
	console.log = originalConsoleLog;
});

// Global test utilities
declare global {
	namespace jest {
		interface Matchers<R> {
			toBeValidUUID(): R;
			toBeValidTimestamp(): R;
			toBeWithinRange(min: number, max: number): R;
		}
	}
}

// Custom matchers
expect.extend({
	toBeValidUUID(received: string) {
		const uuidRegex = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
		const pass = uuidRegex.test(received);
		return {
			message: () => `expected ${received} ${pass ? 'not ' : ''}to be a valid UUID`,
			pass,
		};
	},

	toBeValidTimestamp(received: Date | string | number) {
		const date = new Date(received);
		const pass = !isNaN(date.getTime());
		return {
			message: () => `expected ${received} ${pass ? 'not ' : ''}to be a valid timestamp`,
			pass,
		};
	},

	toBeWithinRange(received: number, min: number, max: number) {
		const pass = received >= min && received <= max;
		return {
			message: () => `expected ${received} ${pass ? 'not ' : ''}to be within range ${min} to ${max}`,
			pass,
		};
	},
});

// Export for use in tests
export {};
