// EN: Unit tests for @goodgo/logger — Winston logger factory.
// VI: Unit tests cho @goodgo/logger — factory Winston logger.
import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';

// EN: Mock winston so tests run without actual I/O.
// VI: Mock winston để test chạy không có I/O thực.
vi.mock('winston', async () => {
  const mockLogger = {
    level: 'info',
    error: vi.fn(),
    warn: vi.fn(),
    info: vi.fn(),
    debug: vi.fn(),
  };
  const mockTransportConsole = vi.fn().mockImplementation(() => ({}));
  const mockTransportFile = vi.fn().mockImplementation(() => ({}));
  const createLogger = vi.fn().mockReturnValue(mockLogger);
  const format = {
    combine: vi.fn().mockReturnValue({}),
    timestamp: vi.fn().mockReturnValue({}),
    colorize: vi.fn().mockReturnValue({}),
    printf: vi.fn().mockReturnValue({}),
    json: vi.fn().mockReturnValue({}),
  };
  const transports = {
    Console: mockTransportConsole,
    File: mockTransportFile,
  };
  return {
    default: { createLogger, format, transports },
    createLogger,
    format,
    transports,
  };
});

import winston from 'winston';
import { createLogger, logger } from './index';

// ---------------------------------------------------------------------------
// createLogger
// ---------------------------------------------------------------------------
describe('createLogger', () => {
  beforeEach(() => {
    vi.clearAllMocks();
  });

  it('should call winston.createLogger and return a logger', () => {
    const log = createLogger({ serviceName: 'order-service', level: 'debug' });
    expect(winston.createLogger).toHaveBeenCalled();
    expect(log).toBeDefined();
  });

  it('should add Console transport when enableConsole=true (default)', () => {
    createLogger({ enableConsole: true });
    expect(winston.transports.Console).toHaveBeenCalled();
  });

  it('should NOT add Console transport when enableConsole=false', () => {
    vi.clearAllMocks();
    createLogger({ enableConsole: false });
    expect(winston.transports.Console).not.toHaveBeenCalled();
  });

  it('should add File transports when enableFile=true', () => {
    createLogger({ enableFile: true, logDir: '/tmp/logs' });
    expect(winston.transports.File).toHaveBeenCalled();
  });

  it('should NOT add File transports when enableFile=false (default)', () => {
    vi.clearAllMocks();
    createLogger({ enableFile: false });
    expect(winston.transports.File).not.toHaveBeenCalled();
  });

  it('should pass serviceName as defaultMeta.service', () => {
    createLogger({ serviceName: 'merchant-service' });
    const callArg = (winston.createLogger as ReturnType<typeof vi.fn>).mock.calls.at(-1)?.[0];
    expect(callArg?.defaultMeta?.service).toBe('merchant-service');
  });

  it('should use provided level', () => {
    createLogger({ level: 'error' });
    const callArg = (winston.createLogger as ReturnType<typeof vi.fn>).mock.calls.at(-1)?.[0];
    expect(callArg?.level).toBe('error');
  });

  it('should use defaults when no config provided', () => {
    createLogger();
    expect(winston.createLogger).toHaveBeenCalled();
  });
});

// ---------------------------------------------------------------------------
// default logger singleton
// ---------------------------------------------------------------------------
describe('default logger instance', () => {
  it('should be defined', () => {
    expect(logger).toBeDefined();
  });

  it('should have logging methods', () => {
    expect(typeof logger.info).toBe('function');
    expect(typeof logger.error).toBe('function');
    expect(typeof logger.warn).toBe('function');
    expect(typeof logger.debug).toBe('function');
  });
});
