import db from '../../config/database';
import { logger } from '../../utils/logger';
import { BillingQuota, ResourceType } from './BillingService';

/**
 * [BIZ_BILL_01] 企业配额与订阅计费中心 (Quota & Subscription Billing)
 * @description 核心配额校验与用量统计服务
 */
export class QuotaService {
  /**
   * 获取租户当前配额与用量
   */
  static async getQuota(tenantId: string): Promise<BillingQuota | null> {
    try {
      const quota = await db('cf_tenant_quota').where({ tenant_id: tenantId }).first();
      if (!quota) return null;

      return {
        tenantId: quota.tenant_id,
        planId: quota.plan_id,
        seatsLimit: quota.seats_limit,
        shopsLimit: quota.shops_limit,
        nodesLimit: quota.nodes_limit,
        taskMonthlyLimit: quota.task_monthly_limit,
        aiCallLimit: quota.ai_call_limit,
        usedSeats: quota.used_seats,
        usedShops: quota.used_shops,
        usedNodes: quota.used_nodes,
        usedTasks: quota.used_tasks,
        usedAiCalls: quota.used_ai_calls,
        expiredAt: quota.expired_at ? new Date(quota.expired_at) : null,
        resetAt: quota.reset_at ? new Date(quota.reset_at) : null,
      };
    } catch (error: any) {
      logger.error(`[QuotaService] Error fetching quota for tenant ${tenantId}: ${error.message}`);
      return null;
    }
  }

  /**
   * 检查配额是否允许
   */
  static async checkQuota(tenantId: string, resourceType: ResourceType): Promise<{ allowed: boolean; message?: string }> {
    const quota = await this.getQuota(tenantId);
    if (!quota) {
      return { allowed: false, message: 'No quota record found for this tenant.' };
    }

    // 检查是否过期
    if (quota.expiredAt && quota.expiredAt < new Date()) {
      return { allowed: false, message: 'Subscription has expired.' };
    }

    // 映射资源类型到字段名
    const limitField = this.getLimitField(resourceType);
    const usageField = this.getUsageField(resourceType);

    const limit = quota[limitField as keyof BillingQuota] as number;
    const used = quota[usageField as keyof BillingQuota] as number;

    if (used >= limit) {
      return {
        allowed: false,
        message: `Quota exceeded for ${resourceType}. Limit: ${limit}, Used: ${used}. Please upgrade your plan.`,
      };
    }

    return { allowed: true };
  }

  /**
   * 增加用量
   */
  static async incrementUsage(tenantId: string, resourceType: ResourceType, amount: number = 1): Promise<boolean> {
    const check = await this.checkQuota(tenantId, resourceType);
    if (!check.allowed) return false;

    // 数据库字段名映射 (used_seats, used_shops, etc)
    const dbField = `used_${resourceType}`;
    
    try {
      await db('cf_tenant_quota')
        .where({ tenant_id: tenantId })
        .increment(dbField, amount)
        .update({ updated_at: db.fn.now() });
        
      logger.info(`[QuotaService] Incremented ${resourceType} for tenant ${tenantId} by ${amount}`);
      return true;
    } catch (error: any) {
      logger.error(`[QuotaService] Error incrementing usage: ${error.message}`);
      return false;
    }
  }

  /**
   * 激活/更新租户套餐
   */
  static async updateQuota(tenantId: string, planId: string, durationDays: number = 30): Promise<boolean> {
    try {
      const plan = await db('cf_billing_plan').where({ id: planId }).first();
      if (!plan) return false;

      const expiredAt = new Date();
      expiredAt.setDate(expiredAt.getDate() + durationDays);

      const resetAt = new Date();
      resetAt.setMonth(resetAt.getMonth() + 1);

      const quotaData = {
        plan_id: planId,
        seats_limit: plan.seats_limit,
        shops_limit: plan.shops_limit,
        nodes_limit: plan.nodes_limit,
        task_monthly_limit: plan.task_monthly_limit,
        ai_call_limit: plan.ai_call_limit,
        expired_at: expiredAt,
        reset_at: resetAt,
        updated_at: db.fn.now()
      };

      const exists = await db('cf_tenant_quota').where({ tenant_id: tenantId }).first();
      if (exists) {
        await db('cf_tenant_quota').where({ tenant_id: tenantId }).update(quotaData);
      } else {
        await db('cf_tenant_quota').insert({
          tenant_id: tenantId,
          ...quotaData,
          used_seats: 0,
          used_shops: 0,
          used_nodes: 0,
          used_tasks: 0,
          used_ai_calls: 0,
          created_at: db.fn.now()
        });
      }
      return true;
    } catch (error: any) {
      logger.error(`[QuotaService] Error updating quota: ${error.message}`);
      return false;
    }
  }

  /**
   * 重置周期性配额 (Tasks/AI Calls)
   */
  static async resetPeriodicQuota(tenantId: string): Promise<void> {
    try {
      await db('cf_tenant_quota')
        .where({ tenant_id: tenantId })
        .update({
          used_tasks: 0,
          used_ai_calls: 0,
          reset_at: db.fn.now(),
          updated_at: db.fn.now(),
        });
      logger.info(`[QuotaService] Reset periodic quota for tenant ${tenantId}`);
    } catch (error: any) {
      logger.error(`[QuotaService] Error resetting periodic quota: ${error.message}`);
    }
  }

  private static getLimitField(resourceType: ResourceType): string {
    switch (resourceType) {
      case 'seats': return 'seatsLimit';
      case 'shops': return 'shopsLimit';
      case 'nodes': return 'nodesLimit';
      case 'tasks': return 'taskMonthlyLimit';
      case 'ai_calls': return 'aiCallLimit';
      default: throw new Error(`Unknown resource type: ${resourceType}`);
    }
  }

  private static getUsageField(resourceType: ResourceType): string {
    switch (resourceType) {
      case 'seats': return 'usedSeats';
      case 'shops': return 'usedShops';
      case 'nodes': return 'usedNodes';
      case 'tasks': return 'usedTasks';
      case 'ai_calls': return 'usedAiCalls';
      default: throw new Error(`Unknown resource type: ${resourceType}`);
    }
  }
}
