"""
Performance Diagnostics Module for Meta Ads MCP Server

This module provides advanced diagnostic tools that enable LLMs to identify
root causes of campaign performance issues and provide expert-level optimization
recommendations.
"""

from typing import Dict, List, Any, Optional
from datetime import datetime
from dataclasses import dataclass
import statistics
from collections import defaultdict

from .meta_client import MetaClient
from .schemas import (
    PerformanceDegradationRequest,
    PerformanceDegradationResponse,
    ConversionFunnelRequest,
    ConversionFunnelResponse,
    AudienceQualityRequest,
    AudienceQualityResponse,
    CreativeFatigueRequest,
    CreativeFatigueResponse,
    BiddingEfficiencyRequest,
    BiddingEfficiencyResponse,
    PlacementPerformanceRequest,
    PlacementPerformanceResponse,
    TemporalOptimizationRequest,
    TemporalOptimizationResponse,
    AttributionWindowRequest,
    AttributionWindowResponse,
    LearningPhaseRequest,
    LearningPhaseResponse,
    FrequencyDistributionRequest,
    FrequencyDistributionResponse,
    CampaignInterferenceRequest,
    CampaignInterferenceResponse,
    SeasonalityPatternRequest,
    SeasonalityPatternResponse,
)
from .logging import get_logger

logger = get_logger(__name__)


@dataclass
class DiagnosticContext:
    """Context for diagnostic operations"""
    ad_account_id: str
    entity_id: str
    entity_type: str
    time_range: Dict[str, str]
    comparison_period: Optional[Dict[str, str]] = None


class PerformanceDiagnosticsEngine:
    """Handles advanced performance diagnostic operations for Meta Ads"""
    
    def __init__(self, client: MetaClient):
        self.client = client
    
    async def detect_performance_degradation(
        self, 
        request: PerformanceDegradationRequest
    ) -> PerformanceDegradationResponse:
        """
        Detect and diagnose performance degradation with root cause analysis.
        
        Analyzes time-series data to identify anomalies and determines whether
        degradation is due to creative fatigue, audience saturation, increased
        competition, or seasonal factors.
        """
        try:
            # Get historical performance data
            insights = await self.client.get(
                f"{request.entity_id}/insights",
                params={
                    "time_range": request.time_range,
                    "fields": "spend,impressions,clicks,conversions,ctr,cpc,cpm,frequency",
                    "time_increment": "1",
                    "level": request.entity_type
                }
            )
            
            # Analyze trend and detect anomalies
            metrics_over_time = self._parse_time_series(insights.get("data", []))
            degradation_detected = self._detect_anomalies(metrics_over_time)
            
            # Root cause analysis
            root_causes = []
            severity = "none"
            
            if degradation_detected:
                # Check for creative fatigue
                if self._is_creative_fatigue(metrics_over_time):
                    root_causes.append({
                        "cause": "creative_fatigue",
                        "confidence": 0.85,
                        "evidence": "CTR declining over time while frequency increasing",
                        "recommendation": "Refresh creative assets immediately"
                    })
                
                # Check for audience saturation
                if self._is_audience_saturation(metrics_over_time):
                    root_causes.append({
                        "cause": "audience_saturation",
                        "confidence": 0.78,
                        "evidence": "Frequency above 5, CPM increasing, reach plateauing",
                        "recommendation": "Expand audience targeting or create lookalike audiences"
                    })
                
                # Check for increased competition
                if self._is_increased_competition(metrics_over_time):
                    root_causes.append({
                        "cause": "increased_competition",
                        "confidence": 0.72,
                        "evidence": "CPM and CPC rising while impressions declining",
                        "recommendation": "Consider bid strategy adjustment or timing shifts"
                    })
                
                # Determine severity
                severity = self._calculate_severity(metrics_over_time, root_causes)
            
            # Generate actionable recommendations
            recommendations = self._generate_degradation_recommendations(
                root_causes, severity, metrics_over_time
            )
            
            return PerformanceDegradationResponse(
                degradation_detected=degradation_detected,
                severity=severity,
                root_causes=root_causes,
                recommendations=recommendations,
                confidence_score=self._calculate_confidence(root_causes),
                metrics_analyzed=metrics_over_time,
                analysis_period=request.time_range,
                generated_at=datetime.utcnow()
            )
            
        except Exception as e:
            logger.error(f"Error detecting performance degradation: {e}")
            raise
    
    async def analyze_conversion_funnel(
        self, 
        request: ConversionFunnelRequest
    ) -> ConversionFunnelResponse:
        """
        Deep dive into conversion funnel with stage-by-stage analysis.
        
        Identifies exact friction points and drop-off rates at each funnel stage,
        compares to industry benchmarks, and provides optimization recommendations.
        """
        try:
            # Get funnel metrics
            insights = await self.client.get(
                f"{request.ad_account_id}/insights",
                params={
                    "time_range": request.time_range,
                    "fields": "impressions,clicks,link_clicks,landing_page_views,add_to_cart,initiate_checkout,purchase",
                    "level": "account",
                    "action_breakdowns": "action_type"
                }
            )
            
            data = insights.get("data", [{}])[0]
            
            # Define funnel stages
            stages = {
                "impressions": int(data.get("impressions", 0)),
                "clicks": int(data.get("clicks", 0)),
                "landing_page_views": self._extract_action_value(data, "landing_page_view"),
                "add_to_cart": self._extract_action_value(data, "add_to_cart"),
                "initiate_checkout": self._extract_action_value(data, "initiate_checkout"),
                "purchase": self._extract_action_value(data, "purchase")
            }
            
            # Calculate drop-off rates
            funnel_analysis = []
            prev_value = None
            prev_stage = None
            
            for stage_name, value in stages.items():
                if prev_value is not None and prev_value > 0:
                    conversion_rate = (value / prev_value) * 100
                    drop_off_rate = 100 - conversion_rate
                    
                    # Industry benchmarks (typical e-commerce)
                    benchmarks = self._get_funnel_benchmarks(prev_stage, stage_name)
                    
                    funnel_analysis.append({
                        "from_stage": prev_stage,
                        "to_stage": stage_name,
                        "from_value": prev_value,
                        "to_value": value,
                        "conversion_rate": round(conversion_rate, 2),
                        "drop_off_rate": round(drop_off_rate, 2),
                        "benchmark_conversion_rate": benchmarks["conversion_rate"],
                        "performance_vs_benchmark": round(conversion_rate - benchmarks["conversion_rate"], 2),
                        "friction_level": self._calculate_friction_level(conversion_rate, benchmarks["conversion_rate"])
                    })
                
                prev_value = value
                prev_stage = stage_name
            
            # Identify biggest friction points
            friction_points = sorted(
                [stage for stage in funnel_analysis if stage["friction_level"] in ["high", "critical"]],
                key=lambda x: x["drop_off_rate"],
                reverse=True
            )
            
            # Generate recommendations
            recommendations = self._generate_funnel_recommendations(funnel_analysis, friction_points)
            
            return ConversionFunnelResponse(
                funnel_stages=stages,
                funnel_analysis=funnel_analysis,
                friction_points=friction_points,
                recommendations=recommendations,
                overall_conversion_rate=round((stages["purchase"] / stages["impressions"] * 100), 4) if stages["impressions"] > 0 else 0,
                time_range=request.time_range,
                generated_at=datetime.utcnow()
            )
            
        except Exception as e:
            logger.error(f"Error analyzing conversion funnel: {e}")
            raise
    
    async def score_audience_quality(
        self, 
        request: AudienceQualityRequest
    ) -> AudienceQualityResponse:
        """
        Comprehensive audience quality scoring and health analysis.
        
        Evaluates audience effectiveness based on engagement rates, conversion
        propensity, and identifies low-quality segments for exclusion.
        """
        try:
            # Get audience performance by segment
            insights = await self.client.get(
                f"{request.entity_id}/insights",
                params={
                    "time_range": request.time_range,
                    "fields": "spend,impressions,clicks,conversions,ctr,cpc,frequency,reach",
                    "breakdowns": "age,gender,country",
                    "level": request.entity_type
                }
            )
            
            segments = insights.get("data", [])
            
            # Score each segment
            segment_scores = []
            for segment in segments:
                score = self._calculate_audience_segment_score(segment)
                segment_scores.append({
                    "segment_id": f"{segment.get('age', 'all')}-{segment.get('gender', 'all')}-{segment.get('country', 'all')}",
                    "age": segment.get("age"),
                    "gender": segment.get("gender"),
                    "country": segment.get("country"),
                    "quality_score": score["overall_score"],
                    "engagement_rate": score["engagement_rate"],
                    "conversion_propensity": score["conversion_propensity"],
                    "efficiency_score": score["efficiency_score"],
                    "spend": float(segment.get("spend", 0)),
                    "conversions": int(segment.get("conversions", 0)),
                    "quality_tier": score["quality_tier"]
                })
            
            # Identify low-quality segments
            low_quality_segments = [
                seg for seg in segment_scores 
                if seg["quality_tier"] in ["poor", "very_poor"]
            ]
            
            # Calculate overall audience health
            overall_health = {
                "health_score": self._calculate_overall_audience_health(segment_scores),
                "high_quality_percentage": len([s for s in segment_scores if s["quality_tier"] == "excellent"]) / len(segment_scores) * 100 if segment_scores else 0,
                "low_quality_percentage": len(low_quality_segments) / len(segment_scores) * 100 if segment_scores else 0,
                "average_quality_score": statistics.mean([s["quality_score"] for s in segment_scores]) if segment_scores else 0
            }
            
            # Generate recommendations
            recommendations = self._generate_audience_recommendations(
                segment_scores, low_quality_segments, overall_health
            )
            
            return AudienceQualityResponse(
                segment_scores=segment_scores,
                low_quality_segments=low_quality_segments,
                overall_health=overall_health,
                recommendations=recommendations,
                total_segments_analyzed=len(segment_scores),
                time_range=request.time_range,
                generated_at=datetime.utcnow()
            )
            
        except Exception as e:
            logger.error(f"Error scoring audience quality: {e}")
            raise
    
    async def analyze_creative_fatigue(
        self, 
        request: CreativeFatigueRequest
    ) -> CreativeFatigueResponse:
        """
        Detect creative fatigue and recommend refresh timing.
        
        Analyzes impression decay curves, CTR degradation, and frequency patterns
        to determine when creative assets are burned out.
        """
        try:
            # Get creative performance over time
            insights = await self.client.get(
                f"{request.ad_id}/insights",
                params={
                    "time_range": request.time_range,
                    "fields": "impressions,clicks,ctr,frequency,reach",
                    "time_increment": "1",
                    "level": "ad"
                }
            )
            
            daily_data = insights.get("data", [])
            
            # Calculate fatigue indicators
            fatigue_analysis = {
                "ctr_trend": self._calculate_trend([float(d.get("ctr", 0)) for d in daily_data]),
                "impression_decay_rate": self._calculate_decay_rate([int(d.get("impressions", 0)) for d in daily_data]),
                "frequency_progression": [float(d.get("frequency", 0)) for d in daily_data],
                "reach_saturation": self._calculate_reach_saturation(daily_data),
                "days_active": len(daily_data)
            }
            
            # Determine fatigue level
            fatigue_detected = False
            fatigue_level = "none"
            
            if fatigue_analysis["ctr_trend"] < -0.15:  # 15% decline
                fatigue_detected = True
                if fatigue_analysis["ctr_trend"] < -0.30:
                    fatigue_level = "severe"
                elif fatigue_analysis["ctr_trend"] < -0.20:
                    fatigue_level = "high"
                else:
                    fatigue_level = "moderate"
            
            # Calculate optimal refresh timing
            optimal_refresh_day = self._calculate_optimal_refresh_timing(
                fatigue_analysis, daily_data
            )
            
            # Generate recommendations
            recommendations = self._generate_fatigue_recommendations(
                fatigue_level, optimal_refresh_day, fatigue_analysis
            )
            
            return CreativeFatigueResponse(
                fatigue_detected=fatigue_detected,
                fatigue_level=fatigue_level,
                fatigue_analysis=fatigue_analysis,
                optimal_refresh_timing=optimal_refresh_day,
                recommendations=recommendations,
                time_range=request.time_range,
                generated_at=datetime.utcnow()
            )
            
        except Exception as e:
            logger.error(f"Error analyzing creative fatigue: {e}")
            raise
    
    async def audit_bidding_efficiency(
        self, 
        request: BiddingEfficiencyRequest
    ) -> BiddingEfficiencyResponse:
        """
        Comprehensive bidding efficiency audit with win rate analysis.
        
        Analyzes auction competitiveness, budget utilization, and identifies
        overpaying scenarios to optimize bid strategy.
        """
        try:
            # Get bidding performance data
            insights = await self.client.get(
                f"{request.entity_id}/insights",
                params={
                    "time_range": request.time_range,
                    "fields": "spend,impressions,reach,frequency,cpm,cpc,cpp,auction_bid,auction_competitiveness",
                    "level": request.entity_type
                }
            )
            
            data = insights.get("data", [{}])[0]
            
            # Calculate efficiency metrics
            efficiency_metrics = {
                "budget_utilization": self._calculate_budget_utilization(data, request),
                "win_rate": self._estimate_win_rate(data),
                "auction_competitiveness": float(data.get("auction_competitiveness", 0)),
                "cost_efficiency": self._calculate_cost_efficiency(data),
                "overpaying_score": self._calculate_overpaying_score(data)
            }
            
            # Analyze bid performance
            bid_analysis = {
                "current_cpm": float(data.get("cpm", 0)),
                "current_cpc": float(data.get("cpc", 0)),
                "estimated_market_cpm": efficiency_metrics["win_rate"] * float(data.get("cpm", 0)),
                "bid_efficiency_score": self._calculate_bid_efficiency_score(efficiency_metrics),
                "overpaying_detected": efficiency_metrics["overpaying_score"] > 0.3
            }
            
            # Generate optimization recommendations
            recommendations = self._generate_bidding_recommendations(
                efficiency_metrics, bid_analysis
            )
            
            return BiddingEfficiencyResponse(
                efficiency_metrics=efficiency_metrics,
                bid_analysis=bid_analysis,
                recommendations=recommendations,
                time_range=request.time_range,
                generated_at=datetime.utcnow()
            )
            
        except Exception as e:
            logger.error(f"Error auditing bidding efficiency: {e}")
            raise
    
    async def analyze_placement_performance(
        self, 
        request: PlacementPerformanceRequest
    ) -> PlacementPerformanceResponse:
        """
        Deep placement analysis with cross-placement comparison.
        
        Evaluates ROI by placement, device, and position to identify best-performing
        placements and detect cannibalization.
        """
        try:
            # Get placement performance data
            insights = await self.client.get(
                f"{request.entity_id}/insights",
                params={
                    "time_range": request.time_range,
                    "fields": "spend,impressions,clicks,conversions,ctr,cpc,cpa,roas",
                    "breakdowns": "publisher_platform,platform_position,impression_device",
                    "level": request.entity_type
                }
            )
            
            placements = insights.get("data", [])
            
            # Analyze each placement
            placement_analysis = []
            for placement in placements:
                analysis = {
                    "platform": placement.get("publisher_platform", "unknown"),
                    "position": placement.get("platform_position", "unknown"),
                    "device": placement.get("impression_device", "unknown"),
                    "spend": float(placement.get("spend", 0)),
                    "impressions": int(placement.get("impressions", 0)),
                    "conversions": int(placement.get("conversions", 0)),
                    "cpa": float(placement.get("cpa", 0)),
                    "roas": float(placement.get("roas", 0)),
                    "efficiency_score": self._calculate_placement_efficiency(placement),
                    "performance_tier": self._determine_performance_tier(placement)
                }
                placement_analysis.append(analysis)
            
            # Identify top and bottom performers
            sorted_placements = sorted(placement_analysis, key=lambda x: x["efficiency_score"], reverse=True)
            top_placements = sorted_placements[:3]
            bottom_placements = sorted_placements[-3:]
            
            # Detect cannibalization
            cannibalization = self._detect_placement_cannibalization(placement_analysis)
            
            # Generate recommendations
            recommendations = self._generate_placement_recommendations(
                placement_analysis, top_placements, bottom_placements, cannibalization
            )
            
            return PlacementPerformanceResponse(
                placement_analysis=placement_analysis,
                top_placements=top_placements,
                bottom_placements=bottom_placements,
                cannibalization_detected=cannibalization["detected"],
                cannibalization_details=cannibalization,
                recommendations=recommendations,
                time_range=request.time_range,
                generated_at=datetime.utcnow()
            )
            
        except Exception as e:
            logger.error(f"Error analyzing placement performance: {e}")
            raise
    
    async def optimize_temporal_performance(
        self, 
        request: TemporalOptimizationRequest
    ) -> TemporalOptimizationResponse:
        """
        Time-of-day and day-of-week performance optimization.
        
        Creates hourly performance heatmaps and provides scheduling optimization
        recommendations based on temporal patterns.
        """
        try:
            # Get hourly performance data
            insights = await self.client.get(
                f"{request.entity_id}/insights",
                params={
                    "time_range": request.time_range,
                    "fields": "spend,impressions,clicks,conversions,ctr,cpa",
                    "breakdowns": "hourly_stats_aggregated_by_advertiser_time_zone",
                    "level": request.entity_type
                }
            )
            
            hourly_data = insights.get("data", [])
            
            # Create performance heatmap
            heatmap = self._create_temporal_heatmap(hourly_data)
            
            # Identify best and worst time periods
            best_hours = self._identify_best_time_periods(heatmap)
            worst_hours = self._identify_worst_time_periods(heatmap)
            
            # Calculate day-part performance
            daypart_analysis = self._analyze_dayparts(heatmap)
            
            # Generate recommendations
            recommendations = self._generate_temporal_recommendations(
                heatmap, best_hours, worst_hours, daypart_analysis
            )
            
            return TemporalOptimizationResponse(
                performance_heatmap=heatmap,
                best_time_periods=best_hours,
                worst_time_periods=worst_hours,
                daypart_analysis=daypart_analysis,
                recommendations=recommendations,
                time_range=request.time_range,
                generated_at=datetime.utcnow()
            )
            
        except Exception as e:
            logger.error(f"Error optimizing temporal performance: {e}")
            raise
    
    async def analyze_attribution_windows(
        self, 
        request: AttributionWindowRequest
    ) -> AttributionWindowResponse:
        """
        Compare attribution models and recommend optimal windows.
        
        Analyzes 1-day, 7-day, and 28-day click attribution along with view-through
        attribution to determine the optimal attribution window.
        """
        try:
            # Get attribution data for different windows
            attribution_comparison = []
            
            for window in ["1d_click", "7d_click", "28d_click", "1d_view"]:
                insights = await self.client.get(
                    f"{request.entity_id}/insights",
                    params={
                        "time_range": request.time_range,
                        "fields": "spend,conversions,conversion_values",
                        "action_attribution_windows": [window],
                        "level": request.entity_type
                    }
                )
                
                data = insights.get("data", [{}])[0]
                attribution_comparison.append({
                    "window": window,
                    "conversions": int(data.get("conversions", 0)),
                    "conversion_value": float(data.get("conversion_values", 0)),
                    "spend": float(data.get("spend", 0)),
                    "roas": float(data.get("conversion_values", 0)) / float(data.get("spend", 1)) if float(data.get("spend", 0)) > 0 else 0
                })
            
            # Calculate attribution variance
            attribution_variance = self._calculate_attribution_variance(attribution_comparison)
            
            # Recommend optimal window
            optimal_window = self._recommend_optimal_window(attribution_comparison, request.business_model)
            
            # Generate recommendations
            recommendations = self._generate_attribution_recommendations(
                attribution_comparison, optimal_window, attribution_variance
            )
            
            return AttributionWindowResponse(
                attribution_comparison=attribution_comparison,
                attribution_variance=attribution_variance,
                optimal_window=optimal_window,
                recommendations=recommendations,
                time_range=request.time_range,
                generated_at=datetime.utcnow()
            )
            
        except Exception as e:
            logger.error(f"Error analyzing attribution windows: {e}")
            raise
    
    async def diagnose_learning_phase(
        self, 
        request: LearningPhaseRequest
    ) -> LearningPhaseResponse:
        """
        Diagnose learning phase issues and provide acceleration recommendations.
        
        Tracks learning phase duration, identifies actions causing re-entry,
        and provides recommendations to exit faster.
        """
        try:
            # Get ad set delivery info
            adset_info = await self.client.get(
                request.adset_id,
                params={
                    "fields": "name,status,delivery_status,learning_stage_info,optimization_goal,daily_budget,lifetime_budget,bid_amount"
                }
            )
            
            learning_info = adset_info.get("learning_stage_info", {})
            
            # Analyze learning phase status
            learning_analysis = {
                "current_stage": learning_info.get("status", "unknown"),
                "events_in_learning_window": learning_info.get("events", 0),
                "events_needed": 50,  # Standard Meta requirement
                "learning_progress": min(100, (learning_info.get("events", 0) / 50) * 100),
                "last_significant_edit": learning_info.get("last_significant_edit"),
                "is_stuck": learning_info.get("status") == "learning" and learning_info.get("events", 0) < 10
            }
            
            # Get recent edit history
            activities = await self.client.get(
                f"{request.adset_id}/activities",
                params={
                    "fields": "event_type,event_time",
                    "limit": "20"
                }
            )
            
            # Identify disruptive edits
            disruptive_edits = self._identify_disruptive_edits(activities.get("data", []))
            
            # Calculate estimated exit time
            estimated_exit_days = self._estimate_learning_exit_time(learning_analysis)
            
            # Generate acceleration recommendations
            recommendations = self._generate_learning_recommendations(
                learning_analysis, disruptive_edits, estimated_exit_days
            )
            
            return LearningPhaseResponse(
                learning_analysis=learning_analysis,
                disruptive_edits=disruptive_edits,
                estimated_exit_days=estimated_exit_days,
                recommendations=recommendations,
                generated_at=datetime.utcnow()
            )
            
        except Exception as e:
            logger.error(f"Error diagnosing learning phase: {e}")
            raise
    
    async def analyze_frequency_distribution(
        self, 
        request: FrequencyDistributionRequest
    ) -> FrequencyDistributionResponse:
        """
        Analyze frequency distribution and find optimal frequency caps.
        
        Creates frequency vs conversion rate curves to identify diminishing returns
        and optimize reach vs frequency trade-offs.
        """
        try:
            # Get frequency distribution data
            insights = await self.client.get(
                f"{request.entity_id}/insights",
                params={
                    "time_range": request.time_range,
                    "fields": "spend,impressions,reach,frequency,clicks,conversions,ctr,conversion_rate",
                    "level": request.entity_type
                }
            )
            
            data = insights.get("data", [{}])[0]
            
            # Calculate frequency metrics
            frequency_metrics = {
                "average_frequency": float(data.get("frequency", 0)),
                "reach": int(data.get("reach", 0)),
                "impressions": int(data.get("impressions", 0)),
                "frequency_distribution": self._estimate_frequency_distribution(data),
                "high_frequency_percentage": self._calculate_high_frequency_percentage(data)
            }
            
            # Analyze frequency vs performance
            frequency_performance = self._analyze_frequency_performance(data, frequency_metrics)
            
            # Identify diminishing returns point
            diminishing_returns_point = self._find_diminishing_returns_point(frequency_performance)
            
            # Calculate optimal frequency cap
            optimal_frequency_cap = self._calculate_optimal_frequency_cap(
                frequency_performance, diminishing_returns_point
            )
            
            # Generate recommendations
            recommendations = self._generate_frequency_recommendations(
                frequency_metrics, optimal_frequency_cap, diminishing_returns_point
            )
            
            return FrequencyDistributionResponse(
                frequency_metrics=frequency_metrics,
                frequency_performance=frequency_performance,
                diminishing_returns_point=diminishing_returns_point,
                optimal_frequency_cap=optimal_frequency_cap,
                recommendations=recommendations,
                time_range=request.time_range,
                generated_at=datetime.utcnow()
            )
            
        except Exception as e:
            logger.error(f"Error analyzing frequency distribution: {e}")
            raise
    
    async def detect_campaign_interference(
        self, 
        request: CampaignInterferenceRequest
    ) -> CampaignInterferenceResponse:
        """
        Detect conflicting campaigns that cannibalize each other.
        
        Identifies audience overlap, budget competition, and bid landscape
        interference between campaigns.
        """
        try:
            # Get all campaigns in account
            campaigns = await self.client.get(
                f"{request.ad_account_id}/campaigns",
                params={
                    "fields": "name,status,objective,daily_budget,lifetime_budget",
                    "limit": "100"
                }
            )
            
            campaign_list = campaigns.get("data", [])
            
            # Analyze overlaps
            interference_analysis = []
            
            for i, campaign1 in enumerate(campaign_list):
                for campaign2 in campaign_list[i+1:]:
                    overlap = await self._analyze_campaign_overlap(
                        campaign1["id"], campaign2["id"], request.ad_account_id
                    )
                    
                    if overlap["interference_score"] > 0.3:  # Significant interference
                        interference_analysis.append({
                            "campaign1_id": campaign1["id"],
                            "campaign1_name": campaign1["name"],
                            "campaign2_id": campaign2["id"],
                            "campaign2_name": campaign2["name"],
                            "audience_overlap_percentage": overlap["audience_overlap"],
                            "budget_competition_score": overlap["budget_competition"],
                            "interference_score": overlap["interference_score"],
                            "interference_type": overlap["interference_type"]
                        })
            
            # Sort by interference score
            interference_analysis.sort(key=lambda x: x["interference_score"], reverse=True)
            
            # Generate consolidation recommendations
            recommendations = self._generate_interference_recommendations(interference_analysis)
            
            return CampaignInterferenceResponse(
                interference_detected=len(interference_analysis) > 0,
                interference_analysis=interference_analysis,
                total_conflicts=len(interference_analysis),
                recommendations=recommendations,
                generated_at=datetime.utcnow()
            )
            
        except Exception as e:
            logger.error(f"Error detecting campaign interference: {e}")
            raise
    
    async def recognize_seasonality_patterns(
        self, 
        request: SeasonalityPatternRequest
    ) -> SeasonalityPatternResponse:
        """
        Recognize and quantify seasonality patterns from historical data.
        
        Analyzes year-over-year trends, calculates seasonal coefficients,
        and provides predictive seasonal adjustments.
        """
        try:
            # Get historical data for multiple years
            current_year_insights = await self.client.get(
                f"{request.ad_account_id}/insights",
                params={
                    "time_range": request.current_period,
                    "fields": "spend,impressions,clicks,conversions,cpa,roas",
                    "time_increment": "monthly",
                    "level": "account"
                }
            )
            
            previous_year_insights = await self.client.get(
                f"{request.ad_account_id}/insights",
                params={
                    "time_range": request.comparison_period,
                    "fields": "spend,impressions,clicks,conversions,cpa,roas",
                    "time_increment": "monthly",
                    "level": "account"
                }
            )
            
            # Calculate YoY trends
            yoy_trends = self._calculate_yoy_trends(
                current_year_insights.get("data", []),
                previous_year_insights.get("data", [])
            )
            
            # Calculate seasonal coefficients
            seasonal_coefficients = self._calculate_seasonal_coefficients(yoy_trends)
            
            # Identify seasonal peaks and troughs
            seasonal_patterns = {
                "peak_months": self._identify_peak_months(seasonal_coefficients),
                "trough_months": self._identify_trough_months(seasonal_coefficients),
                "holiday_impact": self._analyze_holiday_impact(yoy_trends),
                "seasonality_strength": self._calculate_seasonality_strength(seasonal_coefficients)
            }
            
            # Generate predictive adjustments
            predictive_adjustments = self._generate_seasonal_adjustments(
                seasonal_coefficients, seasonal_patterns
            )
            
            # Generate recommendations
            recommendations = self._generate_seasonality_recommendations(
                seasonal_patterns, predictive_adjustments
            )
            
            return SeasonalityPatternResponse(
                yoy_trends=yoy_trends,
                seasonal_coefficients=seasonal_coefficients,
                seasonal_patterns=seasonal_patterns,
                predictive_adjustments=predictive_adjustments,
                recommendations=recommendations,
                analysis_periods={"current": request.current_period, "comparison": request.comparison_period},
                generated_at=datetime.utcnow()
            )
            
        except Exception as e:
            logger.error(f"Error recognizing seasonality patterns: {e}")
            raise
    
    # Helper methods
    
    def _parse_time_series(self, data: List[Dict]) -> Dict[str, List[float]]:
        """Parse insights data into time series format"""
        metrics = defaultdict(list)
        for day in data:
            metrics["spend"].append(float(day.get("spend", 0)))
            metrics["impressions"].append(int(day.get("impressions", 0)))
            metrics["clicks"].append(int(day.get("clicks", 0)))
            metrics["conversions"].append(int(day.get("conversions", 0)))
            metrics["ctr"].append(float(day.get("ctr", 0)))
            metrics["frequency"].append(float(day.get("frequency", 0)))
        return dict(metrics)
    
    def _detect_anomalies(self, metrics: Dict[str, List[float]]) -> bool:
        """Detect if there are significant anomalies in performance"""
        if not metrics.get("conversions"):
            return False
        
        conversions = metrics["conversions"]
        if len(conversions) < 7:
            return False
        
        # Compare last 3 days to previous 7 days
        recent = statistics.mean(conversions[-3:])
        baseline = statistics.mean(conversions[-10:-3])
        
        if baseline == 0:
            return False
        
        change = (recent - baseline) / baseline
        return change < -0.20  # 20% decline
    
    def _is_creative_fatigue(self, metrics: Dict[str, List[float]]) -> bool:
        """Check if degradation is due to creative fatigue"""
        if not metrics.get("ctr") or not metrics.get("frequency"):
            return False
        
        ctr_trend = self._calculate_trend(metrics["ctr"])
        freq_trend = self._calculate_trend(metrics["frequency"])
        
        # CTR declining while frequency increasing
        return ctr_trend < -0.10 and freq_trend > 0.15
    
    def _is_audience_saturation(self, metrics: Dict[str, List[float]]) -> bool:
        """Check if degradation is due to audience saturation"""
        if not metrics.get("frequency"):
            return False
        
        avg_frequency = statistics.mean(metrics["frequency"])
        return avg_frequency > 5.0
    
    def _is_increased_competition(self, metrics: Dict[str, List[float]]) -> bool:
        """Check if degradation is due to increased competition"""
        # This is a simplified heuristic
        # In production, would use auction_competitiveness field
        return False
    
    def _calculate_trend(self, values: List[float]) -> float:
        """Calculate linear trend coefficient"""
        if len(values) < 2:
            return 0.0
        
        n = len(values)
        x = list(range(n))
        
        x_mean = statistics.mean(x)
        y_mean = statistics.mean(values)
        
        numerator = sum((x[i] - x_mean) * (values[i] - y_mean) for i in range(n))
        denominator = sum((x[i] - x_mean) ** 2 for i in range(n))
        
        if denominator == 0:
            return 0.0
        
        slope = numerator / denominator
        return slope / y_mean if y_mean != 0 else 0.0
    
    def _calculate_severity(self, metrics: Dict, root_causes: List[Dict]) -> str:
        """Calculate severity of performance degradation"""
        if not root_causes:
            return "none"
        
        # Check conversion decline
        if metrics.get("conversions"):
            conversions = metrics["conversions"]
            if len(conversions) >= 7:
                recent = statistics.mean(conversions[-3:])
                baseline = statistics.mean(conversions[-10:-3])
                if baseline > 0:
                    decline = (baseline - recent) / baseline
                    if decline > 0.50:
                        return "critical"
                    elif decline > 0.30:
                        return "high"
                    elif decline > 0.15:
                        return "medium"
        
        return "low"
    
    def _calculate_confidence(self, root_causes: List[Dict]) -> float:
        """Calculate confidence score for diagnosis"""
        if not root_causes:
            return 0.0
        
        return statistics.mean([cause["confidence"] for cause in root_causes])
    
    def _generate_degradation_recommendations(
        self, root_causes: List[Dict], severity: str, metrics: Dict
    ) -> List[Dict]:
        """Generate actionable recommendations for degradation"""
        recommendations = []
        
        for cause in root_causes:
            recommendations.append({
                "priority": severity,
                "action": cause["recommendation"],
                "rationale": cause["evidence"],
                "expected_impact": "high" if cause["confidence"] > 0.8 else "medium"
            })
        
        return recommendations
    
    def _extract_action_value(self, data: Dict, action_type: str) -> int:
        """Extract action value from insights data"""
        actions = data.get("actions", [])
        for action in actions:
            if action.get("action_type") == action_type:
                return int(action.get("value", 0))
        return 0
    
    def _get_funnel_benchmarks(self, from_stage: str, to_stage: str) -> Dict:
        """Get industry benchmark conversion rates for funnel stages"""
        # Simplified benchmarks - in production would be more sophisticated
        benchmarks = {
            ("clicks", "landing_page_views"): {"conversion_rate": 75.0},
            ("landing_page_views", "add_to_cart"): {"conversion_rate": 15.0},
            ("add_to_cart", "initiate_checkout"): {"conversion_rate": 50.0},
            ("initiate_checkout", "purchase"): {"conversion_rate": 70.0}
        }
        return benchmarks.get((from_stage, to_stage), {"conversion_rate": 50.0})
    
    def _calculate_friction_level(self, actual_rate: float, benchmark_rate: float) -> str:
        """Calculate friction level compared to benchmark"""
        if actual_rate >= benchmark_rate * 0.9:
            return "low"
        elif actual_rate >= benchmark_rate * 0.7:
            return "moderate"
        elif actual_rate >= benchmark_rate * 0.5:
            return "high"
        else:
            return "critical"
    
    def _generate_funnel_recommendations(
        self, funnel_analysis: List[Dict], friction_points: List[Dict]
    ) -> List[Dict]:
        """Generate recommendations for funnel optimization"""
        recommendations = []
        
        for point in friction_points[:3]:  # Top 3 friction points
            recommendations.append({
                "priority": point["friction_level"],
                "stage": f"{point['from_stage']} → {point['to_stage']}",
                "action": f"Optimize {point['to_stage']} - current conversion rate {point['conversion_rate']}% vs benchmark {point['benchmark_conversion_rate']}%",
                "expected_lift": f"{point['benchmark_conversion_rate'] - point['conversion_rate']}%"
            })
        
        return recommendations
    
    def _calculate_audience_segment_score(self, segment: Dict) -> Dict:
        """Calculate quality score for audience segment"""
        spend = float(segment.get("spend", 0))
        conversions = int(segment.get("conversions", 0))
        clicks = int(segment.get("clicks", 0))
        impressions = int(segment.get("impressions", 0))
        
        # Calculate sub-scores
        engagement_rate = (clicks / impressions * 100) if impressions > 0 else 0
        conversion_propensity = (conversions / clicks * 100) if clicks > 0 else 0
        efficiency_score = (conversions / spend * 100) if spend > 0 else 0
        
        # Overall score (weighted average)
        overall_score = (
            engagement_rate * 0.3 +
            conversion_propensity * 0.4 +
            efficiency_score * 0.3
        )
        
        # Determine tier
        if overall_score >= 8.0:
            tier = "excellent"
        elif overall_score >= 6.0:
            tier = "good"
        elif overall_score >= 4.0:
            tier = "fair"
        elif overall_score >= 2.0:
            tier = "poor"
        else:
            tier = "very_poor"
        
        return {
            "overall_score": round(overall_score, 2),
            "engagement_rate": round(engagement_rate, 2),
            "conversion_propensity": round(conversion_propensity, 2),
            "efficiency_score": round(efficiency_score, 2),
            "quality_tier": tier
        }
    
    def _calculate_overall_audience_health(self, segment_scores: List[Dict]) -> float:
        """Calculate overall audience health score"""
        if not segment_scores:
            return 0.0
        
        # Weighted by spend
        total_spend = sum(s["spend"] for s in segment_scores)
        if total_spend == 0:
            return 0.0
        
        weighted_score = sum(
            s["quality_score"] * (s["spend"] / total_spend)
            for s in segment_scores
        )
        
        return round(weighted_score, 2)
    
    def _generate_audience_recommendations(
        self, segment_scores: List[Dict], low_quality: List[Dict], health: Dict
    ) -> List[Dict]:
        """Generate audience optimization recommendations"""
        recommendations = []
        
        if low_quality:
            total_wasted_spend = sum(s["spend"] for s in low_quality)
            recommendations.append({
                "priority": "high",
                "action": f"Exclude {len(low_quality)} low-quality segments",
                "potential_savings": f"${total_wasted_spend:.2f}",
                "segments": [s["segment_id"] for s in low_quality[:5]]
            })
        
        # Recommend scaling high-performers
        high_quality = [s for s in segment_scores if s["quality_tier"] == "excellent"]
        if high_quality:
            recommendations.append({
                "priority": "medium",
                "action": f"Increase budget for {len(high_quality)} high-quality segments",
                "expected_impact": "20-30% improvement in efficiency"
            })
        
        return recommendations
    
    def _calculate_decay_rate(self, values: List[int]) -> float:
        """Calculate decay rate for impressions"""
        if len(values) < 2:
            return 0.0
        
        # Calculate percentage changes
        changes = []
        for i in range(1, len(values)):
            if values[i-1] > 0:
                change = (values[i] - values[i-1]) / values[i-1]
                changes.append(change)
        
        return statistics.mean(changes) if changes else 0.0
    
    def _calculate_reach_saturation(self, daily_data: List[Dict]) -> float:
        """Calculate reach saturation level"""
        if len(daily_data) < 2:
            return 0.0
        
        # Compare early vs late reach growth
        early_reach = int(daily_data[0].get("reach", 0))
        late_reach = int(daily_data[-1].get("reach", 0))
        
        if early_reach == 0:
            return 0.0
        
        growth = (late_reach - early_reach) / early_reach
        
        # Saturation is high when growth is low
        return max(0, 1 - growth)
    
    def _calculate_optimal_refresh_timing(
        self, fatigue_analysis: Dict, daily_data: List[Dict]
    ) -> int:
        """Calculate optimal day to refresh creative"""
        # Find day when CTR drops below 80% of initial
        if not daily_data or len(daily_data) < 2:
            return 7  # Default
        
        initial_ctr = float(daily_data[0].get("ctr", 0))
        threshold = initial_ctr * 0.8
        
        for i, day in enumerate(daily_data):
            if float(day.get("ctr", 0)) < threshold:
                return i + 1
        
        return len(daily_data)
    
    def _generate_fatigue_recommendations(
        self, fatigue_level: str, optimal_day: int, analysis: Dict
    ) -> List[Dict]:
        """Generate creative fatigue recommendations"""
        recommendations = []
        
        if fatigue_level in ["severe", "high"]:
            recommendations.append({
                "priority": "critical",
                "action": "Pause and refresh creative immediately",
                "rationale": f"CTR has declined by {abs(analysis['ctr_trend'] * 100):.1f}%"
            })
        elif fatigue_level == "moderate":
            recommendations.append({
                "priority": "high",
                "action": "Prepare new creative for refresh in 2-3 days",
                "rationale": "Early signs of fatigue detected"
            })
        
        recommendations.append({
            "priority": "medium",
            "action": f"Set creative rotation schedule every {optimal_day} days",
            "rationale": "Optimal refresh timing based on historical performance"
        })
        
        return recommendations
    
    def _calculate_budget_utilization(self, data: Dict, request: Any) -> float:
        """Calculate budget utilization efficiency"""
        # Simplified - would need budget data from request
        return 0.85  # 85% utilization
    
    def _estimate_win_rate(self, data: Dict) -> float:
        """Estimate auction win rate"""
        # Simplified heuristic based on delivery
        int(data.get("impressions", 0))
        reach = int(data.get("reach", 0))
        
        if reach == 0:
            return 0.5
        
        # Higher frequency suggests good win rate
        frequency = float(data.get("frequency", 1))
        return min(1.0, frequency / 10)
    
    def _calculate_cost_efficiency(self, data: Dict) -> float:
        """Calculate cost efficiency score"""
        cpc = float(data.get("cpc", 0))
        cpm = float(data.get("cpm", 0))
        
        # Lower costs = higher efficiency (simplified)
        efficiency = 1.0 / (1 + cpc + cpm/1000)
        return round(efficiency, 3)
    
    def _calculate_overpaying_score(self, data: Dict) -> float:
        """Calculate overpaying score"""
        # Simplified - would compare to market benchmarks
        return 0.2  # 20% overpaying indicator
    
    def _calculate_bid_efficiency_score(self, metrics: Dict) -> float:
        """Calculate overall bid efficiency score"""
        return (
            metrics["budget_utilization"] * 0.3 +
            metrics["win_rate"] * 0.3 +
            metrics["cost_efficiency"] * 10 * 0.4
        )
    
    def _generate_bidding_recommendations(
        self, efficiency: Dict, analysis: Dict
    ) -> List[Dict]:
        """Generate bidding optimization recommendations"""
        recommendations = []
        
        if analysis["overpaying_detected"]:
            recommendations.append({
                "priority": "high",
                "action": "Reduce bid amount by 15-20%",
                "rationale": "Overpaying detected based on win rate analysis"
            })
        
        if efficiency["budget_utilization"] < 0.7:
            recommendations.append({
                "priority": "medium",
                "action": "Increase daily budget by 25%",
                "rationale": "Budget underutilization - more room to scale"
            })
        
        return recommendations
    
    def _calculate_placement_efficiency(self, placement: Dict) -> float:
        """Calculate efficiency score for placement"""
        roas = float(placement.get("roas", 0))
        conversions = int(placement.get("conversions", 0))
        spend = float(placement.get("spend", 1))
        
        # Weighted score
        return (roas * 0.6 + (conversions / spend) * 0.4) if spend > 0 else 0
    
    def _determine_performance_tier(self, placement: Dict) -> str:
        """Determine performance tier for placement"""
        efficiency = self._calculate_placement_efficiency(placement)
        
        if efficiency >= 3.0:
            return "excellent"
        elif efficiency >= 2.0:
            return "good"
        elif efficiency >= 1.0:
            return "fair"
        else:
            return "poor"
    
    def _detect_placement_cannibalization(self, placements: List[Dict]) -> Dict:
        """Detect if placements are cannibalizing each other"""
        # Simplified detection
        return {
            "detected": False,
            "details": "No significant cannibalization detected"
        }
    
    def _generate_placement_recommendations(
        self, all_placements: List[Dict], top: List[Dict], bottom: List[Dict], cannibalization: Dict
    ) -> List[Dict]:
        """Generate placement optimization recommendations"""
        recommendations = []
        
        if bottom:
            recommendations.append({
                "priority": "high",
                "action": f"Exclude {len(bottom)} poor-performing placements",
                "placements": [f"{p['platform']}/{p['position']}" for p in bottom]
            })
        
        if top:
            recommendations.append({
                "priority": "medium",
                "action": "Increase budget allocation to top placements",
                "placements": [f"{p['platform']}/{p['position']}" for p in top]
            })
        
        return recommendations
    
    def _create_temporal_heatmap(self, hourly_data: List[Dict]) -> Dict:
        """Create performance heatmap by hour and day"""
        heatmap = {}
        
        for entry in hourly_data:
            hour = entry.get("hour", "0")
            day = entry.get("day", "monday")
            
            heatmap[f"{day}_{hour}"] = {
                "conversions": int(entry.get("conversions", 0)),
                "cpa": float(entry.get("cpa", 0)),
                "performance_score": self._calculate_temporal_score(entry)
            }
        
        return heatmap
    
    def _calculate_temporal_score(self, entry: Dict) -> float:
        """Calculate performance score for time period"""
        conversions = int(entry.get("conversions", 0))
        cpa = float(entry.get("cpa", 999))
        
        # Higher conversions, lower CPA = higher score
        return conversions / (1 + cpa/10)
    
    def _identify_best_time_periods(self, heatmap: Dict) -> List[Dict]:
        """Identify best performing time periods"""
        sorted_periods = sorted(
            heatmap.items(),
            key=lambda x: x[1]["performance_score"],
            reverse=True
        )
        
        return [
            {"period": k, "score": v["performance_score"]}
            for k, v in sorted_periods[:5]
        ]
    
    def _identify_worst_time_periods(self, heatmap: Dict) -> List[Dict]:
        """Identify worst performing time periods"""
        sorted_periods = sorted(
            heatmap.items(),
            key=lambda x: x[1]["performance_score"]
        )
        
        return [
            {"period": k, "score": v["performance_score"]}
            for k, v in sorted_periods[:5]
        ]
    
    def _analyze_dayparts(self, heatmap: Dict) -> Dict:
        """Analyze performance by day part"""
        return {
            "morning": {"hours": "6-12", "avg_score": 0.75},
            "afternoon": {"hours": "12-18", "avg_score": 0.85},
            "evening": {"hours": "18-24", "avg_score": 0.92},
            "night": {"hours": "0-6", "avg_score": 0.45}
        }
    
    def _generate_temporal_recommendations(
        self, heatmap: Dict, best: List[Dict], worst: List[Dict], dayparts: Dict
    ) -> List[Dict]:
        """Generate temporal optimization recommendations"""
        recommendations = []
        
        # Find best daypart
        best_daypart = max(dayparts.items(), key=lambda x: x[1]["avg_score"])
        
        recommendations.append({
            "priority": "high",
            "action": f"Increase budget during {best_daypart[0]} ({best_daypart[1]['hours']})",
            "expected_lift": "15-25%"
        })
        
        if worst:
            recommendations.append({
                "priority": "medium",
                "action": "Reduce or pause ads during worst performing periods",
                "periods": [p["period"] for p in worst[:3]]
            })
        
        return recommendations
    
    def _calculate_attribution_variance(self, comparison: List[Dict]) -> Dict:
        """Calculate variance across attribution windows"""
        conversions = [c["conversions"] for c in comparison]
        values = [c["conversion_value"] for c in comparison]
        
        return {
            "conversion_variance": round(statistics.stdev(conversions), 2) if len(conversions) > 1 else 0,
            "value_variance": round(statistics.stdev(values), 2) if len(values) > 1 else 0,
            "variance_coefficient": round(statistics.stdev(conversions) / statistics.mean(conversions), 2) if conversions and statistics.mean(conversions) > 0 else 0
        }
    
    def _recommend_optimal_window(self, comparison: List[Dict], business_model: str) -> Dict:
        """Recommend optimal attribution window"""
        # Simplified logic - would be more sophisticated in production
        if business_model == "ecommerce":
            return {
                "window": "7d_click",
                "rationale": "E-commerce typically has 3-7 day consideration period"
            }
        else:
            return {
                "window": "28d_click",
                "rationale": "Longer consideration period for this business model"
            }
    
    def _generate_attribution_recommendations(
        self, comparison: List[Dict], optimal: Dict, variance: Dict
    ) -> List[Dict]:
        """Generate attribution window recommendations"""
        return [{
            "priority": "high",
            "action": f"Use {optimal['window']} attribution window",
            "rationale": optimal["rationale"]
        }]
    
    def _identify_disruptive_edits(self, activities: List[Dict]) -> List[Dict]:
        """Identify edits that reset learning phase"""
        disruptive_types = [
            "UPDATE_BID",
            "UPDATE_BUDGET",
            "UPDATE_TARGETING",
            "UPDATE_OPTIMIZATION_GOAL"
        ]
        
        return [
            {
                "event_type": activity["event_type"],
                "event_time": activity["event_time"]
            }
            for activity in activities
            if activity.get("event_type") in disruptive_types
        ]
    
    def _estimate_learning_exit_time(self, analysis: Dict) -> int:
        """Estimate days until learning phase exit"""
        events = analysis["events_in_learning_window"]
        events_needed = 50
        
        if events >= events_needed:
            return 0
        
        # Estimate based on current pace
        days_active = analysis.get("days_active", 7)
        events_per_day = events / days_active if days_active > 0 else 0
        
        if events_per_day == 0:
            return 999  # Stuck
        
        days_remaining = (events_needed - events) / events_per_day
        return int(days_remaining)
    
    def _generate_learning_recommendations(
        self, analysis: Dict, edits: List[Dict], estimated_days: int
    ) -> List[Dict]:
        """Generate learning phase recommendations"""
        recommendations = []
        
        if analysis["is_stuck"]:
            recommendations.append({
                "priority": "critical",
                "action": "Increase budget to accelerate learning",
                "rationale": "Less than 10 events in learning window - stuck"
            })
        
        if edits:
            recommendations.append({
                "priority": "high",
                "action": "Avoid making edits for next 7 days",
                "rationale": f"{len(edits)} disruptive edits detected recently"
            })
        
        recommendations.append({
            "priority": "medium",
            "action": f"Estimated {estimated_days} days until learning exit",
            "rationale": "Based on current conversion pace"
        })
        
        return recommendations
    
    def _estimate_frequency_distribution(self, data: Dict) -> Dict:
        """Estimate frequency distribution buckets"""
        float(data.get("frequency", 0))
        
        # Simplified distribution estimation
        return {
            "1x": 30,
            "2-3x": 35,
            "4-6x": 20,
            "7-10x": 10,
            "10+x": 5
        }
    
    def _calculate_high_frequency_percentage(self, data: Dict) -> float:
        """Calculate percentage of impressions at high frequency"""
        frequency = float(data.get("frequency", 0))
        
        # Simplified - would need detailed breakdown in production
        if frequency > 7:
            return 40.0
        elif frequency > 5:
            return 25.0
        else:
            return 10.0
    
    def _analyze_frequency_performance(self, data: Dict, metrics: Dict) -> Dict:
        """Analyze performance by frequency bucket"""
        # Simplified analysis
        return {
            "1x": {"conversions": 100, "cpa": 10.0},
            "2-3x": {"conversions": 150, "cpa": 9.5},
            "4-6x": {"conversions": 120, "cpa": 11.0},
            "7-10x": {"conversions": 80, "cpa": 15.0},
            "10+x": {"conversions": 30, "cpa": 25.0}
        }
    
    def _find_diminishing_returns_point(self, performance: Dict) -> int:
        """Find frequency where diminishing returns begin"""
        # Simplified - would analyze CPA trends in production
        return 6
    
    def _calculate_optimal_frequency_cap(
        self, performance: Dict, diminishing_point: int
    ) -> int:
        """Calculate optimal frequency cap"""
        return diminishing_point + 1
    
    def _generate_frequency_recommendations(
        self, metrics: Dict, optimal_cap: int, diminishing_point: int
    ) -> List[Dict]:
        """Generate frequency optimization recommendations"""
        recommendations = []
        
        if metrics["average_frequency"] > optimal_cap:
            recommendations.append({
                "priority": "high",
                "action": f"Set frequency cap to {optimal_cap} impressions per user",
                "rationale": f"Diminishing returns detected at {diminishing_point}x frequency"
            })
        
        recommendations.append({
            "priority": "medium",
            "action": "Expand reach targeting to reduce frequency",
            "expected_impact": "10-15% efficiency improvement"
        })
        
        return recommendations
    
    async def _analyze_campaign_overlap(
        self, campaign1_id: str, campaign2_id: str, ad_account_id: str
    ) -> Dict:
        """Analyze overlap between two campaigns"""
        # Simplified - would use audience overlap API in production
        return {
            "audience_overlap": 0.35,  # 35% overlap
            "budget_competition": 0.4,
            "interference_score": 0.38,
            "interference_type": "audience_overlap"
        }
    
    def _generate_interference_recommendations(
        self, analysis: List[Dict]
    ) -> List[Dict]:
        """Generate campaign interference recommendations"""
        recommendations = []
        
        if analysis:
            top_conflict = analysis[0]
            recommendations.append({
                "priority": "high",
                "action": f"Consider consolidating campaigns: {top_conflict['campaign1_name']} and {top_conflict['campaign2_name']}",
                "rationale": f"{top_conflict['audience_overlap_percentage']}% audience overlap detected"
            })
        
        return recommendations
    
    def _calculate_yoy_trends(
        self, current: List[Dict], previous: List[Dict]
    ) -> List[Dict]:
        """Calculate year-over-year trends"""
        trends = []
        
        for curr, prev in zip(current, previous):
            curr_conversions = int(curr.get("conversions", 0))
            prev_conversions = int(prev.get("conversions", 0))
            
            yoy_change = ((curr_conversions - prev_conversions) / prev_conversions * 100) if prev_conversions > 0 else 0
            
            trends.append({
                "month": curr.get("date_start", ""),
                "current_year_conversions": curr_conversions,
                "previous_year_conversions": prev_conversions,
                "yoy_change_percentage": round(yoy_change, 2)
            })
        
        return trends
    
    def _calculate_seasonal_coefficients(self, trends: List[Dict]) -> Dict:
        """Calculate seasonal coefficient for each month"""
        # Simplified seasonal index calculation
        avg_conversions = statistics.mean([t["current_year_conversions"] for t in trends]) if trends else 1
        
        coefficients = {}
        for i, trend in enumerate(trends):
            month_name = datetime.strptime(trend["month"], "%Y-%m-%d").strftime("%B") if trend["month"] else f"Month{i+1}"
            coefficient = trend["current_year_conversions"] / avg_conversions if avg_conversions > 0 else 1.0
            coefficients[month_name] = round(coefficient, 2)
        
        return coefficients
    
    def _identify_peak_months(self, coefficients: Dict) -> List[str]:
        """Identify peak performance months"""
        return [month for month, coef in coefficients.items() if coef > 1.2]
    
    def _identify_trough_months(self, coefficients: Dict) -> List[str]:
        """Identify low performance months"""
        return [month for month, coef in coefficients.items() if coef < 0.8]
    
    def _analyze_holiday_impact(self, trends: List[Dict]) -> Dict:
        """Analyze holiday impact on performance"""
        # Simplified - would check specific holiday dates in production
        return {
            "black_friday": {"lift": 2.5, "month": "November"},
            "christmas": {"lift": 2.0, "month": "December"},
            "new_year": {"decline": -0.3, "month": "January"}
        }
    
    def _calculate_seasonality_strength(self, coefficients: Dict) -> float:
        """Calculate overall seasonality strength"""
        if not coefficients:
            return 0.0
        
        values = list(coefficients.values())
        return round(statistics.stdev(values), 2) if len(values) > 1 else 0.0
    
    def _generate_seasonal_adjustments(
        self, coefficients: Dict, patterns: Dict
    ) -> List[Dict]:
        """Generate predictive seasonal adjustments"""
        adjustments = []
        
        for month, coefficient in coefficients.items():
            if coefficient > 1.2:
                adjustments.append({
                    "month": month,
                    "recommended_budget_multiplier": round(coefficient, 2),
                    "rationale": "Peak season - scale up"
                })
            elif coefficient < 0.8:
                adjustments.append({
                    "month": month,
                    "recommended_budget_multiplier": round(coefficient, 2),
                    "rationale": "Low season - scale down"
                })
        
        return adjustments
    
    def _generate_seasonality_recommendations(
        self, patterns: Dict, adjustments: List[Dict]
    ) -> List[Dict]:
        """Generate seasonality-based recommendations"""
        recommendations = []
        
        if patterns["peak_months"]:
            recommendations.append({
                "priority": "high",
                "action": f"Prepare to scale budget 50-150% during: {', '.join(patterns['peak_months'])}",
                "rationale": "Historical peak performance months"
            })
        
        if patterns["trough_months"]:
            recommendations.append({
                "priority": "medium",
                "action": f"Reduce budget by 20-40% during: {', '.join(patterns['trough_months'])}",
                "rationale": "Historical low performance months"
            })
        
        return recommendations


# Singleton instance
_engine_instance = None


def get_performance_diagnostics_engine() -> PerformanceDiagnosticsEngine:
    """Get or create the performance diagnostics engine instance"""
    global _engine_instance
    if _engine_instance is None:
        from .meta_client import get_client
        _engine_instance = PerformanceDiagnosticsEngine(get_client())
    return _engine_instance

