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

export interface APIUsageRecord {
  tenantId: string;
  provider: 'OPENAI' | 'VERTEX_AI' | 'CLAUDE';
  model: string;
  tokensUsed: number;
  estimatedCost?: number; // USD (Optional, calculated if missing)
  traceId: string;
}

/**
 * [CORE_TELE_08] 租户级 API 成本与资源利用率对齐审计 (Cost Attribution)
 * @description 核心逻辑：精准计算并审计每个租户对外部 AI 模型 (OpenAI/Google/Anthropic) 的使用成本。
 */
export class CostAttributionService {
  private static readonly COST_TABLE = 'cf_api_cost_attribution';
  
  /**
   * 初始化表结构
   */
  static async initTable() {
    const hasTable = await db.schema.hasTable(this.COST_TABLE);
    if (!hasTable) {
      console.log(`📦 Creating ${this.COST_TABLE} table...`);
      await db.schema.createTable(this.COST_TABLE, (table) => {
        table.increments('id').primary();
        table.string('tenant_id', 64).notNullable();
        table.string('provider', 32).notNullable();
        table.string('model', 64);
        table.integer('tokens_used').defaultTo(0);
        table.decimal('estimated_cost', 12, 6); // 高精度金额
        table.string('trace_id', 128);
        table.timestamp('created_at').defaultTo(db.fn.now());
        table.index(['tenant_id', 'created_at']);
      });
      console.log(`✅ Table ${this.COST_TABLE} created`);
    }
  }

  // 模拟价目表 (Price per 1k tokens)
  private static readonly PRICING_MODEL: Record<string, number> = {
    'gpt-4o': 0.01,
    'gpt-4-turbo': 0.03,
    'claude-3-opus': 0.015,
    'Default': 0.005
  };

  /**
   * 记录并分析 API 成本消耗 (CORE_TELE_08)
   */
  static async recordUsage(usage: APIUsageRecord) {
    if (!(await FeatureGovernanceService.isEnabled('CORE_TELE_COST_ATTRIBUTION', usage.tenantId))) {
      return;
    }

    try {
      // 1. 计算成本 (如果缺失)
      const rate = this.PRICING_MODEL[usage.model] || this.PRICING_MODEL['Default'];
      const estimatedCost = usage.estimatedCost || (usage.tokensUsed / 1000) * rate;

      // 2. 写入审计表
      await db(this.COST_TABLE).insert({
        tenant_id: usage.tenantId,
        provider: usage.provider,
        model: usage.model,
        tokens_used: usage.tokensUsed,
        estimated_cost: estimatedCost,
        trace_id: usage.traceId,
        created_at: new Date()
      });
      
      logger.info(`[CostAttribution] Recorded $${estimatedCost.toFixed(4)} usage for Tenant ${usage.tenantId} (Model: ${usage.model})`);

      // 3. 联动配额熔断器：检查日预算是否超支 (BIZ_GOV_07)
      await this.checkDailyBudget(usage.tenantId, estimatedCost);

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

  /**
   * 检查日预算并触发熔断 (BIZ_GOV_07)
   */
  private static async checkDailyBudget(tenantId: string, currentSpend: number) {
    const today = new Date();
    today.setHours(0, 0, 0, 0);

    const result = await db(this.COST_TABLE)
      .where({ tenant_id: tenantId })
      .andWhere('created_at', '>=', today)
      .sum('estimated_cost as total_daily_spend')
      .first();

    const totalDailySpend = Number(result?.total_daily_spend || 0);

    // 联动 QuotaCircuitBreakerService 检查 AGI_COST 资源
    const allowed = await QuotaCircuitBreakerService.checkAndConsume(
      tenantId, 
      'AGI_COST_USD', 
      currentSpend 
    );

    if (!allowed) {
      logger.error(`[CostAttribution] Tenant ${tenantId} EXCEEDED daily AI budget! Total Spend: $${totalDailySpend.toFixed(2)}`);
    }
  }

  /**
   * 获取租户实时账单
   */
  static async getTenantBill(tenantId: string, startDate?: Date): Promise<any> {
    const query = db(this.COST_TABLE)
      .where({ tenant_id: tenantId })
      .select(
        db.raw('SUM(tokens_used) as total_tokens'),
        db.raw('SUM(estimated_cost) as total_cost'),
        'provider'
      )
      .groupBy('provider');
    
    if (startDate) {
      query.andWhere('created_at', '>=', startDate);
    }

    return await query;
  }

  /**
   * 获取全平台成本 Top 租户
   */
  static async getTopSpenders(limit: number = 5): Promise<any[]> {
    return await db(this.COST_TABLE)
      .select('tenant_id')
      .sum('estimated_cost as total_cost')
      .groupBy('tenant_id')
      .orderBy('total_cost', 'desc')
      .limit(limit);
  }
}
