/**
 * Database Helper for Tests
 *
 * Provides mock database connection management for testing.
 * Avoids SQLite binding issues by using mock implementation.
 */

interface MockSequelize {
	authenticate: jest.Mock;
	query: jest.Mock;
	transaction: jest.Mock;
	close: jest.Mock;
}

let testSequelize: MockSequelize | null = null;

/**
 * Initialize test database connection (mock)
 */
export async function initTestDatabase(): Promise<MockSequelize> {
	if (testSequelize) {
		return testSequelize;
	}

	// Create mock sequelize instance
	testSequelize = {
		authenticate: jest.fn().mockResolvedValue(true),
		query: jest.fn().mockResolvedValue([]),
		transaction: jest.fn().mockImplementation((callback) => {
			const mockTransaction = { commit: jest.fn(), rollback: jest.fn() };
			return callback(mockTransaction);
		}),
		close: jest.fn().mockResolvedValue(true),
	};

	await testSequelize.authenticate();
	return testSequelize;
}

/**
 * Get the test database connection
 */
export function getTestDatabase(): MockSequelize {
	if (!testSequelize) {
		throw new Error('Test database not initialized. Call initTestDatabase() first.');
	}
	return testSequelize;
}

/**
 * Close test database connection
 */
export async function closeTestDatabase(): Promise<void> {
	if (testSequelize) {
		await testSequelize.close();
		testSequelize = null;
	}
}

/**
 * Clear all data from test database
 */
export async function clearTestData(): Promise<void> {
  const db = getTestDatabase();
  
  // Since we're using mock, just clear the mock data
  // In real implementation, you would:
  // const tables = await db.getQueryInterface().showAllTables();
  // for (const table of tables) {
  //   await db.query(`DELETE FROM ${table}`);
  // }
  
  // For mock implementation, we just reset the mocks
  jest.clearAllMocks();
  if (testSequelize) {
    await testSequelize.query('PRAGMA foreign_keys = ON');
  }
}

/**
 * Run migrations for test database
 */
export async function runMigrations(): Promise<void> {
	if (!testSequelize) {
		throw new Error('Test database not initialized');
	}

	// In a real scenario, you would run your actual migrations here
	// For now, this is a placeholder
}

/**
 * Seed test data
 */
export async function seedTestData(): Promise<void> {
	if (!testSequelize) {
		throw new Error('Test database not initialized');
	}

	// In a real scenario, you would seed your test data here
	// For now, this is a placeholder
}

/**
 * Transaction helper for isolated tests
 */
export async function runInTransaction<T>(callback: (transaction: any) => Promise<T>): Promise<T> {
	if (!testSequelize) {
		throw new Error('Test database not initialized');
	}

	const transaction = await testSequelize.transaction();

	try {
		const result = await callback(transaction);
		await transaction.rollback();
		return result;
	} catch (error) {
		await transaction.rollback();
		throw error;
	}
}

/**
 * Raw query helper
 */
export async function query(sql: string, replacements?: Record<string, any>): Promise<any[]> {
	if (!testSequelize) {
		throw new Error('Test database not initialized');
	}

	const [results] = await testSequelize.query(sql, {
		replacements,
		type: 'SELECT',
	});

	return results as any[];
}
