/**
 * Logger Integration Tests
 *
 * Tests the core functionality of the simplified @stock-bot/logger package.
 */

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

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

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

  describe('Core Logger Functionality', () => {
    it('should log messages at different levels', () => {
      // Test multiple log levels
      logger.debug('Debug message');
      logger.info('Info message');
      logger.warn('Warning message');
      logger.error('Error message');

      // Get captured logs
      const logs = testLoggerInstance.getCapturedLogs();

      // Verify logs were captured
      expect(logs.length).toBe(4);
      expect(logs[0].level).toBe('debug');
      expect(logs[0].msg).toBe('Debug message');
      expect(logs[1].level).toBe('info');
      expect(logs[1].msg).toBe('Info message');
      expect(logs[2].level).toBe('warn');
      expect(logs[2].msg).toBe('Warning message');
      expect(logs[3].level).toBe('error');
      expect(logs[3].msg).toBe('Error message');
    });

    it('should log objects as structured logs', () => {
      // Log an object
      logger.info('User logged in', { userId: '123', action: 'login' });

      // Get captured logs
      const logs = testLoggerInstance.getCapturedLogs();

      // Verify structured log
      expect(logs.length).toBe(1);
      expect(logs[0].userId).toBe('123');
      expect(logs[0].action).toBe('login');
      expect(logs[0].msg).toBe('User logged in');
    });

    it('should handle error objects in error logs', () => {
      const testError = new Error('Test error message');

      // Log error with error object
      logger.error('Something went wrong', { error: testError });

      // Get captured logs
      const logs = testLoggerInstance.getCapturedLogs();

      // Verify error was logged
      expect(logs.length).toBe(1);
      expect(logs[0].level).toBe('error');
      expect(logs[0].msg).toBe('Something went wrong');
    });

    it('should create child loggers with additional context', () => {
      // Create a child logger with additional context
      const childLogger = logger.child({
        transactionId: 'tx-789',
        operation: 'payment',
      });

      // Log with child logger
      childLogger.info('Child logger test');

      // Get captured logs
      const logs = testLoggerInstance.getCapturedLogs();

      // Verify child logger logged something
      expect(logs.length).toBe(1);
      expect(logs[0].msg).toBe('Child logger test');
    });
  });

  describe('Factory Functions', () => {
    it('should export factory functions', () => {
      // Verify that the factory functions are exported and callable
      expect(typeof getLogger).toBe('function');
    });

    it('should create different logger instances', () => {
      const logger1Instance = loggerTestHelpers.createTestLogger('service-1');
      const logger2Instance = loggerTestHelpers.createTestLogger('service-2');

      logger1Instance.logger.info('Message from service 1');
      logger2Instance.logger.info('Message from service 2');

      const logs1 = logger1Instance.getCapturedLogs();
      expect(logs1.length).toBe(1);
      expect(logs1[0].service).toBe('service-1');

      const logs2 = logger2Instance.getCapturedLogs();
      expect(logs2.length).toBe(1);
      expect(logs2[0].service).toBe('service-2');
    });
  });

  describe('Error Handling', () => {
    it('should normalize Error objects', () => {
      const error = new Error('Test error');
      error.stack = 'Error stack trace';

      logger.error('Error occurred', error);

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

    it('should handle error-like objects', () => {
      const errorLike = {
        name: 'CustomError',
        message: 'Custom error message',
        code: 'ERR_CUSTOM',
      };

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

      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 primitive error values', () => {
      logger.error('String error occurred', { error: 'Simple string error' });

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

  describe('Metadata Handling', () => {
    it('should include metadata in logs', () => {
      const metadata = {
        requestId: 'req-123',
        userId: 'user-456',
        operation: 'data-fetch',
      };

      logger.info('Operation completed', metadata);

      const logs = testLoggerInstance.getCapturedLogs();
      expect(logs.length).toBe(1);
      expect(logs[0].requestId).toBe('req-123');
      expect(logs[0].userId).toBe('user-456');
      expect(logs[0].operation).toBe('data-fetch');
    });

    it('should handle object messages', () => {
      const objectMessage = {
        event: 'user_action',
        action: 'login',
        timestamp: Date.now(),
      };

      logger.info(objectMessage);

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