/**
 * Zulip账号关联数据模块
 *
 * 功能描述：
 * - 提供Zulip账号关联数据的访问接口和服务注册
 * - 封装TypeORM实体和Repository的依赖注入配置
 * - 为业务层提供统一的数据访问服务接口
 * - 支持数据库和内存模式的动态切换和环境适配
 * - 集成缓存和日志系统，提升性能和可观测性
 *
 * 职责分离：
 * - 模块配置：管理依赖注入和服务提供者的注册
 * - 环境适配：根据配置自动选择数据库或内存存储模式
 * - 服务导出：为其他模块提供数据访问服务的统一接口
 * - 全局注册：通过@Global装饰器实现全局模块共享
 * - 依赖管理：集成缓存、日志等基础设施服务
 *
 * 最近修改：
 * - 2026-01-12: 性能优化 - 集成缓存模块和AppLoggerService，提升性能和可观测性
 * - 2026-01-07: 代码规范优化 - 使用统一的常量文件，提高代码质量
 * - 2026-01-07: 代码规范优化 - 完善文件头注释和方法三级注释
 * - 2026-01-07: 功能完善 - 优化环境检测逻辑和模块配置
 * - 2025-01-07: 架构优化 - 实现动态模块配置和环境自适应
 * - 2025-01-05: 功能扩展 - 添加内存模式支持和自动切换机制
 *
 * @author angjustinl
 * @version 1.2.0
 * @since 2025-01-05
 * @lastModified 2026-01-12
 */

import { Module, DynamicModule, Global } from '@nestjs/common';
import { TypeOrmModule } from '@nestjs/typeorm';
import { CacheModule } from '@nestjs/cache-manager';
import { ZulipAccounts } from './zulip_accounts.entity';
import { ZulipAccountsRepository } from './zulip_accounts.repository';
import { ZulipAccountsMemoryRepository } from './zulip_accounts_memory.repository';
import { ZulipAccountsService } from './zulip_accounts.service';
import { ZulipAccountsMemoryService } from './zulip_accounts_memory.service';
import { AppLoggerService } from '../../utils/logger/logger.service';
import { REQUIRED_DB_ENV_VARS } from './zulip_accounts.constants';

/**
 * 检查数据库配置是否完整
 *
 * 业务逻辑：
 * 1. 遍历所有必需的数据库环境变量名称
 * 2. 检查每个环境变量是否在process.env中存在且有值
 * 3. 只有当所有必需变量都存在时才返回true
 * 4. 用于决定使用数据库模式还是内存模式
 *
 * @returns 是否配置了完整的数据库连接信息
 *
 * @example
 * // 检查数据库配置
 * if (isDatabaseConfigured()) {
 *   console.log('使用数据库模式');
 * } else {
 *   console.log('使用内存模式');
 * }
 */
function isDatabaseConfigured(): boolean {
  return REQUIRED_DB_ENV_VARS.every(varName => process.env[varName]);
}

@Global()
@Module({})
export class ZulipAccountsModule {
  /**
   * 创建数据库模式的Zulip账号模块
   *
   * 业务逻辑：
   * 1. 导入TypeORM模块并注册ZulipAccounts实体
   * 2. 集成缓存模块提供数据缓存能力
   * 3. 注册数据库版本的Repository和Service实现
   * 4. 配置依赖注入的提供者和别名映射
   * 5. 导出服务接口供其他模块使用
   * 6. 确保TypeORM功能的完整集成和事务支持
   * 7. 集成AppLoggerService提供结构化日志
   *
   * @returns 配置了TypeORM和缓存的动态模块，包含数据库访问功能
   *
   * @example
   * // 在应用模块中使用数据库模式
   * @Module({
   *   imports: [ZulipAccountsModule.forDatabase()],
   * })
   * export class AppModule {}
   */
  static forDatabase(): DynamicModule {
    return {
      module: ZulipAccountsModule,
      imports: [
        TypeOrmModule.forFeature([ZulipAccounts]),
        CacheModule.register({
          ttl: 300, // 5分钟默认TTL
          max: 1000, // 最大缓存项数
        }),
      ],
      providers: [
        ZulipAccountsRepository,
        AppLoggerService,
        {
          provide: 'ZulipAccountsService',
          useClass: ZulipAccountsService,
        },
      ],
      exports: [
        ZulipAccountsRepository,
        'ZulipAccountsService',
        TypeOrmModule,
        AppLoggerService,
      ],
    };
  }

  /**
   * 创建内存模式的Zulip账号模块
   *
   * 业务逻辑：
   * 1. 注册内存版本的Repository和Service实现
   * 2. 集成基础缓存模块（内存模式也可以使用缓存）
   * 3. 配置依赖注入的提供者，使用内存存储类
   * 4. 不依赖TypeORM和数据库连接
   * 5. 适用于开发、测试和演示环境
   * 6. 提供与数据库模式相同的接口和功能
   * 7. 集成AppLoggerService提供结构化日志
   *
   * @returns 配置了内存存储和缓存的动态模块，无需数据库连接
   *
   * @example
   * // 在测试环境中使用内存模式
   * @Module({
   *   imports: [ZulipAccountsModule.forMemory()],
   * })
   * export class TestModule {}
   */
  static forMemory(): DynamicModule {
    return {
      module: ZulipAccountsModule,
      imports: [
        CacheModule.register({
          ttl: 300, // 5分钟默认TTL
          max: 500, // 内存模式使用较小的缓存
        }),
      ],
      providers: [
        AppLoggerService,
        {
          provide: 'ZulipAccountsRepository',
          useClass: ZulipAccountsMemoryRepository,
        },
        {
          provide: 'ZulipAccountsService',
          useClass: ZulipAccountsMemoryService,
        },
      ],
      exports: [
        'ZulipAccountsRepository',
        'ZulipAccountsService',
        AppLoggerService,
      ],
    };
  }

  /**
   * 根据环境自动选择模式
   *
   * 业务逻辑：
   * 1. 调用isDatabaseConfigured()检查数据库配置完整性
   * 2. 如果数据库配置完整，返回数据库模式的动态模块
   * 3. 如果数据库配置不完整，返回内存模式的动态模块
   * 4. 实现环境自适应，简化模块配置和部署流程
   * 5. 确保应用在不同环境下都能正常启动和运行
   *
   * @returns 根据环境配置自动选择的动态模块
   *
   * @example
   * // 在主模块中使用自动模式选择
   * @Module({
   *   imports: [ZulipAccountsModule.forRoot()],
   * })
   * export class AppModule {}
   */
  static forRoot(): DynamicModule {
    return isDatabaseConfigured()
      ? ZulipAccountsModule.forDatabase()
      : ZulipAccountsModule.forMemory();
  }
}
