import { describe, it, expect, vi } from 'vitest';
import * as fs from 'fs/promises';
import * as path from 'path';
import { FileLogger } from '@d8d/shared-utils';

// 直接测试文件日志器，不依赖外部模块
describe('文件日志功能测试', () => {
  // 模拟 fs 模块
  vi.mock('fs/promises', () => ({
    mkdir: vi.fn().mockResolvedValue(undefined),
    appendFile: vi.fn().mockResolvedValue(undefined)
  }));

  vi.mock('path', () => ({
    join: (...args: string[]) => args.join('/'),
    dirname: (filePath: string) => filePath.split('/').slice(0, -1).join('/')
  }));

  beforeEach(() => {
    vi.clearAllMocks();
    // 设置环境变量
    process.env.LOG_DIR = './test-logs';
  });

  afterEach(() => {
    delete process.env.LOG_DIR;
  });

  it('应该正确创建日志器实例', () => {
    const logger = new FileLogger('test-service');

    expect(logger).toBeDefined();
    expect(logger).toHaveProperty('info');
    expect(logger).toHaveProperty('warn');
    expect(logger).toHaveProperty('error');
    expect(logger).toHaveProperty('debug');
  });

  it('应该正确格式化日志消息', async () => {
    const logger = new FileLogger('test-service');

    // 测试私有方法需要一些技巧，这里我们测试公开方法
    const testMessage = '测试消息';
    const testMetadata = { key: 'value' };

    // 直接调用方法
    await logger.info(testMessage, testMetadata);

    // 验证 fs.appendFile 被调用
    expect(fs.appendFile).toHaveBeenCalled();

    const callArgs = (fs.appendFile as any).mock.calls[0];
    const filePath = callArgs[0];
    const message = callArgs[1];

    expect(filePath).toContain('test-service.log');
    expect(message).toContain('[INFO]');
    expect(message).toContain(testMessage);
    expect(message).toContain(JSON.stringify(testMetadata, null, 2));
  });

  it('应该支持不同的日志级别', async () => {
    const logger = new FileLogger('test-service');

    await logger.info('信息日志');
    await logger.warn('警告日志');
    await logger.error('错误日志');
    await logger.debug('调试日志');

    expect(fs.appendFile).toHaveBeenCalledTimes(4);

    // 验证不同级别的日志格式
    const calls = (fs.appendFile as any).mock.calls;
    expect(calls[0][1]).toContain('[INFO]');
    expect(calls[1][1]).toContain('[WARN]');
    expect(calls[2][1]).toContain('[ERROR]');
    expect(calls[3][1]).toContain('[DEBUG]');
  });

  it('应该正确处理没有元数据的日志', async () => {
    const logger = new FileLogger('test-service');

    await logger.info('简单日志');

    const callArgs = (fs.appendFile as any).mock.calls[0];
    const message = callArgs[1];

    expect(message).toContain('[INFO]');
    expect(message).toContain('简单日志');
    // 不应该包含额外的换行和空对象
    expect(message.split('\n').length).toBe(2); // 消息 + 空行
  });

  it('应该使用自定义日志目录', async () => {
    const customLogDir = '/custom/logs';
    const logger = new FileLogger('test-service', customLogDir);

    await logger.info('测试自定义目录');

    const callArgs = (fs.appendFile as any).mock.calls[0];
    const filePath = callArgs[0];

    expect(filePath).toContain(customLogDir);
  });

  it('应该在写入失败时不抛出错误', async () => {
    const logger = new FileLogger('test-service');

    // 模拟写入失败
    (fs.appendFile as any).mockRejectedValue(new Error('磁盘已满'));

    // 不应该抛出错误
    await expect(logger.info('测试错误处理')).resolves.not.toThrow();
  });
});