/**
 * Tests for QueueManager logging serialization
 *
 * Verifies that QueueManager uses logError utility for error serialization
 * instead of console.error which outputs [object Object].
 */

import { describe, test, expect, vi, beforeEach } from 'vitest';
import { QueueManager } from '$lib/server/queue/QueueManager';
import * as logger from '$lib/server/utils/logger';
import type { QueueUpdateCallback } from '$lib/server/queue/types';

describe('QueueManager logging', () => {
	let manager: QueueManager;
	let logErrorSpy: any;

	beforeEach(() => {
		manager = new QueueManager();
		logErrorSpy = vi.spyOn(logger, 'logError').mockImplementation(() => {});
	});

	test('should use logError when subscriber throws error', () => {
		const failingCallback: QueueUpdateCallback = () => {
			throw new Error('Subscriber failed');
		};

		manager.subscribe(failingCallback);

		// Enqueue an item (this will notify subscribers)
		manager.enqueue('https://instagram.com/p/test123');

		expect(logErrorSpy).toHaveBeenCalledWith('[QueueManager] Subscriber error', expect.any(Error));
	});

	test('should serialize complex error objects', () => {
		const complexError = {
			code: 'ERR_SUBSCRIBER',
			message: 'Callback failed',
			details: { reason: 'Network timeout' }
		};

		const failingCallback: QueueUpdateCallback = () => {
			throw complexError;
		};

		manager.subscribe(failingCallback);
		manager.enqueue('https://instagram.com/p/test456');

		expect(logErrorSpy).toHaveBeenCalledWith('[QueueManager] Subscriber error', complexError);
	});

	test('should not prevent other subscribers from being notified on error', () => {
		const consoleErrorSpy = vi.spyOn(console, 'error').mockImplementation(() => {});
		const failingCallback: QueueUpdateCallback = () => {
			throw new Error('First subscriber fails');
		};
		const successCallback = vi.fn();

		manager.subscribe(failingCallback);
		manager.subscribe(successCallback);

		manager.enqueue('https://instagram.com/p/test789');

		// Error should be logged via logError
		expect(logErrorSpy).toHaveBeenCalled();

		// Second subscriber should still be called
		expect(successCallback).toHaveBeenCalled();

		// Should not contain [object Object] in console output
		const errorMessages = consoleErrorSpy.mock.calls.map((call) => call.join(' '));

		const hasObjectObject = errorMessages.some((msg) => msg.includes('[object Object]'));

		expect(hasObjectObject).toBe(false);
	});

	test('should handle Error instances with custom properties', () => {
		const customError: any = new Error('Custom error');
		customError.statusCode = 500;
		customError.details = { field: 'url', issue: 'invalid' };

		const failingCallback: QueueUpdateCallback = () => {
			throw customError;
		};

		manager.subscribe(failingCallback);
		manager.enqueue('https://instagram.com/p/custom');

		expect(logErrorSpy).toHaveBeenCalledWith(
			'[QueueManager] Subscriber error',
			expect.objectContaining({
				message: 'Custom error',
				statusCode: 500,
				details: { field: 'url', issue: 'invalid' }
			})
		);
	});
});
