import { RedisService } from '../../utils/RedisService';
import { logger } from '../../utils/logger';
import os from 'os';

/**
 * [BIZ_KER_113] 租户资源占用热力图 (Resource Heatmap)
 * @description 核心逻辑：记录各租户在 API 请求或后台任务中的资源占用。
 * 利用 Redis 实时收集租户的 CPU、内存占用以及请求频率。
 * 生成 24 小时内的资源消耗热力图，识别资源滥用与负载波峰。
 */
export class TenantUsageService {
  private static readonly USAGE_PREFIX = 'tenant_usage:';
  private static readonly RETENTION_DAYS = 30; // 记录保留 30 天

  /**
   * 记录租户资源占用指标
   */
  static async recordUsage(tenantId: string, metric: 'cpu' | 'memory' | 'request', value: number) {
    const redis = RedisService.getClient();
    const now = new Date();
    const dateKey = now.toISOString().split('T')[0];
    const hour = now.getHours();
    
    // 生成 Redis Key: tenant_usage:{tenantId}:{dateKey}
    const baseKey = `${this.USAGE_PREFIX}${tenantId}:${dateKey}`;

    try {
      // 1. 记录小时级峰值 (ZSET 分数即为资源消耗)
      const field = `${metric}:${hour}`;
      await redis.hincrby(baseKey, field, Math.ceil(value));

      // 2. 记录当日总次数 (用于计算平均值)
      await redis.hincrby(baseKey, `${metric}:total`, 1);
      await redis.hincrby(baseKey, `${metric}:sum`, Math.ceil(value));

      // 3. 设置过期时间
      await redis.expire(baseKey, this.RETENTION_DAYS * 24 * 60 * 60);

    } catch (err: any) {
      logger.error(`[TenantUsage] Failed to record usage for ${tenantId}: ${err.message}`);
    }
  }

  /**
   * 模拟当前系统级资源监控
   */
  static async monitorSystemResources() {
    const cpuLoad = os.loadavg()[0]; // 1 分钟平均负载
    const memoryUsage = 1 - (os.freemem() / os.totalmem()); // 内存占用比例

    // 将系统资源占用按活跃租户平均分摊 (模拟逻辑)
    // 实际场景应结合各租户的实时请求频率进行分摊
    logger.debug(`[TenantUsage] System Metrics: CPU=${cpuLoad.toFixed(2)}, MEM=${(memoryUsage * 100).toFixed(2)}%`);
  }

  /**
   * 获取租户资源热力图数据
   */
  static async getHeatmapData(tenantId: string, date?: string): Promise<any> {
    const redis = RedisService.getClient();
    const dateKey = date || new Date().toISOString().split('T')[0];
    const baseKey = `${this.USAGE_PREFIX}${tenantId}:${dateKey}`;

    try {
      const stats = await redis.hgetall(baseKey);
      if (!stats || Object.keys(stats).length === 0) return null;

      const heatmap: Record<string, number[]> = {
        cpu: new Array(24).fill(0),
        memory: new Array(24).fill(0),
        request: new Array(24).fill(0)
      };

      for (const field in stats) {
        const [metric, hourStr] = field.split(':');
        if (hourStr === 'total' || hourStr === 'sum') continue;
        
        const hour = parseInt(hourStr);
        if (metric in heatmap) {
          heatmap[metric][hour] = parseInt(stats[field]);
        }
      }

      return {
        tenantId,
        date: dateKey,
        heatmap
      };
    } catch (err: any) {
      logger.error(`[TenantUsage] Failed to get heatmap: ${err.message}`);
      return null;
    }
  }
}
