/**
 * 用户服务基类单元测试
 * 
 * 功能描述：
 * - 测试BaseUsersService抽象基类的所有方法
 * - 验证统一异常处理机制的正确性
 * - 测试日志记录系统的功能
 * - 确保错误格式化和数据脱敏的正确性
 * 
 * 测试覆盖：
 * - 异常处理方法：handleServiceError, handleSearchError
 * - 日志记录方法：logStart, logSuccess, formatError
 * - 数据脱敏方法：sanitizeLogData
 * - 错误格式化：formatError
 * 
 * 测试策略：
 * - 创建具体实现类来测试抽象基类
 * - 模拟各种异常情况验证处理逻辑
 * - 验证日志记录的格式和内容
 * - 测试数据脱敏的安全性
 * 
 * @author moyin
 * @version 1.0.0
 * @since 2025-01-07
 */

import { Test, TestingModule } from '@nestjs/testing';
import { Logger, ConflictException, NotFoundException, BadRequestException } from '@nestjs/common';
import { BaseUsersService } from './base_users.service';

/**
 * 测试用的具体实现类
 * 
 * 由于BaseUsersService是抽象类，需要创建具体实现来进行测试
 * 这个类继承了所有基类的方法，用于测试基类功能
 */
class TestUsersService extends BaseUsersService {
  constructor() {
    super();
  }

  // 公开受保护的方法以便测试
  public testFormatError(error: unknown): string {
    return this.formatError(error);
  }

  public testHandleServiceError(error: unknown, operation: string, context?: Record<string, any>): never {
    return this.handleServiceError(error, operation, context);
  }

  public testHandleSearchError(error: unknown, operation: string, context?: Record<string, any>): any[] {
    return this.handleSearchError(error, operation, context);
  }

  public testLogSuccess(operation: string, context?: Record<string, any>, duration?: number): void {
    return this.logSuccess(operation, context, duration);
  }

  public testLogStart(operation: string, context?: Record<string, any>): void {
    return this.logStart(operation, context);
  }

  public testSanitizeLogData(data: Record<string, any>): Record<string, any> {
    return this.sanitizeLogData(data);
  }
}

describe('BaseUsersService', () => {
  let service: TestUsersService;
  let loggerSpy: jest.SpyInstance;
  let loggerErrorSpy: jest.SpyInstance;
  let loggerWarnSpy: jest.SpyInstance;

  beforeEach(async () => {
    const module: TestingModule = await Test.createTestingModule({
      providers: [TestUsersService],
    }).compile();

    service = module.get<TestUsersService>(TestUsersService);
    
    // Mock Logger methods
    loggerSpy = jest.spyOn(Logger.prototype, 'log').mockImplementation();
    loggerErrorSpy = jest.spyOn(Logger.prototype, 'error').mockImplementation();
    loggerWarnSpy = jest.spyOn(Logger.prototype, 'warn').mockImplementation();
  });

  afterEach(() => {
    jest.clearAllMocks();
  });

  describe('formatError()', () => {
    it('应该正确格式化Error对象', () => {
      const error = new Error('测试错误信息');
      const result = service.testFormatError(error);
      
      expect(result).toBe('测试错误信息');
    });

    it('应该正确格式化字符串错误', () => {
      const error = '字符串错误信息';
      const result = service.testFormatError(error);
      
      expect(result).toBe('字符串错误信息');
    });

    it('应该正确格式化数字错误', () => {
      const error = 404;
      const result = service.testFormatError(error);
      
      expect(result).toBe('404');
    });

    it('应该正确格式化null和undefined', () => {
      expect(service.testFormatError(null)).toBe('null');
      expect(service.testFormatError(undefined)).toBe('undefined');
    });
  });

  describe('handleServiceError()', () => {
    it('应该直接重新抛出ConflictException', () => {
      const error = new ConflictException('用户名已存在');
      
      expect(() => {
        service.testHandleServiceError(error, '创建用户');
      }).toThrow(ConflictException);
      
      expect(loggerErrorSpy).toHaveBeenCalledWith(
        '创建用户失败',
        expect.objectContaining({
          operation: '创建用户',
          error: '用户名已存在',
          timestamp: expect.any(String)
        }),
        expect.any(String)
      );
    });

    it('应该直接重新抛出NotFoundException', () => {
      const error = new NotFoundException('用户不存在');
      
      expect(() => {
        service.testHandleServiceError(error, '查询用户');
      }).toThrow(NotFoundException);
    });

    it('应该将系统异常转换为BadRequestException', () => {
      const error = new Error('数据库连接失败');
      
      expect(() => {
        service.testHandleServiceError(error, '创建用户');
      }).toThrow(BadRequestException);
      
      expect(() => {
        service.testHandleServiceError(error, '创建用户');
      }).toThrow('创建用户失败，请稍后重试');
    });
  });

  describe('handleSearchError()', () => {
    it('应该返回空数组而不抛出异常', () => {
      const error = new Error('搜索服务不可用');
      
      const result = service.testHandleSearchError(error, '搜索用户', { keyword: 'test' });
      
      expect(result).toEqual([]);
      expect(loggerWarnSpy).toHaveBeenCalledWith(
        '搜索用户失败，返回空结果',
        expect.objectContaining({
          operation: '搜索用户',
          error: '搜索服务不可用',
          context: { keyword: 'test' },
          timestamp: expect.any(String)
        })
      );
    });
  });

  describe('logSuccess()', () => {
    it('应该记录基本的成功日志', () => {
      service.testLogSuccess('创建用户');
      
      expect(loggerSpy).toHaveBeenCalledWith(
        '创建用户成功',
        expect.objectContaining({
          operation: '创建用户',
          timestamp: expect.any(String)
        })
      );
    });

    it('应该记录包含上下文的成功日志', () => {
      const context = { userId: '123', username: 'testuser' };
      
      service.testLogSuccess('创建用户', context);
      
      expect(loggerSpy).toHaveBeenCalledWith(
        '创建用户成功',
        expect.objectContaining({
          operation: '创建用户',
          context: context,
          timestamp: expect.any(String)
        })
      );
    });
  });

  describe('logStart()', () => {
    it('应该记录基本的开始日志', () => {
      service.testLogStart('创建用户');
      
      expect(loggerSpy).toHaveBeenCalledWith(
        '开始创建用户',
        expect.objectContaining({
          operation: '创建用户',
          timestamp: expect.any(String)
        })
      );
    });
  });

  describe('sanitizeLogData()', () => {
    it('应该脱敏邮箱地址', () => {
      const data = { email: 'test@example.com', username: 'testuser' };
      
      const result = service.testSanitizeLogData(data);
      
      expect(result.email).toBe('te***@example.com');
      expect(result.username).toBe('testuser');
    });

    it('应该脱敏手机号', () => {
      const data = { phone: '13800138000', username: 'testuser' };
      
      const result = service.testSanitizeLogData(data);
      
      expect(result.phone).toBe('138****00');
      expect(result.username).toBe('testuser');
    });

    it('应该移除密码哈希', () => {
      const data = { 
        password_hash: 'hashed_password_string', 
        username: 'testuser' 
      };
      
      const result = service.testSanitizeLogData(data);
      
      expect(result.password_hash).toBe('[REDACTED]');
      expect(result.username).toBe('testuser');
    });

    it('应该处理包含所有敏感信息的数据', () => {
      const data = {
        email: 'user@example.com',
        phone: '13800138000',
        password_hash: 'secret_hash',
        username: 'testuser',
        role: 1
      };
      
      const result = service.testSanitizeLogData(data);
      
      expect(result.email).toBe('us***@example.com');
      expect(result.phone).toBe('138****00');
      expect(result.password_hash).toBe('[REDACTED]');
      expect(result.username).toBe('testuser');
      expect(result.role).toBe(1);
    });

    it('应该处理空数据', () => {
      const data = {};
      
      const result = service.testSanitizeLogData(data);
      
      expect(result).toEqual({});
    });
  });
});