"""
Data retrieval tools for comprehensive Meta Ads data access.

This module provides tools for retrieving detailed historical data,
granular performance metrics, and batch data operations.
"""

from datetime import datetime
from typing import Any, Dict, List, Optional

from .meta_client import MetaClient
from .errors import MetaApiError
from .logging import get_logger

logger = get_logger(__name__)


class HistoricalDataRetriever:
    """Retrieves comprehensive historical data for analysis."""

    def __init__(self, client: MetaClient):
        self._client = client

    async def get_campaign_performance_history(
        self,
        campaign_id: str,
        start_date: str,
        end_date: str,
        breakdowns: Optional[List[str]] = None,
        fields: List[str] = None,
        time_increment: int = 1,
    ) -> Dict[str, Any]:
        """
        Get detailed historical performance data for a campaign.
        """
        if fields is None:
            fields = ["spend", "impressions", "clicks", "ctr", "cpc", "cpm", "conversions"]

        params = {
            "fields": ",".join(fields),
            "time_range": {"since": start_date, "until": end_date},
            "time_increment": time_increment,
        }

        if breakdowns:
            params["breakdowns"] = ",".join(breakdowns)

        try:
            response = await self._client.get(f"{campaign_id}/insights", params=params)
            
            # Process and structure the data
            insights_data = response.get("data", [])
            
            # Calculate summary statistics
            total_spend = sum(float(insight.get("spend", 0)) for insight in insights_data)
            total_impressions = sum(int(insight.get("impressions", 0)) for insight in insights_data)
            total_clicks = sum(int(insight.get("clicks", 0)) for insight in insights_data)
            total_conversions = sum(
                sum(action.get("value", 0) for action in insight.get("actions", []) 
                    if action.get("action_type") == "offsite_conversion.fb_pixel_purchase")
                for insight in insights_data
            )

            return {
                "campaign_id": campaign_id,
                "date_range": {"start": start_date, "end": end_date},
                "summary": {
                    "total_spend": total_spend,
                    "total_impressions": total_impressions,
                    "total_clicks": total_clicks,
                    "total_conversions": total_conversions,
                    "avg_ctr": total_clicks / total_impressions if total_impressions > 0 else 0,
                    "avg_cpc": total_spend / total_clicks if total_clicks > 0 else 0,
                },
                "daily_data": insights_data,
                "breakdowns": breakdowns,
                "next_recommended_actions": [
                    "Analyze performance trends over time",
                    "Compare with previous periods",
                    "Identify best performing days/segments",
                ],
            }
        except MetaApiError as exc:
            logger.error("Failed to get campaign performance history", campaign_id=campaign_id, error=exc.to_dict())
            raise

    async def get_spend_trends(
        self,
        ad_account_id: str,
        start_date: str,
        end_date: str,
        group_by: str = "day",
        include_forecast: bool = False,
    ) -> Dict[str, Any]:
        """
        Get spending patterns over time with optional forecasting.
        """
        params = {
            "fields": "spend,impressions,clicks",
            "time_range": {"since": start_date, "until": end_date},
            "time_increment": 1 if group_by == "day" else 7 if group_by == "week" else 30,
        }

        try:
            response = await self._client.get(f"{ad_account_id}/insights", params=params)
            insights_data = response.get("data", [])

            # Process spending data
            spend_data = []
            total_spend = 0
            for insight in insights_data:
                spend = float(insight.get("spend", 0))
                spend_data.append({
                    "date": insight.get("date_start"),
                    "spend": spend,
                    "impressions": int(insight.get("impressions", 0)),
                    "clicks": int(insight.get("clicks", 0)),
                })
                total_spend += spend

            # Calculate trends
            if len(spend_data) > 1:
                first_spend = spend_data[0]["spend"]
                last_spend = spend_data[-1]["spend"]
                spend_trend = ((last_spend - first_spend) / first_spend * 100) if first_spend > 0 else 0
            else:
                spend_trend = 0

            result = {
                "ad_account_id": ad_account_id,
                "date_range": {"start": start_date, "end": end_date},
                "group_by": group_by,
                "total_spend": total_spend,
                "spend_trend_percentage": spend_trend,
                "daily_spend": spend_data,
                "summary": {
                    "avg_daily_spend": total_spend / len(spend_data) if spend_data else 0,
                    "max_daily_spend": max(item["spend"] for item in spend_data) if spend_data else 0,
                    "min_daily_spend": min(item["spend"] for item in spend_data) if spend_data else 0,
                },
            }

            # Add simple forecast if requested
            if include_forecast and len(spend_data) >= 7:
                recent_avg = sum(item["spend"] for item in spend_data[-7:]) / 7
                result["forecast"] = {
                    "next_7_days_estimated": recent_avg * 7,
                    "next_30_days_estimated": recent_avg * 30,
                    "confidence": "medium",  # Simple forecast
                }

            result["next_recommended_actions"] = [
                "Analyze spending patterns for optimization opportunities",
                "Compare spending trends with performance metrics",
                "Identify high-spend, low-performance periods",
            ]

            return result
        except MetaApiError as exc:
            logger.error("Failed to get spend trends", ad_account_id=ad_account_id, error=exc.to_dict())
            raise

    async def get_audience_performance_history(
        self,
        ad_account_id: str,
        start_date: str,
        end_date: str,
        audience_ids: Optional[List[str]] = None,
        breakdowns: List[str] = None,
    ) -> Dict[str, Any]:
        """
        Get historical performance data for audience segments.
        """
        if breakdowns is None:
            breakdowns = ["age", "gender"]

        params = {
            "fields": "spend,impressions,clicks,ctr,cpc,conversions",
            "time_range": {"since": start_date, "until": end_date},
            "breakdowns": ",".join(breakdowns),
        }

        if audience_ids:
            params["filtering"] = [{"field": "adset.id", "operator": "IN", "value": audience_ids}]

        try:
            response = await self._client.get(f"{ad_account_id}/insights", params=params)
            insights_data = response.get("data", [])

            # Group by audience segments
            audience_performance = {}
            for insight in insights_data:
                # Extract audience segment info from breakdowns
                segment_key = "_".join([
                    insight.get(f"breakdowns.{breakdown}", "unknown") 
                    for breakdown in breakdowns
                ])
                
                if segment_key not in audience_performance:
                    audience_performance[segment_key] = {
                        "segment": segment_key,
                        "total_spend": 0,
                        "total_impressions": 0,
                        "total_clicks": 0,
                        "total_conversions": 0,
                        "daily_data": [],
                    }

                spend = float(insight.get("spend", 0))
                impressions = int(insight.get("impressions", 0))
                clicks = int(insight.get("clicks", 0))
                conversions = sum(
                    action.get("value", 0) for action in insight.get("actions", [])
                    if action.get("action_type") == "offsite_conversion.fb_pixel_purchase"
                )

                audience_performance[segment_key]["total_spend"] += spend
                audience_performance[segment_key]["total_impressions"] += impressions
                audience_performance[segment_key]["total_clicks"] += clicks
                audience_performance[segment_key]["total_conversions"] += conversions
                audience_performance[segment_key]["daily_data"].append(insight)

            # Calculate efficiency metrics
            for segment_data in audience_performance.values():
                if segment_data["total_clicks"] > 0:
                    segment_data["avg_ctr"] = segment_data["total_clicks"] / segment_data["total_impressions"]
                    segment_data["avg_cpc"] = segment_data["total_spend"] / segment_data["total_clicks"]
                else:
                    segment_data["avg_ctr"] = 0
                    segment_data["avg_cpc"] = 0

            return {
                "ad_account_id": ad_account_id,
                "date_range": {"start": start_date, "end": end_date},
                "breakdowns": breakdowns,
                "audience_segments": list(audience_performance.values()),
                "summary": {
                    "total_segments": len(audience_performance),
                    "best_performing_segment": max(
                        audience_performance.values(),
                        key=lambda x: x["total_conversions"]
                    )["segment"] if audience_performance else None,
                },
                "next_recommended_actions": [
                    "Identify top-performing audience segments",
                    "Analyze segment performance trends",
                    "Consider expanding successful segments",
                ],
            }
        except MetaApiError as exc:
            logger.error("Failed to get audience performance history", ad_account_id=ad_account_id, error=exc.to_dict())
            raise

    async def get_creative_performance_history(
        self,
        ad_account_id: str,
        start_date: str,
        end_date: str,
        creative_ids: Optional[List[str]] = None,
        include_fatigue_analysis: bool = True,
    ) -> Dict[str, Any]:
        """
        Get historical creative performance with fatigue analysis.
        """
        params = {
            "fields": "spend,impressions,clicks,ctr,cpc,conversions,reach,frequency",
            "time_range": {"since": start_date, "until": end_date},
            "breakdowns": "creative_id",
        }

        if creative_ids:
            params["filtering"] = [{"field": "creative.id", "operator": "IN", "value": creative_ids}]

        try:
            response = await self._client.get(f"{ad_account_id}/insights", params=params)
            insights_data = response.get("data", [])

            # Group by creative
            creative_performance = {}
            for insight in insights_data:
                creative_id = insight.get("breakdowns.creative_id", "unknown")
                
                if creative_id not in creative_performance:
                    creative_performance[creative_id] = {
                        "creative_id": creative_id,
                        "total_spend": 0,
                        "total_impressions": 0,
                        "total_clicks": 0,
                        "total_conversions": 0,
                        "total_reach": 0,
                        "daily_data": [],
                    }

                spend = float(insight.get("spend", 0))
                impressions = int(insight.get("impressions", 0))
                clicks = int(insight.get("clicks", 0))
                reach = int(insight.get("reach", 0))
                conversions = sum(
                    action.get("value", 0) for action in insight.get("actions", [])
                    if action.get("action_type") == "offsite_conversion.fb_pixel_purchase"
                )

                creative_performance[creative_id]["total_spend"] += spend
                creative_performance[creative_id]["total_impressions"] += impressions
                creative_performance[creative_id]["total_clicks"] += clicks
                creative_performance[creative_id]["total_conversions"] += conversions
                creative_performance[creative_id]["total_reach"] += reach
                creative_performance[creative_id]["daily_data"].append(insight)

            # Calculate fatigue analysis if requested
            if include_fatigue_analysis:
                for creative_id, data in creative_performance.items():
                    if len(data["daily_data"]) >= 7:
                        # Simple fatigue detection: declining CTR over time
                        recent_ctr = sum(
                            float(day.get("ctr", 0)) for day in data["daily_data"][-3:]
                        ) / 3
                        early_ctr = sum(
                            float(day.get("ctr", 0)) for day in data["daily_data"][:3]
                        ) / 3
                        
                        fatigue_score = (early_ctr - recent_ctr) / early_ctr if early_ctr > 0 else 0
                        data["fatigue_analysis"] = {
                            "fatigue_score": fatigue_score,
                            "is_fatigued": fatigue_score > 0.2,  # 20% decline threshold
                            "early_ctr": early_ctr,
                            "recent_ctr": recent_ctr,
                        }

            return {
                "ad_account_id": ad_account_id,
                "date_range": {"start": start_date, "end": end_date},
                "creatives": list(creative_performance.values()),
                "summary": {
                    "total_creatives": len(creative_performance),
                    "fatigued_creatives": sum(
                        1 for data in creative_performance.values()
                        if data.get("fatigue_analysis", {}).get("is_fatigued", False)
                    ) if include_fatigue_analysis else 0,
                },
                "next_recommended_actions": [
                    "Identify fatigued creatives for rotation",
                    "Analyze top-performing creative elements",
                    "Plan creative refresh schedule",
                ],
            }
        except MetaApiError as exc:
            logger.error("Failed to get creative performance history", ad_account_id=ad_account_id, error=exc.to_dict())
            raise

    async def get_hourly_breakdown(
        self,
        entity_id: str,
        entity_type: str,
        start_date: str,
        end_date: str,
        timezone: str = "UTC",
    ) -> Dict[str, Any]:
        """
        Get hour-by-hour performance data for dayparting analysis.
        """
        params = {
            "fields": "spend,impressions,clicks,ctr,cpc,conversions",
            "time_range": {"since": start_date, "until": end_date},
            "breakdowns": "hourly_stats_aggregated_by_advertiser_time_zone",
        }

        try:
            response = await self._client.get(f"{entity_id}/insights", params=params)
            insights_data = response.get("data", [])

            # Process hourly data
            hourly_data = {}
            for insight in insights_data:
                hour = insight.get("breakdowns.hourly_stats_aggregated_by_advertiser_time_zone", "unknown")
                hourly_data[hour] = {
                    "hour": hour,
                    "spend": float(insight.get("spend", 0)),
                    "impressions": int(insight.get("impressions", 0)),
                    "clicks": int(insight.get("clicks", 0)),
                    "ctr": float(insight.get("ctr", 0)),
                    "cpc": float(insight.get("cpc", 0)),
                    "conversions": sum(
                        action.get("value", 0) for action in insight.get("actions", [])
                        if action.get("action_type") == "offsite_conversion.fb_pixel_purchase"
                    ),
                }

            # Find best and worst performing hours
            best_hour = max(hourly_data.values(), key=lambda x: x["conversions"]) if hourly_data else None
            worst_hour = min(hourly_data.values(), key=lambda x: x["conversions"]) if hourly_data else None

            return {
                "entity_id": entity_id,
                "entity_type": entity_type,
                "date_range": {"start": start_date, "end": end_date},
                "timezone": timezone,
                "hourly_data": list(hourly_data.values()),
                "analysis": {
                    "best_performing_hour": best_hour["hour"] if best_hour else None,
                    "worst_performing_hour": worst_hour["hour"] if worst_hour else None,
                    "total_hours_analyzed": len(hourly_data),
                },
                "next_recommended_actions": [
                    "Optimize ad scheduling based on hourly performance",
                    "Increase bids during high-performing hours",
                    "Consider pausing during low-performing hours",
                ],
            }
        except MetaApiError as exc:
            logger.error("Failed to get hourly breakdown", entity_id=entity_id, error=exc.to_dict())
            raise

    async def compare_periods(
        self,
        entity_id: str,
        entity_type: str,
        period_a_start: str,
        period_a_end: str,
        period_b_start: str,
        period_b_end: str,
        metrics: List[str] = None,
    ) -> Dict[str, Any]:
        """
        Compare performance across two time periods.
        """
        if metrics is None:
            metrics = ["spend", "impressions", "clicks", "conversions"]

        # Get data for both periods
        period_a_data = await self.get_campaign_performance_history(
            entity_id, period_a_start, period_a_end, fields=metrics
        )
        period_b_data = await self.get_campaign_performance_history(
            entity_id, period_b_start, period_b_end, fields=metrics
        )

        # Calculate comparisons
        comparison = {}
        for metric in metrics:
            period_a_value = period_a_data["summary"].get(f"total_{metric}", 0)
            period_b_value = period_b_data["summary"].get(f"total_{metric}", 0)
            
            if period_a_value > 0:
                change_percentage = ((period_b_value - period_a_value) / period_a_value) * 100
            else:
                change_percentage = 0 if period_b_value == 0 else 100

            comparison[metric] = {
                "period_a": period_a_value,
                "period_b": period_b_value,
                "change_absolute": period_b_value - period_a_value,
                "change_percentage": change_percentage,
                "trend": "up" if change_percentage > 0 else "down" if change_percentage < 0 else "stable",
            }

        return {
            "entity_id": entity_id,
            "entity_type": entity_type,
            "period_a": {"start": period_a_start, "end": period_a_end},
            "period_b": {"start": period_b_start, "end": period_b_end},
            "comparison": comparison,
            "overall_trend": "improving" if sum(
                comp["change_percentage"] for comp in comparison.values()
            ) > 0 else "declining",
            "next_recommended_actions": [
                "Analyze factors contributing to performance changes",
                "Identify successful strategies from better period",
                "Adjust strategy based on comparison insights",
            ],
        }


class GranularMetricsRetriever:
    """Retrieves detailed performance breakdowns by various dimensions."""

    def __init__(self, client: MetaClient):
        self._client = client

    async def get_performance_by_demographics(
        self,
        entity_id: str,
        entity_type: str,
        start_date: str,
        end_date: str,
        demographics: List[str] = None,
        metrics: List[str] = None,
    ) -> Dict[str, Any]:
        """
        Get performance breakdown by age and gender demographics.
        """
        if demographics is None:
            demographics = ["age", "gender"]
        if metrics is None:
            metrics = ["spend", "impressions", "clicks", "ctr", "cpc", "conversions"]

        params = {
            "fields": ",".join(metrics),
            "time_range": {"since": start_date, "until": end_date},
            "breakdowns": ",".join(demographics),
        }

        try:
            response = await self._client.get(f"{entity_id}/insights", params=params)
            insights_data = response.get("data", [])

            # Process demographic data
            demographic_performance = {}
            for insight in insights_data:
                # Create demographic key
                demo_key = "_".join([
                    insight.get(f"breakdowns.{demo}", "unknown") 
                    for demo in demographics
                ])
                
                if demo_key not in demographic_performance:
                    demographic_performance[demo_key] = {
                        "demographic": demo_key,
                        "total_spend": 0,
                        "total_impressions": 0,
                        "total_clicks": 0,
                        "total_conversions": 0,
                    }

                demographic_performance[demo_key]["total_spend"] += float(insight.get("spend", 0))
                demographic_performance[demo_key]["total_impressions"] += int(insight.get("impressions", 0))
                demographic_performance[demo_key]["total_clicks"] += int(insight.get("clicks", 0))
                demographic_performance[demo_key]["total_conversions"] += sum(
                    action.get("value", 0) for action in insight.get("actions", [])
                    if action.get("action_type") == "offsite_conversion.fb_pixel_purchase"
                )

            # Calculate efficiency metrics
            for demo_data in demographic_performance.values():
                if demo_data["total_clicks"] > 0:
                    demo_data["avg_ctr"] = demo_data["total_clicks"] / demo_data["total_impressions"]
                    demo_data["avg_cpc"] = demo_data["total_spend"] / demo_data["total_clicks"]
                else:
                    demo_data["avg_ctr"] = 0
                    demo_data["avg_cpc"] = 0

            return {
                "entity_id": entity_id,
                "entity_type": entity_type,
                "date_range": {"start": start_date, "end": end_date},
                "demographics": demographics,
                "demographic_performance": list(demographic_performance.values()),
                "best_demographic": max(
                    demographic_performance.values(),
                    key=lambda x: x["total_conversions"]
                )["demographic"] if demographic_performance else None,
                "next_recommended_actions": [
                    "Focus budget on top-performing demographics",
                    "Create demographic-specific campaigns",
                    "Test creative variations for different demographics",
                ],
            }
        except MetaApiError as exc:
            logger.error("Failed to get demographic performance", entity_id=entity_id, error=exc.to_dict())
            raise

    async def get_performance_by_device(
        self,
        entity_id: str,
        entity_type: str,
        start_date: str,
        end_date: str,
        device_types: List[str] = None,
        metrics: List[str] = None,
    ) -> Dict[str, Any]:
        """
        Get performance breakdown by device type.
        """
        if device_types is None:
            device_types = ["desktop", "mobile", "tablet"]
        if metrics is None:
            metrics = ["spend", "impressions", "clicks", "ctr", "cpc", "conversions"]

        params = {
            "fields": ",".join(metrics),
            "time_range": {"since": start_date, "until": end_date},
            "breakdowns": "impression_device",
        }

        try:
            response = await self._client.get(f"{entity_id}/insights", params=params)
            insights_data = response.get("data", [])

            # Process device data
            device_performance = {}
            for insight in insights_data:
                device = insight.get("breakdowns.impression_device", "unknown")
                
                if device not in device_performance:
                    device_performance[device] = {
                        "device": device,
                        "total_spend": 0,
                        "total_impressions": 0,
                        "total_clicks": 0,
                        "total_conversions": 0,
                    }

                device_performance[device]["total_spend"] += float(insight.get("spend", 0))
                device_performance[device]["total_impressions"] += int(insight.get("impressions", 0))
                device_performance[device]["total_clicks"] += int(insight.get("clicks", 0))
                device_performance[device]["total_conversions"] += sum(
                    action.get("value", 0) for action in insight.get("actions", [])
                    if action.get("action_type") == "offsite_conversion.fb_pixel_purchase"
                )

            # Calculate efficiency metrics
            for device_data in device_performance.values():
                if device_data["total_clicks"] > 0:
                    device_data["avg_ctr"] = device_data["total_clicks"] / device_data["total_impressions"]
                    device_data["avg_cpc"] = device_data["total_spend"] / device_data["total_clicks"]
                else:
                    device_data["avg_ctr"] = 0
                    device_data["avg_cpc"] = 0

            return {
                "entity_id": entity_id,
                "entity_type": entity_type,
                "date_range": {"start": start_date, "end": end_date},
                "device_performance": list(device_performance.values()),
                "best_device": max(
                    device_performance.values(),
                    key=lambda x: x["total_conversions"]
                )["device"] if device_performance else None,
                "next_recommended_actions": [
                    "Optimize creative formats for top-performing devices",
                    "Adjust bids by device type",
                    "Consider device-specific landing pages",
                ],
            }
        except MetaApiError as exc:
            logger.error("Failed to get device performance", entity_id=entity_id, error=exc.to_dict())
            raise

    async def get_performance_by_placement(
        self,
        entity_id: str,
        entity_type: str,
        start_date: str,
        end_date: str,
        placements: List[str] = None,
        metrics: List[str] = None,
    ) -> Dict[str, Any]:
        """
        Get performance breakdown by ad placement.
        """
        if placements is None:
            placements = ["facebook_feed", "instagram_feed", "messenger", "audience_network"]
        if metrics is None:
            metrics = ["spend", "impressions", "clicks", "ctr", "cpc", "conversions"]

        params = {
            "fields": ",".join(metrics),
            "time_range": {"since": start_date, "until": end_date},
            "breakdowns": "placement",
        }

        try:
            response = await self._client.get(f"{entity_id}/insights", params=params)
            insights_data = response.get("data", [])

            # Process placement data
            placement_performance = {}
            for insight in insights_data:
                placement = insight.get("breakdowns.placement", "unknown")
                
                if placement not in placement_performance:
                    placement_performance[placement] = {
                        "placement": placement,
                        "total_spend": 0,
                        "total_impressions": 0,
                        "total_clicks": 0,
                        "total_conversions": 0,
                    }

                placement_performance[placement]["total_spend"] += float(insight.get("spend", 0))
                placement_performance[placement]["total_impressions"] += int(insight.get("impressions", 0))
                placement_performance[placement]["total_clicks"] += int(insight.get("clicks", 0))
                placement_performance[placement]["total_conversions"] += sum(
                    action.get("value", 0) for action in insight.get("actions", [])
                    if action.get("action_type") == "offsite_conversion.fb_pixel_purchase"
                )

            # Calculate efficiency metrics
            for placement_data in placement_performance.values():
                if placement_data["total_clicks"] > 0:
                    placement_data["avg_ctr"] = placement_data["total_clicks"] / placement_data["total_impressions"]
                    placement_data["avg_cpc"] = placement_data["total_spend"] / placement_data["total_clicks"]
                else:
                    placement_data["avg_ctr"] = 0
                    placement_data["avg_cpc"] = 0

            return {
                "entity_id": entity_id,
                "entity_type": entity_type,
                "date_range": {"start": start_date, "end": end_date},
                "placement_performance": list(placement_performance.values()),
                "best_placement": max(
                    placement_performance.values(),
                    key=lambda x: x["total_conversions"]
                )["placement"] if placement_performance else None,
                "next_recommended_actions": [
                    "Optimize creative formats for top placements",
                    "Adjust placement-specific bids",
                    "Consider removing underperforming placements",
                ],
            }
        except MetaApiError as exc:
            logger.error("Failed to get placement performance", entity_id=entity_id, error=exc.to_dict())
            raise

    async def get_performance_by_time(
        self,
        entity_id: str,
        entity_type: str,
        start_date: str,
        end_date: str,
        time_breakdown: str = "hour",
        timezone: str = "UTC",
        metrics: List[str] = None,
    ) -> Dict[str, Any]:
        """
        Get performance breakdown by time (hour, day, week).
        """
        if metrics is None:
            metrics = ["spend", "impressions", "clicks", "ctr", "cpc", "conversions"]

        if time_breakdown == "hour":
            breakdown = "hourly_stats_aggregated_by_advertiser_time_zone"
            time_increment = 1
        elif time_breakdown == "day":
            breakdown = None
            time_increment = 1
        elif time_breakdown == "week":
            breakdown = None
            time_increment = 7
        else:
            raise ValueError("time_breakdown must be 'hour', 'day', or 'week'")

        params = {
            "fields": ",".join(metrics),
            "time_range": {"since": start_date, "until": end_date},
            "time_increment": time_increment,
        }

        if breakdown:
            params["breakdowns"] = breakdown

        try:
            response = await self._client.get(f"{entity_id}/insights", params=params)
            insights_data = response.get("data", [])

            # Process time-based data
            time_performance = []
            for insight in insights_data:
                time_key = insight.get(f"breakdowns.{breakdown}", insight.get("date_start", "unknown"))
                
                time_performance.append({
                    "time_period": time_key,
                    "spend": float(insight.get("spend", 0)),
                    "impressions": int(insight.get("impressions", 0)),
                    "clicks": int(insight.get("clicks", 0)),
                    "ctr": float(insight.get("ctr", 0)),
                    "cpc": float(insight.get("cpc", 0)),
                    "conversions": sum(
                        action.get("value", 0) for action in insight.get("actions", [])
                        if action.get("action_type") == "offsite_conversion.fb_pixel_purchase"
                    ),
                })

            # Find best and worst performing time periods
            best_period = max(time_performance, key=lambda x: x["conversions"]) if time_performance else None
            worst_period = min(time_performance, key=lambda x: x["conversions"]) if time_performance else None

            return {
                "entity_id": entity_id,
                "entity_type": entity_type,
                "date_range": {"start": start_date, "end": end_date},
                "time_breakdown": time_breakdown,
                "timezone": timezone,
                "time_performance": time_performance,
                "analysis": {
                    "best_period": best_period["time_period"] if best_period else None,
                    "worst_period": worst_period["time_period"] if worst_period else None,
                    "total_periods": len(time_performance),
                },
                "next_recommended_actions": [
                    f"Optimize scheduling based on {time_breakdown}ly performance",
                    "Increase bids during high-performing periods",
                    "Consider pausing during low-performing periods",
                ],
            }
        except MetaApiError as exc:
            logger.error("Failed to get time-based performance", entity_id=entity_id, error=exc.to_dict())
            raise

    async def get_delivery_insights(
        self,
        entity_id: str,
        entity_type: str,
        start_date: str,
        end_date: str,
        include_pacing: bool = True,
        include_delivery: bool = True,
    ) -> Dict[str, Any]:
        """
        Get delivery and pacing insights for campaigns.
        """
        params = {
            "fields": "spend,impressions,clicks,delivery_info",
            "time_range": {"since": start_date, "until": end_date},
        }

        try:
            response = await self._client.get(f"{entity_id}/insights", params=params)
            insights_data = response.get("data", [])

            # Process delivery data
            delivery_analysis = {
                "total_spend": 0,
                "total_impressions": 0,
                "delivery_status": "unknown",
                "pacing_analysis": {},
            }

            for insight in insights_data:
                delivery_analysis["total_spend"] += float(insight.get("spend", 0))
                delivery_analysis["total_impressions"] += int(insight.get("impressions", 0))

            # Get campaign/adset details for pacing analysis
            if include_pacing:
                entity_response = await self._client.get(entity_id, params={"fields": "daily_budget,lifetime_budget,status"})
                entity_data = entity_response.get("data", {})
                
                daily_budget = float(entity_data.get("daily_budget", 0))
                if daily_budget > 0:
                    days_in_period = (datetime.strptime(end_date, "%Y-%m-%d") - datetime.strptime(start_date, "%Y-%m-%d")).days + 1
                    expected_spend = daily_budget * days_in_period
                    actual_spend = delivery_analysis["total_spend"]
                    
                    delivery_analysis["pacing_analysis"] = {
                        "daily_budget": daily_budget,
                        "expected_spend": expected_spend,
                        "actual_spend": actual_spend,
                        "pacing_percentage": (actual_spend / expected_spend * 100) if expected_spend > 0 else 0,
                        "pacing_status": "on_track" if 80 <= (actual_spend / expected_spend * 100) <= 120 else "off_track",
                    }

            return {
                "entity_id": entity_id,
                "entity_type": entity_type,
                "date_range": {"start": start_date, "end": end_date},
                "delivery_analysis": delivery_analysis,
                "next_recommended_actions": [
                    "Review delivery status and pacing",
                    "Adjust budgets if pacing is off track",
                    "Monitor delivery for optimization opportunities",
                ],
            }
        except MetaApiError as exc:
            logger.error("Failed to get delivery insights", entity_id=entity_id, error=exc.to_dict())
            raise

    async def get_frequency_distribution(
        self,
        entity_id: str,
        entity_type: str,
        start_date: str,
        end_date: str,
        max_frequency: int = 10,
        include_reach: bool = True,
    ) -> Dict[str, Any]:
        """
        Get ad frequency distribution analysis.
        """
        params = {
            "fields": "reach,frequency,impressions",
            "time_range": {"since": start_date, "until": end_date},
        }

        try:
            response = await self._client.get(f"{entity_id}/insights", params=params)
            insights_data = response.get("data", [])

            # Process frequency data
            total_reach = sum(int(insight.get("reach", 0)) for insight in insights_data)
            total_impressions = sum(int(insight.get("impressions", 0)) for insight in insights_data)
            avg_frequency = total_impressions / total_reach if total_reach > 0 else 0

            frequency_analysis = {
                "total_reach": total_reach,
                "total_impressions": total_impressions,
                "average_frequency": avg_frequency,
                "frequency_status": "optimal" if 1 <= avg_frequency <= 3 else "low" if avg_frequency < 1 else "high",
            }

            return {
                "entity_id": entity_id,
                "entity_type": entity_type,
                "date_range": {"start": start_date, "end": end_date},
                "frequency_analysis": frequency_analysis,
                "recommendations": [
                    "Frequency is optimal" if frequency_analysis["frequency_status"] == "optimal"
                    else "Consider increasing reach to improve frequency" if frequency_analysis["frequency_status"] == "low"
                    else "Consider reducing frequency to avoid ad fatigue",
                ],
                "next_recommended_actions": [
                    "Monitor frequency trends over time",
                    "Adjust targeting to optimize frequency",
                    "Refresh creatives if frequency is too high",
                ],
            }
        except MetaApiError as exc:
            logger.error("Failed to get frequency distribution", entity_id=entity_id, error=exc.to_dict())
            raise
