/**
 * Advanced Logger Tests
 *
 * Tests for advanced logger functionality including complex metadata handling,
 * child loggers, and advanced error scenarios.
 */

import { afterEach, beforeEach, describe, expect, it } from 'bun:test';
import { Logger, shutdownLoggers } from '../src';
import { loggerTestHelpers } from './setup';

describe('Advanced Logger Features', () => {
  let logger: Logger;
  let testLoggerInstance: ReturnType<typeof loggerTestHelpers.createTestLogger>;

  beforeEach(() => {
    testLoggerInstance = loggerTestHelpers.createTestLogger('advanced-features');
    logger = testLoggerInstance.logger;
  });
  afterEach(async () => {
    testLoggerInstance.clearCapturedLogs();
    // Clear any global logger cache
    await shutdownLoggers();
  });

  describe('Complex Metadata Handling', () => {
    it('should handle nested metadata objects', () => {
      const complexMetadata = {
        user: { id: '123', name: 'John Doe' },
        session: { id: 'sess-456', timeout: 3600 },
        request: { method: 'POST', path: '/api/test' },
      };

      logger.info('Complex operation', complexMetadata);

      const logs = testLoggerInstance.getCapturedLogs();
      expect(logs.length).toBe(1);
      expect(logs[0].user).toEqual({ id: '123', name: 'John Doe' });
      expect(logs[0].session).toEqual({ id: 'sess-456', timeout: 3600 });
      expect(logs[0].request).toEqual({ method: 'POST', path: '/api/test' });
    });

    it('should handle arrays in metadata', () => {
      const arrayMetadata = {
        tags: ['user', 'authentication', 'success'],
        ids: [1, 2, 3, 4],
      };

      logger.info('Array metadata test', arrayMetadata);

      const logs = testLoggerInstance.getCapturedLogs();
      expect(logs.length).toBe(1);
      expect(logs[0].tags).toEqual(['user', 'authentication', 'success']);
      expect(logs[0].ids).toEqual([1, 2, 3, 4]);
    });

    it('should handle null and undefined metadata values', () => {
      const nullMetadata = {
        nullValue: null,
        undefinedValue: undefined,
        emptyString: '',
        zeroValue: 0,
      };

      logger.info('Null metadata test', nullMetadata);

      const logs = testLoggerInstance.getCapturedLogs();
      expect(logs.length).toBe(1);
      expect(logs[0].nullValue).toBe(null);
      expect(logs[0].emptyString).toBe('');
      expect(logs[0].zeroValue).toBe(0);
    });
  });

  describe('Child Logger Functionality', () => {
    it('should create child logger with additional context', () => {
      const childLogger = logger.child({
        component: 'auth-service',
        version: '1.2.3',
      });

      childLogger.info('Child logger message');

      const logs = testLoggerInstance.getCapturedLogs();
      expect(logs.length).toBe(1);
      expect(logs[0].component).toBe('auth-service');
      expect(logs[0].version).toBe('1.2.3');
      expect(logs[0].msg).toBe('Child logger message');
    });

    it('should support nested child loggers', () => {
      const childLogger = logger.child({ level1: 'parent' });
      const grandChildLogger = childLogger.child({ level2: 'child' });

      grandChildLogger.warn('Nested child message');

      const logs = testLoggerInstance.getCapturedLogs();
      expect(logs.length).toBe(1);
      expect(logs[0].level1).toBe('parent');
      expect(logs[0].level2).toBe('child');
      expect(logs[0].level).toBe('warn');
    });

    it('should merge child context with log metadata', () => {
      const childLogger = logger.child({ service: 'api' });

      childLogger.info('Request processed', {
        requestId: 'req-789',
        duration: 150,
      });

      const logs = testLoggerInstance.getCapturedLogs();
      expect(logs.length).toBe(1);
      expect(logs[0].service).toBe('api');
      expect(logs[0].requestId).toBe('req-789');
      expect(logs[0].duration).toBe(150);
    });
  });

  describe('Advanced Error Handling', () => {
    it('should handle Error objects with custom properties', () => {
      const customError = new Error('Custom error message');
      (customError as any).code = 'ERR_CUSTOM';
      (customError as any).statusCode = 500;

      logger.error('Custom error occurred', { error: customError });

      const logs = testLoggerInstance.getCapturedLogs();
      expect(logs.length).toBe(1);
      expect(logs[0].level).toBe('error');
      expect(logs[0].msg).toBe('Custom error occurred');
    });

    it('should handle multiple errors in metadata', () => {
      const error1 = new Error('First error');
      const error2 = new Error('Second error');

      logger.error('Multiple errors', {
        primaryError: error1,
        secondaryError: error2,
        context: 'batch processing',
      });

      const logs = testLoggerInstance.getCapturedLogs();
      expect(logs.length).toBe(1);
      expect(logs[0].context).toBe('batch processing');
    });
    it('should handle error objects with circular references', () => {
      const errorWithCircular: any = { name: 'CircularError', message: 'Circular reference error' };
      // Create a simple circular reference
      errorWithCircular.self = errorWithCircular;

      // Should not throw when logging circular references
      expect(() => {
        logger.error('Circular error test', { error: errorWithCircular });
      }).not.toThrow();

      const logs = testLoggerInstance.getCapturedLogs();
      expect(logs.length).toBe(1);
      expect(logs[0].level).toBe('error');

      // Clean up circular reference to prevent memory issues
      delete errorWithCircular.self;
    });
  });
  describe('Performance and Edge Cases', () => {
    it('should handle moderate metadata objects', () => {
      const moderateMetadata: any = {};
      for (let i = 0; i < 10; i++) {
        moderateMetadata[`key${i}`] = `value${i}`;
      }

      logger.debug('Moderate metadata test', moderateMetadata);

      const logs = testLoggerInstance.getCapturedLogs();
      expect(logs.length).toBe(1);
      expect(logs[0].key0).toBe('value0');
      expect(logs[0].key9).toBe('value9');
    });

    it('should handle special characters in messages', () => {
      const specialMessage = 'Special chars: 🚀 ñ ü';

      logger.info(specialMessage);

      const logs = testLoggerInstance.getCapturedLogs();
      expect(logs.length).toBe(1);
      expect(logs[0].msg).toBe(specialMessage);
    });

    it('should handle empty and whitespace-only messages', () => {
      logger.info('');
      logger.info('   ');

      const logs = testLoggerInstance.getCapturedLogs();
      expect(logs.length).toBe(2);
      expect(logs[0].msg).toBe('');
      expect(logs[1].msg).toBe('   ');
    });
  });
});
