from __future__ import annotations

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

from pydantic import BaseModel, ConfigDict, Field, model_validator


class HttpMethod(str, Enum):
    GET = "GET"
    POST = "POST"
    DELETE = "DELETE"
    PUT = "PUT"
    PATCH = "PATCH"


class GraphBodyEncoding(str, Enum):
    JSON = "json"
    FORM = "form"


class GraphFile(BaseModel):
    """Represents a file to upload to the Graph API."""

    field: str = Field(..., description="Form field name for the file upload")
    filename: str = Field(..., description="File name as sent to Graph API")
    data: str = Field(..., description="File payload, encoded according to `encoding`")
    encoding: str = Field(default="base64", description="Payload encoding (base64 or text)")
    content_type: Optional[str] = Field(default=None, description="Optional MIME type override")

    @model_validator(mode="after")
    def validate_encoding(self) -> "GraphFile":
        allowed = {"base64", "text"}
        if self.encoding not in allowed:
            raise ValueError(f"encoding must be one of {allowed}")
        return self


class GraphRequest(BaseModel):
    """Schema for a raw Graph API invocation."""

    model_config = ConfigDict(extra="forbid")

    method: HttpMethod
    path: str = Field(..., description="Graph API path, e.g. 'act_123/campaigns'")
    params: Dict[str, Any] | None = Field(default=None, description="Query parameters")
    body: Dict[str, Any] | None = Field(default=None, description="Request body payload")
    encoding: GraphBodyEncoding = Field(default=GraphBodyEncoding.JSON, description="Body encoding (json or form)")
    files: List[GraphFile] | None = Field(default=None, description="Optional files for multipart upload")
    headers: Dict[str, str] | None = Field(default=None, description="Additional headers")
    use_appsecret_proof: bool = Field(default=True, description="Send appsecret_proof when app secret configured")

    @model_validator(mode="after")
    def normalize_path(self) -> "GraphRequest":
        self.path = self.path.lstrip("/")
        if not self.path:
            raise ValueError("path must not be empty")
        if self.files and self.encoding != GraphBodyEncoding.FORM:
            raise ValueError("encoding must be 'form' when files are supplied")
        return self


class InsightsBreakdown(str, Enum):
    # Demographics
    age = "age"
    gender = "gender"
    country = "country"
    region = "region"
    
    # Device & Placement
    impression_device = "impression_device"
    placement = "placement"
    publisher_platform = "publisher_platform"
    platform_position = "platform_position"
    
    # Time-based
    hourly_stats_aggregated_by_advertiser_time_zone = "hourly_stats_aggregated_by_advertiser_time_zone"
    day_of_week = "day_of_week"
    
    # Action-based
    action_type = "action_type"
    action_destination = "action_destination"
    
    # Additional breakdowns
    delivery_by_region = "delivery_by_region"
    delivery_by_age = "delivery_by_age"
    delivery_by_gender = "delivery_by_gender"
    delivery_by_placement = "delivery_by_placement"


class TimeRangePreset(str, Enum):
    """Predefined time range options for insights."""
    last_7_days = "last_7_days"
    last_14_days = "last_14_days"
    last_30_days = "last_30_days"
    last_90_days = "last_90_days"
    this_month = "this_month"
    last_month = "last_month"
    this_quarter = "this_quarter"
    last_quarter = "last_quarter"
    this_year = "this_year"
    last_year = "last_year"


class InsightsRequest(BaseModel):
    """Enhanced schema for querying the Ads Insights API."""

    model_config = ConfigDict(extra="forbid")

    ad_account_id: str = Field(..., description="Ad account ID, e.g. 'act_123456'")
    level: str = Field(default="ad", description="Insights level (campaign, adset, ad, etc.)")
    fields: List[str] = Field(
        default_factory=lambda: ["impressions", "spend", "clicks", "ctr", "cpm", "cpc"],
        description="Metrics to retrieve"
    )
    time_range: Dict[str, str] | None = Field(
        default=None, 
        description="Custom time range: { 'since': 'YYYY-MM-DD', 'until': 'YYYY-MM-DD' }"
    )
    time_preset: TimeRangePreset | None = Field(
        default=None,
        description="Predefined time range preset"
    )
    filtering: List[Dict[str, Any]] | None = Field(
        default=None,
        description="Filters to apply to the data"
    )
    breakdowns: List[InsightsBreakdown] | None = Field(
        default=None,
        description="Breakdown dimensions for the data"
    )
    action_breakdowns: List[str] | None = Field(
        default=None,
        description="Action breakdowns (e.g., 'action_type', 'action_destination')"
    )
    attribution_windows: List[str] | None = Field(
        default=None,
        description="Attribution windows (e.g., '1d_click', '7d_view')"
    )
    limit: int = Field(default=100, le=1000, ge=1, description="Number of results to return")
    after: Optional[str] = Field(default=None, description="Paging cursor to resume from")
    date_preset: Optional[str] = Field(
        default=None,
        description="Meta's date preset (overrides time_range and time_preset)"
    )

    @model_validator(mode="after")
    def validate_time_range(self) -> "InsightsRequest":
        """Ensure only one time range method is specified."""
        time_methods = [self.time_range, self.time_preset, self.date_preset]
        specified_methods = [method for method in time_methods if method is not None]
        
        if len(specified_methods) > 1:
            raise ValueError("Only one of time_range, time_preset, or date_preset can be specified")
        
        return self


class GraphBatchOperation(BaseModel):
    """Single operation inside a Graph batch request."""

    method: HttpMethod
    relative_url: str
    body: Dict[str, Any] | None = None
    headers: Dict[str, str] | None = None
    name: Optional[str] = None
    depends_on: Optional[str] = Field(default=None, description="Operation name this call depends on")


class GraphBatchRequest(BaseModel):
    """Schema for Meta Graph batch operations."""

    model_config = ConfigDict(extra="forbid")

    operations: List[GraphBatchOperation]
    include_headers: bool = Field(default=False)

    @model_validator(mode="after")
    def validate_non_empty(self) -> "GraphBatchRequest":
        if not self.operations:
            raise ValueError("operations must contain at least one batch item")
        return self


class CreateAdObjectRequest(BaseModel):
    """Generic request to create an ad object using POST."""

    model_config = ConfigDict(extra="allow")

    parent_id: str = Field(..., description="Resource under which the new object will be created")
    resource: str = Field(..., description="Resource edge, e.g. 'campaigns', 'adsets', 'ads'")
    payload: Dict[str, Any] = Field(default_factory=dict)
    encoding: GraphBodyEncoding = Field(default=GraphBodyEncoding.FORM)


class UpdateAdObjectRequest(BaseModel):
    """Generic request to update an ad object using POST."""

    model_config = ConfigDict(extra="allow")

    object_id: str = Field(..., description="ID of the object to update")
    updates: Dict[str, Any] = Field(..., description="Fields to update")
    encoding: GraphBodyEncoding = Field(default=GraphBodyEncoding.FORM)


class BulkStatusUpdateRequest(BaseModel):
    """Request to update status of multiple ad objects."""

    model_config = ConfigDict(extra="forbid")

    object_ids: List[str] = Field(..., description="List of object IDs to update")
    status: str = Field(..., description="New status (ACTIVE, PAUSED, ARCHIVED)")
    object_type: str = Field(..., description="Type of objects (campaign, adset, ad)")
    ad_account_id: str = Field(..., description="Ad account ID for the objects")


# ============================================================================
# v24.0 COMPLIANCE SCHEMAS
# Breaking changes in Meta Marketing API v24.0 (October 2025)
# ============================================================================

class MigrateToAdvantagePlusRequest(BaseModel):
    """Request to migrate an existing campaign to Advantage+ structure.
    
    REQUIRED for v24.0+: Old ASC/AAC creation is deprecated.
    """

    model_config = ConfigDict(extra="forbid")

    campaign_id: str = Field(..., description="Campaign ID to migrate")
    migrate_to_advantage_plus: bool = Field(
        default=True, 
        description="Set to true to migrate (required for v24.0+)"
    )


class CampaignCreateV24(BaseModel):
    """v24.0 compliant campaign creation request.
    
    Key changes:
    - is_adset_budget_sharing_enabled is REQUIRED for ad set level budgets
    - ASC/AAC creation deprecated - use migrate_to_advantage_plus for existing
    """

    model_config = ConfigDict(extra="allow")

    ad_account_id: str = Field(..., description="Ad account ID")
    name: str = Field(..., description="Campaign name")
    objective: str = Field(..., description="Campaign objective")
    status: str = Field(default="PAUSED", description="Initial status")
    special_ad_categories: List[str] = Field(
        default_factory=list, 
        description="Special ad categories (empty for standard)"
    )
    # v24.0+: REQUIRED when using ad set level budgets
    is_adset_budget_sharing_enabled: Optional[bool] = Field(
        default=True,
        description="v24.0+: Required for ad set level budgets. Enables up to 20% budget sharing."
    )
    buying_type: str = Field(default="AUCTION", description="Buying type")


class AdSetCreateV24(BaseModel):
    """v24.0 compliant ad set creation request.
    
    Key changes:
    - placement_soft_opt_out for limited spend on excluded placements
    - facebook_video_feeds placement DEPRECATED (use Reels)
    """

    model_config = ConfigDict(extra="allow")

    ad_account_id: str = Field(..., description="Ad account ID")
    campaign_id: str = Field(..., description="Campaign ID")
    name: str = Field(..., description="Ad set name")
    daily_budget: Optional[int] = Field(default=None, description="Daily budget in cents")
    lifetime_budget: Optional[int] = Field(default=None, description="Lifetime budget in cents")
    billing_event: str = Field(default="IMPRESSIONS", description="Billing event")
    optimization_goal: str = Field(..., description="Optimization goal")
    bid_strategy: str = Field(
        default="LOWEST_COST_WITHOUT_CAP", 
        description="Bid strategy"
    )
    targeting: Dict[str, Any] = Field(..., description="Targeting spec")
    status: str = Field(default="PAUSED", description="Initial status")
    # v24.0+: New field for limited spend on excluded placements
    placement_soft_opt_out: Optional[List[str]] = Field(
        default=None,
        description="v24.0+: Placements to allocate up to 5% spend to for performance"
    )


class CatalogBatchV24(BaseModel):
    """v24.0 compliant catalog batch request.
    
    Key changes:
    - 30MB payload limit
    - allow_upsert now supported
    """

    model_config = ConfigDict(extra="forbid")

    product_catalog_id: str = Field(..., description="Product catalog ID")
    requests: List[Dict[str, Any]] = Field(..., description="Batch operations (max 5000 items)")
    allow_upsert: bool = Field(
        default=False,
        description="v24.0+: If true, create or update products"
    )

    @model_validator(mode="after")
    def validate_payload_size(self) -> "CatalogBatchV24":
        """v24.0+: Payload limited to 30MB."""
        import json
        payload_size = len(json.dumps(self.requests).encode('utf-8'))
        max_size = 30 * 1024 * 1024  # 30MB
        if payload_size > max_size:
            raise ValueError(f"Payload size ({payload_size} bytes) exceeds v24.0 limit of 30MB")
        if len(self.requests) > 5000:
            raise ValueError("Maximum 5000 items per batch request")
        return self


class LookalikeSpecV24(BaseModel):
    """v24.0 lookalike audience spec with strict type enforcement."""

    model_config = ConfigDict(extra="forbid")

    origin_audience_id: str = Field(..., description="Source audience ID")
    ratio: float = Field(..., ge=0.01, le=0.20, description="Lookalike ratio (1-20%)")
    country: str = Field(..., description="Target country code")
    # v24.0+: Required valid types only
    type: str = Field(
        default="similarity",
        description="Lookalike type: similarity or reach"
    )


# ============================================================================
# v24.0 FLAGGED RESOURCE CHECKS
# v24.0+: Flagged audiences and conversions now fail on update
# Must check before any update operation
# ============================================================================

class CheckFlaggedAudienceRequest(BaseModel):
    """Check if a custom audience is flagged before update operations.
    
    v24.0+: Updating flagged custom audiences will fail.
    Use this tool to check status before attempting updates.
    """

    model_config = ConfigDict(extra="forbid")

    audience_id: str = Field(..., description="Custom audience ID to check")
    fields: List[str] = Field(
        default_factory=lambda: ["id", "name", "is_flagged", "flagged_reason", "operation_status"],
        description="Fields to retrieve"
    )


class CheckFlaggedAudienceResponse(BaseModel):
    """Response for flagged audience check."""

    audience_id: str
    name: str
    is_flagged: bool
    flagged_reason: Optional[str] = None
    operation_status: Optional[Dict[str, Any]] = None
    can_update: bool = Field(description="Whether update operations are allowed")
    resolution_steps: Optional[List[str]] = Field(
        default=None,
        description="Steps to resolve if flagged"
    )


class CheckFlaggedConversionRequest(BaseModel):
    """Check if a custom conversion is flagged before update operations.
    
    v24.0+: Updating flagged custom conversions will fail.
    Use this tool to check status before attempting updates.
    """

    model_config = ConfigDict(extra="forbid")

    custom_conversion_id: str = Field(..., description="Custom conversion ID to check")
    fields: List[str] = Field(
        default_factory=lambda: ["id", "name", "is_flagged", "flagged_reason"],
        description="Fields to retrieve"
    )


class CheckFlaggedConversionResponse(BaseModel):
    """Response for flagged conversion check."""

    custom_conversion_id: str
    name: str
    is_flagged: bool
    flagged_reason: Optional[str] = None
    can_update: bool = Field(description="Whether update operations are allowed")
    resolution_url: str = Field(
        default="https://www.facebook.com/business/help/2455915321411996",
        description="URL to resolve flagged conversion"
    )


class ValidateLookalikeSpecRequest(BaseModel):
    """Validate lookalike_spec before creating lookalike audience.
    
    v24.0+: Strict type enforcement on lookalike_spec fields.
    Use this tool to validate spec before creation.
    """

    model_config = ConfigDict(extra="forbid")

    ad_account_id: str = Field(..., description="Ad account ID")
    lookalike_spec: LookalikeSpecV24 = Field(..., description="Lookalike spec to validate")


class ValidateLookalikeSpecResponse(BaseModel):
    """Response for lookalike spec validation."""

    is_valid: bool
    errors: List[str] = Field(default_factory=list)
    warnings: List[str] = Field(default_factory=list)
    origin_audience_valid: bool = Field(description="Whether source audience is valid and not flagged")



class CustomAudienceSubtype(str, Enum):
    """Types of custom audiences."""
    CUSTOM = "CUSTOM"
    WEBSITE = "WEBSITE"
    APP = "APP"
    OFFLINE_CONVERSION = "OFFLINE_CONVERSION"
    CLAIM = "CLAIM"
    PARTNER = "PARTNER"
    MANUAL = "MANUAL"
    VIDEO = "VIDEO"
    LOOKALIKE = "LOOKALIKE"
    ENGAGEMENT = "ENGAGEMENT"
    DATA_SET = "DATA_SET"
    BAG_OF_ACCOUNTS = "BAG_OF_ACCOUNTS"
    STUDY_RULE_AUDIENCE = "STUDY_RULE_AUDIENCE"
    FOX = "FOX"


class CreateCustomAudienceRequest(BaseModel):
    """Request to create a custom audience."""

    model_config = ConfigDict(extra="forbid")

    ad_account_id: str = Field(..., description="Ad account ID")
    name: str = Field(..., description="Name of the custom audience")
    description: str = Field(default="", description="Description of the audience")
    subtype: CustomAudienceSubtype = Field(..., description="Type of custom audience")
    customer_file_source: str = Field(default="USER_PROVIDED_ONLY", description="Source of customer data")
    retention_days: int = Field(default=30, ge=1, le=180, description="Days to retain the audience")
    rule: Optional[Dict[str, Any]] = Field(default=None, description="Rule for audience creation")
    prefill: bool = Field(default=False, description="Whether to prefill the audience")
    is_eligible_for_sac_campaigns: bool = Field(default=False, description="Compliance flag for Special Ad Categories")


class CreateLookalikeAudienceRequest(BaseModel):
    """Request to create a lookalike audience."""

    model_config = ConfigDict(extra="forbid")

    ad_account_id: str = Field(..., description="Ad account ID")
    name: str = Field(..., description="Name of the lookalike audience")
    origin_audience_id: str = Field(..., description="ID of the source audience")
    ratio: float = Field(default=0.01, ge=0.01, le=0.10, description="Lookalike ratio (1-10%)")
    country: str = Field(..., description="Country code for the lookalike audience")
    description: str = Field(default="", description="Description of the audience")


class GetAudienceInsightsRequest(BaseModel):
    """Request to get audience insights."""

    model_config = ConfigDict(extra="forbid")

    ad_account_id: str = Field(..., description="Ad account ID")
    audience_id: str = Field(..., description="Audience ID to analyze")
    fields: List[str] = Field(
        default_factory=lambda: ["audience_size", "audience_size_lower_bound", "audience_size_upper_bound"],
        description="Fields to retrieve"
    )


class CreativeAssetType(str, Enum):
    """Types of creative assets."""
    IMAGE = "IMAGE"
    VIDEO = "VIDEO"
    CAROUSEL_IMAGE = "CAROUSEL_IMAGE"
    CAROUSEL_VIDEO = "CAROUSEL_VIDEO"


class UploadCreativeAssetRequest(BaseModel):
    """Request to upload a creative asset."""

    model_config = ConfigDict(extra="forbid")

    ad_account_id: str = Field(..., description="Ad account ID")
    asset_type: CreativeAssetType = Field(..., description="Type of creative asset")
    files: List[GraphFile] = Field(..., description="Files to upload")
    name: Optional[str] = Field(default=None, description="Name for the asset")
    description: Optional[str] = Field(default=None, description="Description of the asset")


class GetCreativeAssetsRequest(BaseModel):
    """Request to get creative assets."""

    model_config = ConfigDict(extra="forbid")

    ad_account_id: str = Field(..., description="Ad account ID")
    asset_type: Optional[CreativeAssetType] = Field(default=None, description="Filter by asset type")
    fields: List[str] = Field(
        default_factory=lambda: ["id", "name", "url", "width", "height", "created_time"],
        description="Fields to retrieve"
    )
    limit: int = Field(default=100, le=1000, ge=1, description="Number of results to return")
    after: Optional[str] = Field(default=None, description="Paging cursor to resume from")


# Conversion Tracking & Pixel Management Schemas
class CreatePixelRequest(BaseModel):
    """Request to create a Facebook Pixel."""

    model_config = ConfigDict(extra="forbid")

    ad_account_id: str = Field(..., description="Ad account ID")
    name: str = Field(..., description="Name of the pixel")
    description: Optional[str] = Field(default=None, description="Description of the pixel")


class UpdatePixelRequest(BaseModel):
    """Request to update a Facebook Pixel."""

    model_config = ConfigDict(extra="forbid")

    pixel_id: str = Field(..., description="Pixel ID to update")
    name: Optional[str] = Field(default=None, description="New name for the pixel")
    description: Optional[str] = Field(default=None, description="New description for the pixel")


class GetPixelRequest(BaseModel):
    """Request to get pixel information."""

    model_config = ConfigDict(extra="forbid")

    pixel_id: str = Field(..., description="Pixel ID")
    fields: List[str] = Field(
        default_factory=lambda: ["id", "name", "description", "creation_time", "last_fired_time"],
        description="Fields to retrieve"
    )


class PixelStatsRequest(BaseModel):
    """Request to get pixel statistics."""

    model_config = ConfigDict(extra="forbid")

    pixel_id: str = Field(..., description="Pixel ID")
    start_time: str = Field(..., description="Start time (ISO 8601 format)")
    end_time: str = Field(..., description="End time (ISO 8601 format)")
    aggregation: str = Field(default="pixel_fire", description="Aggregation type")


class CreateCustomConversionRequest(BaseModel):
    """Request to create a custom conversion."""

    model_config = ConfigDict(extra="forbid")

    ad_account_id: str = Field(..., description="Ad account ID")
    name: str = Field(..., description="Name of the custom conversion")
    pixel_id: str = Field(..., description="Pixel ID")
    event_name: str = Field(..., description="Event name to track")
    value: Optional[float] = Field(default=None, description="Conversion value")
    currency: Optional[str] = Field(default="USD", description="Currency code")


class ListConversionsRequest(BaseModel):
    """Request to list custom conversions."""

    model_config = ConfigDict(extra="forbid")

    ad_account_id: str = Field(..., description="Ad account ID")
    fields: List[str] = Field(
        default_factory=lambda: ["id", "name", "pixel", "event_name", "value", "currency"],
        description="Fields to retrieve"
    )
    limit: int = Field(default=100, le=1000, ge=1, description="Number of results to return")


class ServerSideEventRequest(BaseModel):
    """Request to send server-side events (CAPI)."""

    model_config = ConfigDict(extra="forbid")

    pixel_id: str = Field(..., description="Pixel ID")
    access_token: str = Field(..., description="Access token for the pixel")
    events: List[Dict[str, Any]] = Field(..., description="List of events to send")
    test_event_code: Optional[str] = Field(default=None, description="Test event code for testing")
    partner_agent: Optional[str] = Field(default=None, description="Partner agent identifier")


# Multi-Account Management Schemas
class GetBusinessHierarchyRequest(BaseModel):
    """Request to get business hierarchy."""

    model_config = ConfigDict(extra="forbid")

    business_id: str = Field(..., description="Business ID")
    include_inactive: bool = Field(default=False, description="Include inactive accounts")


class CrossAccountInsightsRequest(BaseModel):
    """Request for cross-account insights."""

    model_config = ConfigDict(extra="forbid")

    account_ids: List[str] = Field(..., description="List of ad account IDs")
    fields: List[str] = Field(
        default_factory=lambda: ["impressions", "spend", "clicks", "ctr", "cpm", "cpc"],
        description="Fields to retrieve"
    )
    time_range: Optional[Dict[str, str]] = Field(default=None, description="Time range for insights")
    level: str = Field(default="campaign", description="Insights level")


class CrossAccountOperationRequest(BaseModel):
    """Request for cross-account operations."""

    model_config = ConfigDict(extra="forbid")

    account_ids: List[str] = Field(..., description="List of ad account IDs")
    operation: str = Field(..., description="Operation to perform")
    parameters: Dict[str, Any] = Field(..., description="Operation parameters")
    parallel_execution: bool = Field(default=True, description="Execute operations in parallel")


class ValidateAccountAccessRequest(BaseModel):
    """Request to validate account access."""

    model_config = ConfigDict(extra="forbid")

    account_ids: List[str] = Field(..., description="List of account IDs to validate")


# Budget & Bid Management Schemas
class CampaignBudgetOptimizationRequest(BaseModel):
    """Request for campaign budget optimization."""

    model_config = ConfigDict(extra="forbid")

    campaign_id: str = Field(..., description="Campaign ID to optimize")
    optimization_goal: str = Field(..., description="Optimization goal (REACH, IMPRESSIONS, etc.)")
    budget_amount: Optional[float] = Field(default=None, description="Target budget amount")
    currency: str = Field(default="USD", description="Currency code")


class BidStrategyRequest(BaseModel):
    """Request to update bid strategy."""

    model_config = ConfigDict(extra="forbid")

    adset_id: str = Field(..., description="Ad set ID")
    bid_strategy: str = Field(..., description="Bid strategy (LOWEST_COST_WITHOUT_CAP, etc.)")
    bid_amount: Optional[float] = Field(default=None, description="Bid amount")
    optimization_goal: str = Field(..., description="Optimization goal")


class BidCapRequest(BaseModel):
    """Request to set bid cap."""

    model_config = ConfigDict(extra="forbid")

    adset_id: str = Field(..., description="Ad set ID")
    bid_cap: float = Field(..., description="Bid cap amount")
    currency: str = Field(default="USD", description="Currency code")


class BudgetRecommendationRequest(BaseModel):
    """Request for budget recommendations."""

    model_config = ConfigDict(extra="forbid")

    adset_id: str = Field(..., description="Ad set ID")
    optimization_goal: str = Field(..., description="Optimization goal")
    current_budget: Optional[float] = Field(default=None, description="Current budget")
    target_roas: Optional[float] = Field(default=None, description="Target ROAS")


class AdSetOptimizationRequest(BaseModel):
    """Request for ad set optimization."""

    model_config = ConfigDict(extra="forbid")

    adset_id: str = Field(..., description="Ad set ID")
    optimization_goal: str = Field(..., description="Optimization goal")
    budget_amount: Optional[float] = Field(default=None, description="Budget amount")
    bid_strategy: Optional[str] = Field(default=None, description="Bid strategy")
    bid_amount: Optional[float] = Field(default=None, description="Bid amount")


# Automated Rules Schemas
class RuleCondition(BaseModel):
    """Rule condition for automated rules."""

    model_config = ConfigDict(extra="forbid")

    field: str = Field(..., description="Field to check")
    operator: str = Field(..., description="Comparison operator")
    value: Any = Field(..., description="Value to compare against")


class RuleAction(BaseModel):
    """Rule action for automated rules."""

    model_config = ConfigDict(extra="forbid")

    action_type: str = Field(..., description="Type of action to take")
    parameters: Dict[str, Any] = Field(default_factory=dict, description="Action parameters")


class CreateRuleRequest(BaseModel):
    """Request to create an automated rule."""

    model_config = ConfigDict(extra="forbid")

    ad_account_id: str = Field(..., description="Ad account ID")
    name: str = Field(..., description="Rule name")
    description: Optional[str] = Field(default=None, description="Rule description")
    conditions: List[RuleCondition] = Field(..., description="Rule conditions")
    actions: List[RuleAction] = Field(..., description="Rule actions")
    schedule_type: str = Field(default="immediate", description="Schedule type")
    enabled: bool = Field(default=True, description="Whether rule is enabled")


class UpdateRuleRequest(BaseModel):
    """Request to update an automated rule."""

    model_config = ConfigDict(extra="forbid")

    rule_id: str = Field(..., description="Rule ID to update")
    name: Optional[str] = Field(default=None, description="New rule name")
    description: Optional[str] = Field(default=None, description="New rule description")
    conditions: Optional[List[RuleCondition]] = Field(default=None, description="New rule conditions")
    actions: Optional[List[RuleAction]] = Field(default=None, description="New rule actions")
    enabled: Optional[bool] = Field(default=None, description="Whether rule is enabled")


class ListRulesRequest(BaseModel):
    """Request to list automated rules."""

    model_config = ConfigDict(extra="forbid")

    ad_account_id: str = Field(..., description="Ad account ID")
    fields: List[str] = Field(
        default_factory=lambda: ["id", "name", "description", "status", "created_time"],
        description="Fields to retrieve"
    )
    limit: int = Field(default=100, le=1000, ge=1, description="Number of results to return")


class RuleExecutionHistoryRequest(BaseModel):
    """Request to get rule execution history."""

    model_config = ConfigDict(extra="forbid")

    rule_id: str = Field(..., description="Rule ID")
    start_time: Optional[str] = Field(default=None, description="Start time (ISO 8601)")
    end_time: Optional[str] = Field(default=None, description="End time (ISO 8601)")
    limit: int = Field(default=100, le=1000, ge=1, description="Number of results to return")


# Advanced Reporting Schemas
class AttributionModelRequest(BaseModel):
    """Request for attribution modeling."""

    model_config = ConfigDict(extra="forbid")

    ad_account_id: str = Field(..., description="Ad account ID")
    attribution_model: str = Field(..., description="Attribution model (LAST_CLICK, FIRST_CLICK, etc.)")
    conversion_event: str = Field(..., description="Conversion event to analyze")
    time_range: Optional[Dict[str, str]] = Field(default=None, description="Time range for analysis")
    breakdowns: Optional[List[str]] = Field(default=None, description="Breakdown dimensions")


class ConversionLiftRequest(BaseModel):
    """Request for conversion lift studies."""

    model_config = ConfigDict(extra="forbid")

    ad_account_id: str = Field(..., description="Ad account ID")
    study_name: str = Field(..., description="Name of the lift study")
    conversion_event: str = Field(..., description="Conversion event to measure")
    test_group_size: float = Field(..., description="Percentage of users in test group")
    duration_days: int = Field(..., description="Study duration in days")


class ABTestRequest(BaseModel):
    """Request for A/B test creation."""

    model_config = ConfigDict(extra="forbid")

    ad_account_id: str = Field(..., description="Ad account ID")
    test_name: str = Field(..., description="Name of the A/B test")
    test_type: str = Field(..., description="Type of test (CREATIVE, AUDIENCE, etc.)")
    control_campaign_id: str = Field(..., description="Control campaign ID")
    treatment_campaign_id: str = Field(..., description="Treatment campaign ID")
    test_percentage: float = Field(..., description="Percentage of audience in test")
    duration_days: int = Field(..., description="Test duration in days")


class ABTestResultsRequest(BaseModel):
    """Request for A/B test results."""

    model_config = ConfigDict(extra="forbid")

    test_id: str = Field(..., description="A/B test ID")
    fields: List[str] = Field(
        default_factory=lambda: ["id", "name", "status", "results"],
        description="Fields to retrieve"
    )


class CrossDeviceReportRequest(BaseModel):
    """Request for cross-device reporting."""

    model_config = ConfigDict(extra="forbid")

    ad_account_id: str = Field(..., description="Ad account ID")
    time_range: Dict[str, str] = Field(..., description="Time range for report")
    breakdowns: Optional[List[str]] = Field(default=None, description="Breakdown dimensions")
    fields: List[str] = Field(
        default_factory=lambda: ["impressions", "clicks", "conversions", "cost_per_conversion"],
        description="Metrics to include"
    )


class VideoMetricsRequest(BaseModel):
    """Request for video performance metrics."""

    model_config = ConfigDict(extra="forbid")

    ad_account_id: str = Field(..., description="Ad account ID")
    time_range: Dict[str, str] = Field(..., description="Time range for analysis")
    video_breakdowns: Optional[List[str]] = Field(default=None, description="Video-specific breakdowns")
    fields: List[str] = Field(
        default_factory=lambda: ["video_views", "video_view_rate", "video_play_actions", "video_avg_time_watched"],
        description="Video metrics to include"
    )


# Campaign Templates & Duplication Schemas
class CampaignDuplicationRequest(BaseModel):
    """Request to duplicate a campaign."""

    model_config = ConfigDict(extra="forbid")

    source_campaign_id: str = Field(..., description="Source campaign ID to duplicate")
    new_campaign_name: str = Field(..., description="Name for the new campaign")
    new_adset_names: Optional[Dict[str, str]] = Field(default=None, description="New names for ad sets")
    new_ad_names: Optional[Dict[str, str]] = Field(default=None, description="New names for ads")
    copy_creative_assets: bool = Field(default=True, description="Whether to copy creative assets")


class CampaignTemplateRequest(BaseModel):
    """Request to create a campaign template."""

    model_config = ConfigDict(extra="forbid")

    campaign_id: str = Field(..., description="Campaign ID to save as template")
    template_name: str = Field(..., description="Name for the template")
    template_description: Optional[str] = Field(default=None, description="Template description")
    include_audiences: bool = Field(default=True, description="Include audience targeting")
    include_creatives: bool = Field(default=True, description="Include creative assets")


class ApplyTemplateRequest(BaseModel):
    """Request to create campaign from template."""

    model_config = ConfigDict(extra="forbid")

    template_id: str = Field(..., description="Template ID to apply")
    new_campaign_name: str = Field(..., description="Name for the new campaign")
    ad_account_id: str = Field(..., description="Target ad account ID")
    customizations: Optional[Dict[str, Any]] = Field(default=None, description="Customizations to apply")


# Webhook Management Schemas
class CreateWebhookSubscriptionRequest(BaseModel):
    """Request to create a webhook subscription."""

    model_config = ConfigDict(extra="forbid")

    object_type: str = Field(..., description="Type of object to subscribe to")
    callback_url: str = Field(..., description="URL to receive webhook events")
    fields: List[str] = Field(..., description="Fields to include in webhook payload")
    verify_token: str = Field(..., description="Token for webhook verification")
    ad_account_id: Optional[str] = Field(default=None, description="Ad account ID (required for some object types)")


class ListWebhookSubscriptionsRequest(BaseModel):
    """Request to list webhook subscriptions."""

    model_config = ConfigDict(extra="forbid")

    fields: List[str] = Field(
        default_factory=lambda: ["id", "object", "callback_url", "active", "created_time"],
        description="Fields to retrieve"
    )


class DeleteWebhookSubscriptionRequest(BaseModel):
    """Request to delete a webhook subscription."""

    model_config = ConfigDict(extra="forbid")

    subscription_id: str = Field(..., description="Subscription ID to delete")


class TestWebhookRequest(BaseModel):
    """Request to test a webhook subscription."""

    model_config = ConfigDict(extra="forbid")

    subscription_id: str = Field(..., description="Subscription ID to test")


class VerifyWebhookRequest(BaseModel):
    """Request to verify webhook signature."""

    model_config = ConfigDict(extra="forbid")

    payload: str = Field(..., description="Raw webhook payload")
    signature: str = Field(..., description="X-Hub-Signature-256 header value")
    app_secret: str = Field(..., description="App secret for signature verification")


# Audit Logging Schemas
class GetAuditLogsRequest(BaseModel):
    """Request to get audit logs."""

    model_config = ConfigDict(extra="forbid")

    resource_type: Optional[str] = Field(default=None, description="Filter by resource type")
    resource_id: Optional[str] = Field(default=None, description="Filter by resource ID")
    operation_type: Optional[str] = Field(default=None, description="Filter by operation type")
    user_id: Optional[str] = Field(default=None, description="Filter by user ID")
    ad_account_id: Optional[str] = Field(default=None, description="Filter by ad account ID")
    start_time: Optional[str] = Field(default=None, description="Start time (ISO 8601)")
    end_time: Optional[str] = Field(default=None, description="End time (ISO 8601)")
    limit: int = Field(default=100, le=1000, ge=1, description="Number of results to return")


class GetPerformanceMetricsRequest(BaseModel):
    """Request to get performance metrics."""

    model_config = ConfigDict(extra="forbid")

    operation_type: Optional[str] = Field(default=None, description="Filter by operation type")
    resource_type: Optional[str] = Field(default=None, description="Filter by resource type")
    ad_account_id: Optional[str] = Field(default=None, description="Filter by ad account ID")
    start_time: Optional[str] = Field(default=None, description="Start time (ISO 8601)")
    end_time: Optional[str] = Field(default=None, description="End time (ISO 8601)")
    limit: int = Field(default=100, le=1000, ge=1, description="Number of results to return")


class TrackChangesRequest(BaseModel):
    """Request to track changes between old and new data."""

    model_config = ConfigDict(extra="forbid")

    resource_type: str = Field(..., description="Type of resource")
    resource_id: str = Field(..., description="ID of the resource")
    old_data: Dict[str, Any] = Field(..., description="Previous state of the resource")
    new_data: Dict[str, Any] = Field(..., description="New state of the resource")
    user_id: Optional[str] = Field(default=None, description="ID of the user making changes")
    ad_account_id: Optional[str] = Field(default=None, description="Ad account ID")


# Advanced Search Schemas
class FilterConditionRequest(BaseModel):
    """Request for a filter condition."""

    model_config = ConfigDict(extra="forbid")

    field: str = Field(..., description="Field to filter on")
    operator: str = Field(..., description="Filter operator")
    value: Any = Field(..., description="Value to compare against")
    case_sensitive: bool = Field(default=False, description="Case sensitive comparison")


class SortConditionRequest(BaseModel):
    """Request for a sort condition."""

    model_config = ConfigDict(extra="forbid")

    field: str = Field(..., description="Field to sort by")
    direction: str = Field(..., description="Sort direction (asc/desc)")


class SearchQueryRequest(BaseModel):
    """Request for advanced search."""

    model_config = ConfigDict(extra="forbid")

    ad_account_id: str = Field(..., description="Ad account ID to search in")
    text_query: Optional[str] = Field(default=None, description="Text search query")
    filters: Optional[List[FilterConditionRequest]] = Field(default=None, description="Filter conditions")
    sort_conditions: Optional[List[SortConditionRequest]] = Field(default=None, description="Sort conditions")
    tags: Optional[List[str]] = Field(default=None, description="Tags to filter by")
    limit: int = Field(default=100, le=1000, ge=1, description="Number of results to return")
    offset: int = Field(default=0, ge=0, description="Number of results to skip")


class CreateTagRequest(BaseModel):
    """Request to create a campaign tag."""

    model_config = ConfigDict(extra="forbid")

    ad_account_id: str = Field(..., description="Ad account ID")
    name: str = Field(..., description="Tag name")
    color: str = Field(default="#007bff", description="Tag color")
    description: Optional[str] = Field(default=None, description="Tag description")


class TagCampaignRequest(BaseModel):
    """Request to tag a campaign."""

    model_config = ConfigDict(extra="forbid")

    campaign_id: str = Field(..., description="Campaign ID to tag")
    tag_id: str = Field(..., description="Tag ID to apply")


class GetCampaignTagsRequest(BaseModel):
    """Request to get campaign tags."""

    model_config = ConfigDict(extra="forbid")

    campaign_id: str = Field(..., description="Campaign ID")


# Helper Tools Schemas
class CampaignHealthRequest(BaseModel):
    """Request for campaign health analysis."""

    model_config = ConfigDict(extra="forbid")

    campaign_id: str = Field(..., description="Campaign ID to analyze")
    days_back: int = Field(default=7, ge=1, le=90, description="Number of days to analyze")


class OptimizationSuggestionsRequest(BaseModel):
    """Request for optimization suggestions."""

    model_config = ConfigDict(extra="forbid")

    campaign_id: str = Field(..., description="Campaign ID to analyze")
    days_back: int = Field(default=7, ge=1, le=90, description="Number of days to analyze")


class CreativeAnalysisRequest(BaseModel):
    """Request for creative performance analysis."""

    model_config = ConfigDict(extra="forbid")

    campaign_id: str = Field(..., description="Campaign ID to analyze")
    days_back: int = Field(default=7, ge=1, le=90, description="Number of days to analyze")


class AudienceOverlapRequest(BaseModel):
    """Request for audience overlap analysis."""

    model_config = ConfigDict(extra="forbid")

    ad_account_id: str = Field(..., description="Ad account ID")
    audience_ids: Optional[List[str]] = Field(default=None, description="Specific audience IDs to check")


# Observability Schemas
class GetMetricsRequest(BaseModel):
    """Request to get Prometheus metrics."""

    model_config = ConfigDict(extra="forbid")

    format: str = Field(default="prometheus", description="Metrics format (prometheus, json)")
    include_help: bool = Field(default=True, description="Include help text")


class SetupObservabilityRequest(BaseModel):
    """Request to setup observability."""

    model_config = ConfigDict(extra="forbid")

    service_name: str = Field(default="meta-ads-mcp", description="Service name")
    service_version: str = Field(default="1.0.0", description="Service version")
    enable_prometheus: bool = Field(default=True, description="Enable Prometheus metrics")
    enable_tracing: bool = Field(default=True, description="Enable OpenTelemetry tracing")
    enable_metrics: bool = Field(default=True, description="Enable OpenTelemetry metrics")


# Historical Data Retrieval Schemas
class CampaignPerformanceHistoryRequest(BaseModel):
    """Request for detailed historical campaign performance data."""

    model_config = ConfigDict(extra="forbid")

    campaign_id: str = Field(..., description="Campaign ID")
    start_date: str = Field(..., description="Start date (YYYY-MM-DD)")
    end_date: str = Field(..., description="End date (YYYY-MM-DD)")
    breakdowns: Optional[List[str]] = Field(default=None, description="Breakdown dimensions")
    fields: List[str] = Field(default_factory=lambda: ["spend", "impressions", "clicks", "ctr", "cpc", "cpm", "conversions"], description="Metrics to retrieve")
    time_increment: int = Field(default=1, description="Time increment in days")


class SpendTrendsRequest(BaseModel):
    """Request for spending patterns over time."""

    model_config = ConfigDict(extra="forbid")

    ad_account_id: str = Field(..., description="Ad account ID")
    start_date: str = Field(..., description="Start date (YYYY-MM-DD)")
    end_date: str = Field(..., description="End date (YYYY-MM-DD)")
    group_by: str = Field(default="day", description="Group by: day, week, month")
    include_forecast: bool = Field(default=False, description="Include spending forecast")


class AudiencePerformanceHistoryRequest(BaseModel):
    """Request for historical audience segment performance."""

    model_config = ConfigDict(extra="forbid")

    ad_account_id: str = Field(..., description="Ad account ID")
    audience_ids: Optional[List[str]] = Field(default=None, description="Specific audience IDs")
    start_date: str = Field(..., description="Start date (YYYY-MM-DD)")
    end_date: str = Field(..., description="End date (YYYY-MM-DD)")
    breakdowns: List[str] = Field(default_factory=lambda: ["age", "gender"], description="Breakdown dimensions")


class CreativePerformanceHistoryRequest(BaseModel):
    """Request for historical creative performance trends."""

    model_config = ConfigDict(extra="forbid")

    ad_account_id: str = Field(..., description="Ad account ID")
    creative_ids: Optional[List[str]] = Field(default=None, description="Specific creative IDs")
    start_date: str = Field(..., description="Start date (YYYY-MM-DD)")
    end_date: str = Field(..., description="End date (YYYY-MM-DD)")
    include_fatigue_analysis: bool = Field(default=True, description="Include creative fatigue analysis")


class HourlyBreakdownRequest(BaseModel):
    """Request for hour-by-hour performance data."""

    model_config = ConfigDict(extra="forbid")

    entity_id: str = Field(..., description="Campaign, adset, or ad ID")
    entity_type: str = Field(..., description="Entity type: campaign, adset, or ad")
    start_date: str = Field(..., description="Start date (YYYY-MM-DD)")
    end_date: str = Field(..., description="End date (YYYY-MM-DD)")
    timezone: str = Field(default="UTC", description="Timezone for hour breakdown")


class ComparePeriodsRequest(BaseModel):
    """Request to compare performance across time periods."""

    model_config = ConfigDict(extra="forbid")

    entity_id: str = Field(..., description="Entity ID to compare")
    entity_type: str = Field(..., description="Entity type")
    period_a_start: str = Field(..., description="Period A start date")
    period_a_end: str = Field(..., description="Period A end date")
    period_b_start: str = Field(..., description="Period B start date")
    period_b_end: str = Field(..., description="Period B end date")
    metrics: List[str] = Field(default_factory=lambda: ["spend", "impressions", "clicks", "conversions"], description="Metrics to compare")


# Granular Performance Metrics Schemas
class PerformanceByDemographicsRequest(BaseModel):
    """Request for performance breakdown by demographics."""

    model_config = ConfigDict(extra="forbid")

    entity_id: str = Field(..., description="Entity ID")
    entity_type: str = Field(..., description="Entity type")
    start_date: str = Field(..., description="Start date (YYYY-MM-DD)")
    end_date: str = Field(..., description="End date (YYYY-MM-DD)")
    demographics: List[str] = Field(default_factory=lambda: ["age", "gender"], description="Demographic breakdowns")
    metrics: List[str] = Field(default_factory=lambda: ["spend", "impressions", "clicks", "ctr", "cpc", "conversions"], description="Metrics to retrieve")


class PerformanceByDeviceRequest(BaseModel):
    """Request for performance breakdown by device type."""

    model_config = ConfigDict(extra="forbid")

    entity_id: str = Field(..., description="Entity ID")
    entity_type: str = Field(..., description="Entity type")
    start_date: str = Field(..., description="Start date (YYYY-MM-DD)")
    end_date: str = Field(..., description="End date (YYYY-MM-DD)")
    device_types: List[str] = Field(default_factory=lambda: ["desktop", "mobile", "tablet"], description="Device types to include")
    metrics: List[str] = Field(default_factory=lambda: ["spend", "impressions", "clicks", "ctr", "cpc", "conversions"], description="Metrics to retrieve")


class PerformanceByPlacementRequest(BaseModel):
    """Request for performance breakdown by ad placement."""

    model_config = ConfigDict(extra="forbid")

    entity_id: str = Field(..., description="Entity ID")
    entity_type: str = Field(..., description="Entity type")
    start_date: str = Field(..., description="Start date (YYYY-MM-DD)")
    end_date: str = Field(..., description="End date (YYYY-MM-DD)")
    placements: List[str] = Field(default_factory=lambda: ["facebook_feed", "instagram_feed", "messenger", "audience_network"], description="Placements to include")
    metrics: List[str] = Field(default_factory=lambda: ["spend", "impressions", "clicks", "ctr", "cpc", "conversions"], description="Metrics to retrieve")


class PerformanceByTimeRequest(BaseModel):
    """Request for performance breakdown by time."""

    model_config = ConfigDict(extra="forbid")

    entity_id: str = Field(..., description="Entity ID")
    entity_type: str = Field(..., description="Entity type")
    start_date: str = Field(..., description="Start date (YYYY-MM-DD)")
    end_date: str = Field(..., description="End date (YYYY-MM-DD)")
    time_breakdown: str = Field(default="hour", description="Time breakdown: hour, day, week")
    timezone: str = Field(default="UTC", description="Timezone for time breakdown")
    metrics: List[str] = Field(default_factory=lambda: ["spend", "impressions", "clicks", "ctr", "cpc", "conversions"], description="Metrics to retrieve")


class DeliveryInsightsRequest(BaseModel):
    """Request for delivery and pacing insights."""

    model_config = ConfigDict(extra="forbid")

    entity_id: str = Field(..., description="Entity ID")
    entity_type: str = Field(..., description="Entity type")
    start_date: str = Field(..., description="Start date (YYYY-MM-DD)")
    end_date: str = Field(..., description="End date (YYYY-MM-DD)")
    include_pacing: bool = Field(default=True, description="Include budget pacing analysis")
    include_delivery: bool = Field(default=True, description="Include delivery status analysis")


class FrequencyDistributionByDateRangeRequest(BaseModel):
    """Request for ad frequency distribution analysis."""

    model_config = ConfigDict(extra="forbid")

    entity_id: str = Field(..., description="Entity ID")
    entity_type: str = Field(..., description="Entity type")
    start_date: str = Field(..., description="Start date (YYYY-MM-DD)")
    end_date: str = Field(..., description="End date (YYYY-MM-DD)")
    max_frequency: int = Field(default=10, description="Maximum frequency to analyze")
    include_reach: bool = Field(default=True, description="Include reach analysis")


# Granular Budget Management Schemas
class GetCurrentBudgetRequest(BaseModel):
    """Request to get current budget and spend status."""

    model_config = ConfigDict(extra="forbid")

    entity_id: str = Field(..., description="Campaign or adset ID")
    entity_type: str = Field(..., description="Entity type: campaign or adset")


class GetBudgetRecommendationsRequest(BaseModel):
    """Request to get Meta's budget recommendations."""

    model_config = ConfigDict(extra="forbid")

    entity_id: str = Field(..., description="Campaign or adset ID")
    entity_type: str = Field(..., description="Entity type: campaign or adset")
    include_forecast: bool = Field(default=True, description="Include spending forecast")


class SetDailyBudgetRequest(BaseModel):
    """Request to set daily budget with validation."""

    model_config = ConfigDict(extra="forbid")

    entity_id: str = Field(..., description="Campaign or adset ID")
    entity_type: str = Field(..., description="Entity type: campaign or adset")
    daily_budget: float = Field(..., description="Daily budget amount")
    validate_limits: bool = Field(default=True, description="Validate against account limits")


class SetLifetimeBudgetRequest(BaseModel):
    """Request to set lifetime budget."""

    model_config = ConfigDict(extra="forbid")

    entity_id: str = Field(..., description="Campaign or adset ID")
    entity_type: str = Field(..., description="Entity type: campaign or adset")
    lifetime_budget: float = Field(..., description="Lifetime budget amount")
    validate_limits: bool = Field(default=True, description="Validate against account limits")


class AdjustBudgetRelativeRequest(BaseModel):
    """Request to adjust budget by percentage."""

    model_config = ConfigDict(extra="forbid")

    entity_id: str = Field(..., description="Campaign or adset ID")
    entity_type: str = Field(..., description="Entity type: campaign or adset")
    adjustment_percentage: float = Field(..., description="Budget adjustment percentage (e.g., 20 for +20%)")
    max_adjustment: Optional[float] = Field(default=None, description="Maximum absolute adjustment amount")
    validate_limits: bool = Field(default=True, description="Validate against account limits")


class PauseOnLimitRequest(BaseModel):
    """Request to set automatic pause when limit reached."""

    model_config = ConfigDict(extra="forbid")

    entity_id: str = Field(..., description="Campaign or adset ID")
    entity_type: str = Field(..., description="Entity type: campaign or adset")
    limit_type: str = Field(..., description="Limit type: daily_budget or lifetime_budget")
    limit_amount: float = Field(..., description="Limit amount")
    action: str = Field(default="pause", description="Action when limit reached: pause or notify")


class ScheduleBudgetChangeRequest(BaseModel):
    """Request to schedule future budget changes."""

    model_config = ConfigDict(extra="forbid")

    entity_id: str = Field(..., description="Campaign or adset ID")
    entity_type: str = Field(..., description="Entity type: campaign or adset")
    new_budget: float = Field(..., description="New budget amount")
    schedule_date: str = Field(..., description="Date to apply change (YYYY-MM-DD)")
    schedule_time: str = Field(default="00:00", description="Time to apply change (HH:MM)")
    timezone: str = Field(default="UTC", description="Timezone for scheduling")


# Advanced Bid Control Schemas
class GetCurrentBidRequest(BaseModel):
    """Request to get current bid strategy and amounts."""

    model_config = ConfigDict(extra="forbid")

    entity_id: str = Field(..., description="Campaign or adset ID")
    entity_type: str = Field(..., description="Entity type: campaign or adset")


class SetBidStrategyRequest(BaseModel):
    """Request to change bid strategy."""

    model_config = ConfigDict(extra="forbid")

    entity_id: str = Field(..., description="Campaign or adset ID")
    entity_type: str = Field(..., description="Entity type: campaign or adset")
    bid_strategy: str = Field(..., description="Bid strategy: LOWEST_COST_WITHOUT_CAP, LOWEST_COST_WITH_BID_CAP, TARGET_COST, BID_CAP")
    bid_amount: Optional[float] = Field(default=None, description="Bid amount (required for TARGET_COST and BID_CAP)")


class SetBidCapRequest(BaseModel):
    """Request to set bid cap."""

    model_config = ConfigDict(extra="forbid")

    entity_id: str = Field(..., description="Campaign or adset ID")
    entity_type: str = Field(..., description="Entity type: campaign or adset")
    bid_cap: float = Field(..., description="Bid cap amount")
    validate_limits: bool = Field(default=True, description="Validate against account limits")


class SetTargetCostRequest(BaseModel):
    """Request to set target cost."""

    model_config = ConfigDict(extra="forbid")

    entity_id: str = Field(..., description="Campaign or adset ID")
    entity_type: str = Field(..., description="Entity type: campaign or adset")
    target_cost: float = Field(..., description="Target cost amount")
    validate_limits: bool = Field(default=True, description="Validate against account limits")


class GetAuctionInsightsRequest(BaseModel):
    """Request to get auction competitiveness data."""

    model_config = ConfigDict(extra="forbid")

    entity_id: str = Field(..., description="Campaign or adset ID")
    entity_type: str = Field(..., description="Entity type: campaign or adset")
    start_date: str = Field(..., description="Start date (YYYY-MM-DD)")
    end_date: str = Field(..., description="End date (YYYY-MM-DD)")
    include_competitors: bool = Field(default=True, description="Include competitor analysis")


class SimulateBidChangeRequest(BaseModel):
    """Request to preview impact before applying bid changes."""

    model_config = ConfigDict(extra="forbid")

    entity_id: str = Field(..., description="Campaign or adset ID")
    entity_type: str = Field(..., description="Entity type: campaign or adset")
    new_bid_strategy: str = Field(..., description="New bid strategy")
    new_bid_amount: Optional[float] = Field(default=None, description="New bid amount")
    simulation_period: int = Field(default=7, description="Simulation period in days")


# Scheduling & Automation Schemas
class CreateScheduleRequest(BaseModel):
    """Request to schedule a future action."""

    model_config = ConfigDict(extra="forbid")

    entity_id: str = Field(..., description="Entity ID to schedule action for")
    entity_type: str = Field(..., description="Entity type: campaign, adset, or ad")
    action_type: str = Field(..., description="Action type: pause, resume, budget_change, bid_change")
    action_params: Dict[str, Any] = Field(..., description="Parameters for the action")
    schedule_date: str = Field(..., description="Date to execute action (YYYY-MM-DD)")
    schedule_time: str = Field(default="00:00", description="Time to execute action (HH:MM)")
    timezone: str = Field(default="UTC", description="Timezone for scheduling")
    recurring: bool = Field(default=False, description="Whether to repeat this action")
    recurring_frequency: Optional[str] = Field(default=None, description="Recurring frequency: daily, weekly, monthly")


class ListSchedulesRequest(BaseModel):
    """Request to list scheduled actions."""

    model_config = ConfigDict(extra="forbid")

    entity_id: Optional[str] = Field(default=None, description="Filter by entity ID")
    entity_type: Optional[str] = Field(default=None, description="Filter by entity type")
    status: Optional[str] = Field(default=None, description="Filter by status: pending, completed, cancelled")
    limit: int = Field(default=50, description="Maximum number of schedules to return")


class CancelScheduleRequest(BaseModel):
    """Request to cancel a scheduled action."""

    model_config = ConfigDict(extra="forbid")

    schedule_id: str = Field(..., description="Schedule ID to cancel")


class GetDaypartingRequest(BaseModel):
    """Request to get current dayparting settings."""

    model_config = ConfigDict(extra="forbid")

    entity_id: str = Field(..., description="Campaign or adset ID")
    entity_type: str = Field(..., description="Entity type: campaign or adset")


class SetDaypartingRequest(BaseModel):
    """Request to configure ad scheduling by day/hour."""

    model_config = ConfigDict(extra="forbid")

    entity_id: str = Field(..., description="Campaign or adset ID")
    entity_type: str = Field(..., description="Entity type: campaign or adset")
    dayparting_schedule: Dict[str, List[int]] = Field(..., description="Dayparting schedule: {day: [hours]}")
    timezone: str = Field(default="UTC", description="Timezone for dayparting")
    bid_adjustments: Optional[Dict[str, float]] = Field(default=None, description="Bid adjustments by day/hour")


# Comparison & Benchmarking Schemas
class CompareCampaignsRequest(BaseModel):
    """Request to compare multiple campaigns side-by-side."""

    model_config = ConfigDict(extra="forbid")

    campaign_ids: List[str] = Field(..., description="List of campaign IDs to compare")
    start_date: str = Field(..., description="Start date for comparison (YYYY-MM-DD)")
    end_date: str = Field(..., description="End date for comparison (YYYY-MM-DD)")
    metrics: List[str] = Field(default_factory=lambda: ["spend", "impressions", "clicks", "ctr", "cpc", "conversions"], description="Metrics to compare")
    include_breakdowns: bool = Field(default=False, description="Include demographic/device breakdowns")


class CompareAdsetsRequest(BaseModel):
    """Request to compare multiple ad sets."""

    model_config = ConfigDict(extra="forbid")

    adset_ids: List[str] = Field(..., description="List of adset IDs to compare")
    start_date: str = Field(..., description="Start date for comparison (YYYY-MM-DD)")
    end_date: str = Field(..., description="End date for comparison (YYYY-MM-DD)")
    metrics: List[str] = Field(default_factory=lambda: ["spend", "impressions", "clicks", "ctr", "cpc", "conversions"], description="Metrics to compare")
    include_audience_breakdown: bool = Field(default=False, description="Include audience performance breakdown")


class CompareCreativesRequest(BaseModel):
    """Request to compare creative performance."""

    model_config = ConfigDict(extra="forbid")

    creative_ids: List[str] = Field(..., description="List of creative IDs to compare")
    start_date: str = Field(..., description="Start date for comparison (YYYY-MM-DD)")
    end_date: str = Field(..., description="End date for comparison (YYYY-MM-DD)")
    metrics: List[str] = Field(default_factory=lambda: ["spend", "impressions", "clicks", "ctr", "cpc", "conversions"], description="Metrics to compare")
    include_fatigue_analysis: bool = Field(default=True, description="Include creative fatigue analysis")


class CompareTimePeriodsRequest(BaseModel):
    """Request to compare same campaign across time periods."""

    model_config = ConfigDict(extra="forbid")

    entity_id: str = Field(..., description="Entity ID to compare")
    entity_type: str = Field(..., description="Entity type: campaign, adset, or ad")
    period_a_start: str = Field(..., description="Period A start date (YYYY-MM-DD)")
    period_a_end: str = Field(..., description="Period A end date (YYYY-MM-DD)")
    period_b_start: str = Field(..., description="Period B start date (YYYY-MM-DD)")
    period_b_end: str = Field(..., description="Period B end date (YYYY-MM-DD)")
    metrics: List[str] = Field(default_factory=lambda: ["spend", "impressions", "clicks", "ctr", "cpc", "conversions"], description="Metrics to compare")
    include_trend_analysis: bool = Field(default=True, description="Include trend analysis between periods")


class CompareToAccountAverageRequest(BaseModel):
    """Request to compare entity to account-level averages."""

    model_config = ConfigDict(extra="forbid")

    entity_id: str = Field(..., description="Entity ID to compare")
    entity_type: str = Field(..., description="Entity type: campaign, adset, or ad")
    ad_account_id: str = Field(..., description="Ad account ID for comparison")
    start_date: str = Field(..., description="Start date for comparison (YYYY-MM-DD)")
    end_date: str = Field(..., description="End date for comparison (YYYY-MM-DD)")
    metrics: List[str] = Field(default_factory=lambda: ["spend", "impressions", "clicks", "ctr", "cpc", "conversions"], description="Metrics to compare")
    include_percentiles: bool = Field(default=True, description="Include percentile rankings")


class CalculatePercentilesRequest(BaseModel):
    """Request to calculate performance percentiles."""

    model_config = ConfigDict(extra="forbid")

    ad_account_id: str = Field(..., description="Ad account ID")
    entity_type: str = Field(..., description="Entity type: campaign, adset, or ad")
    start_date: str = Field(..., description="Start date for analysis (YYYY-MM-DD)")
    end_date: str = Field(..., description="End date for analysis (YYYY-MM-DD)")
    metrics: List[str] = Field(default_factory=lambda: ["spend", "impressions", "clicks", "ctr", "cpc", "conversions"], description="Metrics to analyze")
    percentiles: List[int] = Field(default_factory=lambda: [25, 50, 75, 90, 95], description="Percentiles to calculate")


class AsyncJobStatusRequest(BaseModel):
    """Retrieve the status of a long-running async job."""

    job_id: str = Field(..., description="Async job ID returned by the Graph API")
    fields: List[str] | None = Field(default=None, description="Optional fields to request on the job object")


class ToolExecutionContext(BaseModel):
    """Metadata describing the MCP tool invocation context."""

    request_id: str
    client: str | None = None
    actor: str | None = None
    metadata: Dict[str, Any] | None = None


class ToolResult(BaseModel):
    """Standard response envelope for tool execution."""

    ok: bool = True
    data: Any | None = None
    error: Dict[str, Any] | None = None


class HealthCheckResult(BaseModel):
    ok: bool
    api_version: str
    ad_account_id: Optional[str] = None
    business_id: Optional[str] = None


# Data Aggregation Tools Schemas
class AggregateByObjectiveRequest(BaseModel):
    ad_account_id: str
    time_range: Dict[str, str]
    fields: List[str] = Field(default_factory=lambda: ["spend", "impressions", "clicks", "conversions", "cpm", "cpc", "ctr", "conversion_rate"])
    breakdowns: Optional[List[str]] = None
    filters: Optional[List[Dict[str, Any]]] = None


class AggregateByStatusRequest(BaseModel):
    ad_account_id: str
    object_type: str  # campaign, adset, ad
    time_range: Dict[str, str]
    fields: List[str] = Field(default_factory=lambda: ["spend", "impressions", "clicks", "conversions", "cpm", "cpc", "ctr", "conversion_rate"])
    filters: Optional[List[Dict[str, Any]]] = None


class AggregateSpendingDistributionRequest(BaseModel):
    ad_account_id: str
    object_type: str  # campaign, adset, ad
    time_range: Dict[str, str]
    percentiles: List[float] = Field(default_factory=lambda: [25, 50, 75, 90, 95, 99])
    filters: Optional[List[Dict[str, Any]]] = None


class AggregatePerformanceSummaryRequest(BaseModel):
    ad_account_id: str
    object_type: str  # campaign, adset, ad
    time_range: Dict[str, str]
    fields: List[str] = Field(default_factory=lambda: ["spend", "impressions", "clicks", "conversions", "cpm", "cpc", "ctr", "conversion_rate"])
    include_trends: bool = True
    filters: Optional[List[Dict[str, Any]]] = None


class IdentifyTopPerformersRequest(BaseModel):
    ad_account_id: str
    object_type: str  # campaign, adset, ad
    time_range: Dict[str, str]
    performance_metric: str  # e.g., "conversions", "ctr", "conversion_rate"
    limit: int = 10
    minimum_spend: float = 0.0
    fields: List[str] = Field(default_factory=lambda: ["spend", "impressions", "clicks", "conversions", "cpm", "cpc", "ctr", "conversion_rate"])
    filters: Optional[List[Dict[str, Any]]] = None


class IdentifyBottomPerformersRequest(BaseModel):
    ad_account_id: str
    object_type: str  # campaign, adset, ad
    time_range: Dict[str, str]
    performance_metric: str  # e.g., "conversions", "ctr", "conversion_rate"
    limit: int = 10
    minimum_spend: float = 0.0
    fields: List[str] = Field(default_factory=lambda: ["spend", "impressions", "clicks", "conversions", "cpm", "cpc", "ctr", "conversion_rate"])
    filters: Optional[List[Dict[str, Any]]] = None


class PerformanceMetrics(BaseModel):
    spend: float
    impressions: int
    clicks: int
    conversions: int
    cpm: float
    cpc: float
    ctr: float
    conversion_rate: float


class SpendingDistribution(BaseModel):
    total_spend: float
    average_spend: float
    median_spend: float
    percentile_breakdown: Dict[str, float]
    spend_range: Dict[str, float]


class TopPerformer(BaseModel):
    rank: int
    object_id: str
    object_name: str
    performance_metric_value: float
    spend: float
    impressions: int
    clicks: int


class BottomPerformer(BaseModel):
    rank: int
    object_id: str
    object_name: str
    performance_metric_value: float
    spend: float
    impressions: int
    clicks: int
    improvement_potential: str


class PerformanceSummary(BaseModel):
    metrics: PerformanceMetrics
    trends: Optional[Dict[str, str]] = None
    data_points: int


class ObjectiveSummary(BaseModel):
    objective: str
    campaign_count: int
    metrics: PerformanceMetrics
    top_campaigns: List[str]


class StatusSummary(BaseModel):
    status: str
    object_count: int
    metrics: PerformanceMetrics
    top_objects: List[str]


class AggregateByObjectiveResponse(BaseModel):
    objective_summaries: List[ObjectiveSummary]
    total_campaigns: int
    total_objectives: int
    time_range: Dict[str, str]
    generated_at: datetime


class AggregateByStatusResponse(BaseModel):
    status_summaries: List[StatusSummary]
    total_objects: int
    object_type: str
    time_range: Dict[str, str]
    generated_at: datetime


class AggregateSpendingDistributionResponse(BaseModel):
    distribution: SpendingDistribution
    object_type: str
    time_range: Dict[str, str]
    generated_at: datetime


class AggregatePerformanceSummaryResponse(BaseModel):
    summary: PerformanceSummary
    object_type: str
    time_range: Dict[str, str]
    generated_at: datetime


class IdentifyTopPerformersResponse(BaseModel):
    top_performers: List[TopPerformer]
    object_type: str
    performance_metric: str
    time_range: Dict[str, str]
    generated_at: datetime


class IdentifyBottomPerformersResponse(BaseModel):
    bottom_performers: List[BottomPerformer]
    object_type: str
    performance_metric: str
    time_range: Dict[str, str]
    generated_at: datetime


# Calculation & Analysis Utilities Schemas
class CalculateROIRequest(BaseModel):
    ad_account_id: str
    entity_ids: List[str]
    entity_type: str  # campaign, adset, ad
    time_range: Dict[str, str]


class CalculateROASRequest(BaseModel):
    ad_account_id: str
    entity_ids: List[str]
    entity_type: str  # campaign, adset, ad
    time_range: Dict[str, str]


class CalculateEfficiencyScoreRequest(BaseModel):
    ad_account_id: str
    entity_ids: List[str]
    entity_type: str  # campaign, adset, ad
    time_range: Dict[str, str]
    metrics: List[str] = Field(default_factory=lambda: ["ctr", "cpc", "cpm", "conversion_rate", "cost_per_conversion", "roas"])
    weights: Dict[str, float] = Field(default_factory=lambda: {"ctr": 1.0, "cpc": 1.0, "cpm": 1.0, "conversion_rate": 1.0, "cost_per_conversion": 1.0, "roas": 1.0})


class CalculateTrendRequest(BaseModel):
    ad_account_id: str
    entity_ids: List[str]
    entity_type: str  # campaign, adset, ad
    time_range: Dict[str, str]
    metric: str
    periods: int = 7  # Number of periods to analyze


class CalculateVarianceRequest(BaseModel):
    ad_account_id: str
    entity_ids: List[str]
    entity_type: str  # campaign, adset, ad
    time_range: Dict[str, str]
    metrics: List[str]


class CalculateCorrelationRequest(BaseModel):
    ad_account_id: str
    entity_ids: List[str]
    entity_type: str  # campaign, adset, ad
    time_range: Dict[str, str]
    metrics: List[str]


class CalculatePacingRequest(BaseModel):
    ad_account_id: str
    entity_ids: List[str]
    entity_type: str  # campaign, adset, ad
    time_range: Dict[str, str]


class EfficiencyMetrics(BaseModel):
    ctr: float
    cpc: float
    cpm: float
    conversion_rate: float
    cost_per_conversion: float
    roas: float


class TrendAnalysis(BaseModel):
    slope: float
    intercept: float
    r_squared: float
    trend_direction: str  # increasing, decreasing, stable
    trend_strength: str  # strong, moderate, weak, none


class VarianceAnalysis(BaseModel):
    mean: float
    variance: float
    standard_deviation: float
    coefficient_of_variation: float
    min_value: float
    max_value: float
    range: float


class CorrelationAnalysis(BaseModel):
    metric1: str
    metric2: str
    correlation_coefficient: float
    strength: str  # strong, moderate, weak
    direction: str  # positive, negative


class PacingAnalysis(BaseModel):
    current_spend: float
    daily_budget: float
    lifetime_budget: float
    expected_spend: float
    pacing_percentage: float
    days_elapsed: int
    days_remaining: int
    projected_total_spend: float
    budget_utilization: float


class CalculateROIResponse(BaseModel):
    roi_results: List[Dict[str, Any]]
    aggregate_roi: float
    total_spend: float
    total_conversion_value: float
    total_profit: float
    entity_type: str
    time_range: Dict[str, str]
    generated_at: datetime


class CalculateROASResponse(BaseModel):
    roas_results: List[Dict[str, Any]]
    aggregate_roas: float
    total_spend: float
    total_conversion_value: float
    entity_type: str
    time_range: Dict[str, str]
    generated_at: datetime


class CalculateEfficiencyScoreResponse(BaseModel):
    efficiency_results: List[Dict[str, Any]]
    aggregate_efficiency: float
    entity_type: str
    time_range: Dict[str, str]
    generated_at: datetime


class CalculateTrendResponse(BaseModel):
    trend_results: List[Dict[str, Any]]
    metric: str
    periods: int
    entity_type: str
    time_range: Dict[str, str]
    generated_at: datetime


class CalculateVarianceResponse(BaseModel):
    variance_results: Dict[str, VarianceAnalysis]
    entity_type: str
    time_range: Dict[str, str]
    generated_at: datetime


class CalculateCorrelationResponse(BaseModel):
    correlation_results: Dict[str, CorrelationAnalysis]
    entity_type: str
    time_range: Dict[str, str]
    generated_at: datetime


class CalculatePacingResponse(BaseModel):
    pacing_results: List[Dict[str, Any]]
    entity_type: str
    time_range: Dict[str, str]
    generated_at: datetime


# Validation & Preview Tools Schemas
class ValidateBudgetChangeRequest(BaseModel):
    ad_account_id: str
    entity_id: str
    entity_type: str  # campaign, adset
    new_budget: float
    budget_type: str  # daily, lifetime


class ValidateTargetingRequest(BaseModel):
    ad_account_id: str
    entity_id: str
    entity_type: str  # adset
    targeting_config: Dict[str, Any]


class ValidateCreativeRequest(BaseModel):
    ad_account_id: str
    entity_id: str
    entity_type: str  # ad
    creative_config: Dict[str, Any]


class ValidateCampaignStructureRequest(BaseModel):
    ad_account_id: str
    entity_id: str
    entity_type: str  # campaign
    campaign_config: Dict[str, Any]


class PreviewBudgetImpactRequest(BaseModel):
    ad_account_id: str
    entity_id: str
    entity_type: str  # campaign, adset
    new_budget: float
    budget_type: str  # daily, lifetime


class PreviewBidImpactRequest(BaseModel):
    ad_account_id: str
    entity_id: str
    entity_type: str  # adset
    new_bid: float
    bid_type: str  # bid_amount, target_cost


class ValidationResult(BaseModel):
    is_valid: bool
    confidence: str  # high, medium, low
    issues: List[str]
    warnings: List[str]
    recommendations: List[str]


class BudgetValidation(ValidationResult):
    estimated_impact: str  # minimal, moderate, significant, new_budget, unknown


class TargetingValidation(ValidationResult):
    estimated_reach: int


class CreativeValidation(ValidationResult):
    format_compliance: str  # compliant, partially_compliant, non_compliant, unknown


class CampaignStructureValidation(ValidationResult):
    structure_score: int  # 0-100


class ImpactAnalysis(BaseModel):
    metric_changes: Dict[str, Dict[str, Any]]
    confidence: str  # high, medium, low
    assumptions: List[str]
    risks: List[str]


class BudgetImpactPreview(BaseModel):
    impact_analysis: ImpactAnalysis
    current_budget: float
    proposed_budget: float
    budget_type: str


class BidImpactPreview(BaseModel):
    impact_analysis: ImpactAnalysis
    current_bid: float
    proposed_bid: float
    bid_type: str


class ValidateBudgetChangeResponse(BaseModel):
    validation_result: BudgetValidation
    current_budget: Dict[str, Any]
    proposed_budget: float
    budget_type: str
    entity_id: str
    entity_type: str
    generated_at: datetime


class ValidateTargetingResponse(BaseModel):
    validation_result: TargetingValidation
    current_targeting: Dict[str, Any]
    proposed_targeting: Dict[str, Any]
    entity_id: str
    entity_type: str
    generated_at: datetime


class ValidateCreativeResponse(BaseModel):
    validation_result: CreativeValidation
    current_creative: Dict[str, Any]
    proposed_creative: Dict[str, Any]
    entity_id: str
    entity_type: str
    generated_at: datetime


class ValidateCampaignStructureResponse(BaseModel):
    validation_result: CampaignStructureValidation
    current_structure: Dict[str, Any]
    proposed_structure: Dict[str, Any]
    entity_id: str
    entity_type: str
    generated_at: datetime


class PreviewBudgetImpactResponse(BaseModel):
    impact_analysis: ImpactAnalysis
    current_budget: float
    proposed_budget: float
    budget_type: str
    entity_id: str
    entity_type: str
    generated_at: datetime


class PreviewBidImpactResponse(BaseModel):
    impact_analysis: ImpactAnalysis
    current_bid: float
    proposed_bid: float
    bid_type: str
    entity_id: str
    entity_type: str
    generated_at: datetime


# Intelligent Quick Actions Schemas
class PauseUnderperformersRequest(BaseModel):
    ad_account_id: str
    object_type: str  # campaign, adset, ad
    time_range: Dict[str, str]
    performance_metrics: List[str] = Field(default_factory=lambda: ["conversions", "ctr", "conversion_rate"])
    thresholds: Dict[str, float] = Field(default_factory=lambda: {"conversions": 1, "ctr": 1.0, "conversion_rate": 2.0})
    minimum_spend: float = 10.0
    action_parameters: Dict[str, Any] = Field(default_factory=dict)


class ScaleWinnersRequest(BaseModel):
    ad_account_id: str
    object_type: str  # campaign, adset
    time_range: Dict[str, str]
    performance_metrics: List[str] = Field(default_factory=lambda: ["conversions", "roas"])
    performance_threshold: float = 3.0
    minimum_spend: float = 50.0
    scale_percentage: float = 20.0
    max_budget_increase: float = 1000.0
    action_parameters: Dict[str, Any] = Field(default_factory=dict)


class RotateCreativesRequest(BaseModel):
    ad_account_id: str
    time_range: Dict[str, str]
    fatigue_thresholds: Dict[str, float] = Field(default_factory=lambda: {"frequency": 3.0, "ctr": 1.0})
    rotation_strategy: str = "pause_and_replace"
    action_parameters: Dict[str, Any] = Field(default_factory=dict)


class RebalanceBudgetsRequest(BaseModel):
    ad_account_id: str
    object_type: str  # campaign, adset
    time_range: Dict[str, str]
    performance_metrics: List[str] = Field(default_factory=lambda: ["conversions", "roas", "ctr"])
    rebalancing_strategy: str = "performance_based"
    rebalancing_thresholds: Dict[str, float] = Field(default_factory=dict)
    action_parameters: Dict[str, Any] = Field(default_factory=dict)


class DuplicateWinnerRequest(BaseModel):
    ad_account_id: str
    time_range: Dict[str, str]
    performance_metrics: List[str] = Field(default_factory=lambda: ["conversions", "roas"])
    winner_thresholds: Dict[str, float] = Field(default_factory=lambda: {"roas": 4.0})
    number_of_variations: int = 3
    duplication_strategy: str = "audience_variations"
    action_parameters: Dict[str, Any] = Field(default_factory=dict)


class EmergencyStopRequest(BaseModel):
    ad_account_id: str
    time_range: Dict[str, str]
    entity_types: List[str] = Field(default_factory=lambda: ["campaign", "adset", "ad"])
    emergency_reason: str = "performance_issues"
    action_parameters: Dict[str, Any] = Field(default_factory=dict)


class SmartOptimizationRequest(BaseModel):
    ad_account_id: str
    time_range: Dict[str, str]
    performance_metrics: List[str] = Field(default_factory=lambda: ["conversions", "roas", "ctr", "cpc"])
    optimization_strategy: str = "balanced"
    optimization_thresholds: Dict[str, float] = Field(default_factory=dict)
    action_parameters: Dict[str, Any] = Field(default_factory=dict)


class ActionResult(BaseModel):
    entity_id: str
    entity_name: str
    action: str
    success: bool
    error: Optional[str] = None
    spend_saved: Optional[float] = None
    budget_increase: Optional[float] = None
    budget_change: Optional[float] = None
    impact_score: float


class PerformanceThreshold(BaseModel):
    metric: str
    threshold: float
    operator: str  # greater_than, less_than, equals


class ScalingAction(BaseModel):
    entity_id: str
    entity_name: str
    current_budget: float
    new_budget: float
    scale_percentage: float


class CreativeRotation(BaseModel):
    creative_id: str
    ad_id: str
    rotation_reason: str
    new_creative_id: Optional[str] = None


class BudgetRebalancing(BaseModel):
    entity_id: str
    entity_name: str
    old_budget: float
    new_budget: float
    rebalancing_reason: str


class CampaignDuplication(BaseModel):
    original_campaign_id: str
    new_campaign_id: str
    variation_type: str
    changes_made: List[str]


class EmergencyAction(BaseModel):
    entity_id: str
    entity_type: str
    action_taken: str
    reason: str


class OptimizationPlan(BaseModel):
    strategy: str
    actions: List[Dict[str, Any]]
    estimated_impact: str
    execution_time: str


class PauseUnderperformersResponse(BaseModel):
    action_results: List[ActionResult]
    total_entities_paused: int
    total_spend_saved: float
    underperformers_identified: int
    object_type: str
    time_range: Dict[str, str]
    generated_at: datetime


class ScaleWinnersResponse(BaseModel):
    action_results: List[ActionResult]
    total_entities_scaled: int
    total_budget_increase: float
    winners_identified: int
    object_type: str
    time_range: Dict[str, str]
    generated_at: datetime


class RotateCreativesResponse(BaseModel):
    action_results: List[ActionResult]
    total_creatives_rotated: int
    fatigued_creatives_identified: int
    rotation_strategy: str
    time_range: Dict[str, str]
    generated_at: datetime


class RebalanceBudgetsResponse(BaseModel):
    action_results: List[ActionResult]
    total_entities_rebalanced: int
    total_budget_redistributed: float
    rebalancing_strategy: str
    object_type: str
    time_range: Dict[str, str]
    generated_at: datetime


class DuplicateWinnerResponse(BaseModel):
    action_results: List[ActionResult]
    winner_identified: bool
    campaigns_created: int
    duplication_strategy: str
    time_range: Dict[str, str]
    generated_at: datetime


class EmergencyStopResponse(BaseModel):
    action_results: List[ActionResult]
    total_entities_paused: int
    total_spend_saved: float
    entity_types: List[str]
    emergency_reason: str
    generated_at: datetime


class SmartOptimizationResponse(BaseModel):
    action_results: List[ActionResult]
    total_actions_executed: int
    total_impact_score: float
    optimization_plan: OptimizationPlan
    optimization_strategy: str
    time_range: Dict[str, str]
    generated_at: datetime


# Advanced Analysis Bundles Schemas
class PerformanceCohortRequest(BaseModel):
    ad_account_id: str
    cohort_type: str  # launch_date, objective, strategy
    time_range: Dict[str, str]
    metrics: List[str] = Field(default_factory=lambda: ["spend", "conversions", "impressions", "clicks", "ctr", "cpc", "roas"])
    analysis_parameters: Dict[str, Any] = Field(default_factory=dict)
    data_sources: List[str] = Field(default_factory=lambda: ["insights", "campaigns"])


class EfficiencyFrontierRequest(BaseModel):
    ad_account_id: str
    object_type: str  # campaign, adset, ad
    time_range: Dict[str, str]
    efficiency_metrics: List[str] = Field(default_factory=lambda: ["conversions", "roas", "ctr"])
    optimization_goals: List[str] = Field(default_factory=lambda: ["maximize_roas", "minimize_cpc"])
    analysis_parameters: Dict[str, Any] = Field(default_factory=dict)
    data_sources: List[str] = Field(default_factory=lambda: ["insights"])


class CannibalizationRequest(BaseModel):
    ad_account_id: str
    time_range: Dict[str, str]
    cannibalization_threshold: float = 0.7
    impact_metrics: List[str] = Field(default_factory=lambda: ["conversions", "spend"])
    analysis_parameters: Dict[str, Any] = Field(default_factory=dict)
    data_sources: List[str] = Field(default_factory=lambda: ["campaigns", "insights"])


class TimeDecayRequest(BaseModel):
    ad_account_id: str
    object_type: str  # campaign, adset, ad
    time_range: Dict[str, str]
    decay_metrics: List[str] = Field(default_factory=lambda: ["conversions", "ctr", "cpc"])
    analysis_parameters: Dict[str, Any] = Field(default_factory=dict)
    data_sources: List[str] = Field(default_factory=lambda: ["insights"])


class IncrementalityRequest(BaseModel):
    ad_account_id: str
    baseline_period: Dict[str, str]
    treatment_period: Dict[str, str]
    time_range: Dict[str, str]
    analysis_parameters: Dict[str, Any] = Field(default_factory=dict)
    data_sources: List[str] = Field(default_factory=lambda: ["insights"])


class ContributionMarginsRequest(BaseModel):
    ad_account_id: str
    object_type: str  # campaign, adset, ad
    time_range: Dict[str, str]
    cost_components: List[str] = Field(default_factory=lambda: ["ad_spend", "other_variable_costs", "fixed_costs"])
    analysis_parameters: Dict[str, Any] = Field(default_factory=dict)
    data_sources: List[str] = Field(default_factory=lambda: ["insights", "costs"])


class SaturationPointsRequest(BaseModel):
    ad_account_id: str
    object_type: str  # campaign, adset
    time_range: Dict[str, str]
    optimization_goals: List[str] = Field(default_factory=lambda: ["maximize_conversions", "optimize_roas"])
    analysis_parameters: Dict[str, Any] = Field(default_factory=dict)
    data_sources: List[str] = Field(default_factory=lambda: ["insights", "budgets"])


class CohortAnalysis(BaseModel):
    cohort_id: str
    campaign_count: int
    total_spend: float
    total_conversions: int
    total_impressions: int
    total_clicks: int
    roas: float
    ctr: float
    cpc: float
    performance_trend: str


class EfficiencyPoint(BaseModel):
    entity_id: str
    entity_name: str
    cost: float
    output: float
    efficiency_score: float
    is_on_frontier: bool


class CannibalizationAnalysis(BaseModel):
    campaign1_id: str
    campaign2_id: str
    overlap_score: float
    impact_score: float
    recommendation: str


class DecayAnalysis(BaseModel):
    entity_id: str
    decay_rate: float
    decay_type: str  # none, low, moderate, high
    confidence: str
    recommendations: List[str]


class IncrementalityAnalysis(BaseModel):
    entity_id: str
    baseline_conversions: float
    treatment_conversions: float
    incremental_conversions: float
    incremental_spend: float
    incremental_roas: float
    lift_percentage: float
    confidence: str


class ContributionMargin(BaseModel):
    entity_id: str
    revenue: float
    variable_costs: float
    contribution_margin: float
    contribution_margin_percentage: float
    roas: float
    profit_margin: float
    is_profitable: bool


class SaturationAnalysis(BaseModel):
    entity_id: str
    current_budget: float
    saturation_budget: float
    current_efficiency: float
    saturation_efficiency: float
    optimization_potential: float
    saturation_level: str  # low, medium, high


class PerformanceCohortResponse(BaseModel):
    cohort_analyses: List[CohortAnalysis]
    insights: Dict[str, Any]
    cohort_type: str
    time_range: Dict[str, str]
    generated_at: datetime


class EfficiencyFrontierResponse(BaseModel):
    frontier_points: List[EfficiencyPoint]
    optimization_opportunities: List[Dict[str, Any]]
    efficiency_metrics: List[str]
    object_type: str
    time_range: Dict[str, str]
    generated_at: datetime


class CannibalizationResponse(BaseModel):
    cannibalization_pairs: List[CannibalizationAnalysis]
    impact_analysis: Dict[str, Any]
    overlap_analysis: Dict[str, Any]
    cannibalization_threshold: float
    time_range: Dict[str, str]
    generated_at: datetime


class TimeDecayResponse(BaseModel):
    decay_analyses: List[DecayAnalysis]
    insights: Dict[str, Any]
    decay_metrics: List[str]
    object_type: str
    time_range: Dict[str, str]
    generated_at: datetime


class IncrementalityResponse(BaseModel):
    incrementality_analyses: List[IncrementalityAnalysis]
    overall_analysis: Dict[str, Any]
    baseline_period: Dict[str, str]
    treatment_period: Dict[str, str]
    time_range: Dict[str, str]
    generated_at: datetime


class ContributionMarginsResponse(BaseModel):
    margin_analyses: List[ContributionMargin]
    insights: Dict[str, Any]
    cost_components: List[str]
    object_type: str
    time_range: Dict[str, str]
    generated_at: datetime


class SaturationPointsResponse(BaseModel):
    saturation_analyses: List[SaturationAnalysis]
    recommendations: List[Dict[str, Any]]
    optimization_goals: List[str]
    object_type: str
    time_range: Dict[str, str]
    generated_at: datetime


# Predictive Intelligence Tools Schemas
class PredictBudgetOutcomeRequest(BaseModel):
    ad_account_id: str
    entity_id: str
    entity_type: str  # campaign, adset
    time_range: Dict[str, str]
    budget_scenarios: List[Dict[str, Any]]
    prediction_horizon: int = 7  # days
    optimization_goals: List[str] = Field(default_factory=lambda: ["maximize_roas", "minimize_cpc"])
    prediction_parameters: Dict[str, Any] = Field(default_factory=dict)


class PredictCreativeLifespanRequest(BaseModel):
    ad_account_id: str
    creative_ids: List[str]
    time_range: Dict[str, str]
    fatigue_thresholds: Dict[str, float] = Field(default_factory=lambda: {"frequency": 3.0, "ctr": 1.0})
    prediction_parameters: Dict[str, Any] = Field(default_factory=dict)


class PredictOptimalTimingRequest(BaseModel):
    ad_account_id: str
    entity_id: str
    time_range: Dict[str, str]
    optimization_metrics: List[str] = Field(default_factory=lambda: ["ctr", "cpc", "conversions"])
    scheduling_constraints: List[str] = Field(default_factory=list)
    prediction_parameters: Dict[str, Any] = Field(default_factory=dict)


class PredictAudienceExpansionRequest(BaseModel):
    ad_account_id: str
    entity_id: str
    time_range: Dict[str, str]
    expansion_options: List[str] = Field(default_factory=lambda: ["age_expansion", "geo_expansion", "interest_expansion"])
    impact_metrics: List[str] = Field(default_factory=lambda: ["reach", "cpc", "conversions", "roas"])
    prediction_parameters: Dict[str, Any] = Field(default_factory=dict)


class PredictSeasonalityRequest(BaseModel):
    ad_account_id: str
    entity_id: str
    time_range: Dict[str, str]
    seasonal_periods: List[str] = Field(default_factory=lambda: ["monthly", "weekly", "quarterly"])
    prediction_periods: List[str] = Field(default_factory=lambda: ["next_month", "next_quarter"])
    business_goals: List[str] = Field(default_factory=lambda: ["maximize_conversions", "optimize_spend"])
    prediction_parameters: Dict[str, Any] = Field(default_factory=dict)


class PredictCompetitivePressureRequest(BaseModel):
    ad_account_id: str
    entity_id: str
    time_range: Dict[str, str]
    prediction_horizon: int = 14  # days
    competitive_strategy: str = "balanced"
    prediction_parameters: Dict[str, Any] = Field(default_factory=dict)


class BudgetPrediction(BaseModel):
    scenario_name: str
    current_budget: float
    predicted_budget: float
    predicted_spend: float
    predicted_conversions: float
    predicted_impressions: int
    predicted_clicks: int
    predicted_ctr: float
    predicted_cpc: float
    predicted_roas: float
    confidence: str
    risk_level: str


class CreativeLifespanPrediction(BaseModel):
    creative_id: str
    current_frequency: float
    predicted_fatigue_date: Optional[str]
    fatigue_probability: float
    performance_trend: str
    recommendations: List[str]


class TimingPrediction(BaseModel):
    optimal_hours: List[str]
    optimal_days: List[str]
    hourly_patterns: Dict[str, Any]
    daily_patterns: Dict[str, Any]
    timing_efficiency: float
    confidence: str


class AudienceExpansionPrediction(BaseModel):
    scenario_name: str
    current_reach: int
    predicted_reach: int
    current_spend: float
    predicted_spend: float
    current_conversions: float
    predicted_conversions: float
    current_cpc: float
    predicted_cpc: float
    predicted_roas: float
    predicted_ctr: float
    reach_increase_percentage: float
    efficiency_impact: str


class SeasonalityPrediction(BaseModel):
    period: str
    predicted_performance_multiplier: float
    confidence: str
    seasonal_factors: Dict[str, Any]
    recommendations: List[str]


class CompetitivePressurePrediction(BaseModel):
    time_period: str
    predicted_competition_level: float
    predicted_win_rate: float
    predicted_cpc_impact: str
    confidence: str
    recommendations: List[str]


class PredictBudgetOutcomeResponse(BaseModel):
    predictions: List[BudgetPrediction]
    confidence: str
    recommendations: List[str]
    entity_id: str
    entity_type: str
    prediction_horizon: int
    time_range: Dict[str, str]
    generated_at: datetime


class PredictCreativeLifespanResponse(BaseModel):
    lifespan_predictions: List[CreativeLifespanPrediction]
    insights: Dict[str, Any]
    recommendations: List[str]
    fatigue_thresholds: Dict[str, float]
    time_range: Dict[str, str]
    generated_at: datetime


class PredictOptimalTimingResponse(BaseModel):
    timing_predictions: TimingPrediction
    recommendations: List[str]
    optimization_metrics: List[str]
    entity_id: str
    time_range: Dict[str, str]
    generated_at: datetime


class PredictAudienceExpansionResponse(BaseModel):
    expansion_predictions: List[AudienceExpansionPrediction]
    risk_assessment: Dict[str, Any]
    recommendations: List[str]
    expansion_options: List[str]
    entity_id: str
    time_range: Dict[str, str]
    generated_at: datetime


class PredictSeasonalityResponse(BaseModel):
    seasonal_predictions: List[SeasonalityPrediction]
    seasonal_patterns: Dict[str, Any]
    recommendations: List[str]
    seasonal_periods: List[str]
    entity_id: str
    time_range: Dict[str, str]
    generated_at: datetime


class PredictCompetitivePressureResponse(BaseModel):
    pressure_predictions: List[CompetitivePressurePrediction]
    competitive_trends: Dict[str, Any]
    recommendations: List[str]
    prediction_horizon: int
    entity_id: str
    time_range: Dict[str, str]
    generated_at: datetime


# Strategic Recommendation Engine Schemas
class PortfolioOptimizationRequest(BaseModel):
    ad_account_id: str
    time_range: Dict[str, str]
    business_goals: List[str] = Field(default_factory=lambda: ["maximize_roas", "increase_conversions", "optimize_spend"])
    optimization_goals: List[str] = Field(default_factory=lambda: ["optimize_budget_allocation", "diversify_objectives", "improve_performance"])
    constraints: Dict[str, Any] = Field(default_factory=dict)
    timeline_preferences: Dict[str, Any] = Field(default_factory=dict)


class ScalingRoadmapRequest(BaseModel):
    ad_account_id: str
    time_range: Dict[str, str]
    business_goals: List[str] = Field(default_factory=lambda: ["scale_profitably", "increase_volume", "maintain_quality"])
    scaling_goals: List[str] = Field(default_factory=lambda: ["increase_budget", "expand_audiences", "test_new_strategies"])
    risk_tolerance: str = "medium"  # low, medium, high
    constraints: Dict[str, Any] = Field(default_factory=dict)


class TestingStrategyRequest(BaseModel):
    ad_account_id: str
    time_range: Dict[str, str]
    business_goals: List[str] = Field(default_factory=lambda: ["improve_performance", "reduce_costs", "increase_conversions"])
    testing_priorities: List[str] = Field(default_factory=lambda: ["creative_testing", "audience_testing", "bid_strategy_testing"])
    budget_allocation: Dict[str, float] = Field(default_factory=lambda: {"creative_testing": 30, "audience_testing": 25, "bid_strategy_testing": 20})


class AudienceStrategyRequest(BaseModel):
    ad_account_id: str
    time_range: Dict[str, str]
    business_goals: List[str] = Field(default_factory=lambda: ["expand_reach", "improve_targeting", "increase_quality"])
    audience_goals: List[str] = Field(default_factory=lambda: ["expand_reach", "improve_targeting", "reduce_costs"])
    expansion_strategy: str = "conservative"  # conservative, moderate, aggressive
    targeting_preferences: Dict[str, Any] = Field(default_factory=dict)


class CreativeStrategyRequest(BaseModel):
    ad_account_id: str
    time_range: Dict[str, str]
    business_goals: List[str] = Field(default_factory=lambda: ["improve_engagement", "reduce_fatigue", "increase_conversions"])
    creative_goals: List[str] = Field(default_factory=lambda: ["reduce_fatigue", "expand_formats", "improve_performance"])
    creative_preferences: Dict[str, Any] = Field(default_factory=dict)
    testing_budget: float = 1000.0
    production_constraints: Dict[str, Any] = Field(default_factory=dict)


class BidStrategyMixRequest(BaseModel):
    ad_account_id: str
    time_range: Dict[str, str]
    business_goals: List[str] = Field(default_factory=lambda: ["optimize_costs", "increase_conversions", "improve_efficiency"])
    bid_goals: List[str] = Field(default_factory=lambda: ["optimize_conversions", "control_costs", "maximize_reach"])
    optimization_preferences: Dict[str, Any] = Field(default_factory=dict)
    budget_distribution: Dict[str, float] = Field(default_factory=dict)
    optimization_timeline: str = "4-6 weeks"


class PortfolioRecommendation(BaseModel):
    category: str
    priority: str  # high, medium, low
    title: str
    description: str
    expected_impact: str
    implementation_effort: str  # low, medium, high
    risk_level: str  # low, medium, high
    timeline: str
    specific_actions: List[str]


class ScalingPhase(BaseModel):
    phase_name: str
    phase_order: int
    duration_weeks: int
    budget_increase_percentage: float
    risk_level: str  # low, medium, high
    objectives: List[str]
    success_metrics: Dict[str, str]
    prerequisites: List[str]
    deliverables: List[str]


class TestingPlan(BaseModel):
    test_type: str
    priority: str  # high, medium, low
    budget_percentage: float
    duration_weeks: int
    test_description: str
    success_metrics: List[str]
    test_variants: List[str]
    expected_outcomes: Dict[str, str]
    implementation_steps: List[str]


class AudienceRecommendation(BaseModel):
    audience_type: str
    priority: str  # high, medium, low
    title: str
    description: str
    expected_impact: str
    implementation_effort: str  # low, medium, high
    risk_level: str  # low, medium, high
    targeting_parameters: Dict[str, Any]
    budget_recommendation: str
    success_metrics: List[str]
    implementation_steps: List[str]


class CreativeRecommendation(BaseModel):
    creative_type: str
    priority: str  # high, medium, low
    title: str
    description: str
    expected_impact: str
    implementation_effort: str  # low, medium, high
    risk_level: str  # low, medium, high
    creative_specifications: Dict[str, Any]
    budget_recommendation: str
    success_metrics: List[str]
    implementation_steps: List[str]


class BidStrategyRecommendation(BaseModel):
    bid_strategy: str
    priority: str  # high, medium, low
    title: str
    description: str
    expected_impact: str
    implementation_effort: str  # low, medium, high
    risk_level: str  # low, medium, high
    bid_parameters: Dict[str, Any]
    budget_recommendation: str
    success_metrics: List[str]
    implementation_steps: List[str]


class PortfolioOptimizationResponse(BaseModel):
    recommendations: List[PortfolioRecommendation]
    impact_analysis: Dict[str, Any]
    implementation_roadmap: List[Dict[str, Any]]
    portfolio_analysis: Dict[str, Any]
    business_goals: List[str]
    time_range: Dict[str, str]
    generated_at: datetime


class ScalingRoadmapResponse(BaseModel):
    scaling_phases: List[ScalingPhase]
    risk_assessment: Dict[str, Any]
    monitoring_plan: Dict[str, Any]
    scaling_analysis: Dict[str, Any]
    scaling_goals: List[str]
    risk_tolerance: str
    time_range: Dict[str, str]
    generated_at: datetime


class TestingStrategyResponse(BaseModel):
    testing_plans: List[TestingPlan]
    testing_timeline: List[Dict[str, Any]]
    success_metrics: Dict[str, Any]
    testing_analysis: Dict[str, Any]
    testing_priorities: List[str]
    budget_allocation: Dict[str, float]
    time_range: Dict[str, str]
    generated_at: datetime


class AudienceStrategyResponse(BaseModel):
    audience_recommendations: List[AudienceRecommendation]
    audience_hierarchy: Dict[str, Any]
    targeting_recommendations: List[Dict[str, Any]]
    audience_analysis: Dict[str, Any]
    audience_goals: List[str]
    expansion_strategy: str
    time_range: Dict[str, str]
    generated_at: datetime


class CreativeStrategyResponse(BaseModel):
    creative_recommendations: List[CreativeRecommendation]
    creative_testing_plan: Dict[str, Any]
    production_recommendations: List[Dict[str, Any]]
    creative_analysis: Dict[str, Any]
    creative_goals: List[str]
    creative_preferences: Dict[str, Any]
    time_range: Dict[str, str]
    generated_at: datetime


class BidStrategyMixResponse(BaseModel):
    bid_recommendations: List[BidStrategyRecommendation]
    strategy_allocation: Dict[str, Any]
    optimization_plan: Dict[str, Any]
    bid_analysis: Dict[str, Any]
    bid_goals: List[str]
    optimization_preferences: Dict[str, Any]
    time_range: Dict[str, str]
    generated_at: datetime


# Expert Workflow Automation Schemas
class NewAccountSetupRequest(BaseModel):
    ad_account_id: str
    business_info: Dict[str, Any]
    tracking_requirements: Dict[str, Any] = Field(default_factory=dict)
    audience_strategy: Dict[str, Any] = Field(default_factory=dict)
    campaign_objectives: List[str] = Field(default_factory=lambda: ["CONVERSIONS", "LINK_CLICKS"])
    budget_allocation: Dict[str, float] = Field(default_factory=dict)
    setup_parameters: Dict[str, Any] = Field(default_factory=dict)


class ScaleProfitablyRequest(BaseModel):
    ad_account_id: str
    current_performance: Dict[str, Any]
    performance_thresholds: Dict[str, float] = Field(default_factory=lambda: {"min_roas": 3.0, "min_conversions": 10})
    target_scale: float = 2.0  # 2x scale
    risk_tolerance: str = "moderate"  # conservative, moderate, aggressive
    scaling_parameters: Dict[str, Any] = Field(default_factory=dict)


class CreativeTestingFrameworkRequest(BaseModel):
    ad_account_id: str
    creative_variants: List[str]
    testing_goals: List[str] = Field(default_factory=lambda: ["improve_ctr", "improve_conversion_rate"])
    total_budget: float
    success_metrics: List[str] = Field(default_factory=lambda: ["ctr", "conversion_rate", "roas"])
    testing_parameters: Dict[str, Any] = Field(default_factory=dict)


class AudienceExpansionLadderRequest(BaseModel):
    ad_account_id: str
    expansion_goals: List[str] = Field(default_factory=lambda: ["increase_reach", "maintain_efficiency"])
    risk_tolerance: str = "moderate"
    success_metrics: List[str] = Field(default_factory=lambda: ["roas", "cpa", "reach"])
    expansion_parameters: Dict[str, Any] = Field(default_factory=dict)


class TroubleshootPerformanceRequest(BaseModel):
    ad_account_id: str
    entity_id: str
    priority_metrics: List[str] = Field(default_factory=lambda: ["roas", "cpa", "ctr"])
    troubleshooting_parameters: Dict[str, Any] = Field(default_factory=dict)


class SeasonalPreparationRequest(BaseModel):
    ad_account_id: str
    seasonal_period: str
    expected_volume_increase: float = 150  # 150% increase
    budget_increase: float = 100  # 100% increase
    creative_requirements: Dict[str, Any] = Field(default_factory=dict)
    preparation_parameters: Dict[str, Any] = Field(default_factory=dict)


class CostReductionAuditRequest(BaseModel):
    ad_account_id: str
    performance_thresholds: Dict[str, float] = Field(default_factory=lambda: {"min_roas": 1.5})
    audit_parameters: Dict[str, Any] = Field(default_factory=dict)


class WorkflowStep(BaseModel):
    step_name: str
    step_order: int
    status: str  # completed, failed, partial, pending
    description: str
    actions_taken: List[str]
    result: Dict[str, Any]
    duration_seconds: int
    next_step: Optional[str]


class DiagnosticResult(BaseModel):
    check_name: str
    severity: str  # low, medium, high, unknown
    finding: str
    details: Dict[str, Any]
    recommendation: str
    impact: str


class OptimizationAction(BaseModel):
    action_type: str
    priority: str  # high, medium, low
    description: str
    expected_impact: str
    effort: str  # low, medium, high
    timeline: str
    steps: List[str]


class NewAccountSetupResponse(BaseModel):
    workflow_steps: List[WorkflowStep]
    account_state: Dict[str, Any]
    next_actions: List[str]
    estimated_time_to_results: str
    success_metrics: Dict[str, Any]
    generated_at: datetime


class ScaleProfitablyResponse(BaseModel):
    workflow_steps: List[WorkflowStep]
    scaling_actions_taken: int
    projected_impact: Dict[str, Any]
    monitoring_plan: Dict[str, Any]
    risk_assessment: Dict[str, Any]
    next_review_date: str
    generated_at: datetime


class CreativeTestingFrameworkResponse(BaseModel):
    workflow_steps: List[WorkflowStep]
    test_structure: Dict[str, Any]
    expected_duration: str
    success_criteria: List[str]
    analysis_schedule: str
    generated_at: datetime


class AudienceExpansionLadderResponse(BaseModel):
    workflow_steps: List[WorkflowStep]
    expansion_ladder: List[Dict[str, Any]]
    current_tier: int
    estimated_timeline: str
    success_metrics: List[str]
    next_tier_trigger: str
    generated_at: datetime


class TroubleshootPerformanceResponse(BaseModel):
    diagnostic_results: List[DiagnosticResult]
    optimization_actions: List[OptimizationAction]
    root_causes: List[str]
    recommended_priority: List[OptimizationAction]
    estimated_impact: str
    generated_at: datetime


class SeasonalPreparationResponse(BaseModel):
    workflow_steps: List[WorkflowStep]
    preparation_checklist: List[str]
    budget_plan: Dict[str, Any]
    creative_plan: Dict[str, Any]
    monitoring_plan: Dict[str, Any]
    key_dates: List[str]
    generated_at: datetime


class CostReductionAuditResponse(BaseModel):
    audit_findings: List[Dict[str, Any]]
    cost_reduction_actions: List[OptimizationAction]
    potential_savings: Dict[str, Any]
    quick_wins: List[OptimizationAction]
    implementation_timeline: str
    generated_at: datetime


# Competitive Intelligence Schemas
class AuctionInsightsRequest(BaseModel):
    entity_id: str
    time_range: Dict[str, str]
    metrics_of_interest: List[str] = Field(default_factory=lambda: ["cost_efficiency", "reach", "competition"])


class MarketSaturationRequest(BaseModel):
    ad_account_id: str
    time_range: Dict[str, str]
    target_audience_size: int
    expansion_options: List[str] = Field(default_factory=lambda: ["lookalike", "interests", "geographic", "demographics"])


class ShareOfVoiceRequest(BaseModel):
    ad_account_id: str
    time_range: Dict[str, str]
    market_size: int
    industry_vertical: str = "general"
    target_sov: Optional[float] = None


class AuctionInsightsResponse(BaseModel):
    auction_competitiveness: str
    competitive_pressure_score: float
    estimated_competitor_count: int
    avg_cpm: float
    avg_cpp: float
    auction_overlap_data: Dict[str, Any]
    recommendations: List[str]
    market_conditions: str
    time_range: Dict[str, str]
    generated_at: datetime


class MarketSaturationResponse(BaseModel):
    saturation_level: float
    current_reach: int
    reach_growth_rate: float
    frequency_trend: float
    days_until_saturation: Optional[int]
    expansion_recommendations: List[str]
    market_size_estimate: int
    penetration_percentage: float
    time_range: Dict[str, str]
    generated_at: datetime


class ShareOfVoiceResponse(BaseModel):
    estimated_share_of_voice: float
    impressions: int
    reach: int
    spend: float
    estimated_competitive_spend: float
    relative_position: str
    target_sov: Optional[float]
    gap_to_target: Optional[float]
    growth_recommendations: List[str]
    time_range: Dict[str, str]
    generated_at: datetime


# Advanced Optimization Algorithms Schemas
class BudgetAllocationOptimizationRequest(BaseModel):
    ad_account_id: str
    entity_ids: List[str]
    total_budget: float
    time_range: Dict[str, str]
    optimization_goal: str = "maximize_roas"  # maximize_roas, maximize_conversions, minimize_cpa
    constraints: Dict[str, Any] = Field(default_factory=dict)


class BidOptimizationRequest(BaseModel):
    entity_id: str
    time_range: Dict[str, str]
    target_metric: str = "cpa"  # cpa, roas, cpc
    target_value: float
    bid_constraints: Dict[str, Any] = Field(default_factory=dict)


class CampaignMixOptimizationRequest(BaseModel):
    ad_account_id: str
    time_range: Dict[str, str]
    optimization_objectives: List[str] = Field(default_factory=lambda: ["maximize_roas", "maximize_conversions"])
    risk_tolerance: str = "moderate"  # conservative, moderate, aggressive
    constraints: Dict[str, Any] = Field(default_factory=dict)


class DaypartingOptimizationRequest(BaseModel):
    entity_id: str
    time_range: Dict[str, str]
    optimization_goal: str = "maximize_efficiency"  # maximize_efficiency, maximize_conversions, minimize_cost
    performance_threshold: Dict[str, float] = Field(default_factory=lambda: {"min_conversions": 5})
    schedule_constraints: Dict[str, Any] = Field(default_factory=dict)


class AudiencePrioritizationRequest(BaseModel):
    ad_account_id: str
    time_range: Dict[str, str]
    total_budget: float
    prioritization_criteria: List[str] = Field(default_factory=lambda: ["roas", "conversion_volume", "efficiency"])
    weights: Dict[str, float] = Field(default_factory=lambda: {"roas": 0.4, "conversion_volume": 0.3, "efficiency": 0.3})
    allocation_method: str = "proportional"  # proportional, tiered
    expansion_threshold: float = 5.0


class OptimizationRecommendation(BaseModel):
    entity_id: str
    action: str
    current_value: float
    recommended_value: float
    expected_impact: str
    rationale: str
    priority: str


class HourPerformance(BaseModel):
    hour: int
    day_of_week: str
    avg_spend: float
    avg_conversions: float
    avg_cpa: float
    avg_roas: float
    performance_score: float
    recommendation: str


class BudgetAllocationOptimizationResponse(BaseModel):
    optimal_allocation: Dict[str, float]
    current_allocation: Dict[str, float]
    projected_performance: Dict[str, Any]
    expected_improvement: Dict[str, float]
    recommendations: List[OptimizationRecommendation]
    optimization_method: str
    confidence_level: float
    time_range: Dict[str, str]
    generated_at: datetime


class BidOptimizationResponse(BaseModel):
    optimal_bid: float
    current_bid: float
    expected_impact: Dict[str, Any]
    bid_strategy_recommendation: str
    confidence_score: float
    sensitivity_analysis: Dict[str, Any]
    time_range: Dict[str, str]
    generated_at: datetime


class CampaignMixOptimizationResponse(BaseModel):
    optimal_mix: Dict[str, float]
    current_mix: Dict[str, float]
    risk_return_profile: Dict[str, Any]
    diversification_score: float
    rebalancing_recommendations: List[str]
    expected_sharpe_ratio: float
    time_range: Dict[str, str]
    generated_at: datetime


class DaypartingOptimizationResponse(BaseModel):
    optimal_schedule: Dict[str, Any]
    hour_by_hour_performance: List[HourPerformance]
    expected_cost_savings: float
    expected_efficiency_gain: float
    recommended_hours: List[int]
    time_range: Dict[str, str]
    generated_at: datetime


class AudiencePrioritizationResponse(BaseModel):
    prioritized_audiences: List[Dict[str, Any]]
    recommended_budget_allocation: Dict[str, float]
    audience_tiers: Dict[str, List[str]]
    expansion_recommendations: List[str]
    consolidation_opportunities: List[str]
    time_range: Dict[str, str]
    generated_at: datetime


# Scenario Planning & Simulation Schemas
class SimulateBudgetIncreaseRequest(BaseModel):
    entity_id: str
    time_range: Dict[str, str]
    budget_increase_percentages: List[float] = Field(default_factory=lambda: [25, 50, 100])
    assumptions: Dict[str, Any] = Field(default_factory=dict)


class SimulateBidChangesRequest(BaseModel):
    entity_id: str
    time_range: Dict[str, str]
    new_bid_amounts: List[float]
    optimization_goal: str = "maximize_roas"  # maximize_roas, maximize_conversions, minimize_cpa
    assumptions: Dict[str, Any] = Field(default_factory=dict)


class SimulateAudienceExpansionRequest(BaseModel):
    entity_id: str
    time_range: Dict[str, str]
    expansion_strategies: List[Dict[str, Any]]
    risk_tolerance: str = "moderate"
    assumptions: Dict[str, Any] = Field(default_factory=dict)


class SimulateCreativeRefreshRequest(BaseModel):
    entity_id: str
    time_range: Dict[str, str]
    refresh_strategies: List[Dict[str, Any]]
    assumptions: Dict[str, Any] = Field(default_factory=dict)


class SimulateSeasonalPlanningRequest(BaseModel):
    ad_account_id: str
    seasonal_period: str
    expected_traffic_increase: float
    assumptions: Dict[str, Any] = Field(default_factory=dict)


class CompareStrategiesRequest(BaseModel):
    entity_id: str
    time_range: Dict[str, str]
    strategies: List[Dict[str, Any]]
    evaluation_criteria: List[str] = Field(default_factory=lambda: ["roas", "conversions", "cpa"])
    risk_tolerance: str = "moderate"


class ScenarioOutcome(BaseModel):
    scenario_name: str
    projected_metrics: Dict[str, Any]
    expected_outcomes: List[str]
    risks: List[str]
    probability: float


class SimulateBudgetIncreaseResponse(BaseModel):
    current_performance: Dict[str, Any]
    scenarios: List[ScenarioOutcome]
    recommended_scenario: ScenarioOutcome
    risk_assessment: Dict[str, Any]
    assumptions_used: Dict[str, Any]
    confidence_level: float
    time_range: Dict[str, str]
    generated_at: datetime


class SimulateBidChangesResponse(BaseModel):
    current_performance: Dict[str, Any]
    current_bid: float
    scenarios: List[ScenarioOutcome]
    recommended_bid: str
    auction_dynamics: Dict[str, Any]
    optimization_goal: str
    confidence_level: float
    time_range: Dict[str, str]
    generated_at: datetime


class SimulateAudienceExpansionResponse(BaseModel):
    current_performance: Dict[str, Any]
    scenarios: List[ScenarioOutcome]
    reach_projections: Dict[str, Any]
    quality_vs_volume_tradeoff: Dict[str, Any]
    recommended_approach: str
    risk_tolerance: str
    confidence_level: float
    time_range: Dict[str, str]
    generated_at: datetime


class SimulateCreativeRefreshResponse(BaseModel):
    current_performance: Dict[str, Any]
    fatigue_analysis: Dict[str, Any]
    scenarios: List[ScenarioOutcome]
    expected_lift: Dict[str, float]
    timing_recommendations: List[str]
    confidence_level: float
    time_range: Dict[str, str]
    generated_at: datetime


class SimulateSeasonalPlanningResponse(BaseModel):
    historical_performance: Dict[str, Any]
    scenarios: List[ScenarioOutcome]
    capacity_requirements: Dict[str, Any]
    budget_scaling_plan: Dict[str, Any]
    risk_mitigation_strategies: List[str]
    preparation_timeline: Dict[str, List[str]]
    confidence_level: float
    seasonal_period: str
    generated_at: datetime


class CompareStrategiesResponse(BaseModel):
    baseline_performance: Dict[str, Any]
    strategy_projections: List[ScenarioOutcome]
    comparison_matrix: Dict[str, Dict[str, Any]]
    ranked_strategies: List[Dict[str, Any]]
    recommendation: Dict[str, Any]
    implementation_considerations: Dict[str, str]
    confidence_level: float
    time_range: Dict[str, str]
    generated_at: datetime


# Performance Diagnostics Schemas (12 tools)

class PerformanceDegradationRequest(BaseModel):
    entity_id: str
    entity_type: str = "campaign"
    time_range: Dict[str, str]


class PerformanceDegradationResponse(BaseModel):
    degradation_detected: bool
    severity: str
    root_causes: List[Dict[str, Any]]
    recommendations: List[Dict[str, Any]]
    confidence_score: float
    metrics_analyzed: Dict[str, Any]
    analysis_period: Dict[str, str]
    generated_at: datetime


class ConversionFunnelRequest(BaseModel):
    ad_account_id: str
    time_range: Dict[str, str]


class ConversionFunnelResponse(BaseModel):
    funnel_stages: Dict[str, int]
    funnel_analysis: List[Dict[str, Any]]
    friction_points: List[Dict[str, Any]]
    recommendations: List[Dict[str, Any]]
    overall_conversion_rate: float
    time_range: Dict[str, str]
    generated_at: datetime


class AudienceQualityRequest(BaseModel):
    entity_id: str
    entity_type: str = "campaign"
    time_range: Dict[str, str]


class AudienceQualityResponse(BaseModel):
    segment_scores: List[Dict[str, Any]]
    low_quality_segments: List[Dict[str, Any]]
    overall_health: Dict[str, Any]
    recommendations: List[Dict[str, Any]]
    total_segments_analyzed: int
    time_range: Dict[str, str]
    generated_at: datetime


class CreativeFatigueRequest(BaseModel):
    ad_id: str
    time_range: Dict[str, str]


class CreativeFatigueResponse(BaseModel):
    fatigue_detected: bool
    fatigue_level: str
    fatigue_analysis: Dict[str, Any]
    optimal_refresh_timing: int
    recommendations: List[Dict[str, Any]]
    time_range: Dict[str, str]
    generated_at: datetime


class BiddingEfficiencyRequest(BaseModel):
    entity_id: str
    entity_type: str = "campaign"
    time_range: Dict[str, str]


class BiddingEfficiencyResponse(BaseModel):
    efficiency_metrics: Dict[str, Any]
    bid_analysis: Dict[str, Any]
    recommendations: List[Dict[str, Any]]
    time_range: Dict[str, str]
    generated_at: datetime


class PlacementPerformanceRequest(BaseModel):
    entity_id: str
    entity_type: str = "campaign"
    time_range: Dict[str, str]


class PlacementPerformanceResponse(BaseModel):
    placement_analysis: List[Dict[str, Any]]
    top_placements: List[Dict[str, Any]]
    bottom_placements: List[Dict[str, Any]]
    cannibalization_detected: bool
    cannibalization_details: Dict[str, Any]
    recommendations: List[Dict[str, Any]]
    time_range: Dict[str, str]
    generated_at: datetime


class TemporalOptimizationRequest(BaseModel):
    entity_id: str
    entity_type: str = "campaign"
    time_range: Dict[str, str]


class TemporalOptimizationResponse(BaseModel):
    performance_heatmap: Dict[str, Any]
    best_time_periods: List[Dict[str, Any]]
    worst_time_periods: List[Dict[str, Any]]
    daypart_analysis: Dict[str, Any]
    recommendations: List[Dict[str, Any]]
    time_range: Dict[str, str]
    generated_at: datetime


class AttributionWindowRequest(BaseModel):
    entity_id: str
    entity_type: str = "campaign"
    time_range: Dict[str, str]
    business_model: str = "ecommerce"


class AttributionWindowResponse(BaseModel):
    attribution_comparison: List[Dict[str, Any]]
    attribution_variance: Dict[str, Any]
    optimal_window: Dict[str, Any]
    recommendations: List[Dict[str, Any]]
    time_range: Dict[str, str]
    generated_at: datetime


class LearningPhaseRequest(BaseModel):
    adset_id: str


class LearningPhaseResponse(BaseModel):
    learning_analysis: Dict[str, Any]
    disruptive_edits: List[Dict[str, Any]]
    estimated_exit_days: int
    recommendations: List[Dict[str, Any]]
    generated_at: datetime


class FrequencyDistributionRequest(BaseModel):
    entity_id: str
    entity_type: str = "campaign"
    time_range: Dict[str, str]


class FrequencyDistributionResponse(BaseModel):
    frequency_metrics: Dict[str, Any]
    frequency_performance: Dict[str, Any]
    diminishing_returns_point: int
    optimal_frequency_cap: int
    recommendations: List[Dict[str, Any]]
    time_range: Dict[str, str]
    generated_at: datetime


class CampaignInterferenceRequest(BaseModel):
    ad_account_id: str


class CampaignInterferenceResponse(BaseModel):
    interference_detected: bool
    interference_analysis: List[Dict[str, Any]]
    total_conflicts: int
    recommendations: List[Dict[str, Any]]
    generated_at: datetime


class SeasonalityPatternRequest(BaseModel):
    ad_account_id: str
    current_period: Dict[str, str]
    comparison_period: Dict[str, str]


class SeasonalityPatternResponse(BaseModel):
    yoy_trends: List[Dict[str, Any]]
    seasonal_coefficients: Dict[str, float]
    seasonal_patterns: Dict[str, Any]
    predictive_adjustments: List[Dict[str, Any]]
    recommendations: List[Dict[str, Any]]
    analysis_periods: Dict[str, Any]
    generated_at: datetime


# Cost & Efficiency Analysis Schemas (10 tools)

class MarginalCPARequest(BaseModel):
    entity_id: str
    entity_type: str = "campaign"
    time_range: Dict[str, str]
    target_cpa: Optional[float] = None


class MarginalCPAResponse(BaseModel):
    marginal_analysis: List[Dict[str, Any]]
    diminishing_returns_threshold: Dict[str, Any]
    optimal_spend_level: Dict[str, Any]
    recommendations: List[Dict[str, Any]]
    time_range: Dict[str, str]
    generated_at: datetime


class WastedSpendRequest(BaseModel):
    ad_account_id: str
    time_range: Dict[str, str]
    min_spend_threshold: float = 50.0
    min_roas_threshold: float = 1.0
    max_cpa_threshold: float = 100.0
    total_budget: float


class WastedSpendResponse(BaseModel):
    total_wasted_spend: float
    wasted_segments: List[Dict[str, Any]]
    reallocation_plan: Dict[str, Any]
    recommendations: List[Dict[str, Any]]
    potential_savings_percentage: float
    time_range: Dict[str, str]
    generated_at: datetime


class CrossCampaignEfficiencyRequest(BaseModel):
    campaign_ids: List[str]
    time_range: Dict[str, str]
    total_budget: float


class CrossCampaignEfficiencyResponse(BaseModel):
    campaign_efficiency: List[Dict[str, Any]]
    reallocation_model: Dict[str, Any]
    portfolio_metrics: Dict[str, Any]
    recommendations: List[Dict[str, Any]]
    time_range: Dict[str, str]
    generated_at: datetime


class CACTrendRequest(BaseModel):
    ad_account_id: str
    time_range: Dict[str, str]
    time_increment: str = "monthly"
    average_customer_ltv: float
    average_margin_percentage: float


class CACTrendResponse(BaseModel):
    cac_trend: List[Dict[str, Any]]
    trend_analysis: Dict[str, Any]
    payback_analysis: Dict[str, Any]
    profitability_threshold: Dict[str, Any]
    recommendations: List[Dict[str, Any]]
    time_range: Dict[str, str]
    generated_at: datetime


class BudgetPacingDiagnosticRequest(BaseModel):
    campaign_id: str
    time_range: Dict[str, str]


class BudgetPacingDiagnosticResponse(BaseModel):
    pacing_metrics: Dict[str, Any]
    issues_detected: List[Dict[str, Any]]
    budget_exhaustion_prediction: Dict[str, Any]
    optimal_daily_budget: Dict[str, Any]
    recommendations: List[Dict[str, Any]]
    time_range: Dict[str, str]
    generated_at: datetime


class ValueBiddingAnalysisRequest(BaseModel):
    entity_id: str
    entity_type: str = "campaign"
    time_range: Dict[str, str]
    current_bid_strategy: str
    target_roas: float
    customer_ltv: float


class ValueBiddingAnalysisResponse(BaseModel):
    value_metrics: Dict[str, Any]
    bid_strategy_analysis: Dict[str, Any]
    strategy_comparison: List[Dict[str, Any]]
    recommendations: List[Dict[str, Any]]
    time_range: Dict[str, str]
    generated_at: datetime


class QualityQuantityTradeoffRequest(BaseModel):
    entity_id: str
    entity_type: str = "campaign"
    time_range: Dict[str, str]
    priority: str = "balanced"


class QualityQuantityTradeoffResponse(BaseModel):
    volume_efficiency_curve: List[Dict[str, Any]]
    optimal_balance: Dict[str, Any]
    scale_analysis: Dict[str, Any]
    recommendations: List[Dict[str, Any]]
    time_range: Dict[str, str]
    generated_at: datetime


class AuctionCompetitivenessRequest(BaseModel):
    entity_id: str
    entity_type: str = "campaign"
    time_range: Dict[str, str]


class AuctionCompetitivenessResponse(BaseModel):
    competitiveness_metrics: Dict[str, Any]
    market_share_estimate: Dict[str, Any]
    positioning_analysis: Dict[str, Any]
    recommendations: List[Dict[str, Any]]
    time_range: Dict[str, str]
    generated_at: datetime


class AccountSpendEfficiencyRequest(BaseModel):
    ad_account_id: str
    time_range: Dict[str, str]


class AccountSpendEfficiencyResponse(BaseModel):
    account_metrics: Dict[str, Any]
    campaign_contributions: List[Dict[str, Any]]
    underutilized_budget: Dict[str, Any]
    rebalancing_plan: Dict[str, Any]
    recommendations: List[Dict[str, Any]]
    time_range: Dict[str, str]
    generated_at: datetime


class ProfitMarginRequest(BaseModel):
    entity_id: str
    entity_type: str = "campaign"
    time_range: Dict[str, str]
    cogs_percentage: float


class ProfitMarginResponse(BaseModel):
    profit_metrics: Dict[str, Any]
    breakeven_analysis: Dict[str, Any]
    profit_scenarios: List[Dict[str, Any]]
    recommendations: List[Dict[str, Any]]
    time_range: Dict[str, str]
    generated_at: datetime


# Audience Intelligence Schemas (8 tools)

class AudienceSaturationRequest(BaseModel):
    entity_id: str
    entity_type: str = "campaign"
    time_range: Dict[str, str]
    ad_account_id: str


class AudienceSaturationResponse(BaseModel):
    saturation_metrics: Dict[str, Any]
    expansion_opportunities: List[Dict[str, Any]]
    growth_runway: Dict[str, Any]
    recommendations: List[Dict[str, Any]]
    time_range: Dict[str, str]
    generated_at: datetime


class DemographicProfilerRequest(BaseModel):
    entity_id: str
    entity_type: str = "campaign"
    time_range: Dict[str, str]


class DemographicProfilerResponse(BaseModel):
    demographic_profiles: List[Dict[str, Any]]
    high_value_segments: List[Dict[str, Any]]
    underperforming_segments: List[Dict[str, Any]]
    targeting_refinements: Dict[str, Any]
    recommendations: List[Dict[str, Any]]
    time_range: Dict[str, str]
    generated_at: datetime


class InterestLayerRequest(BaseModel):
    entity_id: str
    time_range: Dict[str, str]
    ad_account_id: str


class InterestLayerResponse(BaseModel):
    interest_analysis: List[Dict[str, Any]]
    interest_overlaps: List[Dict[str, Any]]
    expansion_suggestions: List[Dict[str, Any]]
    pruning_recommendations: List[Dict[str, Any]]
    recommendations: List[Dict[str, Any]]
    time_range: Dict[str, str]
    generated_at: datetime


class LookalikeQualityRequest(BaseModel):
    lookalike_audience_id: str
    source_audience_id: Optional[str] = None
    time_range: Dict[str, str]
    current_lal_percentage: int = 1


class LookalikeQualityResponse(BaseModel):
    quality_metrics: Dict[str, Any]
    optimal_percentage: Dict[str, Any]
    seed_analysis: Dict[str, Any]
    expansion_recommendations: List[Dict[str, Any]]
    recommendations: List[Dict[str, Any]]
    time_range: Dict[str, str]
    generated_at: datetime


class AudienceOverlapHeatmapRequest(BaseModel):
    campaign_ids: List[str]
    ad_account_id: str
    min_overlap_threshold: float = 30.0


class AudienceOverlapHeatmapResponse(BaseModel):
    overlap_matrix: List[Dict[str, Any]]
    consolidation_opportunities: List[Dict[str, Any]]
    exclusion_recommendations: List[Dict[str, Any]]
    recommendations: List[Dict[str, Any]]
    generated_at: datetime


class CustomAudienceHealthRequest(BaseModel):
    custom_audience_id: str
    lookback_days: int = 90


class CustomAudienceHealthResponse(BaseModel):
    health_metrics: Dict[str, Any]
    size_trends: Dict[str, Any]
    refresh_optimization: Dict[str, Any]
    data_quality_assessment: Dict[str, Any]
    recommendations: List[Dict[str, Any]]
    generated_at: datetime


class GeographicPerformanceRequest(BaseModel):
    entity_id: str
    entity_type: str = "campaign"
    time_range: Dict[str, str]


class GeographicPerformanceResponse(BaseModel):
    location_analysis: List[Dict[str, Any]]
    top_markets: List[Dict[str, Any]]
    expansion_opportunities: List[Dict[str, Any]]
    geographic_recommendations: Dict[str, Any]
    recommendations: List[Dict[str, Any]]
    time_range: Dict[str, str]
    generated_at: datetime


class BehaviorTargetingRequest(BaseModel):
    entity_id: str
    time_range: Dict[str, str]
    ad_account_id: str


class BehaviorTargetingResponse(BaseModel):
    behavior_analysis: List[Dict[str, Any]]
    device_patterns: List[Dict[str, Any]]
    purchase_behavior_analysis: Dict[str, Any]
    combination_suggestions: List[Dict[str, Any]]
    recommendations: List[Dict[str, Any]]
    time_range: Dict[str, str]
    generated_at: datetime


# Creative Intelligence Schemas (8 tools)

class AdCopyAnalysisRequest(BaseModel):
    ad_ids: List[str]
    time_range: Dict[str, str]


class AdCopyAnalysisResponse(BaseModel):
    headline_analysis: Dict[str, Any]
    cta_analysis: Dict[str, Any]
    copy_length_analysis: Dict[str, Any]
    sentiment_analysis: Dict[str, Any]
    recommendations: List[Dict[str, Any]]
    time_range: Dict[str, str]
    generated_at: datetime


class VisualElementScorerRequest(BaseModel):
    ad_id: str
    time_range: Dict[str, str]


class VisualElementScorerResponse(BaseModel):
    color_analysis: Dict[str, Any]
    composition_analysis: Dict[str, Any]
    video_analysis: Dict[str, Any]
    thumbnail_analysis: Dict[str, Any]
    recommendations: List[Dict[str, Any]]
    time_range: Dict[str, str]
    generated_at: datetime


class DCOAnalysisRequest(BaseModel):
    ad_id: str
    time_range: Dict[str, str]


class DCOAnalysisResponse(BaseModel):
    asset_combinations: List[Dict[str, Any]]
    winning_patterns: List[Dict[str, Any]]
    underperforming_assets: List[Dict[str, Any]]
    diversity_score: Dict[str, Any]
    recommendations: List[Dict[str, Any]]
    time_range: Dict[str, str]
    generated_at: datetime


class CreativeTestingStatsRequest(BaseModel):
    ad_ids: List[str]
    time_range: Dict[str, str]
    confidence_level: float = 0.95
    minimum_detectable_effect: float = 0.10


class CreativeTestingStatsResponse(BaseModel):
    significance_analysis: Dict[str, Any]
    sample_size_requirements: Dict[str, Any]
    confidence_intervals: List[Dict[str, Any]]
    duration_recommendation: Dict[str, Any]
    recommendations: List[Dict[str, Any]]
    time_range: Dict[str, str]
    generated_at: datetime


class MessageMarketMatchRequest(BaseModel):
    ad_id: str
    time_range: Dict[str, str]


class MessageMarketMatchResponse(BaseModel):
    segment_resonance: List[Dict[str, Any]]
    audience_creative_matrix: Dict[str, Any]
    personalization_opportunities: List[Dict[str, Any]]
    recommendations: List[Dict[str, Any]]
    time_range: Dict[str, str]
    generated_at: datetime


class EmotionalAppealRequest(BaseModel):
    ad_id: str
    time_range: Dict[str, str]


class EmotionalAppealResponse(BaseModel):
    emotional_triggers: List[Dict[str, Any]]
    social_proof_analysis: Dict[str, Any]
    urgency_analysis: Dict[str, Any]
    persuasion_elements: List[Dict[str, Any]]
    recommendations: List[Dict[str, Any]]
    time_range: Dict[str, str]
    generated_at: datetime


class CreativeBenchmarkRequest(BaseModel):
    ad_id: str
    time_range: Dict[str, str]
    industry: str = "default"


class CreativeBenchmarkResponse(BaseModel):
    performance_vs_benchmark: Dict[str, Any]
    best_practice_checklist: List[Dict[str, Any]]
    innovation_score: Dict[str, Any]
    differentiation_analysis: Dict[str, Any]
    recommendations: List[Dict[str, Any]]
    time_range: Dict[str, str]
    generated_at: datetime


class CrossFormatComparisonRequest(BaseModel):
    ad_ids: List[str]
    time_range: Dict[str, str]
    campaign_objective: str = "CONVERSIONS"


class CrossFormatComparisonResponse(BaseModel):
    format_comparison: List[Dict[str, Any]]
    special_format_analysis: Dict[str, Any]
    format_recommendations: Dict[str, Any]
    recommendations: List[Dict[str, Any]]
    time_range: Dict[str, str]
    generated_at: datetime


# Strategic Analysis Schemas (7 tools)

class CampaignArchitectureAuditRequest(BaseModel):
    campaign_id: str


class CampaignArchitectureAuditResponse(BaseModel):
    structure_analysis: Dict[str, Any]
    cbo_analysis: Dict[str, Any]
    consolidation_opportunities: List[Dict[str, Any]]
    best_practices: List[Dict[str, Any]]
    recommendations: List[Dict[str, Any]]
    generated_at: datetime


class ObjectiveAlignmentRequest(BaseModel):
    campaign_id: str
    time_range: Dict[str, str]
    business_funnel_stage: str = "conversion"


class ObjectiveAlignmentResponse(BaseModel):
    objective_analysis: Dict[str, Any]
    funnel_alignment: Dict[str, Any]
    switching_recommendations: List[Dict[str, Any]]
    multi_objective_analysis: Dict[str, Any]
    recommendations: List[Dict[str, Any]]
    time_range: Dict[str, str]
    generated_at: datetime


class PixelConversionOptimizerRequest(BaseModel):
    pixel_id: str
    ad_account_id: str


class PixelConversionOptimizerResponse(BaseModel):
    event_reliability: List[Dict[str, Any]]
    optimization_priority: List[Dict[str, Any]]
    value_optimization: Dict[str, Any]
    conversion_window_analysis: Dict[str, Any]
    recommendations: List[Dict[str, Any]]
    generated_at: datetime


class MobileAppCampaignRequest(BaseModel):
    campaign_id: str
    time_range: Dict[str, str]


class MobileAppCampaignResponse(BaseModel):
    app_event_analysis: Dict[str, Any]
    in_app_behavior: Dict[str, Any]
    deep_link_analysis: Dict[str, Any]
    install_quality: Dict[str, Any]
    recommendations: List[Dict[str, Any]]
    time_range: Dict[str, str]
    generated_at: datetime


class EcommerceCampaignRequest(BaseModel):
    campaign_id: str
    time_range: Dict[str, str]
    catalog_size: Optional[int] = None


class EcommerceCampaignResponse(BaseModel):
    catalog_analysis: Dict[str, Any]
    retargeting_analysis: Dict[str, Any]
    cart_abandonment: Dict[str, Any]
    product_set_optimization: Dict[str, Any]
    recommendations: List[Dict[str, Any]]
    time_range: Dict[str, str]
    generated_at: datetime


class LeadGenCampaignRequest(BaseModel):
    campaign_id: str
    time_range: Dict[str, str]


class LeadGenCampaignResponse(BaseModel):
    form_analysis: Dict[str, Any]
    lead_quality: Dict[str, Any]
    crm_integration: Dict[str, Any]
    form_optimization: Dict[str, Any]
    recommendations: List[Dict[str, Any]]
    time_range: Dict[str, str]
    generated_at: datetime


class BrandPerformanceMixRequest(BaseModel):
    ad_account_id: str
    time_range: Dict[str, str]
    business_maturity: str = "growth"
    growth_stage: str = "scaling"


class BrandPerformanceMixResponse(BaseModel):
    funnel_allocation: Dict[str, Any]
    balance_analysis: Dict[str, Any]
    brand_impact: Dict[str, Any]
    optimal_mix: Dict[str, Any]
    recommendations: List[Dict[str, Any]]
    time_range: Dict[str, str]
    generated_at: datetime

# ============================================================================
# Agency Portfolio Intelligence Schemas (Wave 2)
# ============================================================================


# Portfolio Analysis Schemas (8 tools)
class PortfolioPerformanceDashboardRequest(BaseModel):
    campaign_ids: Optional[List[str]] = None
    ad_account_id: Optional[str] = None
    time_range: Dict[str, str]
    client_id: Optional[str] = None

class PortfolioPerformanceDashboardResponse(BaseModel):
    total_campaigns: int
    total_spend: float
    total_revenue: float
    portfolio_roas: float
    portfolio_cpa: float
    avg_ctr: float
    top_performers: List[Dict[str, Any]]
    bottom_performers: List[Dict[str, Any]]
    client_rollups: List[Dict[str, Any]]
    performance_distribution: Dict[str, Any]
    generated_at: datetime

class CrossCampaignBudgetOptimizerRequest(BaseModel):
    campaign_ids: Optional[List[str]] = None
    ad_account_id: Optional[str] = None
    time_range: Dict[str, str]
    optimization_goal: str = "roas"

class CrossCampaignBudgetOptimizerResponse(BaseModel):
    campaigns_analyzed: int
    reallocation_recommendations: List[Dict[str, Any]]
    high_roas_underfunded: List[Dict[str, Any]]
    low_roas_overfunded: List[Dict[str, Any]]
    opportunity_cost_usd: float
    optimal_allocation: List[Dict[str, Any]]
    projected_roas_improvement: float
    generated_at: datetime

class PortfolioAnomalyScannerRequest(BaseModel):
    campaign_ids: Optional[List[str]] = None
    ad_account_id: Optional[str] = None
    time_range: Dict[str, str]
    comparison_period: Dict[str, str]
    sensitivity: float = 0.8

class PortfolioAnomalyScannerResponse(BaseModel):
    campaigns_scanned: int
    anomalies_detected: int
    critical_issues: int
    performance_degradations: List[Dict[str, Any]]
    spend_spikes: List[Dict[str, Any]]
    delivery_issues: List[Dict[str, Any]]
    prioritized_alerts: List[Dict[str, Any]]
    generated_at: datetime

class ClientPerformanceBenchmarkingRequest(BaseModel):
    campaign_ids: Optional[List[str]] = None
    ad_account_id: Optional[str] = None
    time_range: Dict[str, str]
    peer_group_ids: Optional[List[str]] = None

class ClientPerformanceBenchmarkingResponse(BaseModel):
    clients_analyzed: int
    performance_quartiles: Dict[str, Any]
    best_practices: List[Dict[str, Any]]
    gap_to_best: List[Dict[str, Any]]
    vertical_benchmarks: Dict[str, Any]
    top_performing_clients: List[Dict[str, Any]]
    improvement_opportunities: List[Dict[str, Any]]
    generated_at: datetime

class CampaignClusteringEngineRequest(BaseModel):
    campaign_ids: Optional[List[str]] = None
    ad_account_id: Optional[str] = None
    time_range: Dict[str, str]
    clustering_criteria: List[str] = Field(default_factory=lambda: ["roas", "cpa", "ctr"])

class CampaignClusteringEngineResponse(BaseModel):
    campaigns_clustered: int
    num_clusters: int
    cluster_profiles: List[Dict[str, Any]]
    best_performing_cluster: Dict[str, Any]
    cluster_strategies: List[Dict[str, Any]]
    outliers_detected: List[Dict[str, Any]]
    silhouette_score: float
    generated_at: datetime

class PortfolioRiskAssessmentRequest(BaseModel):
    campaign_ids: Optional[List[str]] = None
    ad_account_id: Optional[str] = None
    time_range: Dict[str, str]

class PortfolioRiskAssessmentResponse(BaseModel):
    campaigns_assessed: int
    concentration_risk_score: float
    top_concentration_risks: List[Dict[str, Any]]
    dependency_analysis: Dict[str, Any]
    diversification_score: float
    risk_adjusted_roas: float
    resilience_metrics: Dict[str, Any]
    risk_recommendations: List[Dict[str, Any]]
    generated_at: datetime

class QuickWinIdentifierRequest(BaseModel):
    campaign_ids: Optional[List[str]] = None
    ad_account_id: Optional[str] = None
    time_range: Dict[str, str]
    min_impact_threshold: float = 1000.0

class QuickWinIdentifierResponse(BaseModel):
    campaigns_analyzed: int
    opportunities_found: int
    top_quick_wins: List[Dict[str, Any]]
    effort_impact_matrix: List[Dict[str, Any]]
    projected_monthly_savings: float
    projected_roas_improvement: float
    estimated_implementation_time: float
    generated_at: datetime

class PortfolioTrendAnalyzerRequest(BaseModel):
    campaign_ids: Optional[List[str]] = None
    ad_account_id: Optional[str] = None
    time_range: Dict[str, str]
    trend_window_days: int = 30

class PortfolioTrendAnalyzerResponse(BaseModel):
    campaigns_analyzed: int
    trend_period_days: int
    metric_trends: Dict[str, Any]
    momentum_indicators: Dict[str, Any]
    seasonal_patterns: Dict[str, Any]
    leading_indicators: List[Dict[str, Any]]
    forecast_next_30_days: Dict[str, Any]
    trend_strength_score: float
    generated_at: datetime


# Automated Monitoring Schemas (7 tools)
class RealTimeSpendMonitorRequest(BaseModel):
    campaign_ids: Optional[List[str]] = None
    ad_account_id: Optional[str] = None
    thresholds: Optional[Dict[str, float]] = None

class RealTimeSpendMonitorResponse(BaseModel):
    campaigns_monitored: int
    total_daily_budget: float
    current_spend: float
    pacing_status: str
    overspend_alerts: List[Dict[str, Any]]
    underspend_alerts: List[Dict[str, Any]]
    eod_projections: List[Dict[str, Any]]
    recommendations: List[Dict[str, Any]]
    generated_at: datetime

class PerformanceDropDetectorRequest(BaseModel):
    campaign_ids: Optional[List[str]] = None
    ad_account_id: Optional[str] = None
    time_range: Dict[str, str]
    comparison_period: Dict[str, str]
    thresholds: Optional[Dict[str, float]] = None

class PerformanceDropDetectorResponse(BaseModel):
    campaigns_analyzed: int
    drops_detected: int
    critical_drops: List[Dict[str, Any]]
    degradation_summary: Dict[str, Any]
    root_cause_hypotheses: List[Dict[str, Any]]
    recommended_actions: List[Dict[str, Any]]
    affected_budget_usd: float
    generated_at: datetime

class CreativeFatigueMonitorRequest(BaseModel):
    ad_ids: Optional[List[str]] = None
    ad_account_id: Optional[str] = None
    time_range: Dict[str, str]

class CreativeFatigueMonitorResponse(BaseModel):
    ads_analyzed: int
    fatigued_ads: int
    fatigue_indicators: List[Dict[str, Any]]
    frequency_performance_curves: List[Dict[str, Any]]
    refresh_timing_recommendations: List[Dict[str, Any]]
    creative_rotation_status: str
    generated_at: datetime

class LearningPhaseTrackerRequest(BaseModel):
    campaign_ids: Optional[List[str]] = None
    ad_account_id: Optional[str] = None

class LearningPhaseTrackerResponse(BaseModel):
    campaigns_tracked: int
    in_learning_phase: int
    stuck_campaigns: List[Dict[str, Any]]
    exit_tracking: Dict[str, Any]
    learning_velocity_scores: List[Dict[str, Any]]
    acceleration_recommendations: List[Dict[str, Any]]
    budget_adjustment_suggestions: List[Dict[str, Any]]
    generated_at: datetime

class BudgetDepletionPredictorRequest(BaseModel):
    campaign_ids: Optional[List[str]] = None
    ad_account_id: Optional[str] = None
    time_range: Dict[str, str]

class BudgetDepletionPredictorResponse(BaseModel):
    campaigns_analyzed: int
    at_risk_campaigns: List[Dict[str, Any]]
    depletion_predictions: List[Dict[str, Any]]
    burn_rate_analysis: List[Dict[str, Any]]
    opportunity_loss_usd: float
    refill_recommendations: List[Dict[str, Any]]
    generated_at: datetime

class AuctionCompetitionMonitorRequest(BaseModel):
    campaign_ids: Optional[List[str]] = None
    ad_account_id: Optional[str] = None
    time_range: Dict[str, str]
    comparison_period: Dict[str, str]

class AuctionCompetitionMonitorResponse(BaseModel):
    campaigns_monitored: int
    avg_cpm_change_pct: float
    cpm_inflation_alerts: List[Dict[str, Any]]
    competition_scores: List[Dict[str, Any]]
    win_rate_trends: List[Dict[str, Any]]
    bid_adjustment_recommendations: List[Dict[str, Any]]
    generated_at: datetime

class DeliveryIssueScannerRequest(BaseModel):
    campaign_ids: Optional[List[str]] = None
    ad_account_id: Optional[str] = None

class DeliveryIssueScannerResponse(BaseModel):
    campaigns_scanned: int
    issues_found: int
    critical_issues: List[Dict[str, Any]]
    delivery_warnings: List[Dict[str, Any]]
    ad_disapprovals: List[str]
    account_quality_issues: List[Dict[str, Any]]
    prioritized_issues: List[Dict[str, Any]]
    resolution_steps: List[Dict[str, Any]]
    generated_at: datetime


# ROAS Optimization Schemas (8 tools)
class ROASDriverAnalysisRequest(BaseModel):
    campaign_ids: Optional[List[str]] = None
    ad_account_id: Optional[str] = None
    time_range: Dict[str, str]

class ROASDriverAnalysisResponse(BaseModel):
    campaigns_analyzed: int
    high_roas_segments: List[Dict[str, Any]]
    low_roas_segments: List[Dict[str, Any]]
    targeting_recommendations: List[Dict[str, Any]]
    budget_shift_suggestions: List[Dict[str, Any]]
    projected_roas_improvement: float
    projected_revenue_increase: float
    generated_at: datetime

class ConversionRateOptimizerRequest(BaseModel):
    campaign_ids: Optional[List[str]] = None
    ad_account_id: Optional[str] = None
    time_range: Dict[str, str]

class ConversionRateOptimizerResponse(BaseModel):
    campaigns_analyzed: int
    overall_cvr: float
    cvr_by_stage: Dict[str, float]
    drop_off_points: List[Dict[str, Any]]
    optimization_recommendations: List[Dict[str, Any]]
    projected_cvr_improvement: float
    generated_at: datetime

class CostPerAcquisitionAnalyzerRequest(BaseModel):
    campaign_ids: Optional[List[str]] = None
    ad_account_id: Optional[str] = None
    time_range: Dict[str, str]
    target_cpa: Optional[float] = None

class CostPerAcquisitionAnalyzerResponse(BaseModel):
    campaigns_analyzed: int
    avg_cpa: float
    cpa_trend: str
    cpa_by_demographic: List[Dict[str, Any]]
    cpa_by_placement: List[Dict[str, Any]]
    high_cost_segments: List[Dict[str, Any]]
    exclusion_recommendations: List[Dict[str, Any]]
    target_cpa_achievement: Dict[str, Any]
    generated_at: datetime

class MarginalROASCalculatorRequest(BaseModel):
    campaign_ids: Optional[List[str]] = None
    ad_account_id: Optional[str] = None
    time_range: Dict[str, str]

class MarginalROASCalculatorResponse(BaseModel):
    campaigns_analyzed: int
    marginal_roas_by_spend: List[Dict[str, Any]]
    diminishing_returns_point: Dict[str, Any]
    optimal_spend_point: Dict[str, Any]
    budget_increase_recommendations: List[Dict[str, Any]]
    revenue_maximization_analysis: Dict[str, Any]
    generated_at: datetime

class WastedSpendIdentifierRequest(BaseModel):
    campaign_ids: Optional[List[str]] = None
    ad_account_id: Optional[str] = None
    time_range: Dict[str, str]

class WastedSpendIdentifierResponse(BaseModel):
    campaigns_analyzed: int
    total_wasted_spend: float
    zero_conversion_placements: List[Dict[str, Any]]
    low_performing_demographics: List[Dict[str, Any]]
    inefficient_time_periods: List[Dict[str, Any]]
    reallocation_opportunities: List[Dict[str, Any]]
    projected_monthly_savings: float
    generated_at: datetime

class ValueOptimizationAnalyzerRequest(BaseModel):
    campaign_ids: Optional[List[str]] = None
    ad_account_id: Optional[str] = None
    time_range: Dict[str, str]

class ValueOptimizationAnalyzerResponse(BaseModel):
    campaigns_analyzed: int
    avg_revenue_per_conversion: float
    revenue_per_conversion_trend: str
    high_value_characteristics: List[Dict[str, Any]]
    aov_optimization_opportunities: List[Dict[str, Any]]
    value_bidding_performance: Dict[str, Any]
    upsell_cross_sell_indicators: List[Dict[str, Any]]
    generated_at: datetime

class FrequencyCapOptimizerRequest(BaseModel):
    campaign_ids: Optional[List[str]] = None
    ad_account_id: Optional[str] = None
    time_range: Dict[str, str]

class FrequencyCapOptimizerResponse(BaseModel):
    campaigns_analyzed: int
    frequency_conversion_curves: List[Dict[str, Any]]
    optimal_frequency_cap: Dict[str, Any]
    diminishing_returns_frequency: Dict[str, Any]
    reach_frequency_tradeoffs: Dict[str, Any]
    budget_efficiency_by_frequency: List[Dict[str, Any]]
    cap_adjustment_recommendations: List[Dict[str, Any]]
    generated_at: datetime

class AttributionWindowAnalyzerRequest(BaseModel):
    campaign_ids: Optional[List[str]] = None
    ad_account_id: Optional[str] = None
    time_range: Dict[str, str]

class AttributionWindowAnalyzerResponse(BaseModel):
    campaigns_analyzed: int
    window_comparison: List[Dict[str, Any]]
    click_vs_view_attribution: Dict[str, Any]
    optimal_window_by_campaign_type: List[Dict[str, Any]]
    revenue_variance_by_window: Dict[str, float]
    window_selection_recommendations: List[Dict[str, Any]]
    generated_at: datetime


# Scale Intelligence Schemas (6 tools)
class ScalabilityAssessorRequest(BaseModel):
    campaign_ids: Optional[List[str]] = None
    ad_account_id: Optional[str] = None
    time_range: Dict[str, str]

class ScalabilityAssessorResponse(BaseModel):
    campaigns_analyzed: int
    current_reach: int
    potential_reach: int
    reach_utilization_pct: float
    saturation_indicators: List[Dict[str, Any]]
    scale_ceiling_usd: float
    spend_headroom_usd: float
    expansion_opportunities: List[Dict[str, Any]]
    generated_at: datetime

class AudienceExpansionFinderRequest(BaseModel):
    campaign_ids: Optional[List[str]] = None
    ad_account_id: Optional[str] = None

class AudienceExpansionFinderResponse(BaseModel):
    campaigns_analyzed: int
    lookalike_performance: List[Dict[str, Any]]
    interest_expansion_suggestions: List[Dict[str, Any]]
    demographic_adjacencies: List[Dict[str, Any]]
    expansion_risk_scores: List[Dict[str, Any]]
    recommendations: List[Dict[str, Any]]
    generated_at: datetime

class PlacementPerformanceAnalyzerRequest(BaseModel):
    campaign_ids: Optional[List[str]] = None
    ad_account_id: Optional[str] = None
    time_range: Dict[str, str]

class PlacementPerformanceAnalyzerResponse(BaseModel):
    campaigns_analyzed: int
    placement_roas: List[Dict[str, Any]]
    auto_vs_manual_comparison: Dict[str, Any]
    underutilized_placements: List[Dict[str, Any]]
    optimal_placement_mix: List[Dict[str, Any]]
    budget_allocation_recommendations: List[Dict[str, Any]]
    generated_at: datetime

class DevicePerformanceOptimizerRequest(BaseModel):
    campaign_ids: Optional[List[str]] = None
    ad_account_id: Optional[str] = None
    time_range: Dict[str, str]

class DevicePerformanceOptimizerResponse(BaseModel):
    campaigns_analyzed: int
    device_roas: List[Dict[str, Any]]
    device_creative_performance: List[Dict[str, Any]]
    cross_device_patterns: Dict[str, Any]
    device_budget_allocation: List[Dict[str, Any]]
    optimization_recommendations: List[Dict[str, Any]]
    generated_at: datetime

class GeographicExpansionAnalyzerRequest(BaseModel):
    campaign_ids: Optional[List[str]] = None
    ad_account_id: Optional[str] = None
    time_range: Dict[str, str]

class GeographicExpansionAnalyzerResponse(BaseModel):
    campaigns_analyzed: int
    geographic_performance: List[Dict[str, Any]]
    underpenetrated_markets: List[Dict[str, Any]]
    geographic_roas_variance: Dict[str, float]
    expansion_priorities: List[Dict[str, Any]]
    localization_recommendations: List[Dict[str, Any]]
    generated_at: datetime

class DaypartingOptimizerRequest(BaseModel):
    campaign_ids: Optional[List[str]] = None
    ad_account_id: Optional[str] = None
    time_range: Dict[str, str]

class DaypartingOptimizerResponse(BaseModel):
    campaigns_analyzed: int
    hourly_performance: List[Dict[str, Any]]
    daily_performance: List[Dict[str, Any]]
    optimal_scheduling_windows: List[Dict[str, Any]]
    budget_pacing_by_time: Dict[str, Any]
    schedule_adjustment_recommendations: List[Dict[str, Any]]
    generated_at: datetime


# Client Reporting Schemas (6 tools)
class ExecutiveSummaryGeneratorRequest(BaseModel):
    campaign_ids: Optional[List[str]] = None
    ad_account_id: Optional[str] = None
    time_range: Dict[str, str]

class ExecutiveSummaryGeneratorResponse(BaseModel):
    report_period: Dict[str, str]
    key_metrics: Dict[str, Any]
    performance_trends: List[Dict[str, Any]]
    wins: List[Dict[str, Any]]
    challenges: List[Dict[str, Any]]
    action_items: List[Dict[str, Any]]
    recommendations: List[Dict[str, Any]]
    generated_at: datetime

class ROIAttributionReporterRequest(BaseModel):
    campaign_ids: Optional[List[str]] = None
    ad_account_id: Optional[str] = None
    time_range: Dict[str, str]
    benchmark_roi: Optional[float] = None

class ROIAttributionReporterResponse(BaseModel):
    report_period: Dict[str, str]
    campaign_attribution: List[Dict[str, Any]]
    spend_to_revenue_mapping: Dict[str, Any]
    roi_trends: Dict[str, Any]
    investment_breakdown: List[Dict[str, Any]]
    benchmark_comparison: Dict[str, Any]
    total_roi: float
    generated_at: datetime

class CampaignComparisonReportRequest(BaseModel):
    campaign_ids: List[str]
    time_range: Dict[str, str]

class CampaignComparisonReportResponse(BaseModel):
    campaigns_compared: int
    comparison_data: List[Dict[str, Any]]
    best_performers: List[Dict[str, Any]]
    worst_performers: List[Dict[str, Any]]
    metric_variance: Dict[str, Any]
    lessons_learned: List[Dict[str, Any]]
    replication_recommendations: List[Dict[str, Any]]
    generated_at: datetime

class MonthOverMonthAnalysisRequest(BaseModel):
    campaign_ids: Optional[List[str]] = None
    ad_account_id: Optional[str] = None
    current_month: Dict[str, str]
    previous_month: Dict[str, str]
    forecast: Optional[Dict[str, float]] = None

class MonthOverMonthAnalysisResponse(BaseModel):
    current_month: Dict[str, str]
    previous_month: Dict[str, str]
    mom_growth_rates: Dict[str, float]
    trends_identified: List[Dict[str, Any]]
    seasonality_adjustments: Dict[str, Any]
    yoy_comparison: Dict[str, Any]
    forecast_vs_actual: Dict[str, Any]
    generated_at: datetime

class CampaignNarrativeBuilderRequest(BaseModel):
    campaign_ids: Optional[List[str]] = None
    ad_account_id: Optional[str] = None
    time_range: Dict[str, str]

class CampaignNarrativeBuilderResponse(BaseModel):
    report_period: Dict[str, str]
    performance_story: str
    metric_context: List[Dict[str, Any]]
    root_cause_explanations: List[Dict[str, Any]]
    optimization_actions_taken: List[Dict[str, Any]]
    results_of_changes: List[Dict[str, Any]]
    generated_at: datetime

class BenchmarkReportGeneratorRequest(BaseModel):
    campaign_ids: Optional[List[str]] = None
    ad_account_id: Optional[str] = None
    time_range: Dict[str, str]
    portfolio_comparison_ids: Optional[List[str]] = None
    industry_vertical: Optional[str] = None

class BenchmarkReportGeneratorResponse(BaseModel):
    report_period: Dict[str, str]
    client_metrics: Dict[str, Any]
    portfolio_average: Dict[str, Any]
    industry_comparison: Dict[str, Any]
    performance_percentile: Dict[str, float]
    gap_analysis: List[Dict[str, Any]]
    improvement_roadmap: List[Dict[str, Any]]
    generated_at: datetime


# Targeting Intelligence Schemas (5 tools)
class DemographicPerformanceProfilerRequest(BaseModel):
    campaign_ids: Optional[List[str]] = None
    ad_account_id: Optional[str] = None
    time_range: Dict[str, str]

class DemographicPerformanceProfilerResponse(BaseModel):
    campaigns_analyzed: int
    demographic_roas_breakdown: List[Dict[str, Any]]
    high_value_demographics: List[Dict[str, Any]]
    underperforming_segments: List[Dict[str, Any]]
    targeting_refinement_recommendations: List[Dict[str, Any]]
    bid_adjustments_by_demographic: List[Dict[str, Any]]
    generated_at: datetime

class InterestTargetingAnalyzerRequest(BaseModel):
    campaign_ids: Optional[List[str]] = None
    ad_account_id: Optional[str] = None

class InterestTargetingAnalyzerResponse(BaseModel):
    campaigns_analyzed: int
    interest_category_performance: List[Dict[str, Any]]
    interest_layering_effectiveness: Dict[str, Any]
    broad_vs_narrow_comparison: Dict[str, Any]
    expansion_pruning_opportunities: Dict[str, Any]
    optimal_interest_combinations: List[Dict[str, Any]]
    generated_at: datetime

class BehaviorTargetingOptimizerRequest(BaseModel):
    campaign_ids: Optional[List[str]] = None
    ad_account_id: Optional[str] = None

class BehaviorTargetingOptimizerResponse(BaseModel):
    campaigns_analyzed: int
    purchase_behavior_roas: List[Dict[str, Any]]
    device_usage_patterns: List[Dict[str, Any]]
    travel_behavior_impact: Dict[str, Any]
    behavior_stacking_effectiveness: Dict[str, Any]
    targeting_recommendations: List[Dict[str, Any]]
    generated_at: datetime

class CustomAudienceHealthMonitorRequest(BaseModel):
    audience_ids: Optional[List[str]] = None
    ad_account_id: Optional[str] = None

class CustomAudienceHealthMonitorResponse(BaseModel):
    audiences_monitored: int
    audience_size_trends: List[Dict[str, Any]]
    match_rate_tracking: List[Dict[str, Any]]
    refresh_frequency_optimization: List[Dict[str, Any]]
    audience_quality_scores: List[Dict[str, Any]]
    maintenance_recommendations: List[Dict[str, Any]]
    generated_at: datetime

class LookalikePerformanceEvaluatorRequest(BaseModel):
    campaign_ids: Optional[List[str]] = None
    ad_account_id: Optional[str] = None

class LookalikePerformanceEvaluatorResponse(BaseModel):
    campaigns_analyzed: int
    lal_percentage_effectiveness: List[Dict[str, Any]]
    source_audience_quality_impact: Dict[str, Any]
    lal_vs_cold_audience_comparison: Dict[str, Any]
    optimal_lal_percentage: Dict[str, Any]
    seed_audience_recommendations: List[Dict[str, Any]]
    generated_at: datetime


# ============================================================================
# Phase 1: Enterprise Tools - Strategic & Tactical (26 tools)
# ============================================================================

# Strategic Layer - Fraud Detection (5 tools)

class AnalyzeClickPatternsRequest(BaseModel):
    """Analyze click patterns to detect bot farms and fraud."""
    ad_account_id: str = Field(..., description="Meta ad account ID")
    entity_id: str = Field(..., description="Campaign/adset/ad ID to analyze")
    entity_type: str = Field(default="campaign", description="Type of entity (campaign, adset, ad)")
    time_range: Optional[Dict[str, str]] = Field(default=None, description="Date range for analysis")
    anomaly_threshold: float = Field(default=2.5, description="Standard deviations for anomaly detection")


class DetectConversionFraudRequest(BaseModel):
    """Detect fraudulent conversion patterns."""
    ad_account_id: str = Field(..., description="Meta ad account ID")
    entity_id: str = Field(..., description="Campaign/adset/ad ID")
    entity_type: str = Field(default="campaign", description="Type of entity")
    time_range: Optional[Dict[str, str]] = Field(default=None, description="Analysis period")
    conversion_event: str = Field(default="Purchase", description="Conversion event to analyze")


class ScorePlacementQualityRequest(BaseModel):
    """Score placement quality to identify fraud-prone placements."""
    ad_account_id: str = Field(..., description="Meta ad account ID")
    entity_id: str = Field(..., description="Campaign/adset/ad ID")
    entity_type: str = Field(default="campaign", description="Type of entity")
    time_range: Optional[Dict[str, str]] = Field(default=None, description="Analysis period")


class FilterInvalidTrafficRequest(BaseModel):
    """Filter and identify invalid traffic (IVT)."""
    ad_account_id: str = Field(..., description="Meta ad account ID")
    entity_id: str = Field(..., description="Campaign/adset/ad ID")
    entity_type: str = Field(default="campaign", description="Type of entity")
    time_range: Optional[Dict[str, str]] = Field(default=None, description="Analysis period")


class MonitorAccountSecurityRequest(BaseModel):
    """Monitor account for security threats and unauthorized access."""
    ad_account_id: str = Field(..., description="Meta ad account ID")
    lookback_days: int = Field(default=7, description="Days to analyze")


# Strategic Layer - Spend Monitoring (3 tools)

class GetRealTimeSpendFeedRequest(BaseModel):
    """Get real-time spend feed for CFO/finance teams."""
    ad_account_id: str = Field(..., description="Meta ad account ID")
    granularity: str = Field(default="hourly", description="'hourly' or 'daily'")
    currency: str = Field(default="USD", description="Target currency for reporting")
    include_forecast: bool = Field(default=True, description="Include spend forecast")


class DetectSpendAnomaliesRequest(BaseModel):
    """Detect unusual spend spikes for security/fraud prevention."""
    ad_account_id: str = Field(..., description="Meta ad account ID")
    lookback_days: int = Field(default=30, description="Days of history to analyze")
    anomaly_threshold: float = Field(default=2.5, description="Standard deviations for anomaly")
    alert_on_spike: bool = Field(default=True, description="Alert on upward spikes")


class EnforceBudgetGuardrailsRequest(BaseModel):
    """Enforce budget guardrails and spending limits."""
    ad_account_id: str = Field(..., description="Meta ad account ID")
    daily_limit: Optional[float] = Field(default=None, description="Maximum daily spend")
    monthly_limit: Optional[float] = Field(default=None, description="Maximum monthly spend")
    auto_pause: bool = Field(default=False, description="Auto-pause campaigns on limit")
    alert_threshold: float = Field(default=0.8, description="Alert when % of limit reached")


# Strategic Layer - Executive Reporting (3 tools)

class GenerateCEODashboardRequest(BaseModel):
    """Generate CEO dashboard with top 5 strategic metrics."""
    ad_account_id: str = Field(..., description="Meta ad account ID")
    time_range: Optional[Dict[str, str]] = Field(default=None, description="Analysis period")
    comparison_period: str = Field(default="previous_period", description="'previous_period', 'last_year', or 'last_quarter'")


class GenerateBoardPresentationRequest(BaseModel):
    """Generate board-ready presentation materials."""
    ad_account_id: str = Field(..., description="Meta ad account ID")
    time_range: Optional[Dict[str, str]] = Field(default=None, description="Analysis period")
    include_competitive: bool = Field(default=True, description="Include competitive analysis")


class GenerateCFOFinancialReportRequest(BaseModel):
    """Generate CFO-focused financial report."""
    ad_account_id: str = Field(..., description="Meta ad account ID")
    time_range: Optional[Dict[str, str]] = Field(default=None, description="Analysis period")
    include_forecast: bool = Field(default=True, description="Include financial forecasts")


# Tactical Layer - Real-Time Intelligence (6 tools)

class GetHourlyPerformanceSnapshotRequest(BaseModel):
    """Get last hour performance vs. yesterday same hour."""
    ad_account_id: str = Field(..., description="Meta ad account ID")
    entity_id: Optional[str] = Field(default=None, description="Specific campaign/adset/ad ID")
    entity_type: str = Field(default="account", description="Type of entity")


class CheckCampaignHealthInstantRequest(BaseModel):
    """5-second campaign health check with red/yellow/green status."""
    ad_account_id: str = Field(..., description="Meta ad account ID")
    entity_id: str = Field(..., description="Campaign/adset/ad ID")
    entity_type: str = Field(default="campaign", description="Type of entity")


class DetectPerformanceDeteriorationRequest(BaseModel):
    """Detect performance deterioration (CTR/CPA/ROAS drops)."""
    ad_account_id: str = Field(..., description="Meta ad account ID")
    entity_id: str = Field(..., description="Campaign/adset/ad ID")
    entity_type: str = Field(default="campaign", description="Type of entity")
    threshold_pct: float = Field(default=20, description="Alert threshold percentage")


class RecommendTop5ActionsRequest(BaseModel):
    """AI-powered: 'Do these 5 things NOW' recommendations."""
    ad_account_id: str = Field(..., description="Meta ad account ID")
    entity_id: Optional[str] = Field(default=None, description="Specific entity ID")
    entity_type: str = Field(default="account", description="Type of entity")


class MonitorBudgetBurnRateRequest(BaseModel):
    """Monitor budget burn rate with pacing alerts."""
    ad_account_id: str = Field(..., description="Meta ad account ID")
    entity_id: str = Field(..., description="Campaign/adset ID")
    entity_type: str = Field(default="campaign", description="Type of entity")
    daily_budget: Optional[float] = Field(default=None, description="Daily budget if known")


class CheckAuctionCompetitionNowRequest(BaseModel):
    """Check real-time auction competition and CPM changes."""
    ad_account_id: str = Field(..., description="Meta ad account ID")
    entity_id: str = Field(..., description="Campaign/adset ID")
    entity_type: str = Field(default="campaign", description="Type of entity")


# Tactical Layer - Campaign Health (4 tools)

class DetectCreativeFatigueRadarRequest(BaseModel):
    """Detect which creative is fatiguing RIGHT NOW."""
    ad_account_id: str = Field(..., description="Meta ad account ID")
    entity_id: str = Field(..., description="Ad or adset ID")
    entity_type: str = Field(default="ad", description="Type of entity (ad, adset)")


class TrackConversionRateRealtimeRequest(BaseModel):
    """Track real-time conversion rate by campaign."""
    ad_account_id: str = Field(..., description="Meta ad account ID")
    entity_id: str = Field(..., description="Campaign/adset/ad ID")
    entity_type: str = Field(default="campaign", description="Type of entity")
    conversion_event: str = Field(default="Purchase", description="Conversion event to track")


class MeasureAudienceExhaustionRequest(BaseModel):
    """Measure audience exhaustion meter - days until saturation."""
    ad_account_id: str = Field(..., description="Meta ad account ID")
    entity_id: str = Field(..., description="Adset or campaign ID")
    entity_type: str = Field(default="adset", description="Type of entity")


class TrackLearningPhaseRequest(BaseModel):
    """Track learning phase status and provide recommendations."""
    ad_account_id: str = Field(..., description="Meta ad account ID")
    entity_id: str = Field(..., description="Adset or campaign ID")
    entity_type: str = Field(default="adset", description="Type of entity")


# Tactical Layer - Budget Optimization (5 tools)

class OptimizePortfolioBudgetRequest(BaseModel):
    """Optimize budget allocation across campaign portfolio."""
    ad_account_id: str = Field(..., description="Meta ad account ID")
    campaign_ids: List[str] = Field(..., description="List of campaign IDs to optimize")
    total_budget: float = Field(..., description="Total budget to allocate")
    optimization_goal: str = Field(default="roas", description="'roas', 'conversions', or 'reach'")
    constraints: Optional[Dict[str, Any]] = Field(default=None, description="Min/max budget constraints")


class CalculateMarginalRoasRequest(BaseModel):
    """Calculate marginal ROAS at different budget levels."""
    ad_account_id: str = Field(..., description="Meta ad account ID")
    campaign_id: str = Field(..., description="Campaign ID to analyze")
    budget_increments: List[float] = Field(default_factory=lambda: [1000, 2000, 5000, 10000], description="Budget increase amounts")


class AutopilotPacingRequest(BaseModel):
    """Auto-adjust budget pacing throughout the day."""
    ad_account_id: str = Field(..., description="Meta ad account ID")
    campaign_id: str = Field(..., description="Campaign ID")
    daily_budget: float = Field(..., description="Target daily budget")
    pacing_strategy: str = Field(default="even", description="'even', 'front_load', or 'back_load'")


class DetectCampaignCeilingRequest(BaseModel):
    """Detect campaign spending ceiling (maximum viable budget)."""
    ad_account_id: str = Field(..., description="Meta ad account ID")
    campaign_id: str = Field(..., description="Campaign ID")


class RescueUnderdeliveringCampaignsRequest(BaseModel):
    """Detect and rescue campaigns not spending their budget."""
    ad_account_id: str = Field(..., description="Meta ad account ID")
    campaign_ids: Optional[List[str]] = Field(default=None, description="Specific campaigns to check")


# ========================================
# Mini-Phase 2A: Multi-Brand Portfolio Management (5 schemas)
# ========================================

class CompareBrandsRequest(BaseModel):
    """Compare 2-5 brands side-by-side with key metrics."""
    ad_account_ids: List[str] = Field(..., description="List of 2-5 ad account IDs to compare", min_length=2, max_length=5)
    time_range: Dict[str, str] = Field(..., description="Time range {'since': 'YYYY-MM-DD', 'until': 'YYYY-MM-DD'}")
    metrics: Optional[List[str]] = Field(
        default=None,
        description="Metrics to compare (defaults to spend, ROAS, CTR, CPC, conversions)"
    )


class IdentifyOutliersRequest(BaseModel):
    """Detect underperforming/overperforming brands using statistical analysis."""
    ad_account_ids: List[str] = Field(..., description="List of ad account IDs to analyze", min_length=3)
    time_range: Dict[str, str] = Field(..., description="Time range for analysis")
    threshold_std_dev: float = Field(
        default=2.0,
        description="Z-score threshold for outlier detection (default: 2.0 = 95% confidence)"
    )


class AllocateBudgetAcrossBrandsRequest(BaseModel):
    """Optimal budget distribution across brands based on performance."""
    ad_account_ids: List[str] = Field(..., description="List of ad account IDs", min_length=2)
    total_budget: float = Field(..., description="Total budget to allocate", gt=0)
    time_range: Dict[str, str] = Field(..., description="Historical period for performance analysis")
    allocation_strategy: str = Field(
        default="performance_weighted",
        description="'performance_weighted', 'equal', or 'custom'"
    )


class BenchmarkByIndustryRequest(BaseModel):
    """Industry-specific benchmarking for brands."""
    ad_account_ids: List[str] = Field(..., description="List of ad account IDs to benchmark")
    industry: str = Field(..., description="Industry vertical (e.g., 'ecommerce', 'saas', 'finance')")
    time_range: Dict[str, str] = Field(..., description="Time range for analysis")


class HealthScorecardRequest(BaseModel):
    """Overall portfolio health metrics and scorecard."""
    ad_account_ids: List[str] = Field(..., description="List of ad account IDs in portfolio")
    time_range: Dict[str, str] = Field(..., description="Time range for health assessment")
    include_risk_analysis: bool = Field(default=True, description="Include risk indicators")
    include_opportunities: bool = Field(default=True, description="Include growth opportunities")


# ========================================
# Phase 2: Cross-Channel Attribution (8 schemas)
# ========================================

class CrossPlatformJourneyRequest(BaseModel):
    """Map user journey across Facebook, Instagram, Messenger, WhatsApp."""
    ad_account_id: str = Field(..., description="Meta ad account ID")
    time_range: Dict[str, str] = Field(..., description="Time range for journey analysis")
    conversion_event: str = Field(..., description="Conversion event to track (e.g., 'purchase', 'lead')")


class FirstTouchAnalysisRequest(BaseModel):
    """First interaction attribution - credit to first touchpoint."""
    ad_account_id: str = Field(..., description="Meta ad account ID")
    time_range: Dict[str, str] = Field(..., description="Time range for attribution analysis")


class LastTouchAnalysisRequest(BaseModel):
    """Last interaction attribution - credit to last touchpoint before conversion."""
    ad_account_id: str = Field(..., description="Meta ad account ID")
    time_range: Dict[str, str] = Field(..., description="Time range for attribution analysis")


class TimeDecayModelRequest(BaseModel):
    """Time-decay attribution - more recent touchpoints get more credit."""
    ad_account_id: str = Field(..., description="Meta ad account ID")
    time_range: Dict[str, str] = Field(..., description="Time range for attribution analysis")
    decay_rate: int = Field(default=7, description="Half-life in days (default: 7 days)")


class PositionBasedModelRequest(BaseModel):
    """Position-based (U-shaped) attribution - 40% first, 40% last, 20% middle."""
    ad_account_id: str = Field(..., description="Meta ad account ID")
    time_range: Dict[str, str] = Field(..., description="Time range for attribution analysis")
    first_touch_weight: float = Field(default=0.40, description="Weight for first touchpoint (default: 0.40)")
    last_touch_weight: float = Field(default=0.40, description="Weight for last touchpoint (default: 0.40)")


class DataDrivenModelRequest(BaseModel):
    """Data-driven (algorithmic) attribution using Meta's ML model."""
    ad_account_id: str = Field(..., description="Meta ad account ID")
    time_range: Dict[str, str] = Field(..., description="Time range for attribution analysis")


class IncrementalityTestRequest(BaseModel):
    """Measure true incremental impact using holdout testing."""
    ad_account_id: str = Field(..., description="Meta ad account ID")
    test_id: str = Field(..., description="Lift study/test ID")


class CrossDeviceTrackingRequest(BaseModel):
    """Desktop vs mobile attribution and cross-device journeys."""
    ad_account_id: str = Field(..., description="Meta ad account ID")
    time_range: Dict[str, str] = Field(..., description="Time range for cross-device analysis")


# ========================================
# Phase 2: Predictive Intelligence (10 schemas)
# ========================================

class ForecastPerformanceRequest(BaseModel):
    """7/14/30-day performance forecast with confidence intervals."""
    ad_account_id: str = Field(..., description="Meta ad account ID")
    entity_id: str = Field(..., description="Campaign/adset/ad ID to forecast")
    entity_type: str = Field(..., description="Entity type: campaign, adset, or ad")
    forecast_days: int = Field(default=7, description="Days to forecast (7, 14, or 30)")
    metrics: List[str] = Field(
        default=["spend", "impressions", "clicks", "conversions", "roas"],
        description="Metrics to forecast"
    )


class PredictCreativeFatigueRequest(BaseModel):
    """When creative will hit fatigue based on frequency/CTR decline."""
    ad_account_id: str = Field(..., description="Meta ad account ID")
    ad_id: str = Field(..., description="Ad ID to analyze")
    fatigue_threshold: float = Field(default=0.30, description="CTR decline % to trigger fatigue alert (default: 30%)")


class PredictBudgetExhaustionRequest(BaseModel):
    """When budget will run out at current spend rate."""
    ad_account_id: str = Field(..., description="Meta ad account ID")
    campaign_id: str = Field(..., description="Campaign ID")
    include_recommendations: bool = Field(default=True, description="Include budget optimization recommendations")


class PredictAudienceSaturationRequest(BaseModel):
    """When audience will be saturated (frequency, reach ceiling)."""
    ad_account_id: str = Field(..., description="Meta ad account ID")
    adset_id: str = Field(..., description="Ad set ID to analyze")
    saturation_threshold: float = Field(default=3.0, description="Frequency threshold for saturation (default: 3.0)")


class PredictSeasonalTrendsRequest(BaseModel):
    """Seasonal patterns and upcoming peak/low periods."""
    ad_account_id: str = Field(..., description="Meta ad account ID")
    lookback_years: int = Field(default=2, description="Years of historical data to analyze (default: 2)")
    forecast_months: int = Field(default=3, description="Months to forecast ahead (default: 3)")


class PredictCompetitorActivityRequest(BaseModel):
    """Predict CPM spikes from competitor activity."""
    ad_account_id: str = Field(..., description="Meta ad account ID")
    time_range: Dict[str, str] = Field(..., description="Historical time range for analysis")
    forecast_days: int = Field(default=14, description="Days to forecast ahead")


class PredictOptimalBudgetRequest(BaseModel):
    """Optimal budget to maximize ROAS based on marginal returns."""
    ad_account_id: str = Field(..., description="Meta ad account ID")
    campaign_id: str = Field(..., description="Campaign ID")
    target_roas: Optional[float] = Field(default=None, description="Target ROAS constraint")
    max_budget: Optional[float] = Field(default=None, description="Maximum budget constraint")


class PredictScalingImpactRequest(BaseModel):
    """Impact of scaling budget by X% (will performance hold?)."""
    ad_account_id: str = Field(..., description="Meta ad account ID")
    campaign_id: str = Field(..., description="Campaign ID")
    scale_percentage: float = Field(..., description="Budget increase percentage (e.g., 50 for +50%)")
    time_range: Dict[str, str] = Field(..., description="Historical period for analysis")


class PredictAudienceExpansionROIRequest(BaseModel):
    """ROI of expanding to lookalike/interest audiences."""
    ad_account_id: str = Field(..., description="Meta ad account ID")
    current_audience_id: str = Field(..., description="Current custom audience ID")
    expansion_type: str = Field(..., description="Expansion type: lookalike, interest, or broad")
    expansion_parameters: Optional[Dict[str, Any]] = Field(default=None, description="Expansion parameters")


class PredictTestWinnerRequest(BaseModel):
    """Predict A/B test winner before statistical significance."""
    ad_account_id: str = Field(..., description="Meta ad account ID")
    test_id: str = Field(..., description="A/B test or campaign ID")
    variant_ids: List[str] = Field(..., description="List of variant IDs to compare")
    confidence_level: float = Field(default=0.95, description="Required confidence level (default: 0.95)")


# ========================================
# Phase 2: Advanced Creative Analysis (8 schemas)
# ========================================

class AnalyzeCreativeElementsRequest(BaseModel):
    """Deep analysis of creative elements (headline, image, CTA, copy)."""
    ad_account_id: str = Field(..., description="Meta ad account ID")
    ad_ids: List[str] = Field(..., description="List of ad IDs to analyze")


class DetectCreativeFatiguePortfolioRequest(BaseModel):
    """Detect creative fatigue across entire ad portfolio."""
    ad_account_id: str = Field(..., description="Meta ad account ID")
    fatigue_threshold: float = Field(default=0.30, description="CTR decline threshold for fatigue (default: 30%)")


class CompareCreativeFormatsRequest(BaseModel):
    """Compare performance across image vs video vs carousel."""
    ad_account_id: str = Field(..., description="Meta ad account ID")
    time_range: Dict[str, str] = Field(..., description="Time range for comparison")


class AnalyzeVideoRetentionRequest(BaseModel):
    """Second-by-second video retention analysis with drop-off points."""
    ad_account_id: str = Field(..., description="Meta ad account ID")
    video_ad_id: str = Field(..., description="Video ad ID to analyze")


class AnalyzeHookEffectivenessRequest(BaseModel):
    """Analyze first 3 seconds hook effectiveness (critical for stopping scroll)."""
    ad_account_id: str = Field(..., description="Meta ad account ID")
    video_ad_ids: List[str] = Field(..., description="List of video ad IDs to analyze")


class OptimizeCreativeMixRequest(BaseModel):
    """Optimal creative rotation strategy (fresh vs proven ratio)."""
    ad_account_id: str = Field(..., description="Meta ad account ID")
    campaign_id: str = Field(..., description="Campaign ID")


class TestCreativeVariationsRequest(BaseModel):
    """Systematic creative testing framework (headlines, images, CTAs)."""
    ad_account_id: str = Field(..., description="Meta ad account ID")
    base_creative_id: str = Field(..., description="Base creative ID to create variations from")
    test_elements: List[str] = Field(..., description="Elements to test (e.g., ['headline', 'image', 'cta'])")


class BenchmarkCreativePerformanceRequest(BaseModel):
    """Compare creative performance against industry benchmarks."""
    ad_account_id: str = Field(..., description="Meta ad account ID")
    industry: str = Field(..., description="Industry vertical (e.g., 'ecommerce', 'saas', 'finance')")
    time_range: Dict[str, str] = Field(..., description="Time range for analysis")


# ========================================
# Phase 2: Advanced Audience Intelligence (10 schemas)
# ========================================

class ProfileConverterAttributesRequest(BaseModel):
    """Deep profile of users who convert (demographics, interests, behaviors)."""
    ad_account_id: str = Field(..., description="Meta ad account ID")
    time_range: Dict[str, str] = Field(..., description="Time range for analysis")
    conversion_event: str = Field(..., description="Conversion event to analyze (e.g., 'Purchase', 'Lead')")


class AnalyzeAudienceOverlapRequest(BaseModel):
    """Measure overlap between custom audiences (avoid redundancy)."""
    ad_account_id: str = Field(..., description="Meta ad account ID")
    audience_ids: List[str] = Field(..., description="List of custom audience IDs to analyze")


class DiscoverHiddenSegmentsRequest(BaseModel):
    """Discover high-value audience segments you're not targeting."""
    ad_account_id: str = Field(..., description="Meta ad account ID")
    time_range: Dict[str, str] = Field(..., description="Time range for discovery analysis")


class OptimizeLookalikeSourcesRequest(BaseModel):
    """Compare lookalike source quality (purchasers vs engaged vs all)."""
    ad_account_id: str = Field(..., description="Meta ad account ID")
    source_audience_ids: List[str] = Field(..., description="List of source audience IDs to compare")


class AnalyzeCustomerLifetimeValueRequest(BaseModel):
    """LTV segmentation by audience (which audiences have highest LTV)."""
    ad_account_id: str = Field(..., description="Meta ad account ID")
    time_range: Dict[str, str] = Field(..., description="Time range for LTV analysis")


class PredictAudienceExpansionSuccessRequest(BaseModel):
    """Model performance before expanding targeting (risk assessment)."""
    ad_account_id: str = Field(..., description="Meta ad account ID")
    current_audience_id: str = Field(..., description="Current audience ID")
    expansion_type: str = Field(..., description="Expansion type: 'lookalike', 'interest', or 'broad'")
    expansion_parameters: Optional[Dict[str, Any]] = Field(default=None, description="Expansion parameters")


class AnalyzeInterestAffinityRequest(BaseModel):
    """Interest targeting performance (which interests actually convert)."""
    ad_account_id: str = Field(..., description="Meta ad account ID")
    time_range: Dict[str, str] = Field(..., description="Time range for interest analysis")


class DetectAudienceSaturationRiskRequest(BaseModel):
    """Early warning system for audience exhaustion."""
    ad_account_id: str = Field(..., description="Meta ad account ID")
    adset_ids: List[str] = Field(..., description="List of ad set IDs to analyze for saturation")


class OptimizeExclusionTargetingRequest(BaseModel):
    """Optimize audience exclusions (who should you NOT target)."""
    ad_account_id: str = Field(..., description="Meta ad account ID")
    time_range: Dict[str, str] = Field(..., description="Time range for exclusion analysis")


class BenchmarkAudienceQualityRequest(BaseModel):
    """Compare audience quality scores across all audiences."""
    ad_account_id: str = Field(..., description="Meta ad account ID")
    time_range: Dict[str, str] = Field(..., description="Time range for quality benchmarking")


# ========================================
# Phase 2: Competitive Intelligence (8 schemas)
# ========================================

class EstimateCompetitorSpendRequest(BaseModel):
    """Estimate competitor ad spend using CPM benchmarks and impression data."""
    industry: str = Field(..., description="Industry vertical (e.g., 'ecommerce', 'saas', 'finance')")
    competitor_pages: List[str] = Field(..., description="List of competitor Facebook page IDs")
    time_range: Dict[str, str] = Field(..., description="Time range for spend estimation")


class AnalyzeCompetitivePositioningRequest(BaseModel):
    """Compare your positioning vs competitors (pricing, messaging, offers)."""
    ad_account_id: str = Field(..., description="Your Meta ad account ID")
    competitor_pages: List[str] = Field(..., description="List of competitor Facebook page IDs")
    time_range: Dict[str, str] = Field(..., description="Time range for positioning analysis")


class TrackShareOfVoiceRequest(BaseModel):
    """Track your share of voice vs competitors in the market."""
    ad_account_id: str = Field(..., description="Your Meta ad account ID")
    competitor_pages: List[str] = Field(..., description="List of competitor Facebook page IDs")
    time_range: Dict[str, str] = Field(..., description="Time range for SOV tracking")


class AnalyzeCompetitorCreativeStrategyRequest(BaseModel):
    """Analyze competitor ad creative (formats, messaging, CTAs)."""
    competitor_pages: List[str] = Field(..., description="List of competitor Facebook page IDs")
    time_range: Dict[str, str] = Field(..., description="Time range for creative analysis")


class DetectCompetitorCampaignLaunchesRequest(BaseModel):
    """Real-time alerts when competitors launch new campaigns."""
    competitor_pages: List[str] = Field(..., description="List of competitor Facebook page IDs to monitor")
    lookback_days: int = Field(default=30, description="Days to look back for new launches (default: 30)")


class BenchmarkPerformanceVsCompetitorsRequest(BaseModel):
    """Compare your KPIs vs estimated competitor benchmarks."""
    ad_account_id: str = Field(..., description="Your Meta ad account ID")
    industry: str = Field(..., description="Industry vertical for benchmarking")
    time_range: Dict[str, str] = Field(..., description="Time range for performance comparison")


class IdentifyMarketOpportunitiesRequest(BaseModel):
    """Find underserved market segments competitors are missing."""
    industry: str = Field(..., description="Industry vertical")
    competitor_pages: List[str] = Field(..., description="List of competitor Facebook page IDs")
    time_range: Dict[str, str] = Field(..., description="Time range for opportunity analysis")


class AnalyzeCompetitiveAuctionPressureRequest(BaseModel):
    """Analyze CPM trends to detect competitive auction pressure."""
    ad_account_id: str = Field(..., description="Your Meta ad account ID")
    time_range: Dict[str, str] = Field(..., description="Time range for auction pressure analysis")


# ========================================
# Phase 3: Conversion Optimization (10 schemas)
# ========================================

class AnalyzeConversionFunnelRequest(BaseModel):
    """Analyze complete conversion funnel from click to purchase."""
    entity_id: str = Field(..., description="Campaign, adset, or ad ID")
    entity_type: str = Field(..., description="Entity type: campaign, adset, or ad")
    time_range: Dict[str, str] = Field(..., description="Time range for funnel analysis")


class OptimizeLandingPagesRequest(BaseModel):
    """Analyze and optimize landing page performance."""
    ad_account_id: str = Field(..., description="Meta ad account ID")
    landing_page_urls: List[str] = Field(..., description="List of landing page URLs to analyze")
    time_range: Dict[str, str] = Field(..., description="Time range for analysis")
    metrics: List[str] = Field(
        default=["bounce_rate", "time_on_page", "conversion_rate", "exit_rate"],
        description="Metrics to analyze"
    )


class TrackPostClickBehaviorRequest(BaseModel):
    """Track user behavior after ad click."""
    entity_id: str = Field(..., description="Campaign, adset, or ad ID")
    entity_type: str = Field(..., description="Entity type: campaign, adset, or ad")
    time_range: Dict[str, str] = Field(..., description="Time range for behavior tracking")
    behavior_events: List[str] = Field(
        default=["page_view", "scroll_depth", "time_on_site", "pages_per_session"],
        description="Behavior events to track"
    )


class AnalyzeConversionPathsRequest(BaseModel):
    """Analyze different paths users take to convert."""
    ad_account_id: str = Field(..., description="Meta ad account ID")
    time_range: Dict[str, str] = Field(..., description="Time range for path analysis")
    max_path_length: int = Field(default=5, description="Maximum path length to analyze")
    min_conversions: int = Field(default=10, description="Minimum conversions to include path")


class DetectCartAbandonmentRequest(BaseModel):
    """Detect and analyze cart abandonment patterns."""
    ad_account_id: str = Field(..., description="Meta ad account ID")
    time_range: Dict[str, str] = Field(..., description="Time range for abandonment analysis")
    abandonment_threshold_minutes: int = Field(
        default=30,
        description="Minutes of inactivity to consider cart abandoned"
    )


class OptimizeCheckoutFlowRequest(BaseModel):
    """Optimize checkout process for higher completion rates."""
    ad_account_id: str = Field(..., description="Meta ad account ID")
    time_range: Dict[str, str] = Field(..., description="Time range for checkout analysis")
    checkout_steps: List[str] = Field(
        default=["cart", "shipping", "payment", "confirmation"],
        description="Checkout steps to analyze"
    )


class AnalyzeFormCompletionRequest(BaseModel):
    """Analyze form completion rates and optimize."""
    ad_account_id: str = Field(..., description="Meta ad account ID")
    form_ids: List[str] = Field(..., description="List of form IDs to analyze")
    time_range: Dict[str, str] = Field(..., description="Time range for form analysis")


class CompareMobileDesktopConversionRequest(BaseModel):
    """Compare conversion rates between mobile and desktop."""
    ad_account_id: str = Field(..., description="Meta ad account ID")
    time_range: Dict[str, str] = Field(..., description="Time range for device comparison")
    metrics: List[str] = Field(
        default=["conversion_rate", "cpa", "roas", "cart_abandonment"],
        description="Metrics to compare"
    )


class OptimizeConversionWindowsRequest(BaseModel):
    """Optimize conversion attribution windows."""
    ad_account_id: str = Field(..., description="Meta ad account ID")
    time_range: Dict[str, str] = Field(..., description="Time range for window analysis")
    test_windows: List[str] = Field(
        default=["1d_click", "7d_click", "1d_view", "7d_view", "28d_click"],
        description="Attribution windows to test"
    )


class AnalyzeMicroConversionsRequest(BaseModel):
    """Analyze micro-conversions leading to macro-conversions."""
    ad_account_id: str = Field(..., description="Meta ad account ID")
    time_range: Dict[str, str] = Field(..., description="Time range for micro-conversion analysis")
    micro_events: List[str] = Field(
        default=["page_view", "video_view", "add_to_wishlist", "search", "lead"],
        description="Micro-conversion events to analyze"
    )
    macro_event: str = Field(default="purchase", description="Macro-conversion event")


# ========================================
# Phase 4: Video & Reels Mastery (8 schemas)
# ========================================

class AnalyzeVideoRetentionHeatmapRequest(BaseModel):
    """Analyze second-by-second video retention with visual heatmap."""
    ad_account_id: str = Field(..., description="Meta ad account ID")
    video_ids: List[str] = Field(..., description="List of video ad IDs to analyze")
    time_range: Dict[str, str] = Field(..., description="Time range for retention analysis")


class AnalyzeReelsHookEffectivenessRequest(BaseModel):
    """Analyze first 3 seconds hook effectiveness."""
    ad_account_id: str = Field(..., description="Meta ad account ID")
    video_ids: List[str] = Field(..., description="List of video ad IDs to analyze")
    time_range: Dict[str, str] = Field(..., description="Time range for hook analysis")
    hook_threshold_seconds: int = Field(default=3, description="Hook duration threshold in seconds")


class CompareSoundOnOffRequest(BaseModel):
    """Compare sound-on vs sound-off video performance."""
    ad_account_id: str = Field(..., description="Meta ad account ID")
    video_ids: List[str] = Field(..., description="List of video ad IDs to compare")
    time_range: Dict[str, str] = Field(..., description="Time range for comparison")
    metrics: List[str] = Field(
        default=["video_play_actions", "video_avg_time_watched_actions", "cost_per_thruplay"],
        description="Metrics to compare"
    )


class OptimizeReelsPerformanceRequest(BaseModel):
    """Optimize Reels-specific performance."""
    ad_account_id: str = Field(..., description="Meta ad account ID")
    reels_ids: List[str] = Field(..., description="List of Reels ad IDs")
    time_range: Dict[str, str] = Field(..., description="Time range for Reels analysis")
    include_benchmarks: bool = Field(default=True, description="Include Reels benchmarks")


class TestVideoThumbnailsRequest(BaseModel):
    """A/B test video thumbnails for click-through."""
    ad_account_id: str = Field(..., description="Meta ad account ID")
    video_id: str = Field(..., description="Video ad ID")
    thumbnail_variants: List[str] = Field(..., description="List of thumbnail URLs to test")
    test_duration_days: int = Field(default=7, description="Duration of A/B test in days")
    min_sample_size: int = Field(default=1000, description="Minimum impressions per variant")


class OptimizeVideoLengthRequest(BaseModel):
    """Find optimal video length for your audience."""
    ad_account_id: str = Field(..., description="Meta ad account ID")
    time_range: Dict[str, str] = Field(..., description="Time range for length analysis")
    video_categories: List[str] = Field(
        default=["0-10s", "10-30s", "30-60s", "60s+"],
        description="Video length categories to analyze"
    )


class AnalyzeEngagementPatternsRequest(BaseModel):
    """Analyze when viewers engage (like, comment, share)."""
    ad_account_id: str = Field(..., description="Meta ad account ID")
    video_ids: List[str] = Field(..., description="List of video ad IDs to analyze")
    time_range: Dict[str, str] = Field(..., description="Time range for engagement analysis")
    engagement_types: List[str] = Field(
        default=["like", "comment", "share", "save"],
        description="Engagement types to analyze"
    )


class OptimizeCTAPlacementRequest(BaseModel):
    """Optimize CTA timing and placement in videos."""
    ad_account_id: str = Field(..., description="Meta ad account ID")
    video_ids: List[str] = Field(..., description="List of video ad IDs with CTAs")
    time_range: Dict[str, str] = Field(..., description="Time range for CTA analysis")
    cta_positions: List[str] = Field(
        default=["start", "middle", "end", "overlay"],
        description="CTA positions to analyze"
    )


# ========================================
# Phase 5: Finance & CFO Integration (8 schemas)
# ========================================

class ModelPLImpactRequest(BaseModel):
    """Model P&L impact of advertising spend."""
    ad_account_id: str = Field(..., description="Meta ad account ID")
    time_range: Dict[str, str] = Field(..., description="Time range for P&L analysis")
    avg_order_value: float = Field(..., description="Average order value")
    cogs_percentage: float = Field(..., description="Cost of goods sold as percentage")
    overhead_percentage: float = Field(default=15.0, description="Overhead allocation percentage")
    customer_ltv: float = Field(..., description="Customer lifetime value")
    purchase_frequency_per_year: float = Field(default=2.0, description="Purchase frequency per year")


class ForecastBudgetNeedsRequest(BaseModel):
    """Forecast future budget needs with confidence intervals."""
    ad_account_id: str = Field(..., description="Meta ad account ID")
    forecast_months: int = Field(default=6, description="Months to forecast")
    growth_target_percentage: float = Field(..., description="Target growth percentage")
    confidence_level: float = Field(default=0.95, description="Confidence level (0.90, 0.95, 0.99)")
    include_seasonality: bool = Field(default=True, description="Include seasonal patterns")


class CalculateAdvancedROIRequest(BaseModel):
    """Calculate advanced ROI with CAC/LTV integration."""
    ad_account_id: str = Field(..., description="Meta ad account ID")
    time_range: Dict[str, str] = Field(..., description="Time range for ROI calculation")
    customer_ltv: float = Field(..., description="Customer lifetime value")
    retention_rate: float = Field(..., description="Customer retention rate (0-1)")
    discount_rate: float = Field(default=0.10, description="Discount rate for NPV calculation")


class AnalyzeCashFlowImpactRequest(BaseModel):
    """Analyze cash flow impact of advertising spend."""
    ad_account_id: str = Field(..., description="Meta ad account ID")
    time_range: Dict[str, str] = Field(..., description="Time range for cash flow analysis")
    payment_terms_days: int = Field(default=30, description="Customer payment terms in days")
    ad_payment_terms_days: int = Field(default=30, description="Meta ad payment terms in days")
    operating_cash_buffer: float = Field(..., description="Desired operating cash buffer")


class GenerateFinanceReportRequest(BaseModel):
    """Generate CFO-friendly financial report."""
    ad_account_id: str = Field(..., description="Meta ad account ID")
    time_range: Dict[str, str] = Field(..., description="Time range for report")
    report_type: str = Field(
        default="comprehensive",
        description="Report type: comprehensive, executive_summary, variance_analysis"
    )
    include_benchmarks: bool = Field(default=True, description="Include industry benchmarks")
    comparison_period: Optional[Dict[str, str]] = Field(
        default=None,
        description="Comparison period for YoY or MoM analysis"
    )


class CalculatePaybackPeriodRequest(BaseModel):
    """Calculate customer acquisition payback period."""
    ad_account_id: str = Field(..., description="Meta ad account ID")
    time_range: Dict[str, str] = Field(..., description="Time range for payback calculation")
    gross_margin_percentage: float = Field(..., description="Gross margin as percentage")
    avg_monthly_value_per_customer: float = Field(..., description="Average monthly value per customer")


class TrackUnitEconomicsRequest(BaseModel):
    """Track unit economics over time."""
    ad_account_id: str = Field(..., description="Meta ad account ID")
    time_range: Dict[str, str] = Field(..., description="Time range for tracking")
    time_granularity: str = Field(
        default="monthly",
        description="Time granularity: daily, weekly, monthly"
    )
    metrics: List[str] = Field(
        default=["cac", "ltv", "cac_payback", "contribution_margin"],
        description="Unit economics metrics to track"
    )


class AnalyzeBudgetVarianceRequest(BaseModel):
    """Analyze budget vs actual spend variance."""
    ad_account_id: str = Field(..., description="Meta ad account ID")
    time_range: Dict[str, str] = Field(..., description="Time range for variance analysis")
    planned_budget: float = Field(..., description="Planned budget amount")
    variance_threshold_percentage: float = Field(
        default=10.0,
        description="Variance threshold for alerts (%)"
    )
