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

/**
 * [BIZ_FIN_13] 租户级信用额度动态管理 (Credit Line Mgmt)
 * @description 核心逻辑：管理租户授信额度的分配、扣减、释放及信用分评估。支持基于回款表现与风险分动态调配额度。
 */
export class CreditLimitService {
  private static readonly TABLE_NAME = 'cf_tenant_credits';

  /**
   * 初始化数据库表
   */
  static async initTable() {
    const hasTable = await db.schema.hasTable(this.TABLE_NAME);
    if (!hasTable) {
      logger.info(`📦 Creating ${this.TABLE_NAME} table...`);
      await db.schema.createTable(this.TABLE_NAME, (table) => {
        table.string('tenant_id', 64).primary();
        table.decimal('total_limit', 15, 2).defaultTo(10000);
        table.decimal('used_amount', 15, 2).defaultTo(0);
        table.string('currency', 8).defaultTo('USD');
        table.integer('credit_score').defaultTo(80);
        table.json('risk_metrics');
        table.timestamps(true, true);
      });
    }
  }

  /**
   * 获取租户当前信用信息
   */
  static async getCreditInfo(tenantId: string) {
    // Feature Flag Check
    if (!(await FeatureGovernanceService.isEnabled('BIZ_FIN_CREDIT_LINE', tenantId))) {
      return null;
    }

    const info = await db(this.TABLE_NAME)
      .where({ tenant_id: tenantId })
      .first();
    
    if (!info) {
      const defaultInfo = {
        tenant_id: tenantId,
        total_limit: 10000,
        used_amount: 0,
        currency: 'USD',
        credit_score: 80,
        risk_metrics: JSON.stringify({ default: true })
      };
      await db(this.TABLE_NAME).insert(defaultInfo);
      return defaultInfo;
    }
    return info;
  }

  /**
   * 检查并扣减额度 (预占)
   */
  static async reserveCredit(tenantId: string, amount: number, traceId: string): Promise<boolean> {
    return await db.transaction(async (trx) => {
      const credit = await trx('cf_tenant_credits')
        .where({ tenant_id: tenantId })
        .forUpdate()
        .first();

      if (!credit || (credit.total_limit - credit.used_amount) < amount) {
        return false;
      }

      const newUsedAmount = credit.used_amount + amount;
      await trx('cf_tenant_credits')
        .where({ tenant_id: tenantId })
        .update({
          used_amount: newUsedAmount,
          updated_at: db.fn.now()
        });

      await AuditService.log({
        tenantId,
        userId: 'SYSTEM',
        module: 'FINANCE',
        action: 'RESERVE_CREDIT',
        resourceType: 'TENANT_CREDIT',
        resourceId: tenantId,
        traceId,
        afterSnapshot: { amount, newUsedAmount },
        result: 'success',
        source: 'node',
        metadata: { reason: 'Order placement reservation' }
      });

      return true;
    });
  }

  /**
   * 释放额度 (订单取消或完成支付后)
   */
  static async releaseCredit(tenantId: string, amount: number, traceId: string): Promise<void> {
    await db.transaction(async (trx) => {
      const credit = await trx('cf_tenant_credits')
        .where({ tenant_id: tenantId })
        .forUpdate()
        .first();

      if (!credit) return;

      const newUsedAmount = Math.max(0, credit.used_amount - amount);
      await trx('cf_tenant_credits')
        .where({ tenant_id: tenantId })
        .update({
          used_amount: newUsedAmount,
          updated_at: db.fn.now()
        });

      await AuditService.log({
        tenantId,
        userId: 'SYSTEM',
        module: 'FINANCE',
        action: 'RELEASE_CREDIT',
        resourceType: 'TENANT_CREDIT',
        resourceId: tenantId,
        traceId,
        afterSnapshot: { amount, newUsedAmount },
        result: 'success',
        source: 'node',
        metadata: { reason: 'Credit release' }
      });
    });
  }

  /**
   * 动态调整信用分 (基于回款表现、退款率等)
   */
  static async updateCreditScore(tenantId: string, delta: number, traceId: string): Promise<void> {
    await db.transaction(async (trx) => {
      const credit = await trx('cf_tenant_credits')
        .where({ tenant_id: tenantId })
        .forUpdate()
        .first();

      if (!credit) return;

      const newScore = Math.min(100, Math.max(0, credit.credit_score + delta));
      
      // 如果信用分大幅提升，自动上调总额度
      let newTotalLimit = credit.total_limit;
      if (newScore > 90 && credit.credit_score <= 90) {
        newTotalLimit = credit.total_limit * 1.2; // 提升 20%
      }

      await trx('cf_tenant_credits')
        .where({ tenant_id: tenantId })
        .update({
          credit_score: newScore,
          total_limit: newTotalLimit,
          updated_at: db.fn.now()
        });

      await AuditService.log({
        tenantId,
        userId: 'SYSTEM',
        module: 'FINANCE',
        action: 'UPDATE_CREDIT_SCORE',
        resourceType: 'TENANT_CREDIT',
        resourceId: tenantId,
        traceId,
        afterSnapshot: { newScore, newTotalLimit },
        result: 'success',
        source: 'node',
        metadata: { delta }
      });
    });
  }
}
