import db from '../../config/database';
import { RedisService } from '../../utils/RedisService';
import { logger } from '../../utils/logger';

/**
 * [BIZ_KER_112] 动态 Feature Flag 建议系统 (Flags)
 * @description 核心逻辑：实现基于租户与权重的动态功能开关。
 * 支持蓝绿发布、灰度放量与紧急熔断（Kill Switch）。
 * 通过 Redis 缓存加速校验，支持实时更新开关状态。
 */
export class FeatureToggleService {
  private static readonly FLAGS_TABLE = 'cf_feature_flags';
  private static readonly REDIS_PREFIX = 'feature_flags:';

  /**
   * 初始化数据库表
   */
  static async initTable() {
    const hasTable = await db.schema.hasTable(this.FLAGS_TABLE);
    if (!hasTable) {
      logger.info(`📦 Creating ${this.FLAGS_TABLE} table...`);
      await db.schema.createTable(this.FLAGS_TABLE, (table) => {
        table.increments('id').primary();
        table.string('feature_key', 64).notNullable().unique();
        table.boolean('is_enabled').defaultTo(false);
        table.integer('rollout_percentage').defaultTo(100); // 灰度比例 (0-100)
        table.json('allowed_tenant_ids'); // 白名单租户
        table.string('description', 255);
        table.timestamp('created_at').defaultTo(db.fn.now());
        table.timestamp('updated_at').defaultTo(db.fn.now());
      });
      logger.info(`✅ Table ${this.FLAGS_TABLE} created`);
    }
  }

  /**
   * 检查功能是否开启
   */
  static async isEnabled(featureKey: string, tenantId?: string): Promise<boolean> {
    try {
      // 1. 从 Redis 快速获取
      const redisKey = `${this.REDIS_PREFIX}${featureKey}`;
      const cached = await RedisService.get(redisKey);
      let flag: any;

      if (cached) {
        flag = JSON.parse(cached);
      } else {
        // 2. Redis 未命中，从数据库拉取并回填缓存
        flag = await db(this.FLAGS_TABLE).where({ feature_key: featureKey }).first();
        if (!flag) return false;
        await RedisService.set(redisKey, JSON.stringify(flag), 3600); // 缓存 1 小时
      }

      // 3. 执行逻辑校验
      if (!flag.is_enabled) return false;

      // 白名单检查
      if (tenantId && flag.allowed_tenant_ids) {
        const allowedIds = JSON.parse(flag.allowed_tenant_ids);
        if (allowedIds.length > 0 && !allowedIds.includes(tenantId)) return false;
      }

      // 灰度比例检查 (基于租户 ID 哈希)
      if (tenantId && flag.rollout_percentage < 100) {
        const hash = this.hashCode(tenantId + featureKey);
        if (Math.abs(hash % 100) >= flag.rollout_percentage) return false;
      }

      return true;
    } catch (err: any) {
      logger.error(`[FeatureToggle] Check failed for ${featureKey}: ${err.message}`);
      return false; // Fail-Safe: 异常情况下默认关闭
    }
  }

  /**
   * 更新开关状态并清除缓存
   */
  static async updateFlag(featureKey: string, updates: Partial<any>) {
    try {
      await db(this.FLAGS_TABLE).where({ feature_key: featureKey }).update({
        ...updates,
        updated_at: new Date()
      });
      await RedisService.getClient().del(`${this.REDIS_PREFIX}${featureKey}`);
      logger.info(`[FeatureToggle] Updated flag for ${featureKey}`);
    } catch (err: any) {
      logger.error(`[FeatureToggle] Update failed for ${featureKey}: ${err.message}`);
    }
  }

  private static hashCode(str: string): number {
    let hash = 0;
    for (let i = 0; i < str.length; i++) {
      const char = str.charCodeAt(i);
      hash = ((hash << 5) - hash) + char;
      hash |= 0;
    }
    return hash;
  }
}
