import { Injectable, Logger } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { Rule, RuleAction, RuleConditionMetric, RuleConditionOperator } from '../entities/rule.entity';
import { MetaAdsService } from '../../meta-ads/services/meta-ads.service';
import { NormalizedCampaignInsight } from '../../meta-ads/interfaces/campaign-insight.interface';
import { MetaLevel } from '../../meta-ads/dto/fetch-insights.dto';
import { NotificationService } from '../../notifications/services/notification.service';

@Injectable()
/**
 * RuleEngineService: محرك القواعد والأتمتة
 * هذا الملف هو "العقل" الذي يراقب الإعلانات ويتخذ قرارات تلقائية (Auto-Pilot)
 */
export class RuleEngineService {
  private readonly logger = new Logger(RuleEngineService.name);

  /**
   * constructor: هنا يحدث "حقن التبعيات" (Dependency Injection)
   * بدلاً من إنشاء الخدمات يدوياً، نطلب من NestJS تزويدنا بها جاهزة
   * 
   * @param ruleRepository - المرجع للتعامل مع جدول القواعد في قاعدة البيانات
   * @param metaAdsService - الخدمة المسؤولة عن التواصل مع واجهة برمجة تطبيقات ميتا
   * @param notificationService - الخدمة المسؤولة عن إرسال التنبيهات (Telegram/Slack/FCM)
   */
  constructor(
    @InjectRepository(Rule)
    private readonly ruleRepository: Repository<Rule>,
    private readonly metaAdsService: MetaAdsService,
    private readonly notificationService: NotificationService,
  ) {}

  /**
   * Process all active rules for a specific platform
   * معالجة جميع القواعد النشطة لمنصة معينة
   */
  async processActiveRules(platform: 'meta' | 'tiktok' | 'google'): Promise<void> {
    const activeRules = await this.ruleRepository.find({
      where: { isActive: true, platform },
      relations: ['user'],
    });

    this.logger.log(`Processing ${activeRules.length} active rules for ${platform}`);

    for (const rule of activeRules) {
      try {
        await this.evaluateRule(rule);
      } catch (error) {
        this.logger.error(`Error processing rule ${rule.id}: ${error.message}`);
      }
    }
  }

  /**
   * Evaluate a single rule against live API data
   */
  private async evaluateRule(rule: Rule): Promise<void> {
    const userId = rule.user.id;
    
    // 1. Fetch live metrics based on platform
    if (rule.platform === 'meta') {
      const accounts = await this.metaAdsService.getConnectedAccounts(userId);
      for (const account of accounts) {
        // If rule targets a specific account ID or 'all'
        const insights = await this.metaAdsService.fetchInsights({ 
          userId, 
          adAccountId: account.externalAdAccountId,
          level: MetaLevel.CAMPAIGN 
        });
        
        for (const insight of insights) {
          // If rule targets a specific campaign, skip others
          if (rule.targetId !== 'all' && insight.campaignId !== rule.targetId) continue;

          const isTriggered = this.checkConditions(rule, insight);
          
          if (isTriggered) {
            this.logger.warn(`Rule "${rule.name}" TRIGGERED for campaign ${insight.campaignName} (User: ${userId})`);
            await this.executeAction(rule, insight, account.accessToken);
          }
        }
      }
    }
  }

  /**
   * Check if metrics meet rule conditions
   */
  private checkConditions(rule: Rule, data: NormalizedCampaignInsight): boolean {
    return rule.conditions.every((condition) => {
      const metricValue = this.getMetricValue(data, condition.metric);
      
      switch (condition.operator) {
        case RuleConditionOperator.GREATER_THAN:
          return metricValue > condition.value;
        case RuleConditionOperator.LESS_THAN:
          return metricValue < condition.value;
        case RuleConditionOperator.EQUAL:
          return metricValue === condition.value;
        default:
          return false;
      }
    });
  }

  /**
   * Extract specific metric from normalized data
   */
  private getMetricValue(data: NormalizedCampaignInsight, metric: RuleConditionMetric): number {
    switch (metric) {
      case RuleConditionMetric.SPEND: return data.spend;
      case RuleConditionMetric.ROAS: return data.spend > 0 ? (data.clicks * 2) / data.spend : 0; // Mock ROAS logic
      case RuleConditionMetric.CPA: return data.clicks > 0 ? data.spend / data.clicks : 0;
      case RuleConditionMetric.CTR: return data.ctr;
      case RuleConditionMetric.CLICKS: return data.clicks;
      default: return 0;
    }
  }

  /**
   * Execute the defined action (e.g., Pause Ad)
   */
  private async executeAction(rule: Rule, data: NormalizedCampaignInsight, accessToken?: string): Promise<void> {
    switch (rule.action) {
      case RuleAction.PAUSE:
        this.logger.log(`ACTION: Pausing campaign ${data.campaignId}`);
        if (accessToken) {
          await this.metaAdsService.updateAdStatus(data.campaignId, accessToken, 'PAUSED');
        } else {
          this.logger.warn(`Cannot update status: No access token for account.`);
        }
        break;
      
      case RuleAction.NOTIFY:
        this.logger.log(`ACTION: Sending notification for campaign ${data.campaignName}`);
        
        const channels: ('telegram' | 'fcm')[] = ['telegram'];
        if (rule.user?.fcmToken) {
          channels.push('fcm');
        }

        await this.notificationService.send(
          `🔔 تنبيه الأتمتة: القاعدة "${rule.name}" تحققت لحملة: ${data.campaignName}.\nالمؤشر: ${rule.conditions[0].metric} ${rule.conditions[0].operator} ${rule.conditions[0].value}`,
          channels,
          { fcmToken: rule.user?.fcmToken },
        );
        break;
      
      default:
        this.logger.log(`No action defined for rule ${rule.id}`);
    }
  }
}
