/**
 * 用户服务基类
 * 
 * 功能描述：
 * - 提供统一的异常处理机制
 * - 定义通用的错误处理方法
 * - 统一日志记录格式
 * - 敏感信息脱敏处理
 * 
 * 职责分离：
 * - 异常处理：统一的错误格式化和异常转换
 * - 日志管理：结构化日志记录和敏感信息脱敏
 * - 性能监控：操作成功和失败的统计记录
 * - 搜索优化：搜索异常的特殊处理机制
 * 
 * 最近修改：
 * - 2026-01-15: 代码规范优化 - 为保护方法补充@example示例 (修改者: moyin)
 * - 2026-01-07: 代码规范优化 - 完善注释规范，添加完整的文件头和方法注释
 * - 2026-01-07: 功能新增 - 添加敏感信息脱敏处理和结构化日志记录
 * 
 * @author moyin
 * @version 1.0.2
 * @since 2025-01-07
 * @lastModified 2026-01-15
 */

import { Logger, ConflictException, NotFoundException, BadRequestException } from '@nestjs/common';

export abstract class BaseUsersService {
  protected readonly logger = new Logger(this.constructor.name);

  /**
   * 统一的错误格式化方法
   * 
   * @param error 原始错误对象
   * @returns 格式化后的错误信息字符串
   * 
   * @example
   * ```typescript
   * const errorMsg = this.formatError(new Error('数据库连接失败'));
   * // 返回: "数据库连接失败"
   * ```
   */
  protected formatError(error: unknown): string {
    if (error instanceof Error) {
      return error.message;
    }
    return String(error);
  }

  /**
   * 统一的异常处理方法
   * 
   * @param error 原始错误
   * @param operation 操作名称
   * @param context 上下文信息
   * @throws 处理后的标准异常
   * 
   * @example
   * ```typescript
   * try {
   *   // 业务操作
   * } catch (error) {
   *   this.handleServiceError(error, '创建用户', { username: 'test' });
   * }
   * ```
   */
  protected handleServiceError(error: unknown, operation: string, context?: Record<string, any>): never {
    const errorMessage = this.formatError(error);
    
    // 记录错误日志
    this.logger.error(`${operation}失败`, {
      operation,
      error: errorMessage,
      context: context ? this.sanitizeLogData(context) : undefined,
      timestamp: new Date().toISOString()
    }, error instanceof Error ? error.stack : undefined);

    // 如果是已知的业务异常，直接重新抛出
    if (error instanceof ConflictException || 
        error instanceof NotFoundException || 
        error instanceof BadRequestException) {
      throw error;
    }

    // 系统异常转换为BadRequestException
    throw new BadRequestException(`${operation}失败，请稍后重试`);
  }

  /**
   * 搜索异常的特殊处理（返回空结果而不抛出异常）
   * 
   * @param error 原始错误
   * @param operation 操作名称
   * @param context 上下文信息
   * @returns 空数组
   * 
   * @example
   * ```typescript
   * try {
   *   // 搜索操作
   * } catch (error) {
   *   return this.handleSearchError(error, '搜索用户', { keyword: 'test' });
   * }
   * ```
   */
  protected handleSearchError(error: unknown, operation: string, context?: Record<string, any>): any[] {
    const errorMessage = this.formatError(error);
    
    this.logger.warn(`${operation}失败，返回空结果`, {
      operation,
      error: errorMessage,
      context: context ? this.sanitizeLogData(context) : undefined,
      timestamp: new Date().toISOString()
    });

    return [];
  }

  /**
   * 记录操作成功日志
   * 
   * @param operation 操作名称
   * @param context 上下文信息
   * @param duration 操作耗时
   * 
   * @example
   * ```typescript
   * this.logSuccess('创建用户', { userId: '123', username: 'test' }, 50);
   * ```
   */
  protected logSuccess(operation: string, context?: Record<string, any>, duration?: number): void {
    this.logger.log(`${operation}成功`, {
      operation,
      context: context ? this.sanitizeLogData(context) : undefined,
      duration,
      timestamp: new Date().toISOString()
    });
  }

  /**
   * 记录操作开始日志
   * 
   * @param operation 操作名称
   * @param context 上下文信息
   * 
   * @example
   * ```typescript
   * this.logStart('创建用户', { username: 'test' });
   * ```
   */
  protected logStart(operation: string, context?: Record<string, any>): void {
    this.logger.log(`开始${operation}`, {
      operation,
      context: context ? this.sanitizeLogData(context) : undefined,
      timestamp: new Date().toISOString()
    });
  }

  /**
   * 脱敏处理敏感信息
   * 
   * @param data 原始数据
   * @returns 脱敏后的数据
   * 
   * @example
   * ```typescript
   * const sanitized = this.sanitizeLogData({
   *   email: 'test@example.com',
   *   phone: '13800138000',
   *   password_hash: 'secret'
   * });
   * // 返回: { email: 'te***@example.com', phone: '138****00', password_hash: '[REDACTED]' }
   * ```
   */
  protected sanitizeLogData(data: Record<string, any>): Record<string, any> {
    const sanitized = { ...data };
    
    // 脱敏邮箱
    if (sanitized.email) {
      const email = sanitized.email;
      const [localPart, domain] = email.split('@');
      if (localPart && domain) {
        sanitized.email = `${localPart.substring(0, 2)}***@${domain}`;
      }
    }
    
    // 脱敏手机号
    if (sanitized.phone) {
      const phone = sanitized.phone;
      if (phone.length > 4) {
        sanitized.phone = `${phone.substring(0, 3)}****${phone.substring(phone.length - 2)}`;
      }
    }
    
    // 移除密码哈希
    if (sanitized.password_hash) {
      sanitized.password_hash = '[REDACTED]';
    }
    
    return sanitized;
  }
}