"""
Video Analyzer - Advanced AI-powered video analysis for ViralScan.

Features:
- Hook strength scoring (0-100)
- Script analysis (hook/problem/solution/CTA breakdown)
- Engagement velocity analysis
- Shareability score
- Completion rate prediction
- Monetization potential
- Emerging video detection
- Blue ocean scoring
- Comment sentiment analysis
- AI improvement suggestions
"""

import json
import logging
import math
import re
from collections import defaultdict
from datetime import datetime, timedelta, timezone

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

from backend.models.video import Video
from backend.services import local_ai

logger = logging.getLogger(__name__)

# ── Hook Strength Scoring ──────────────────────────────────────

# Patterns that make strong hooks (weighted)
HOOK_PATTERNS = {
    # Curiosity gap - strongest hooks
    "curiosity": {
        "weight": 15,
        "patterns_pt": [
            r"voce nao vai acreditar",
            r"ninguem te (conta|fala|mostra)",
            r"o (segredo|truque|hack) (que|para)",
            r"por que ninguem",
            r"o que acontece (quando|se)",
            r"descubra (como|por que)",
            r"isso (mudou|vai mudar)",
        ],
        "patterns_en": [
            r"you won'?t believe",
            r"nobody (tells|shows|knows)",
            r"the (secret|trick|hack)",
            r"what happens (when|if)",
            r"find out (how|why)",
            r"this (changed|will change)",
        ],
    },
    # Numbers/lists - very clickable
    "numbers": {
        "weight": 12,
        "patterns_pt": [
            r"^\d+ (dicas|formas|maneiras|passos|razoes|erros|motivos)",
            r"top \d+",
            r"em \d+ (passos|minutos|segundos)",
        ],
        "patterns_en": [
            r"^\d+ (tips|ways|steps|reasons|mistakes)",
            r"top \d+",
            r"in \d+ (steps|minutes|seconds)",
        ],
    },
    # Direct question
    "question": {
        "weight": 10,
        "patterns_pt": [
            r"^(voce|vc) (sabia|ja viu|conhece)",
            r"^(como|por que|quando|onde|qual|o que)\b",
            r"\?$",
        ],
        "patterns_en": [
            r"^(did you know|have you seen|do you know)",
            r"^(how|why|when|where|what|which)\b",
        ],
    },
    # Urgency/FOMO
    "urgency": {
        "weight": 11,
        "patterns_pt": [
            r"(pare|para) (tudo|de|agora)",
            r"(urgente|atencao|cuidado|alerta)",
            r"(antes que|enquanto)",
            r"(ultimo|ultima) chance",
        ],
        "patterns_en": [
            r"stop (everything|scrolling|what)",
            r"(urgent|attention|warning|alert)",
            r"before (it|they|you)",
            r"last chance",
        ],
    },
    # Tutorial/how-to
    "tutorial": {
        "weight": 8,
        "patterns_pt": [
            r"como (fazer|criar|usar|montar|construir)",
            r"tutorial",
            r"passo a passo",
            r"aprenda (a|como)",
        ],
        "patterns_en": [
            r"how to (make|create|use|build)",
            r"tutorial",
            r"step by step",
            r"learn (to|how)",
        ],
    },
    # POV/Story
    "story": {
        "weight": 9,
        "patterns_pt": [
            r"^pov",
            r"quando (voce|eu|a gente)",
            r"a historia de",
            r"(minha|sua) (primeira|ultima) vez",
        ],
        "patterns_en": [
            r"^pov",
            r"when (you|i|we)",
            r"the story of",
            r"(my|your) (first|last) time",
        ],
    },
    # Transformation/result
    "transformation": {
        "weight": 10,
        "patterns_pt": [
            r"antes (e|vs|x) depois",
            r"transformacao",
            r"resultado (final|incrivel|impressionante)",
            r"(de|do|da) .* (para|pra|em) .*",
        ],
        "patterns_en": [
            r"before (and|vs|x) after",
            r"transformation",
            r"(final|amazing|incredible) result",
            r"from .* to .*",
        ],
    },
}

# CTA patterns
CTA_PATTERNS = {
    "follow": [r"segu[ei]", r"follow", r"me siga"],
    "like": [r"curt[aie]", r"like", r"da um like"],
    "comment": [r"coment[ae]", r"comment", r"comenta aqui"],
    "share": [r"compartilh[ae]", r"share", r"envia (pro|pra|para)"],
    "save": [r"salv[ae]", r"save", r"salva (esse|este|pra)"],
    "link": [r"link (na|no) bio", r"link in bio"],
}


def calculate_hook_score(title: str, description: str = "") -> dict:
    """
    Calculate hook strength score (0-100) based on text patterns.
    Also identifies hook type and gives improvement tips.
    """
    text = f"{title} {description}".lower().strip()
    if not text:
        return {"score": 0, "hook_type": "none", "patterns_found": [], "tips": []}

    score = 20  # Base score for having any text
    patterns_found = []
    hook_types_found = []

    for hook_type, config in HOOK_PATTERNS.items():
        weight = config["weight"]
        for pattern in config["patterns_pt"] + config["patterns_en"]:
            if re.search(pattern, text):
                score += weight
                patterns_found.append(hook_type)
                if hook_type not in hook_types_found:
                    hook_types_found.append(hook_type)
                break  # Only count each hook_type once

    # Bonus: short, punchy title (optimal 5-10 words)
    word_count = len(title.split())
    if 3 <= word_count <= 10:
        score += 5
    elif word_count > 20:
        score -= 5

    # Bonus: emoji usage (grabs attention)
    emoji_count = len(re.findall(r"[\U0001F600-\U0001F9FF\U00002700-\U000027BF]", title))
    if 1 <= emoji_count <= 3:
        score += 3

    # Bonus: caps usage (attention)
    caps_words = len(re.findall(r"\b[A-Z]{2,}\b", title))
    if 1 <= caps_words <= 3:
        score += 3
    elif caps_words > 5:
        score -= 3  # Too spammy

    # CTA detection
    ctas_found = []
    for cta_type, patterns in CTA_PATTERNS.items():
        for p in patterns:
            if re.search(p, text):
                ctas_found.append(cta_type)
                score += 2
                break

    score = max(0, min(100, score))

    # Determine primary hook type
    primary_type = hook_types_found[0] if hook_types_found else "generic"

    # Tips
    tips = _hook_tips(score, hook_types_found, ctas_found, word_count)

    return {
        "score": score,
        "hook_type": primary_type,
        "hook_types": hook_types_found,
        "ctas_found": ctas_found,
        "patterns_found": patterns_found,
        "word_count": word_count,
        "tips": tips,
    }


def _hook_tips(score: int, hooks: list, ctas: list, word_count: int) -> list[str]:
    tips = []
    if score < 40:
        tips.append("Use um gancho forte nos primeiros 3 segundos (pergunta, numero, ou afirmacao chocante)")
    if "curiosity" not in hooks:
        tips.append("Adicione curiosidade: 'Voce nao vai acreditar...' ou 'Ninguem te conta...'")
    if "numbers" not in hooks:
        tips.append("Use numeros: '3 dicas', 'em 5 passos', 'Top 10'")
    if not ctas:
        tips.append("Adicione um CTA: 'Salva esse video!', 'Comenta aqui!', 'Segue pra mais!'")
    if word_count > 15:
        tips.append("Encurte o titulo - titulos com 5-10 palavras performam melhor")
    if "save" not in ctas:
        tips.append("Peca para salvar - saves aumentam o alcance no algoritmo")
    return tips[:4]


# ── Shareability Score ─────────────────────────────────────────

def calculate_shareability(video_data: dict) -> dict:
    """
    Shareability Score (0-100): predicts how likely people will share.
    Based on STEPPS framework (Jonah Berger):
    - Social Currency (makes sharer look good)
    - Triggers (top of mind)
    - Emotion (high arousal emotions)
    - Public (visible/imitable)
    - Practical Value (useful)
    - Stories (narrative arc)
    """
    views = max(video_data.get("views", 0), 1)
    shares = video_data.get("shares", 0)
    comments = video_data.get("comments", 0)
    likes = video_data.get("likes", 0)
    title = (video_data.get("title", "") + " " + video_data.get("description", "")).lower()
    hashtags = video_data.get("hashtags", [])
    duration = _normalize_duration(video_data.get("duration", 0), video_data.get("platform", ""))

    score = 0
    factors = []

    # 1. Actual share ratio (strongest signal)
    share_ratio = shares / views if views > 0 else 0
    if share_ratio > 0.03:
        score += 30
        factors.append("Share ratio excepcional (>3%)")
    elif share_ratio > 0.01:
        score += 20
        factors.append("Share ratio alto (>1%)")
    elif share_ratio > 0.005:
        score += 10
        factors.append("Share ratio bom (>0.5%)")

    # 2. Practical value (tutorials, tips, hacks)
    practical_words = ["como", "how to", "dica", "tip", "hack", "tutorial", "passo", "step",
                       "aprenda", "learn", "facil", "easy", "rapido", "quick"]
    if any(w in title for w in practical_words):
        score += 15
        factors.append("Conteudo pratico/util (alto valor de compartilhamento)")

    # 3. Emotion triggers
    emotion_words = ["incrivel", "amazing", "chocante", "shocking", "triste", "sad",
                     "hilario", "funny", "medo", "fear", "raiva", "anger",
                     "emocionante", "inspiring", "fofo", "cute"]
    emotion_hits = sum(1 for w in emotion_words if w in title)
    if emotion_hits >= 2:
        score += 15
        factors.append("Alto gatilho emocional")
    elif emotion_hits >= 1:
        score += 8
        factors.append("Gatilho emocional presente")

    # 4. Social currency (makes sharer look smart/cool)
    social_words = ["segredo", "secret", "ninguem sabe", "nobody knows",
                    "exclusivo", "exclusive", "primeiro", "first"]
    if any(w in title for w in social_words):
        score += 10
        factors.append("Social currency (faz quem compartilha parecer bem informado)")

    # 5. Short format (easier to share)
    if 0 < duration <= 30:
        score += 10
        factors.append("Formato curto (facil de compartilhar)")
    elif 0 < duration <= 60:
        score += 5
        factors.append("Duracao razoavel para compartilhamento")

    # 6. Comment-to-like ratio (engagement depth)
    if likes > 0:
        comment_ratio = comments / likes
        if comment_ratio > 0.1:
            score += 10
            factors.append("Alto engajamento em comentarios (gera discussao)")
        elif comment_ratio > 0.05:
            score += 5

    # 7. Trending hashtags boost
    trending_tags = {"viral", "fyp", "foryou", "trending", "explore", "parati"}
    if set(h.lower().strip("#") for h in (hashtags or [])) & trending_tags:
        score += 5
        factors.append("Hashtags trending ajudam distribuicao")

    score = max(0, min(100, score))

    return {
        "score": score,
        "factors": factors,
        "share_ratio": round(share_ratio * 100, 3),
        "label": _shareability_label(score),
    }


def _shareability_label(score: int) -> str:
    if score >= 80:
        return "Super Compartilhavel"
    if score >= 60:
        return "Muito Compartilhavel"
    if score >= 40:
        return "Compartilhavel"
    if score >= 20:
        return "Pouco Compartilhavel"
    return "Baixo Potencial"


# ── Engagement Velocity ────────────────────────────────────────

def calculate_engagement_velocity(video_data: dict) -> dict:
    """
    Measures how fast engagement is growing.
    High velocity = video is being actively pushed by algorithm.
    """
    views = max(video_data.get("views", 0), 1)
    likes = video_data.get("likes", 0)
    comments = video_data.get("comments", 0)
    shares = video_data.get("shares", 0)
    published_at = video_data.get("published_at")

    hours = _hours_since(published_at)
    total_engagement = likes + comments + shares

    # Engagement per hour
    eng_per_hour = total_engagement / max(hours, 0.5)

    # Views per hour
    views_per_hour = views / max(hours, 0.5)

    # Engagement acceleration (higher for newer videos with lots of engagement)
    freshness_bonus = 1.0
    if hours < 6:
        freshness_bonus = 2.0
    elif hours < 12:
        freshness_bonus = 1.5
    elif hours < 24:
        freshness_bonus = 1.2

    velocity_raw = eng_per_hour * freshness_bonus

    # Normalize to 0-100
    # Reference: 1000 eng/hr = great, 100 = good, 10 = ok
    velocity_score = min(100, math.log10(max(velocity_raw, 1)) / math.log10(10000) * 100)

    # Status
    if velocity_score >= 80:
        status = "exploding"
        label = "Explodindo"
    elif velocity_score >= 60:
        status = "accelerating"
        label = "Acelerando"
    elif velocity_score >= 40:
        status = "growing"
        label = "Crescendo"
    elif velocity_score >= 20:
        status = "stable"
        label = "Estavel"
    else:
        status = "slow"
        label = "Lento"

    return {
        "velocity_score": round(velocity_score, 1),
        "engagement_per_hour": round(eng_per_hour, 1),
        "views_per_hour": round(views_per_hour, 1),
        "hours_since_published": round(hours, 1),
        "status": status,
        "label": label,
        "freshness_bonus": freshness_bonus,
    }


# ── Completion Rate Predictor ──────────────────────────────────

def predict_completion_rate(video_data: dict) -> dict:
    """
    Predict video completion rate based on known patterns.
    Uses duration, engagement signals, and content type.
    """
    duration = _normalize_duration(video_data.get("duration", 0), video_data.get("platform", ""))
    views = max(video_data.get("views", 0), 1)
    likes = video_data.get("likes", 0)
    comments = video_data.get("comments", 0)
    shares = video_data.get("shares", 0)
    title = (video_data.get("title", "") or "").lower()

    # Base rate by duration (industry averages)
    if duration <= 0:
        base_rate = 50
    elif duration <= 7:
        base_rate = 85  # Very short = high completion
    elif duration <= 15:
        base_rate = 75
    elif duration <= 30:
        base_rate = 60
    elif duration <= 60:
        base_rate = 45
    elif duration <= 180:
        base_rate = 30
    else:
        base_rate = 20

    # Adjust by engagement signals
    engagement_rate = (likes + comments + shares) / views
    if engagement_rate > 0.10:
        base_rate += 10  # High engagement = people watched
    elif engagement_rate > 0.05:
        base_rate += 5
    elif engagement_rate < 0.01:
        base_rate -= 5

    # Adjust by content type (some types retain better)
    if any(w in title for w in ["tutorial", "como", "how to", "passo"]):
        base_rate += 5  # Tutorials retain well
    if any(w in title for w in ["satisfying", "satisfatorio", "asmr"]):
        base_rate += 8  # Satisfying content retains very well
    if any(w in title for w in ["antes e depois", "before after", "transformacao"]):
        base_rate += 7  # Transformation = watch till end

    predicted = max(10, min(95, base_rate))

    if predicted >= 70:
        label = "Excelente retencao"
    elif predicted >= 50:
        label = "Boa retencao"
    elif predicted >= 35:
        label = "Retencao media"
    else:
        label = "Retencao baixa"

    return {
        "predicted_rate": predicted,
        "label": label,
        "duration": duration,
        "factors": {
            "duration_impact": "positivo" if duration <= 30 else "neutro" if duration <= 60 else "negativo",
            "engagement_signal": "forte" if engagement_rate > 0.05 else "medio" if engagement_rate > 0.02 else "fraco",
        },
    }


# ── Monetization Potential ─────────────────────────────────────

def calculate_monetization_potential(video_data: dict) -> dict:
    """
    Estimate monetization potential (0-100).
    Based on niche RPM, engagement, and commerce signals.
    """
    views = video_data.get("views", 0)
    platform = video_data.get("platform", "")
    shop_product_url = video_data.get("shop_product_url", "")
    hashtags = [h.lower() for h in (video_data.get("hashtags", []) or [])]
    title = (video_data.get("title", "") or "").lower()
    engagement_rate = video_data.get("engagement_rate", 0)

    score = 0
    factors = []

    # 1. Commerce signals
    if shop_product_url:
        score += 25
        factors.append("Produto vinculado (TikTok Shop)")
    commerce_tags = {"tiktokshop", "shopee", "amazon", "afiliado", "affiliate",
                     "desconto", "promocao", "compre", "link"}
    if set(h.strip("#") for h in hashtags) & commerce_tags:
        score += 15
        factors.append("Tags de comercio/afiliado")

    # 2. High RPM niches
    high_rpm = {"financ", "invest", "crypto", "tech", "saude", "health",
                "fitness", "negocio", "business", "imobili", "real estate"}
    medium_rpm = {"beleza", "beauty", "moda", "fashion", "receita", "cooking",
                  "decoracao", "casa", "home", "educacao", "education"}
    if any(k in title or any(k in h for h in hashtags) for k in high_rpm):
        score += 20
        factors.append("Nicho de alto RPM")
    elif any(k in title or any(k in h for h in hashtags) for k in medium_rpm):
        score += 10
        factors.append("Nicho de RPM medio")

    # 3. View potential
    if views >= 1_000_000:
        score += 20
        factors.append("Milhoes de views (alto potencial de receita)")
    elif views >= 100_000:
        score += 12
        factors.append("100K+ views")
    elif views >= 10_000:
        score += 5

    # 4. Engagement (higher = better monetization)
    eng = engagement_rate if isinstance(engagement_rate, (int, float)) else 0
    if eng > 5:
        score += 10
        factors.append("Engagement alto (>5%)")
    elif eng > 2:
        score += 5

    # 5. Platform bonus
    if platform == "youtube":
        score += 5  # YouTube has better monetization

    score = max(0, min(100, score))

    return {
        "score": score,
        "factors": factors,
        "label": _monetization_label(score),
        "has_commerce": bool(shop_product_url),
    }


def _monetization_label(score: int) -> str:
    if score >= 75:
        return "Excelente"
    if score >= 50:
        return "Bom"
    if score >= 25:
        return "Moderado"
    return "Baixo"


# ── Blue Ocean Score ───────────────────────────────────────────

def calculate_blue_ocean(video_data: dict, db: Session) -> dict:
    """
    Blue Ocean Score: high demand (views) + low competition.
    Finds niches that are underserved but have viral potential.
    """
    title = (video_data.get("title", "") or "").lower()
    hashtags = [h.lower().strip("#") for h in (video_data.get("hashtags", []) or [])]
    views = video_data.get("views", 0)
    outlier_ratio = video_data.get("outlier_ratio", 1)
    is_small_creator = video_data.get("is_small_creator", False)

    # Calculate demand (views + outlier = high demand)
    demand = 0
    if views >= 1_000_000:
        demand = 100
    elif views >= 500_000:
        demand = 80
    elif views >= 100_000:
        demand = 60
    elif views >= 50_000:
        demand = 40
    elif views >= 10_000:
        demand = 20

    if outlier_ratio >= 10:
        demand = min(100, demand + 20)

    # Estimate competition by counting similar videos in DB
    competition = 50  # Default medium
    if hashtags:
        from sqlalchemy import func
        # Count videos with same hashtags (rough competition proxy)
        similar_count = 0
        for tag in hashtags[:3]:
            count = db.query(func.count(Video.id)).filter(
                Video.hashtags.contains(tag)
            ).scalar() or 0
            similar_count += count

        if similar_count <= 5:
            competition = 10  # Very low competition
        elif similar_count <= 20:
            competition = 30
        elif similar_count <= 50:
            competition = 50
        elif similar_count <= 100:
            competition = 70
        else:
            competition = 90

    # Small creator success = less competition
    if is_small_creator and outlier_ratio >= 5:
        competition = max(0, competition - 20)

    # Blue ocean = high demand, low competition
    blue_score = (demand * 0.5) + ((100 - competition) * 0.5)
    blue_score = max(0, min(100, blue_score))

    return {
        "score": round(blue_score, 1),
        "demand": demand,
        "competition": competition,
        "label": "Blue Ocean" if blue_score >= 60 else "Oportunidade" if blue_score >= 40 else "Red Ocean",
    }


# ── Emerging Video Detection ───────────────────────────────────

def detect_emerging_videos(db: Session, hours: int = 24, min_velocity: float = 30) -> list[dict]:
    """
    Find videos published < N hours ago with high engagement velocity.
    These are the freshest opportunities to replicate.
    """
    from datetime import timedelta
    cutoff = datetime.now(timezone.utc) - timedelta(hours=hours)

    videos = db.query(Video).filter(
        Video.published_at >= cutoff,
        Video.views >= 10_000,
    ).order_by(Video.views.desc()).limit(200).all()

    emerging = []
    for v in videos:
        vdata = _video_to_dict(v)
        velocity = calculate_engagement_velocity(vdata)
        if velocity["velocity_score"] >= min_velocity:
            emerging.append({
                "video_id": v.id,
                "title": v.title,
                "platform": v.platform,
                "url": v.url,
                "views": v.views,
                "viral_score": v.viral_score,
                "thumbnail_url": v.thumbnail_url,
                "velocity": velocity,
                "hours_ago": velocity["hours_since_published"],
            })

    emerging.sort(key=lambda x: x["velocity"]["velocity_score"], reverse=True)
    return emerging[:50]


# ── AI-Powered Script Analysis ─────────────────────────────────

async def analyze_script_ai(title: str, description: str = "", transcript: str = "") -> dict:
    """
    Use local LLM (Qwen 2.5 3B) to analyze video script structure.
    Identifies: hook, problem, solution, CTA, emotional arc.
    """
    text = transcript or f"{title}\n{description}"
    if not text.strip():
        return {"success": False, "error": "Sem texto para analisar"}

    system = """Voce e um especialista em conteudo viral para redes sociais.
Analise o texto do video e retorne APENAS um JSON valido (sem markdown, sem ```).
Formato exato:
{"hook": "texto do gancho", "problem": "problema apresentado", "solution": "solucao oferecida", "cta": "call to action", "emotional_arc": "emocao predominante", "strengths": ["ponto forte 1", "ponto forte 2"], "weaknesses": ["ponto fraco 1"], "suggestions": ["melhoria 1", "melhoria 2"]}"""

    prompt = f"Analise este conteudo de video viral:\n\n{text[:2000]}"

    response = await local_ai.llm_chat(prompt, system=system, temperature=0.2)
    if not response:
        return {"success": False, "error": "LLM indisponivel"}

    # Parse JSON from response
    try:
        # Try to extract JSON from response
        json_match = re.search(r"\{.*\}", response, re.DOTALL)
        if json_match:
            data = json.loads(json_match.group())
            data["success"] = True
            return data
    except (json.JSONDecodeError, AttributeError):
        pass

    return {"success": True, "raw_analysis": response}


async def suggest_improvements_ai(video_data: dict) -> list[str]:
    """
    Use local LLM to suggest improvements for a video.
    """
    title = video_data.get("title", "")
    views = video_data.get("views", 0)
    likes = video_data.get("likes", 0)
    comments = video_data.get("comments", 0)
    shares = video_data.get("shares", 0)
    duration = video_data.get("duration", 0)
    viral_score = video_data.get("viral_score", 0)
    hashtags = video_data.get("hashtags", [])

    system = "Voce e um consultor de conteudo viral. Responda APENAS com uma lista JSON de strings com 3-5 sugestoes de melhoria praticas e especificas. Sem markdown."

    prompt = f"""Video: {title}
Views: {views:,} | Likes: {likes:,} | Comments: {comments:,} | Shares: {shares:,}
Duracao: {duration}s | Viral Score: {viral_score}
Hashtags: {', '.join(hashtags[:10]) if hashtags else 'nenhuma'}

Liste 3-5 sugestoes praticas para melhorar o desempenho deste video."""

    response = await local_ai.llm_chat(prompt, system=system, temperature=0.4)
    if not response:
        return ["Nao foi possivel gerar sugestoes (LLM indisponivel)"]

    try:
        json_match = re.search(r"\[.*\]", response, re.DOTALL)
        if json_match:
            suggestions = json.loads(json_match.group())
            if isinstance(suggestions, list):
                return suggestions[:5]
    except (json.JSONDecodeError, AttributeError):
        pass

    # Fallback: split by lines
    lines = [l.strip().lstrip("0123456789.-) ") for l in response.split("\n") if l.strip()]
    return lines[:5] if lines else [response[:200]]


# ── AI Hook Scoring (Transcript-based) ────────────────────────

async def analyze_hook_ai(transcript_text: str, title: str = "") -> dict:
    """
    Use local LLM to deeply analyze the hook (first 5-10 seconds) of a video transcript.
    Returns AI-powered score, hook type, reasoning, and improved hook suggestion.
    """
    text = transcript_text or title
    if not text or not text.strip():
        return {"success": False, "error": "Sem texto para analisar hook"}

    # Extract first ~200 chars as the hook portion
    hook_portion = text[:500]

    system = """Voce e um especialista em hooks virais para TikTok/YouTube/Instagram.
Analise o hook (primeiros 5-10 segundos) do video e retorne APENAS um JSON valido (sem markdown, sem ```).
Formato exato:
{"score": 85, "hook_type": "curiosity_gap", "reasoning": "explicacao de por que funciona ou nao", "improved_hook": "versao melhorada do hook", "attention_grab": "forte|medio|fraco", "emotional_trigger": "emocao principal ativada", "cta_implicit": true, "retention_prediction": "alta|media|baixa", "tips": ["dica 1", "dica 2"]}

Hook types possiveis: curiosity_gap, shock_value, question, bold_claim, story_opener, transformation, number_hook, controversy, relatable, tutorial_promise"""

    prompt = f"""Analise o hook deste video viral:

Titulo: {title}
Transcricao (inicio): {hook_portion}

Avalie de 0-100 a forca do hook e sugira melhorias."""

    response = await local_ai.llm_chat(prompt, system=system, temperature=0.2, max_tokens=800)
    if not response:
        return {"success": False, "error": "LLM indisponivel"}

    try:
        json_match = re.search(r"\{.*\}", response, re.DOTALL)
        if json_match:
            data = json.loads(json_match.group())
            data["success"] = True
            data["analyzed_text"] = hook_portion[:200]
            return data
    except (json.JSONDecodeError, AttributeError):
        pass

    return {"success": True, "raw_analysis": response, "score": 50}


# ── Pacing Analysis ────────────────────────────────────────────

def analyze_pacing(video_data: dict) -> dict:
    """
    Analyze video pacing based on duration, engagement signals, and content type.
    Good pacing = high retention. Short + high engagement = fast pacing (good).
    """
    duration = _normalize_duration(video_data.get("duration", 0), video_data.get("platform", ""))
    views = max(video_data.get("views", 0), 1)
    likes = video_data.get("likes", 0)
    comments = video_data.get("comments", 0)
    shares = video_data.get("shares", 0)
    title = (video_data.get("title", "") or "").lower()

    engagement_rate = (likes + comments + shares) / views

    # Pacing score based on engagement density per second
    if duration > 0:
        engagement_per_second = (likes + comments * 3 + shares * 5) / duration
        # Normalize: 100 eng/sec = perfect for short, 10 = good for long
        if duration <= 15:
            pacing_base = min(100, engagement_per_second / 50 * 100)
        elif duration <= 30:
            pacing_base = min(100, engagement_per_second / 30 * 100)
        elif duration <= 60:
            pacing_base = min(100, engagement_per_second / 15 * 100)
        else:
            pacing_base = min(100, engagement_per_second / 5 * 100)
    else:
        pacing_base = 50

    # Content type pacing modifiers
    fast_pacing_signals = ["timelapse", "satisfying", "asmr", "fast", "rapido",
                           "speed", "quick", "hack", "dica"]
    slow_pacing_signals = ["tutorial", "passo a passo", "explicando", "review",
                           "vlog", "story", "historia"]

    pacing_modifier = 0
    detected_style = "balanced"
    if any(w in title for w in fast_pacing_signals):
        pacing_modifier = 10
        detected_style = "fast"
    elif any(w in title for w in slow_pacing_signals):
        pacing_modifier = -5
        detected_style = "methodical"

    # Short videos with high engagement = great pacing
    if duration > 0 and duration <= 30 and engagement_rate > 0.05:
        pacing_modifier += 10

    score = max(0, min(100, pacing_base + pacing_modifier))

    # Ideal duration recommendation
    if score >= 70:
        duration_advice = "Duracao atual esta otima para o engajamento obtido"
    elif duration > 60:
        duration_advice = "Considere encurtar para 15-30s para melhor retencao"
    elif duration <= 7:
        duration_advice = "Video muito curto - 15-30s pode reter melhor"
    else:
        duration_advice = "Aumente o ritmo: cortes rapidos, texto na tela, transicoes"

    # Pattern interrupts recommendation
    if duration > 15:
        interrupts_needed = max(1, duration // 4)
        interrupt_tip = f"Use {interrupts_needed} pattern interrupts (a cada ~4s) para manter atencao"
    else:
        interrupt_tip = "Video curto - mantenha ritmo alto do inicio ao fim"

    return {
        "score": round(score, 1),
        "style": detected_style,
        "duration_advice": duration_advice,
        "interrupt_tip": interrupt_tip,
        "label": "Ritmo excelente" if score >= 70 else "Ritmo bom" if score >= 50 else "Ritmo pode melhorar" if score >= 30 else "Ritmo lento",
    }


# ── Full Video Analysis ────────────────────────────────────────

async def analyze_video_full(video_data: dict, db: Session = None) -> dict:
    """
    Complete analysis of a video. Combines all analyzers.
    Returns comprehensive analysis dict.
    """
    hook = calculate_hook_score(
        video_data.get("title", ""),
        video_data.get("description", ""),
    )
    shareability = calculate_shareability(video_data)
    velocity = calculate_engagement_velocity(video_data)
    completion = predict_completion_rate(video_data)
    monetization = calculate_monetization_potential(video_data)

    pacing = analyze_pacing(video_data)

    result = {
        "hook_score": hook,
        "shareability": shareability,
        "engagement_velocity": velocity,
        "completion_rate": completion,
        "monetization_potential": monetization,
        "pacing": pacing,
    }

    # Blue ocean requires DB
    if db:
        blue_ocean = calculate_blue_ocean(video_data, db)
        result["blue_ocean"] = blue_ocean

    # AI analysis (async)
    try:
        script_analysis = await analyze_script_ai(
            video_data.get("title", ""),
            video_data.get("description", ""),
        )
        result["script_analysis"] = script_analysis
    except Exception as e:
        logger.error(f"AI script analysis error: {e}")
        result["script_analysis"] = {"success": False, "error": str(e)}

    try:
        suggestions = await suggest_improvements_ai(video_data)
        result["ai_suggestions"] = suggestions
    except Exception as e:
        logger.error(f"AI suggestions error: {e}")
        result["ai_suggestions"] = []

    return result


def analyze_comments_sentiment(comments_list: list[str]) -> dict:
    """Analyze sentiment of video comments using VADER."""
    return local_ai.analyze_sentiment_batch(comments_list)


# ── Helpers ────────────────────────────────────────────────────

def _normalize_duration(duration: int, platform: str = "") -> int:
    """Normalize duration to seconds. TikTok stores in milliseconds."""
    if duration <= 0:
        return 0
    # If duration > 1000 and platform is tiktok, it's likely milliseconds
    if duration > 1000 and (platform == "tiktok" or platform == ""):
        return duration // 1000
    return duration


def _hours_since(published_at) -> float:
    if not published_at:
        return 48.0
    now = datetime.now(timezone.utc)
    if isinstance(published_at, str):
        try:
            published_at = datetime.fromisoformat(published_at.replace("Z", "+00:00"))
        except (ValueError, TypeError):
            return 48.0
    if published_at.tzinfo is None:
        published_at = published_at.replace(tzinfo=timezone.utc)
    delta = now - published_at
    return max(delta.total_seconds() / 3600, 0.1)


# ── Save/Share Ratio Analysis ─────────────────────────────────

def calculate_save_share_ratio(video_data: dict) -> dict:
    """
    Analyze save and share ratios - key signals for algorithmic boost.
    High save ratio = evergreen content. High share ratio = viral potential.
    """
    views = max(video_data.get("views", 0), 1)
    likes = video_data.get("likes", 0)
    shares = video_data.get("shares", 0)
    comments = video_data.get("comments", 0)
    # TikTok doesn't expose saves directly, estimate from engagement patterns
    # Save ratio proxy: (likes - comments) / views when likes >> comments
    # High like-to-comment ratio suggests passive engagement (saves)
    estimated_saves = max(0, likes * 0.15)  # Industry avg ~15% of likes are saves

    save_ratio = (estimated_saves / views) * 100
    share_ratio = (shares / views) * 100
    like_ratio = (likes / views) * 100
    comment_ratio = (comments / views) * 100

    # Engagement composition
    total_eng = likes + shares + comments + estimated_saves
    composition = {
        "likes_pct": round((likes / max(total_eng, 1)) * 100, 1),
        "shares_pct": round((shares / max(total_eng, 1)) * 100, 1),
        "comments_pct": round((comments / max(total_eng, 1)) * 100, 1),
        "saves_pct": round((estimated_saves / max(total_eng, 1)) * 100, 1),
    }

    # Algorithm boost signals
    boost_signals = []
    if share_ratio > 1:
        boost_signals.append("Share ratio alto (>1%) - forte sinal de viralidade")
    if save_ratio > 2:
        boost_signals.append("Save ratio alto - conteudo evergreen, algoritmo ama")
    if comment_ratio > 0.5:
        boost_signals.append("Comments alto - gera discussao, boost no alcance")
    if like_ratio > 5:
        boost_signals.append("Like ratio excepcional (>5%)")

    # Algorithmic score (0-100)
    algo_score = min(100, (
        min(30, share_ratio * 15) +
        min(25, save_ratio * 5) +
        min(25, comment_ratio * 10) +
        min(20, like_ratio * 2)
    ))

    return {
        "save_ratio": round(save_ratio, 3),
        "share_ratio": round(share_ratio, 3),
        "like_ratio": round(like_ratio, 3),
        "comment_ratio": round(comment_ratio, 3),
        "estimated_saves": round(estimated_saves),
        "composition": composition,
        "algo_boost_score": round(algo_score, 1),
        "boost_signals": boost_signals,
        "label": "Viral Machine" if algo_score >= 80 else "Alto Potencial" if algo_score >= 60 else "Bom" if algo_score >= 40 else "Medio" if algo_score >= 20 else "Baixo",
    }


# ── Emotional Arc Mapping (IA) ───────────────────────────────

async def map_emotional_arc(title: str, description: str = "") -> dict:
    """
    Map the emotional arc of a video using AI.
    Identifies emotional beats: opening, tension, climax, resolution.
    """
    text = f"{title}\n{description}" if description else title
    if not text.strip():
        return {"success": False, "error": "Sem texto para analisar"}

    system = """Voce e um especialista em storytelling e emocoes em conteudo viral.
Analise o texto e mapeie o arco emocional. Retorne APENAS um JSON valido (sem markdown):
{"opening_emotion": "emocao inicial (ex: curiosidade, choque, humor)",
"tension": "ponto de tensao/conflito",
"climax_emotion": "emocao no climax",
"resolution": "como resolve (satisfacao, surpresa, etc)",
"dominant_emotion": "emocao predominante",
"emotional_intensity": 75,
"arc_type": "tipo (hero_journey, revelation, transformation, humor, educational)",
"engagement_prediction": "como as emocoes afetam engajamento",
"tips": ["dica1", "dica2"]}"""

    prompt = f"Mapeie o arco emocional deste conteudo viral:\n\n{text[:1500]}"

    response = await local_ai.llm_chat(prompt, system=system, temperature=0.3)
    if not response:
        return {"success": False, "error": "LLM indisponivel"}

    try:
        json_match = re.search(r"\{.*\}", response, re.DOTALL)
        if json_match:
            data = json.loads(json_match.group())
            data["success"] = True
            return data
    except (json.JSONDecodeError, AttributeError):
        pass

    return {"success": True, "raw_analysis": response}


# ── Geographic Scan ──────────────────────────────────────────

def scan_by_region(db: Session, region: str = "", language: str = "",
                   days: int = 7, limit: int = 50) -> dict:
    """
    Filter and analyze viral videos by geographic region/language.
    """
    since = datetime.utcnow() - timedelta(days=days)

    query = db.query(Video).filter(
        Video.collected_at >= since,
        Video.viral_score >= 20,
    )

    if region:
        query = query.filter(Video.region == region.upper())
    if language:
        query = query.filter(
            or_(
                Video.language == language.lower(),
                Video.audio_language.ilike(f"{language}%"),
            )
        )

    videos = query.order_by(desc(Video.viral_score)).limit(limit).all()

    # Aggregate by region
    region_stats = defaultdict(lambda: {"count": 0, "total_score": 0, "total_views": 0})
    lang_stats = defaultdict(lambda: {"count": 0, "total_score": 0})

    for v in videos:
        r = v.region or "unknown"
        l = v.language or v.audio_language or "unknown"
        region_stats[r]["count"] += 1
        region_stats[r]["total_score"] += v.viral_score or 0
        region_stats[r]["total_views"] += v.views or 0
        lang_stats[l]["count"] += 1
        lang_stats[l]["total_score"] += v.viral_score or 0

    regions = []
    for r, data in sorted(region_stats.items(), key=lambda x: x[1]["count"], reverse=True):
        regions.append({
            "region": r,
            "video_count": data["count"],
            "avg_score": round(data["total_score"] / data["count"], 1),
            "total_views": data["total_views"],
        })

    languages = []
    for l, data in sorted(lang_stats.items(), key=lambda x: x[1]["count"], reverse=True):
        languages.append({
            "language": l,
            "video_count": data["count"],
            "avg_score": round(data["total_score"] / data["count"], 1),
        })

    video_list = [{
        "id": v.id,
        "title": v.title[:80] if v.title else "",
        "platform": v.platform,
        "region": v.region or "",
        "language": v.language or v.audio_language or "",
        "views": v.views,
        "viral_score": v.viral_score,
        "url": v.url,
        "thumbnail_url": v.thumbnail_url,
    } for v in videos]

    return {
        "filter": {"region": region, "language": language},
        "videos": video_list,
        "total": len(video_list),
        "regions": regions,
        "languages": languages,
    }


def _video_to_dict(v: Video) -> dict:
    return {
        "id": v.id,
        "title": v.title,
        "description": v.description,
        "platform": v.platform,
        "url": v.url,
        "views": v.views or 0,
        "likes": v.likes or 0,
        "comments": v.comments or 0,
        "shares": v.shares or 0,
        "duration": v.duration or 0,
        "hashtags": v.hashtags or [],
        "published_at": v.published_at,
        "viral_score": v.viral_score or 0,
        "engagement_rate": v.engagement_rate or 0,
        "outlier_ratio": v.outlier_ratio or 0,
        "creator_followers": v.creator_followers or 0,
        "is_small_creator": v.is_small_creator,
        "shop_product_url": v.shop_product_url or "",
        "thumbnail_url": v.thumbnail_url or "",
        "replicability_score": v.replicability_score or 0,
    }
