/**
 * Zulip账号关联服务基类
 * 
 * 功能描述：
 * - 提供统一的异常处理机制和错误转换逻辑
 * - 定义通用的错误处理方法和日志记录格式
 * - 为所有Zulip账号服务提供基础功能支持
 * - 统一业务异常的处理和转换规则
 * 
 * 职责分离：
 * - 异常处理：统一处理和转换各类异常为标准业务异常
 * - 日志管理：提供标准化的日志记录方法和格式
 * - 错误格式化：统一错误信息的格式化和输出
 * - 基础服务：为子类提供通用的服务方法
 * 
 * 最近修改：
 * - 2026-01-07: 代码规范优化 - 修复文件命名规范，将短横线改为下划线分隔
 * - 2026-01-07: 代码规范优化 - 完善文件头注释和方法三级注释
 * - 2026-01-07: 功能完善 - 增加搜索异常的特殊处理逻辑
 * - 2026-01-07: 架构优化 - 统一异常处理机制和日志记录格式
 * - 2025-01-07: 初始创建 - 创建基础服务类和异常处理框架
 * 
 * @author angjustinl
 * @version 1.1.0
 * @since 2025-01-07
 * @lastModified 2026-01-07
 */

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

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

  /**
   * 统一的错误格式化方法
   * 
   * 业务逻辑：
   * 1. 检查错误对象类型，判断是否为Error实例
   * 2. 如果是Error实例，提取message属性作为错误信息
   * 3. 如果不是Error实例，将错误对象转换为字符串
   * 4. 返回格式化后的错误信息字符串
   * 
   * @param error 原始错误对象，可能是Error实例或其他类型
   * @returns 格式化后的错误信息字符串，用于日志记录和异常抛出
   * @throws 无异常抛出，该方法保证返回字符串
   * 
   * @example
   * // 处理Error实例
   * const error = new Error('数据库连接失败');
   * const message = this.formatError(error); // 返回: '数据库连接失败'
   * 
   * @example
   * // 处理非Error对象
   * const error = { code: 500, message: '服务器错误' };
   * const message = this.formatError(error); // 返回: '[object Object]'
   */
  protected formatError(error: unknown): string {
    if (error instanceof Error) {
      return error.message;
    }
    return String(error);
  }

  /**
   * 统一的异常处理方法
   * 
   * 业务逻辑：
   * 1. 格式化原始错误信息，提取可读的错误描述
   * 2. 记录详细的错误日志，包含操作名称、错误信息和上下文
   * 3. 检查是否为已知的业务异常类型（ConflictException等）
   * 4. 如果是已知业务异常，直接重新抛出保持异常类型
   * 5. 如果是系统异常，转换为BadRequestException统一处理
   * 6. 确保所有异常都有合适的错误信息和状态码
   * 
   * @param error 原始错误对象，可能是各种类型的异常
   * @param operation 操作名称，用于日志记录和错误追踪
   * @param context 上下文信息，包含相关的业务数据和参数
   * @returns 永不返回，该方法总是抛出异常
   * @throws ConflictException 业务冲突异常，如数据重复
   * @throws NotFoundException 资源不存在异常
   * @throws BadRequestException 请求参数错误或系统异常
   * 
   * @example
   * // 处理数据库唯一约束冲突
   * try {
   *   await this.repository.create(data);
   * } catch (error) {
   *   this.handleServiceError(error, '创建用户', { userId: data.id });
   * }
   * 
   * @example
   * // 处理资源查找失败
   * try {
   *   const user = await this.repository.findById(id);
   *   if (!user) throw new NotFoundException('用户不存在');
   * } catch (error) {
   *   this.handleServiceError(error, '查找用户', { id });
   * }
   */
  protected handleServiceError(error: unknown, operation: string, context?: Record<string, any>): never {
    const errorMessage = this.formatError(error);
    
    // 记录错误日志
    this.logger.error(`${operation}失败`, {
      operation,
      error: errorMessage,
      context,
      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}失败，请稍后重试`);
  }

  /**
   * 搜索异常的特殊处理（返回空结果而不抛出异常）
   * 
   * 业务逻辑：
   * 1. 格式化错误信息，提取可读的错误描述
   * 2. 记录警告级别的日志，避免搜索失败影响系统稳定性
   * 3. 返回空数组而不是抛出异常，保证搜索接口的可用性
   * 4. 记录完整的上下文信息，便于问题排查和监控
   * 5. 使用warn级别日志，区别于error级别的严重异常
   * 
   * @param error 原始错误对象，搜索过程中发生的异常
   * @param operation 操作名称，用于日志记录和问题定位
   * @param context 上下文信息，包含搜索条件和相关参数
   * @returns 空数组，确保搜索接口始终返回有效的数组结果
   * 
   * @example
   * // 处理搜索数据库连接失败
   * try {
   *   const users = await this.repository.search(criteria);
   *   return users;
   * } catch (error) {
   *   return this.handleSearchError(error, '搜索用户', criteria);
   * }
   * 
   * @example
   * // 处理复杂查询超时
   * try {
   *   const results = await this.repository.complexQuery(params);
   *   return { data: results, total: results.length };
   * } catch (error) {
   *   const emptyResults = this.handleSearchError(error, '复杂查询', params);
   *   return { data: emptyResults, total: 0 };
   * }
   */
  protected handleSearchError(error: unknown, operation: string, context?: Record<string, any>): any[] {
    const errorMessage = this.formatError(error);
    
    this.logger.warn(`${operation}失败，返回空结果`, {
      operation,
      error: errorMessage,
      context,
      timestamp: new Date().toISOString()
    });

    return [];
  }

  /**
   * 记录操作成功日志
   * 
   * 业务逻辑：
   * 1. 构建标准化的成功日志信息，包含操作名称和结果
   * 2. 记录上下文信息，便于业务流程追踪和性能分析
   * 3. 可选记录操作耗时，用于性能监控和优化
   * 4. 添加时间戳，确保日志的时序性和可追溯性
   * 5. 使用info级别日志，标识正常的业务操作完成
   * 
   * @param operation 操作名称，描述具体的业务操作类型
   * @param context 上下文信息，包含操作相关的业务数据
   * @param duration 操作耗时（毫秒），用于性能监控，可选参数
   * @returns 无返回值，仅记录日志
   * 
   * @example
   * // 记录简单操作成功
   * this.logSuccess('创建用户', { userId: '12345', username: 'test' });
   * 
   * @example
   * // 记录带耗时的操作成功
   * const startTime = Date.now();
   * // ... 执行业务逻辑
   * const duration = Date.now() - startTime;
   * this.logSuccess('复杂查询', { criteria, resultCount: 100 }, duration);
   */
  protected logSuccess(operation: string, context?: Record<string, any>, duration?: number): void {
    this.logger.log(`${operation}成功`, {
      operation,
      context,
      duration,
      timestamp: new Date().toISOString()
    });
  }

  /**
   * 记录操作开始日志
   * 
   * 业务逻辑：
   * 1. 构建标准化的操作开始日志信息，标记业务流程起点
   * 2. 记录上下文信息，包含操作的输入参数和相关数据
   * 3. 添加时间戳，便于与成功/失败日志进行时序关联
   * 4. 使用info级别日志，标识正常的业务操作开始
   * 5. 为后续的性能分析和问题排查提供起始点标记
   * 
   * @param operation 操作名称，描述即将执行的业务操作类型
   * @param context 上下文信息，包含操作的输入参数和相关数据
   * @returns 无返回值，仅记录日志
   * 
   * @example
   * // 记录数据库操作开始
   * this.logStart('创建用户', { 
   *   gameUserId: '12345', 
   *   email: 'user@example.com' 
   * });
   * 
   * @example
   * // 记录复杂业务流程开始
   * this.logStart('用户认证流程', { 
   *   userId: user.id, 
   *   authMethod: 'oauth',
   *   clientIp: request.ip 
   * });
   */
  protected logStart(operation: string, context?: Record<string, any>): void {
    this.logger.log(`开始${operation}`, {
      operation,
      context,
      timestamp: new Date().toISOString()
    });
  }
}