"""
CreatorCRM - Gestao de Influencers & Parcerias.
Features: discovery, CRM, outreach pipeline, fake follower detection,
influence scoring, media kit generator, revenue dashboard, campaign ROI.
"""

import json
import logging
import math
import uuid
from datetime import datetime, timedelta
from collections import Counter, defaultdict

from sqlalchemy.orm import Session
from sqlalchemy import func, desc, or_

from backend.models.video import Video
from backend.models.creator import Creator

logger = logging.getLogger(__name__)

# In-memory CRM storage
_contacts = {}
_campaigns = {}
_outreach = {}


# ── Influencer Discovery ──────────────────────────────────────

def discover_influencers(db: Session, niche: str = "", platform: str = "",
                          min_followers: int = 1000, max_followers: int = 0,
                          min_engagement: float = 0, sort_by: str = "influence_score",
                          limit: int = 20) -> dict:
    """
    Discover influencers by niche, platform, follower range, engagement rate.
    Returns scored and ranked influencer list.
    """
    query = db.query(Creator)

    if platform:
        query = query.filter(Creator.platform == platform)
    if min_followers > 0:
        query = query.filter(Creator.followers >= min_followers)
    if max_followers > 0:
        query = query.filter(Creator.followers <= max_followers)

    creators = query.limit(500).all()

    if niche:
        niche_lower = niche.lower()
        creators = [c for c in creators if niche_lower in (c.username or "").lower()
                     or niche_lower in (c.display_name or "").lower()]

    results = []
    for c in creators:
        followers = c.followers or 0
        avg_views = c.avg_views or 0
        avg_engagement = c.avg_engagement or 0
        video_count = c.total_videos or 0

        # Engagement rate from stored avg_engagement
        engagement_rate = avg_engagement

        if min_engagement > 0 and engagement_rate < min_engagement:
            continue

        # Influence score (0-100)
        influence = calculate_influence_score(
            followers=followers,
            avg_views=avg_views,
            engagement_rate=engagement_rate,
            video_count=video_count,
        )

        # Size tier
        tier = c.size_tier or _get_tier(followers)

        results.append({
            "id": c.id,
            "username": c.username,
            "display_name": c.display_name or "",
            "platform": c.platform,
            "followers": followers,
            "avg_views": avg_views,
            "video_count": video_count,
            "engagement_rate": round(engagement_rate, 2),
            "influence_score": influence,
            "tier": tier,
            "profile_url": c.profile_url or "",
            "avatar_url": c.avatar_url or "",
        })

    # Sort
    sort_key = {
        "influence_score": lambda x: x["influence_score"],
        "followers": lambda x: x["followers"],
        "engagement": lambda x: x["engagement_rate"],
        "views": lambda x: x["avg_views"],
    }.get(sort_by, lambda x: x["influence_score"])

    results.sort(key=sort_key, reverse=True)

    return {
        "influencers": results[:limit],
        "total_found": len(results),
        "filters": {"niche": niche, "platform": platform, "min_followers": min_followers},
    }


def calculate_influence_score(followers: int = 0, avg_views: int = 0,
                               engagement_rate: float = 0, video_count: int = 0,
                               **kwargs) -> int:
    """
    Calculate influence score 0-100.
    Factors: reach(25%), engagement(30%), consistency(15%), growth_potential(15%), authority(15%).
    """
    # Reach (25%) - based on followers with log scale
    reach = min(math.log10(max(followers, 1)) / 7 * 100, 100)

    # Engagement (30%) - engagement rate vs benchmarks
    if followers < 10000:
        eng_benchmark = 5.0
    elif followers < 100000:
        eng_benchmark = 3.0
    elif followers < 1000000:
        eng_benchmark = 2.0
    else:
        eng_benchmark = 1.0
    engagement = min((engagement_rate / max(eng_benchmark, 0.1)) * 60, 100)

    # Consistency (15%) - video count indicates consistency
    consistency = min(video_count / 50 * 100, 100)

    # Growth potential (15%) - views vs followers ratio
    views_ratio = avg_views / max(followers, 1) * 100
    growth = min(views_ratio * 2, 100)

    # Authority (15%) - based on engagement rate depth
    authority = min(engagement_rate * 10, 100)

    total = (
        reach * 0.25 +
        engagement * 0.30 +
        consistency * 0.15 +
        growth * 0.15 +
        authority * 0.15
    )

    return min(round(total), 100)


def detect_fake_followers(db: Session, creator_id: int) -> dict:
    """
    Detect potential fake followers using engagement anomalies.
    Checks: engagement ratio, views/follower ratio, comment quality patterns.
    """
    creator = db.query(Creator).filter(Creator.id == creator_id).first()
    if not creator:
        return {"error": "Creator nao encontrado"}

    followers = creator.followers or 0
    avg_views = creator.avg_views or 0
    avg_engagement = creator.avg_engagement or 0

    red_flags = []
    authenticity_score = 100

    # Views/follower ratio too low
    vf_ratio = avg_views / max(followers, 1) * 100
    if vf_ratio < 1 and followers > 10000:
        red_flags.append({"flag": "Views muito baixos vs followers", "severity": "high",
                          "detail": f"Apenas {vf_ratio:.1f}% dos followers veem o conteudo"})
        authenticity_score -= 25

    # Engagement too low for tier
    eng_rate = avg_engagement
    if followers > 50000 and eng_rate < 0.5:
        red_flags.append({"flag": "Engagement rate suspeitamente baixo", "severity": "high",
                          "detail": f"Engagement de {eng_rate:.2f}% para {followers:,} followers"})
        authenticity_score -= 20

    # Views vs median views anomaly
    median_views = creator.median_views or 0
    if avg_views > 0 and median_views > 0 and avg_views > median_views * 5:
        red_flags.append({"flag": "Distorcao entre media e mediana de views", "severity": "medium",
                          "detail": f"Media: {avg_views:,.0f} vs Mediana: {median_views:,.0f}"})
        authenticity_score -= 15

    # Very high followers but few videos
    video_count = creator.total_videos or 0
    if followers > 100000 and video_count < 10:
        red_flags.append({"flag": "Poucos videos para muitos followers", "severity": "medium",
                          "detail": f"{followers:,} followers com apenas {video_count} videos"})
        authenticity_score -= 15

    # Sudden follower jumps (would need historical data)
    authenticity_score = max(authenticity_score, 0)

    label = ("Autentico" if authenticity_score >= 80
             else "Suspeito" if authenticity_score >= 50
             else "Provavelmente Fake")

    return {
        "creator_id": creator_id,
        "username": creator.username,
        "followers": followers,
        "authenticity_score": authenticity_score,
        "label": label,
        "red_flags": red_flags,
        "red_flag_count": len(red_flags),
        "recommendation": "Seguro para parceria" if authenticity_score >= 80
                          else "Investigue mais antes de fechar" if authenticity_score >= 50
                          else "Evite parceria - alto risco de followers falsos",
    }


# ── Media Kit Generator ──────────────────────────────────────

async def generate_media_kit(db: Session, creator_id: int) -> dict:
    """
    Auto-generate a media kit for a creator.
    Includes: bio, stats, audience demographics, rate card, top content.
    """
    from backend.services.local_ai import llm_chat

    creator = db.query(Creator).filter(Creator.id == creator_id).first()
    if not creator:
        return {"error": "Creator nao encontrado"}

    followers = creator.followers or 0
    avg_views = creator.avg_views or 0
    eng_rate = creator.avg_engagement or 0
    video_count = creator.total_videos or 0

    # Get top videos
    videos = (
        db.query(Video)
        .filter(Video.creator_id == creator.id)
        .order_by(desc(Video.views))
        .limit(5)
        .all()
    )

    top_videos = [{"title": (v.title or "")[:60], "views": v.views or 0, "likes": v.likes or 0} for v in videos]

    # Sponsorship rate estimation (Brazilian market)
    tier = creator.size_tier or _get_tier(followers)
    rate_card = _estimate_rates(followers, eng_rate, tier)

    # AI bio enhancement
    try:
        system = "Voce e um especialista em marketing de influencia. Escreva em portugues, maximo 100 palavras."
        prompt = f"Crie uma bio profissional para o media kit do criador @{creator.username} ({creator.platform}). Followers: {followers:,}. Engagement: {eng_rate:.1f}%."
        ai_bio = await llm_chat(prompt, system=system, temperature=0.4, max_tokens=300)
    except Exception:
        ai_bio = f"Criador de conteudo @{creator.username} na plataforma {creator.platform} com {followers:,} seguidores."

    return {
        "creator": {
            "username": creator.username,
            "platform": creator.platform,
            "display_name": creator.display_name or "",
            "tier": tier,
            "bio": ai_bio,
        },
        "stats": {
            "followers": followers,
            "avg_views": avg_views,
            "engagement_rate": round(eng_rate, 2),
            "video_count": video_count,
        },
        "top_content": top_videos,
        "rate_card": rate_card,
        "influence_score": calculate_influence_score(
            followers, avg_views, eng_rate, video_count
        ),
        "generated_at": datetime.utcnow().isoformat(),
    }


# ── CRM Contacts & Pipeline ──────────────────────────────────

def add_contact(creator_id: int, name: str = "", email: str = "",
                notes: str = "", tags: list = None, status: str = "lead") -> dict:
    """Add a creator as a CRM contact."""
    contact_id = str(uuid.uuid4())[:8]
    _contacts[contact_id] = {
        "id": contact_id,
        "creator_id": creator_id,
        "name": name,
        "email": email,
        "notes": notes,
        "tags": tags or [],
        "status": status,  # lead, contacted, negotiating, active, inactive
        "created_at": datetime.utcnow().isoformat(),
        "updated_at": datetime.utcnow().isoformat(),
        "interactions": [],
    }
    return _contacts[contact_id]


def update_contact(contact_id: str, **kwargs) -> dict:
    """Update a CRM contact."""
    if contact_id not in _contacts:
        return {"error": "Contato nao encontrado"}
    for k, v in kwargs.items():
        if k in _contacts[contact_id] and k != "id":
            _contacts[contact_id][k] = v
    _contacts[contact_id]["updated_at"] = datetime.utcnow().isoformat()
    return _contacts[contact_id]


def list_contacts(status: str = "", tag: str = "", limit: int = 50) -> list:
    """List CRM contacts with filters."""
    contacts = list(_contacts.values())
    if status:
        contacts = [c for c in contacts if c["status"] == status]
    if tag:
        contacts = [c for c in contacts if tag in c.get("tags", [])]
    contacts.sort(key=lambda x: x["updated_at"], reverse=True)
    return contacts[:limit]


def get_contact(contact_id: str) -> dict:
    """Get a single contact."""
    return _contacts.get(contact_id, {"error": "Contato nao encontrado"})


def delete_contact(contact_id: str) -> bool:
    """Delete a contact."""
    return _contacts.pop(contact_id, None) is not None


def add_interaction(contact_id: str, interaction_type: str, content: str = "") -> dict:
    """Add interaction to contact history. Types: email, dm, call, meeting, note."""
    if contact_id not in _contacts:
        return {"error": "Contato nao encontrado"}
    interaction = {
        "type": interaction_type,
        "content": content,
        "date": datetime.utcnow().isoformat(),
    }
    _contacts[contact_id]["interactions"].append(interaction)
    _contacts[contact_id]["updated_at"] = datetime.utcnow().isoformat()
    return interaction


# ── Outreach Pipeline ─────────────────────────────────────────

async def generate_outreach_message(creator_username: str, brand_name: str = "",
                                      campaign_type: str = "review",
                                      budget: str = "", niche: str = "") -> dict:
    """Generate a personalized outreach message using AI."""
    from backend.services.local_ai import llm_chat

    campaign_descriptions = {
        "review": "review honesto de produto",
        "sponsored": "post patrocinado",
        "affiliate": "programa de afiliados",
        "ugc": "conteudo gerado pelo usuario (UGC)",
        "ambassador": "embaixador da marca",
        "collab": "colaboracao de conteudo",
    }

    campaign_desc = campaign_descriptions.get(campaign_type, campaign_type)

    system = "Voce e um especialista em outreach para influenciadores. Escreva em portugues, tom profissional mas amigavel. Maximo 150 palavras."
    prompt = f"""Crie uma mensagem de outreach para o criador @{creator_username}.
Marca: {brand_name or 'nossa marca'}
Tipo de campanha: {campaign_desc}
Orcamento: {budget or 'a combinar'}
Nicho: {niche or 'geral'}

A mensagem deve: ser personalizada, mostrar que conhece o trabalho do criador, apresentar a proposta claramente, ter CTA."""

    message = await llm_chat(prompt, system=system, temperature=0.4, max_tokens=500)

    return {
        "creator": creator_username,
        "campaign_type": campaign_type,
        "message": message or "Nao foi possivel gerar a mensagem.",
        "subject_line": f"Parceria {brand_name or ''} x @{creator_username}".strip(),
        "follow_up_days": 3,
    }


# ── Campaigns ─────────────────────────────────────────────────

def create_campaign(name: str, campaign_type: str = "review", budget: float = 0,
                     target_creators: list = None, start_date: str = "",
                     end_date: str = "", goals: dict = None) -> dict:
    """Create a marketing campaign."""
    campaign_id = str(uuid.uuid4())[:8]
    _campaigns[campaign_id] = {
        "id": campaign_id,
        "name": name,
        "type": campaign_type,
        "budget": budget,
        "budget_spent": 0,
        "target_creators": target_creators or [],
        "start_date": start_date or datetime.utcnow().isoformat(),
        "end_date": end_date,
        "goals": goals or {"views": 0, "engagement": 0, "conversions": 0},
        "status": "draft",
        "results": {"total_views": 0, "total_engagement": 0, "total_conversions": 0},
        "created_at": datetime.utcnow().isoformat(),
    }
    return _campaigns[campaign_id]


def list_campaigns(status: str = "") -> list:
    """List all campaigns."""
    campaigns = list(_campaigns.values())
    if status:
        campaigns = [c for c in campaigns if c["status"] == status]
    campaigns.sort(key=lambda x: x["created_at"], reverse=True)
    return campaigns


def get_campaign(campaign_id: str) -> dict:
    """Get campaign details."""
    return _campaigns.get(campaign_id, {"error": "Campanha nao encontrada"})


def update_campaign(campaign_id: str, **kwargs) -> dict:
    """Update campaign."""
    if campaign_id not in _campaigns:
        return {"error": "Campanha nao encontrada"}
    for k, v in kwargs.items():
        if k in _campaigns[campaign_id] and k != "id":
            _campaigns[campaign_id][k] = v
    return _campaigns[campaign_id]


def calculate_campaign_roi(campaign_id: str) -> dict:
    """Calculate ROI for a campaign."""
    campaign = _campaigns.get(campaign_id)
    if not campaign:
        return {"error": "Campanha nao encontrada"}

    budget = campaign["budget"] or 1
    results = campaign["results"]

    # CPV (Cost Per View)
    cpv = budget / max(results["total_views"], 1)
    # CPE (Cost Per Engagement)
    cpe = budget / max(results["total_engagement"], 1)
    # CPA (Cost Per Acquisition/Conversion)
    cpa = budget / max(results["total_conversions"], 1)

    # Estimated value generated (R$0.01 per view + R$0.10 per engagement)
    estimated_value = results["total_views"] * 0.01 + results["total_engagement"] * 0.10
    roi = ((estimated_value - budget) / max(budget, 1)) * 100

    return {
        "campaign_id": campaign_id,
        "campaign_name": campaign["name"],
        "budget": budget,
        "budget_spent": campaign["budget_spent"],
        "results": results,
        "metrics": {
            "cpv": round(cpv, 4),
            "cpe": round(cpe, 4),
            "cpa": round(cpa, 2),
            "roi_percent": round(roi, 1),
            "estimated_value": round(estimated_value, 2),
        },
        "label": "Excelente" if roi > 200 else "Bom" if roi > 100 else "Aceitavel" if roi > 0 else "Negativo",
    }


# ── Revenue Dashboard ─────────────────────────────────────────

def get_creator_revenue_dashboard(db: Session, creator_id: int = 0,
                                    days: int = 30) -> dict:
    """
    Multi-source revenue dashboard for a creator.
    Sources: AdSense (est), Shop commissions, Affiliates, Sponsorships.
    """
    since = datetime.utcnow() - timedelta(days=days)

    # Get creator videos
    query = db.query(Video).filter(Video.collected_at >= since)
    if creator_id:
        query = query.filter(Video.creator_id == creator_id)
    videos = query.order_by(desc(Video.views)).limit(100).all()

    if not videos:
        return {"creator_id": creator_id, "total_estimated": 0, "days": days,
                "revenue": {"ad_revenue": 0, "shop_commissions": 0, "affiliate_estimated": 0, "total_estimated": 0},
                "video_count": 0}

    total_views = sum(v.views or 0 for v in videos)
    total_likes = sum(v.likes or 0 for v in videos)

    # AdSense / Creator Fund estimation by platform
    platform_rpms = {"tiktok": 0.5, "youtube": 4.0, "instagram": 1.0}
    ad_revenue = 0
    for v in videos:
        rpm = platform_rpms.get(v.platform, 1.0)
        ad_revenue += (v.views or 0) / 1000 * rpm

    # Shop commission estimation
    shop_videos = [v for v in videos if v.with_shop_entry]
    shop_revenue = len(shop_videos) * 15

    # Affiliate estimation
    affiliate_revenue = total_likes * 0.005 * 50

    # Sponsorship estimation based on followers
    creator = db.query(Creator).filter(Creator.id == creator_id).first() if creator_id else None
    followers = creator.followers if creator else 0
    sponsorship_est = _estimate_rates(followers, 0, _get_tier(followers))

    total = ad_revenue + shop_revenue + affiliate_revenue

    return {
        "creator_id": creator_id,
        "days": days,
        "video_count": len(videos),
        "total_views": total_views,
        "revenue": {
            "ad_revenue": round(ad_revenue, 2),
            "shop_commissions": round(shop_revenue, 2),
            "affiliate_estimated": round(affiliate_revenue, 2),
            "total_estimated": round(total, 2),
        },
        "monthly_projection": round(total * (30 / max(days, 1)), 2),
        "sponsorship_rates": sponsorship_est,
        "per_video_avg": round(total / max(len(videos), 1), 2),
    }


# ── Sponsorship Rate Calculator ──────────────────────────────

def calculate_sponsorship_rate(followers: int, engagement_rate: float = 0,
                                platform: str = "tiktok", niche: str = "geral") -> dict:
    """
    Calculate recommended sponsorship rates based on metrics.
    Brazilian market rates 2026.
    """
    tier = _get_tier(followers)
    rates = _estimate_rates(followers, engagement_rate, tier)

    # Niche premium
    niche_premiums = {
        "financas": 1.5, "tech": 1.3, "beleza": 1.2, "saude": 1.3,
        "fitness": 1.1, "moda": 1.2, "educacao": 1.1, "games": 1.0,
    }
    premium = niche_premiums.get(niche.lower(), 1.0)

    for key in rates:
        if isinstance(rates[key], (int, float)):
            rates[key] = round(rates[key] * premium, 2)

    rates["niche_premium"] = premium
    rates["tier"] = tier
    rates["platform"] = platform

    return rates


# ── CRM Stats ─────────────────────────────────────────────────

def get_crm_stats() -> dict:
    """Overall CRM statistics."""
    contacts = list(_contacts.values())
    campaigns = list(_campaigns.values())

    status_counts = Counter(c["status"] for c in contacts)
    campaign_status = Counter(c["status"] for c in campaigns)

    total_budget = sum(c["budget"] for c in campaigns)
    total_spent = sum(c["budget_spent"] for c in campaigns)

    return {
        "contacts": {
            "total": len(contacts),
            "by_status": dict(status_counts),
        },
        "campaigns": {
            "total": len(campaigns),
            "by_status": dict(campaign_status),
            "total_budget": round(total_budget, 2),
            "total_spent": round(total_spent, 2),
        },
        "interactions": sum(len(c.get("interactions", [])) for c in contacts),
    }


# ── Helper Functions ──────────────────────────────────────────

def _get_tier(followers: int) -> str:
    """Get influencer tier based on follower count."""
    if followers >= 1000000:
        return "mega"
    elif followers >= 500000:
        return "macro"
    elif followers >= 100000:
        return "mid"
    elif followers >= 10000:
        return "micro"
    elif followers >= 1000:
        return "nano"
    return "starter"


def _estimate_rates(followers: int, engagement_rate: float, tier: str) -> dict:
    """Estimate sponsorship rates in BRL."""
    base_rates = {
        "starter": {"post": 50, "story": 25, "video": 100, "live": 150},
        "nano": {"post": 200, "story": 100, "video": 500, "live": 400},
        "micro": {"post": 800, "story": 400, "video": 2000, "live": 1500},
        "mid": {"post": 3000, "story": 1500, "video": 8000, "live": 5000},
        "macro": {"post": 10000, "story": 5000, "video": 25000, "live": 15000},
        "mega": {"post": 30000, "story": 15000, "video": 80000, "live": 50000},
    }

    rates = base_rates.get(tier, base_rates["nano"]).copy()

    # Engagement premium: above average engagement gets +20-50%
    if engagement_rate > 5:
        multiplier = 1.5
    elif engagement_rate > 3:
        multiplier = 1.3
    elif engagement_rate > 1.5:
        multiplier = 1.1
    else:
        multiplier = 1.0

    for key in rates:
        rates[key] = round(rates[key] * multiplier)

    rates["engagement_premium"] = multiplier
    return rates
