/**
 * Zulip账号关联业务服务
 *
 * 功能描述：
 * - 提供Zulip账号关联的完整业务逻辑
 * - 管理账号关联的生命周期
 * - 处理账号验证和同步
 * - 提供统计和监控功能
 * - 实现业务异常转换和错误处理
 * - 集成缓存机制提升查询性能
 * - 支持批量操作和性能监控
 *
 * 职责分离：
 * - 业务逻辑：处理复杂的业务规则和流程
 * - 异常转换：将Repository层异常转换为业务异常
 * - DTO转换：实体对象与响应DTO之间的转换
 * - 缓存管理：管理热点数据的缓存策略
 * - 性能监控：记录操作耗时和性能指标
 * - 日志记录：使用AppLoggerService记录结构化日志
 *
 * 最近修改：
 * - 2026-01-12: 架构优化 - 从core/zulip_core移动到business/zulip，符合架构分层规范 (修改者: moyin)
 * - 2026-01-12: 代码质量优化 - 清理未使用的导入，移除冗余DTO引用 (修改者: moyin)
 *
 * @author angjustinl
 * @version 2.1.0
 * @since 2026-01-12
 * @lastModified 2026-01-12
 */

import { Injectable, Inject, ConflictException, NotFoundException } from '@nestjs/common';
import { CACHE_MANAGER } from '@nestjs/cache-manager';
import { Cache } from 'cache-manager';
import { AppLoggerService } from '../../../core/utils/logger/logger.service';
import {
  CreateZulipAccountDto,
  ZulipAccountResponseDto,
  ZulipAccountStatsResponseDto,
} from '../../../core/db/zulip_accounts/zulip_accounts.dto';

/**
 * Zulip账号关联业务服务基类
 */
abstract class BaseZulipAccountsBusinessService {
  protected readonly logger: AppLoggerService;
  protected readonly moduleName: string;

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

  /**
   * 统一的错误格式化方法
   */
  protected formatError(error: unknown): string {
    if (error instanceof Error) {
      return error.message;
    }
    return String(error);
  }

  /**
   * 统一的异常处理方法
   */
  protected handleServiceError(error: unknown, operation: string, context?: Record<string, any>): never {
    const errorMessage = this.formatError(error);

    this.logger.error(`${operation}失败`, {
      module: this.moduleName,
      operation,
      error: errorMessage,
      context,
      timestamp: new Date().toISOString()
    }, error instanceof Error ? error.stack : undefined);

    if (error instanceof ConflictException ||
        error instanceof NotFoundException) {
      throw error;
    }

    throw new ConflictException(`${operation}失败，请稍后重试`);
  }

  /**
   * 搜索异常的特殊处理
   */
  protected handleSearchError(error: unknown, operation: string, context?: Record<string, any>): any[] {
    const errorMessage = this.formatError(error);

    this.logger.warn(`${operation}失败，返回空结果`, {
      module: this.moduleName,
      operation,
      error: errorMessage,
      context,
      timestamp: new Date().toISOString()
    });

    return [];
  }

  /**
   * 记录操作成功日志
   */
  protected logSuccess(operation: string, context?: Record<string, any>, duration?: number): void {
    this.logger.info(`${operation}成功`, {
      module: this.moduleName,
      operation,
      context,
      duration,
      timestamp: new Date().toISOString()
    });
  }

  /**
   * 记录操作开始日志
   */
  protected logStart(operation: string, context?: Record<string, any>): void {
    this.logger.info(`开始${operation}`, {
      module: this.moduleName,
      operation,
      context,
      timestamp: new Date().toISOString()
    });
  }

  /**
   * 创建性能监控器
   */
  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.handleServiceError(error, operation, {
          ...context,
          ...additionalContext,
          duration
        });
      }
    };
  }

  /**
   * 解析游戏用户ID为BigInt类型
   */
  protected parseGameUserId(gameUserId: string): bigint {
    try {
      return BigInt(gameUserId);
    } catch (error) {
      throw new ConflictException(`无效的游戏用户ID格式: ${gameUserId}`);
    }
  }

  /**
   * 批量解析ID数组为BigInt类型
   */
  protected parseIds(ids: string[]): bigint[] {
    try {
      return ids.map(id => BigInt(id));
    } catch (error) {
      throw new ConflictException(`无效的ID格式: ${ids.join(', ')}`);
    }
  }

  /**
   * 解析单个ID为BigInt类型
   */
  protected parseId(id: string): bigint {
    try {
      return BigInt(id);
    } catch (error) {
      throw new ConflictException(`无效的ID格式: ${id}`);
    }
  }

  /**
   * 抽象方法：将实体转换为响应DTO
   */
  protected abstract toResponseDto(entity: any): any;

  /**
   * 将实体数组转换为响应DTO数组
   */
  protected toResponseDtoArray(entities: any[]): any[] {
    return entities.map(entity => this.toResponseDto(entity));
  }

  /**
   * 构建列表响应对象
   */
  protected buildListResponse(entities: any[]): any {
    const responseAccounts = this.toResponseDtoArray(entities);
    return {
      accounts: responseAccounts,
      total: responseAccounts.length,
      count: responseAccounts.length,
    };
  }
}

/**
 * Zulip账号关联业务服务类
 *
 * 职责：
 * - 处理Zulip账号关联的业务逻辑
 * - 管理账号关联的生命周期和状态
 * - 提供业务级别的异常处理和转换
 * - 实现缓存策略和性能优化
 *
 * 主要方法：
 * - create(): 创建Zulip账号关联
 * - findByGameUserId(): 根据游戏用户ID查找关联
 * - getStatusStatistics(): 获取账号状态统计
 * - toResponseDto(): 实体到DTO的转换
 *
 * 使用场景：
 * - 用户注册时创建Zulip账号关联
 * - 查询用户的Zulip账号信息
 * - 系统监控和统计分析
 * - 账号状态管理和维护
 */
@Injectable()
export class ZulipAccountsBusinessService extends BaseZulipAccountsBusinessService {
  // 缓存键前缀
  private static readonly CACHE_PREFIX = 'zulip_accounts';
  private static readonly CACHE_TTL = 300; // 5分钟缓存
  private static readonly STATS_CACHE_TTL = 60; // 统计数据1分钟缓存

  constructor(
    @Inject('ZulipAccountsRepository') private readonly repository: any,
    @Inject(AppLoggerService) logger: AppLoggerService,
    @Inject(CACHE_MANAGER) private readonly cacheManager: Cache,
  ) {
    super(logger, 'ZulipAccountsBusinessService');
    this.logger.info('ZulipAccountsBusinessService初始化完成', {
      module: 'ZulipAccountsBusinessService',
      operation: 'constructor',
      cacheEnabled: !!this.cacheManager
    });
  }

  /**
   * 创建Zulip账号关联
   *
   * 功能描述：
   * 创建游戏用户与Zulip账号的关联关系
   *
   * 业务逻辑：
   * 1. 验证游戏用户ID格式
   * 2. 调用Repository层创建关联
   * 3. 处理业务异常（重复关联等）
   * 4. 清理相关缓存
   * 5. 转换为业务响应DTO
   *
   * @param createDto 创建关联的数据传输对象
   * @returns Promise<ZulipAccountResponseDto> 创建结果
   *
   * @throws ConflictException 当关联已存在时
   */
  async create(createDto: CreateZulipAccountDto): Promise<ZulipAccountResponseDto> {
    const monitor = this.createPerformanceMonitor('创建Zulip账号关联', {
      gameUserId: createDto.gameUserId
    });

    try {
      const account = await this.repository.create({
        gameUserId: this.parseGameUserId(createDto.gameUserId),
        zulipUserId: createDto.zulipUserId,
        zulipEmail: createDto.zulipEmail,
        zulipFullName: createDto.zulipFullName,
        zulipApiKeyEncrypted: createDto.zulipApiKeyEncrypted,
        status: createDto.status || 'active',
      });

      await this.clearRelatedCache(createDto.gameUserId, createDto.zulipUserId, createDto.zulipEmail);

      const result = this.toResponseDto(account);
      monitor.success({
        accountId: account.id.toString(),
        status: account.status
      });

      return result;

    } catch (error) {
      if (error instanceof Error) {
        if (error.message.includes('already has a Zulip account')) {
          const conflictError = new ConflictException(`游戏用户 ${createDto.gameUserId} 已存在Zulip账号关联`);
          monitor.error(conflictError);
        }
        if (error.message.includes('is already linked')) {
          if (error.message.includes('Zulip user')) {
            const conflictError = new ConflictException(`Zulip用户 ${createDto.zulipUserId} 已被关联到其他游戏账号`);
            monitor.error(conflictError);
          }
          if (error.message.includes('Zulip email')) {
            const conflictError = new ConflictException(`Zulip邮箱 ${createDto.zulipEmail} 已被关联到其他游戏账号`);
            monitor.error(conflictError);
          }
        }
      }

      monitor.error(error);
    }
  }

  /**
   * 根据游戏用户ID查找关联（带缓存）
   *
   * 功能描述：
   * 根据游戏用户ID查找对应的Zulip账号关联信息
   *
   * 业务逻辑：
   * 1. 检查缓存中是否存在
   * 2. 缓存未命中时查询Repository
   * 3. 转换为业务响应DTO
   * 4. 更新缓存
   * 5. 记录查询性能指标
   *
   * @param gameUserId 游戏用户ID
   * @param includeGameUser 是否包含游戏用户信息
   * @returns Promise<ZulipAccountResponseDto | null> 关联信息或null
   */
  async findByGameUserId(gameUserId: string, includeGameUser: boolean = false): Promise<ZulipAccountResponseDto | null> {
    const cacheKey = this.buildCacheKey('game_user', gameUserId, includeGameUser);

    try {
      const cached = await this.cacheManager.get<ZulipAccountResponseDto>(cacheKey);
      if (cached) {
        this.logger.debug('缓存命中', {
          module: this.moduleName,
          operation: 'findByGameUserId',
          gameUserId,
          cacheKey
        });
        return cached;
      }

      const monitor = this.createPerformanceMonitor('根据游戏用户ID查找关联', { gameUserId });

      const account = await this.repository.findByGameUserId(this.parseGameUserId(gameUserId), includeGameUser);

      if (!account) {
        this.logger.debug('未找到Zulip账号关联', {
          module: this.moduleName,
          operation: 'findByGameUserId',
          gameUserId
        });
        monitor.success({ found: false });
        return null;
      }

      const result = this.toResponseDto(account);

      await this.cacheManager.set(cacheKey, result, ZulipAccountsBusinessService.CACHE_TTL);

      monitor.success({ found: true, cached: true });
      return result;

    } catch (error) {
      this.handleServiceError(error, '根据游戏用户ID查找关联', { gameUserId });
    }
  }

  /**
   * 获取账号状态统计（带缓存）
   *
   * 功能描述：
   * 获取所有Zulip账号关联的状态统计信息
   *
   * 业务逻辑：
   * 1. 检查统计数据缓存
   * 2. 缓存未命中时查询Repository
   * 3. 计算总计数据
   * 4. 更新缓存
   * 5. 返回统计结果
   *
   * @returns Promise<ZulipAccountStatsResponseDto> 状态统计信息
   */
  async getStatusStatistics(): Promise<ZulipAccountStatsResponseDto> {
    const cacheKey = this.buildCacheKey('stats');

    try {
      const cached = await this.cacheManager.get<ZulipAccountStatsResponseDto>(cacheKey);
      if (cached) {
        this.logger.debug('统计数据缓存命中', {
          module: this.moduleName,
          operation: 'getStatusStatistics',
          cacheKey
        });
        return cached;
      }

      const monitor = this.createPerformanceMonitor('获取账号状态统计');

      const statistics = await this.repository.getStatusStatistics();

      const result = {
        active: statistics.active || 0,
        inactive: statistics.inactive || 0,
        suspended: statistics.suspended || 0,
        error: statistics.error || 0,
        total: (statistics.active || 0) + (statistics.inactive || 0) +
               (statistics.suspended || 0) + (statistics.error || 0),
      };

      await this.cacheManager.set(cacheKey, result, ZulipAccountsBusinessService.STATS_CACHE_TTL);

      monitor.success({
        total: result.total,
        cached: true
      });

      return result;

    } catch (error) {
      this.handleServiceError(error, '获取账号状态统计');
    }
  }

  /**
   * 将实体转换为响应DTO
   *
   * 功能描述：
   * 将Repository层返回的实体对象转换为业务层的响应DTO
   *
   * @param account 实体对象
   * @returns ZulipAccountResponseDto 响应DTO
   */
  protected toResponseDto(account: any): ZulipAccountResponseDto {
    return {
      id: account.id.toString(),
      gameUserId: account.gameUserId.toString(),
      zulipUserId: account.zulipUserId,
      zulipEmail: account.zulipEmail,
      zulipFullName: account.zulipFullName,
      status: account.status,
      lastVerifiedAt: account.lastVerifiedAt?.toISOString(),
      lastSyncedAt: account.lastSyncedAt?.toISOString(),
      errorMessage: account.errorMessage,
      retryCount: account.retryCount,
      createdAt: account.createdAt.toISOString(),
      updatedAt: account.updatedAt.toISOString(),
      gameUser: account.gameUser,
    };
  }

  /**
   * 构建缓存键
   *
   * @param type 缓存类型
   * @param identifier 标识符
   * @param includeGameUser 是否包含游戏用户信息
   * @returns string 缓存键
   * @private
   */
  private buildCacheKey(type: string, identifier?: string, includeGameUser?: boolean): string {
    const parts = [ZulipAccountsBusinessService.CACHE_PREFIX, type];
    if (identifier) parts.push(identifier);
    if (includeGameUser) parts.push('with_user');
    return parts.join(':');
  }

  /**
   * 清除相关缓存
   *
   * @param gameUserId 游戏用户ID
   * @param zulipUserId Zulip用户ID
   * @param zulipEmail Zulip邮箱
   * @returns Promise<void>
   * @private
   */
  private async clearRelatedCache(gameUserId?: string, zulipUserId?: number, zulipEmail?: string): Promise<void> {
    const keysToDelete: string[] = [];

    keysToDelete.push(this.buildCacheKey('stats'));

    if (gameUserId) {
      keysToDelete.push(this.buildCacheKey('game_user', gameUserId, false));
      keysToDelete.push(this.buildCacheKey('game_user', gameUserId, true));
    }

    if (zulipUserId) {
      keysToDelete.push(this.buildCacheKey('zulip_user', zulipUserId.toString(), false));
      keysToDelete.push(this.buildCacheKey('zulip_user', zulipUserId.toString(), true));
    }

    if (zulipEmail) {
      keysToDelete.push(this.buildCacheKey('zulip_email', zulipEmail, false));
      keysToDelete.push(this.buildCacheKey('zulip_email', zulipEmail, true));
    }

    try {
      await Promise.all(keysToDelete.map(key => this.cacheManager.del(key)));

      this.logger.debug('清除相关缓存', {
        module: this.moduleName,
        operation: 'clearRelatedCache',
        keysCount: keysToDelete.length,
        keys: keysToDelete
      });
    } catch (error) {
      this.logger.warn('清除缓存失败', {
        module: this.moduleName,
        operation: 'clearRelatedCache',
        error: this.formatError(error),
        keys: keysToDelete
      });
    }
  }
}