"""
Dynamic Pricing Utilities for Influencer Marketing

This module provides functions to calculate estimated influencer pricing
based on follower count, engagement rate, and other factors.
"""

import math
from typing import Dict, Tuple, Optional


# Tier order for calculating tier gaps
TIER_ORDER = ["Nano", "Micro", "Mid", "Macro", "Mega"]


def get_tier_from_followers(followers: int) -> str:
    """
    Get tier based purely on follower count (no quality adjustments).

    Args:
        followers: Follower count

    Returns:
        Tier name (Nano, Micro, Mid, Macro, Mega)
    """
    if followers < 10000:
        return "Nano"
    elif followers < 100000:
        return "Micro"
    elif followers < 500000:
        return "Mid"
    elif followers < 1000000:
        return "Macro"
    else:
        return "Mega"


def calculate_estimated_price(
    followers: int,
    engagement_rate: float = 3.0,
    verified: bool = False,
    avg_likes: float = 0,
    avg_comments: float = 0,
    llm_predicted_tier: Optional[str] = None
) -> Dict[str, float]:
    """
    Calculate estimated price per post for an influencer using HYBRID pricing.

    HYBRID APPROACH:
    1. Calculate base price using follower-count-based tier (predictable)
    2. Apply quality multipliers (engagement, verification, etc.)
    3. If LLM predicted a different tier, apply tier adjustment multiplier
    4. Result: Consistent pricing that reflects both quantity AND quality

    Uses a tiered pricing model with multipliers for different follower ranges:
    - Nano (<10K): $1 per 1K followers
    - Micro (10K-100K): $10 per 1K followers
    - Mid (100K-500K): $20 per 1K followers
    - Macro (500K-1M): $50 per 1K followers
    - Mega (1M-10M): $25 per 1K followers
    - Super Mega (>10M): $10 per 1K followers (celebrity pricing)

    Args:
        followers: Follower count
        engagement_rate: Engagement rate percentage (default: 3.0%)
        verified: Whether the account is verified
        avg_likes: Average likes per post (used for quality assessment)
        avg_comments: Average comments per post (comments are more valuable than likes)
        llm_predicted_tier: Optional tier predicted by LLM based on quality metrics

    Returns:
        {
            'estimated_min': float,
            'estimated_max': float,
            'estimated_avg': float,
            'tier': str,  # Follower-based tier
            'llm_tier': str,  # LLM-predicted tier (if provided)
            'tier_adjustment': str,  # 'upgraded', 'downgraded', or 'same'
            'tier_multiplier': float,  # Multiplier applied due to tier difference
            'price_per_1k_followers': float,
            'quality_multiplier': float
        }
    """
    # Follower-based tier (for comparison/fallback)
    if followers < 10000:
        calculated_tier = "Nano"
    elif followers < 100000:
        calculated_tier = "Micro"
    elif followers < 500000:
        calculated_tier = "Mid"
    elif followers < 1000000:
        calculated_tier = "Macro"
    else:
        calculated_tier = "Mega"

    # QUALITY-DRIVEN APPROACH:
    # Use LLM-predicted tier as the primary indicator, but clamp it to avoid massive errors
    # (e.g., a 10M follower account should never be priced as Nano, even if ML says so)
    calculated_tier_idx = TIER_ORDER.index(calculated_tier)
    
    if llm_predicted_tier in TIER_ORDER:
        llm_tier_idx = TIER_ORDER.index(llm_predicted_tier)
        # Clamp to +/- 1 tier from calculated to prevent extreme mispricing
        effective_tier_idx = max(calculated_tier_idx - 1, min(calculated_tier_idx + 1, llm_tier_idx))
        effective_tier = TIER_ORDER[effective_tier_idx]
    else:
        effective_tier = calculated_tier

    # HYBRID BALANCED PRICING (Followers + Quality Tiers)
    # The tier is determined by quality (LLM + Clamp), but scales with followers.
    
    if effective_tier == "Nano":
        base_price_per_1k = 1.0
    elif effective_tier == "Micro":
        base_price_per_1k = 10.0
    elif effective_tier == "Mid":
        base_price_per_1k = 20.0
    elif effective_tier == "Macro":
        base_price_per_1k = 50.0
    else:  # Mega
        base_price_per_1k = 25.0
        # Celebrity discount for extremely high reach
        if followers > 10000000:
            base_price_per_1k = 10.0
    
    # Base price scales with FOLLOWERS, but at a RATE determined by QUALITY (tier)
    followers_in_thousands = followers / 1000
    base_price = base_price_per_1k * followers_in_thousands
    
    # Engagement rate multiplier (higher engagement = higher price)
    engagement_multiplier = 1.0
    if engagement_rate >= 5.0:
        engagement_multiplier = 1.5
    elif engagement_rate >= 3.0:
        engagement_multiplier = 1.2
    elif engagement_rate >= 1.0:
        engagement_multiplier = 1.0
    else:
        engagement_multiplier = 0.7

    # Verification multiplier
    verification_multiplier = 1.3 if verified else 1.0

    # Quality multiplier based on actual engagement numbers
    # This rewards influencers with high absolute engagement, not just high percentages
    quality_multiplier = 1.0

    if avg_likes > 0 or avg_comments > 0:
        # Calculate expected engagement based on followers and engagement rate
        expected_engagement = followers * (engagement_rate / 100)
        actual_engagement = avg_likes + (avg_comments * 3)  # Comments are 3x more valuable

        # Quality ratio: actual vs expected
        if expected_engagement > 0:
            quality_ratio = actual_engagement / expected_engagement

            # Apply quality multiplier
            if quality_ratio >= 1.5:
                quality_multiplier = 1.3  # Exceptional quality (viral content)
            elif quality_ratio >= 1.2:
                quality_multiplier = 1.15  # High quality
            elif quality_ratio >= 0.8:
                quality_multiplier = 1.0  # Normal quality
            elif quality_ratio >= 0.5:
                quality_multiplier = 0.9  # Below average
            else:
                quality_multiplier = 0.75  # Poor quality (possible bot followers)

    # Bot detection multiplier (stronger penalties for fake followers)
    bot_detection_multiplier = 1.0

    if avg_likes > 0 and avg_comments > 0:
        # Calculate engagement-to-follower ratio (absolute numbers)
        engagement_to_follower_ratio = (avg_likes + avg_comments) / followers

        # Red flags for bot followers:
        # 1. Very low absolute engagement despite high follower count
        # 2. Suspiciously low comment-to-like ratio
        # 3. Engagement rate doesn't match actual engagement numbers

        comment_to_like_ratio = avg_comments / avg_likes

        # Severe bot indicators
        if comment_to_like_ratio < 0.003:  # <0.3% (bots rarely comment)
            bot_detection_multiplier = 0.5  # 50% penalty - likely bot followers
        elif comment_to_like_ratio < 0.005:  # <0.5%
            bot_detection_multiplier = 0.7  # 30% penalty - suspicious
        elif comment_to_like_ratio < 0.01:  # <1%
            bot_detection_multiplier = 0.85  # 15% penalty - below average

        # Additional check: Absolute engagement is too low for follower count
        # Even with low engagement rate, there should be SOME engagement
        if followers > 10000:  # Only check for accounts with 10K+ followers
            min_expected_engagement = followers * 0.005  # At least 0.5% engagement
            if (avg_likes + avg_comments) < min_expected_engagement:
                # Likely bought followers - very harsh penalty
                bot_detection_multiplier *= 0.6  # Additional 40% penalty

    # Comment quality bonus (comments indicate deeper engagement)
    comment_quality_bonus = 1.0
    if avg_likes > 0 and avg_comments > 0:
        comment_to_like_ratio = avg_comments / avg_likes

        # Typical comment-to-like ratio is 1-3%
        # Higher ratio = more engaged audience (real followers)
        if comment_to_like_ratio >= 0.05:  # 5%+ is exceptional
            comment_quality_bonus = 1.25  # Increased from 1.2
        elif comment_to_like_ratio >= 0.03:  # 3-5% is very good
            comment_quality_bonus = 1.15  # Increased from 1.1
        elif comment_to_like_ratio >= 0.01:  # 1-3% is normal
            comment_quality_bonus = 1.0
        # Note: Low ratios already penalized in bot_detection_multiplier

    # Calculate final price with quality multipliers
    base_estimated_price = (
        base_price *
        engagement_multiplier *
        verification_multiplier *
        quality_multiplier *
        bot_detection_multiplier *
        comment_quality_bonus
    )

    # FINAL PRICE
    estimated_price = base_estimated_price

    # Add variance (±30%)
    estimated_min = estimated_price * 0.7
    estimated_max = estimated_price * 1.3
    estimated_avg = estimated_price

    return {
        'estimated_min': round(estimated_min, 2),
        'estimated_max': round(estimated_max, 2),
        'estimated_avg': round(estimated_avg, 2),
        'tier': calculated_tier,  # Follower-based tier (benchmark)
        'llm_tier': effective_tier,  # Final quality-based tier
        'is_quality_adjusted': effective_tier != calculated_tier,
        'base_price_per_1k': round(base_price_per_1k, 2),
        'quality_multiplier': round(quality_multiplier * bot_detection_multiplier * comment_quality_bonus, 2)
    }


def get_tier_from_budget(budget_min: float, budget_max: float) -> Tuple[str, Dict[str, float]]:
    """
    Determine appropriate influencer tier(s) based on budget range.
    
    Returns the primary tier and probability distribution across all tiers.
    
    Args:
        budget_min: Minimum budget
        budget_max: Maximum budget
        
    Returns:
        (primary_tier, probability_distribution)
        
    Example:
        >>> get_tier_from_budget(200, 400)
        ('Micro', {'Nano': 0.2, 'Micro': 0.7, 'Mid': 0.1, 'Macro': 0.0, 'Mega': 0.0})
    """
    avg_budget = (budget_min + budget_max) / 2
    
    # Define tier boundaries with overlap zones
    tier_ranges = {
        'Nano': (10, 100),
        'Micro': (100, 1000),
        'Mid': (1000, 5000),
        'Macro': (5000, 25000),
        'Mega': (25000, float('inf'))
    }
    
    # Calculate probability for each tier based on budget overlap
    probabilities = {}
    total_overlap = 0
    
    for tier, (tier_min, tier_max) in tier_ranges.items():
        # Calculate overlap between budget range and tier range
        overlap_min = max(budget_min, tier_min)
        overlap_max = min(budget_max, tier_max)
        
        if overlap_max > overlap_min:
            # There's overlap - calculate how much
            overlap_amount = overlap_max - overlap_min
            total_overlap += overlap_amount
            probabilities[tier] = overlap_amount
        else:
            probabilities[tier] = 0
    
    # Normalize probabilities
    if total_overlap > 0:
        for tier in probabilities:
            probabilities[tier] = round(probabilities[tier] / total_overlap, 2)
    else:
        # No overlap - assign to closest tier
        if avg_budget <= 100:
            probabilities = {'Nano': 1.0, 'Micro': 0.0, 'Mid': 0.0, 'Macro': 0.0, 'Mega': 0.0}
        elif avg_budget <= 1000:
            probabilities = {'Nano': 0.0, 'Micro': 1.0, 'Mid': 0.0, 'Macro': 0.0, 'Mega': 0.0}
        elif avg_budget <= 5000:
            probabilities = {'Nano': 0.0, 'Micro': 0.0, 'Mid': 1.0, 'Macro': 0.0, 'Mega': 0.0}
        elif avg_budget <= 25000:
            probabilities = {'Nano': 0.0, 'Micro': 0.0, 'Mid': 0.0, 'Macro': 1.0, 'Mega': 0.0}
        else:
            probabilities = {'Nano': 0.0, 'Micro': 0.0, 'Mid': 0.0, 'Macro': 0.0, 'Mega': 1.0}
    
    # Get primary tier (highest probability)
    primary_tier = max(probabilities.items(), key=lambda x: x[1])[0]
    
    return primary_tier, probabilities

