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

/**
 * [AUTO_SB_03] 全自动执行熔断保护协议 (Circuit Breaker)
 * @description 核心逻辑：当 AGI 执行出现连续异常或资金回撤时自动切断全自动链路。
 * 保护企业资产，实现从“全自动”向“半自动”的降级切换。
 */
export class AutoCircuitBreakerService {
  private static readonly CIRCUIT_BREAKER_TABLE = 'cf_circuit_breaker_status';

  /**
   * 初始化熔断状态表
   */
  static async initTable() {
    const hasTable = await db.schema.hasTable(this.CIRCUIT_BREAKER_TABLE);
    if (!hasTable) {
      await db.schema.createTable(this.CIRCUIT_BREAKER_TABLE, (table) => {
        table.increments('id').primary();
        table.string('tenant_id', 64).index();
        table.string('module', 64).index();
        table.string('status', 16); // CLOSED (正常), OPEN (熔断)
        table.integer('failure_count').defaultTo(0);
        table.decimal('drawdown_amount', 10, 2).defaultTo(0); // 资金回撤金额
        table.timestamp('last_failure_at');
        table.timestamp('updated_at').defaultTo(db.fn.now());
      });
    }
  }

  /**
   * 检查指定模块是否已熔断
   */
  static async isCircuitOpen(tenantId: string, module: string): Promise<boolean> {
    const status = await db(this.CIRCUIT_BREAKER_TABLE)
      .where({ tenant_id: tenantId, module })
      .first();

    if (!status) return false;
    return status.status === 'OPEN';
  }

  /**
   * 记录执行失败并检查是否触发熔断
   */
  static async reportFailure(tenantId: string, module: string, error: string) {
    logger.warn(`[CircuitBreaker] Failure reported for ${module} in tenant ${tenantId}: ${error}`);

    const currentStatus = await db(this.CIRCUIT_BREAKER_TABLE)
      .where({ tenant_id: tenantId, module })
      .first();

    if (!currentStatus) {
      await db(this.CIRCUIT_BREAKER_TABLE).insert({
        tenant_id: tenantId,
        module,
        status: 'CLOSED',
        failure_count: 1,
        last_failure_at: new Date()
      });
      return;
    }

    const newFailureCount = (currentStatus.failure_count || 0) + 1;
    let newStatus = 'CLOSED';

    // 熔断策略：连续失败 5 次则熔断
    if (newFailureCount >= 5) {
      newStatus = 'OPEN';
      logger.error(`[CircuitBreaker][FATAL] Module ${module} for tenant ${tenantId} is now OPEN (CIRCUIT BROKEN)`);
    }

    await db(this.CIRCUIT_BREAKER_TABLE)
      .where({ tenant_id: tenantId, module })
      .update({
        status: newStatus,
        failure_count: newFailureCount,
        last_failure_at: new Date(),
        updated_at: new Date()
      });
  }

  /**
   * 手动重置熔断器
   */
  static async resetCircuit(tenantId: string, module: string) {
    await db(this.CIRCUIT_BREAKER_TABLE)
      .where({ tenant_id: tenantId, module })
      .update({
        status: 'CLOSED',
        failure_count: 0,
        drawdown_amount: 0,
        updated_at: new Date()
      });
    logger.info(`[CircuitBreaker] Resetting circuit for ${module} in tenant ${tenantId}`);
  }
}
