/**
 * Zulip账号关联数据访问服务基类
 *
 * 功能描述：
 * - 提供统一的数据访问操作基础功能
 * - 集成高性能日志系统，支持结构化日志记录
 * - 定义通用的数据转换方法和性能监控
 * - 为所有Zulip账号数据访问服务提供基础功能支持
 *
 * 职责分离：
 * - 数据访问：统一处理数据访问相关的基础操作
 * - 日志管理：集成AppLoggerService提供高性能日志记录
 * - 性能监控：提供操作耗时统计和性能指标收集
 * - 数据转换：统一数据格式化和转换逻辑
 * - 基础服务：为子类提供通用的数据访问方法
 *
 * 注意：业务异常处理已转移到 src/core/zulip_core/services/zulip_accounts_business.service.ts
 *
 * 最近修改：
 * - 2026-01-12: 架构优化 - 移除业务异常处理，专注数据访问功能 (修改者: moyin)
 * - 2026-01-12: 代码质量优化 - 添加列表响应构建工具方法，彻底消除所有重复代码 (修改者: moyin)
 * - 2026-01-12: 代码质量优化 - 添加数组映射工具方法，进一步减少重复代码 (修改者: moyin)
 * - 2026-01-12: 代码质量优化 - 添加BigInt转换和DTO转换的抽象方法，减少重复代码 (修改者: moyin)
 * - 2026-01-12: 性能优化 - 集成AppLoggerService，添加性能监控和结构化日志
 * - 2026-01-07: 代码规范优化 - 修复文件命名规范，将短横线改为下划线分隔
 * - 2026-01-07: 代码规范优化 - 完善文件头注释和方法三级注释
 * - 2026-01-07: 功能完善 - 增加搜索异常的特殊处理逻辑
 * - 2026-01-07: 架构优化 - 统一异常处理机制和日志记录格式
 * - 2025-01-07: 初始创建 - 创建基础服务类和异常处理框架
 *
 * @author angjustinl
 * @version 2.0.0
 * @since 2025-01-07
 * @lastModified 2026-01-12
 */

import { Inject } from '@nestjs/common';
import { AppLoggerService, LogContext } from '../../utils/logger/logger.service';

export abstract class BaseZulipAccountsService {
  protected readonly logger: AppLoggerService;
  protected readonly moduleName: string;

  constructor(
    @Inject(AppLoggerService) logger: AppLoggerService,
    moduleName: string = 'ZulipAccountsService'
  ) {
    this.logger = logger;
    this.moduleName = moduleName;
  }

  /**
   * 统一的错误格式化方法
   *
   * 数据访问逻辑：
   * 1. 检查错误对象类型，判断是否为Error实例
   * 2. 如果是Error实例，提取message属性作为错误信息
   * 3. 如果不是Error实例，将错误对象转换为字符串
   * 4. 返回格式化后的错误信息字符串
   *
   * @param error 原始错误对象，可能是Error实例或其他类型
   * @returns 格式化后的错误信息字符串，用于日志记录
   * @throws 无异常抛出，该方法保证返回字符串
   */
  protected formatError(error: unknown): string {
    if (error instanceof Error) {
      return error.message;
    }
    return String(error);
  }

  /**
   * 统一的数据访问错误处理方法
   *
   * 数据访问逻辑：
   * 1. 格式化原始错误信息，提取可读的错误描述
   * 2. 使用AppLoggerService记录结构化错误日志
   * 3. 重新抛出原始错误，不进行业务异常转换
   * 4. 确保错误信息被正确记录用于调试
   *
   * @param error 原始错误对象，数据访问过程中发生的异常
   * @param operation 操作名称，用于日志记录和错误追踪
   * @param context 上下文信息，包含相关的数据访问参数
   * @returns 永不返回，该方法总是抛出异常
   * @throws 重新抛出原始错误
   */
  protected handleDataAccessError(error: unknown, operation: string, context?: Record<string, any>): never {
    const errorMessage = this.formatError(error);

    // 使用AppLoggerService记录结构化错误日志
    const logContext: LogContext = {
      module: this.moduleName,
      operation,
      error: errorMessage,
      context,
      timestamp: new Date().toISOString()
    };

    this.logger.error(`${operation}失败`, logContext, error instanceof Error ? error.stack : undefined);

    // 重新抛出原始错误，不进行业务异常转换
    throw error;
  }

  /**
   * 搜索异常的特殊处理（返回空结果而不抛出异常）
   *
   * 数据访问逻辑：
   * 1. 格式化错误信息，提取可读的错误描述
   * 2. 使用AppLoggerService记录警告级别的结构化日志
   * 3. 返回空数组而不是抛出异常，保证搜索接口的可用性
   * 4. 记录完整的上下文信息，便于问题排查和监控
   * 5. 使用warn级别日志，区别于error级别的严重异常
   *
   * @param error 原始错误对象，搜索过程中发生的异常
   * @param operation 操作名称，用于日志记录和问题定位
   * @param context 上下文信息，包含搜索条件和相关参数
   * @returns 空数组，确保搜索接口始终返回有效的数组结果
   */
  protected handleSearchError(error: unknown, operation: string, context?: Record<string, any>): any[] {
    const errorMessage = this.formatError(error);

    // 使用AppLoggerService记录结构化警告日志
    const logContext: LogContext = {
      module: this.moduleName,
      operation,
      error: errorMessage,
      context,
      timestamp: new Date().toISOString()
    };

    this.logger.warn(`${operation}失败，返回空结果`, logContext);

    return [];
  }

  /**
   * 记录操作成功日志
   *
   * 业务逻辑：
   * 1. 构建标准化的成功日志信息，包含操作名称和结果
   * 2. 使用AppLoggerService记录结构化日志信息
   * 3. 记录上下文信息，便于业务流程追踪和性能分析
   * 4. 可选记录操作耗时，用于性能监控和优化
   * 5. 添加时间戳，确保日志的时序性和可追溯性
   * 6. 使用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 {
    const logContext: LogContext = {
      module: this.moduleName,
      operation,
      context,
      duration,
      timestamp: new Date().toISOString()
    };

    this.logger.info(`${operation}成功`, logContext);
  }

  /**
   * 记录操作开始日志
   *
   * 业务逻辑：
   * 1. 构建标准化的操作开始日志信息，标记业务流程起点
   * 2. 使用AppLoggerService记录结构化日志信息
   * 3. 记录上下文信息，包含操作的输入参数和相关数据
   * 4. 添加时间戳，便于与成功/失败日志进行时序关联
   * 5. 使用info级别日志，标识正常的业务操作开始
   * 6. 为后续的性能分析和问题排查提供起始点标记
   *
   * @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 {
    const logContext: LogContext = {
      module: this.moduleName,
      operation,
      context,
      timestamp: new Date().toISOString()
    };

    this.logger.info(`开始${operation}`, logContext);
  }

  /**
   * 创建性能监控器
   *
   * 功能描述：
   * 创建一个性能监控器对象，用于测量操作耗时和记录性能指标
   *
   * 业务逻辑：
   * 1. 记录操作开始时间戳
   * 2. 返回包含结束方法的监控器对象
   * 3. 结束方法自动计算耗时并记录日志
   * 4. 支持成功和失败两种结束状态
   *
   * @param operation 操作名称
   * @param context 操作上下文
   * @returns 性能监控器对象
   *
   * @example
   * ```typescript
   * const monitor = this.createPerformanceMonitor('创建用户', { userId: '123' });
   * try {
   *   const result = await this.repository.create(data);
   *   monitor.success({ result: 'created' });
   *   return result;
   * } catch (error) {
   *   monitor.error(error);
   *   throw error;
   * }
   * ```
   */
  protected createPerformanceMonitor(operation: string, context?: Record<string, any>) {
    const startTime = Date.now();
    this.logStart(operation, context);

    return {
      success: (additionalContext?: Record<string, any>) => {
        const duration = Date.now() - startTime;
        this.logSuccess(operation, { ...context, ...additionalContext }, duration);
      },
      error: (error: unknown, additionalContext?: Record<string, any>) => {
        const duration = Date.now() - startTime;
        this.handleDataAccessError(error, operation, {
          ...context,
          ...additionalContext,
          duration
        });
      }
    };
  }

  /**
   * 解析游戏用户ID为BigInt类型
   *
   * 数据转换逻辑：
   * 1. 将字符串类型的游戏用户ID转换为BigInt类型
   * 2. 统一处理ID转换逻辑，避免重复代码
   * 3. 提供类型安全的转换方法
   *
   * @param gameUserId 游戏用户ID字符串
   * @returns BigInt类型的游戏用户ID
   * @throws Error 当ID格式无效时
   */
  protected parseGameUserId(gameUserId: string): bigint {
    try {
      return BigInt(gameUserId);
    } catch (error) {
      throw new Error(`无效的游戏用户ID格式: ${gameUserId}`);
    }
  }

  /**
   * 批量解析ID数组为BigInt类型
   *
   * 数据转换逻辑：
   * 1. 将字符串ID数组转换为BigInt数组
   * 2. 统一处理批量ID转换逻辑
   * 3. 提供类型安全的批量转换方法
   *
   * @param ids 字符串ID数组
   * @returns BigInt类型的ID数组
   * @throws Error 当任何ID格式无效时
   */
  protected parseIds(ids: string[]): bigint[] {
    try {
      return ids.map(id => BigInt(id));
    } catch (error) {
      throw new Error(`无效的ID格式: ${ids.join(', ')}`);
    }
  }

  /**
   * 解析单个ID为BigInt类型
   *
   * 数据转换逻辑：
   * 1. 将字符串类型的ID转换为BigInt类型
   * 2. 统一处理单个ID转换逻辑
   * 3. 提供类型安全的转换方法
   *
   * @param id 字符串ID
   * @returns BigInt类型的ID
   * @throws Error 当ID格式无效时
   */
  protected parseId(id: string): bigint {
    try {
      return BigInt(id);
    } catch (error) {
      throw new Error(`无效的ID格式: ${id}`);
    }
  }

  /**
   * 抽象方法：将实体转换为响应DTO
   *
   * 功能描述：
   * 子类必须实现此方法，将数据库实体转换为API响应DTO
   *
   * @param entity 数据库实体对象
   * @returns 响应DTO对象
   *
   * @example
   * ```typescript
   * // 在子类中实现
   * protected toResponseDto(account: ZulipAccounts): ZulipAccountResponseDto {
   *   return {
   *     id: account.id.toString(),
   *     gameUserId: account.gameUserId.toString(),
   *     // ... 其他字段
   *   };
   * }
   * ```
   */
  protected abstract toResponseDto(entity: any): any;

  /**
   * 将实体数组转换为响应DTO数组
   *
   * 功能描述：
   * 统一处理实体数组到DTO数组的转换，减少重复代码
   *
   * @param entities 实体数组
   * @returns 响应DTO数组
   *
   * @example
   * ```typescript
   * const accounts = await this.repository.findMany();
   * const responseAccounts = this.toResponseDtoArray(accounts);
   * ```
   */
  protected toResponseDtoArray(entities: any[]): any[] {
    return entities.map(entity => this.toResponseDto(entity));
  }

  /**
   * 构建列表响应对象
   *
   * 功能描述：
   * 统一构建列表响应对象，减少重复的对象构建代码
   *
   * @param entities 实体数组
   * @returns 标准的列表响应对象
   *
   * @example
   * ```typescript
   * const accounts = await this.repository.findMany();
   * return this.buildListResponse(accounts);
   * ```
   */
  protected buildListResponse(entities: any[]): any {
    const responseAccounts = this.toResponseDtoArray(entities);
    return {
      accounts: responseAccounts,
      total: responseAccounts.length,
      count: responseAccounts.length,
    };
  }
}