"""
Viral Pattern Detector - Analyze viral videos to find repeatable patterns.
Also includes Script Generator and Viral Probability Score.
"""

import re
from datetime import datetime, timedelta
from collections import Counter

from sqlalchemy.orm import Session
from backend.models.video import Video


def analyze_viral_patterns(db: Session, platform: str = "", days: int = 7, min_score: int = 70) -> dict:
    """Analyze top viral videos and extract patterns."""
    since = datetime.utcnow() - timedelta(days=days)
    q = db.query(Video).filter(Video.viral_score >= min_score, Video.collected_at >= since)
    if platform:
        q = q.filter(Video.platform == platform)
    videos = q.order_by(Video.viral_score.desc()).limit(100).all()

    if not videos:
        return {"patterns": [], "total_analyzed": 0}

    # Analyze patterns
    durations = [v.duration for v in videos if v.duration]
    hashtag_counter = Counter()
    hook_words = Counter()
    formats = Counter()
    hours_posted = Counter()

    for v in videos:
        # Hashtags
        if v.hashtags:
            tags = v.hashtags if isinstance(v.hashtags, list) else v.hashtags.split(",")
            for t in tags:
                t = t.strip().strip("#").lower()
                if t:
                    hashtag_counter[t] += 1

        # Hook analysis (first ~50 chars of title/description)
        text = (v.title or v.description or "")[:80].lower()
        if text:
            # Detect hook type
            if any(w in text for w in ["como", "how to", "tutorial", "aprenda"]):
                formats["tutorial"] += 1
            elif any(w in text for w in ["pov", "quando", "when"]):
                formats["pov/storytelling"] += 1
            elif any(w in text for w in ["voce nao", "you won't", "ninguem", "nobody"]):
                formats["curiosity_gap"] += 1
            elif any(w in text for w in ["antes e depois", "before and after", "transformacao"]):
                formats["transformation"] += 1
            elif any(w in text for w in ["reacao", "react", "testei", "tested"]):
                formats["reaction/review"] += 1
            elif any(w in text for w in ["dica", "tip", "hack", "truque"]):
                formats["tips/hacks"] += 1
            elif any(w in text for w in ["top", "melhor", "best", "ranking"]):
                formats["ranking/list"] += 1
            else:
                formats["other"] += 1

            # First 3 words (hook words)
            words = text.split()[:5]
            for w in words:
                w = re.sub(r"[^\w]", "", w)
                if len(w) > 2:
                    hook_words[w] += 1

        # Hour posted
        if v.published_at:
            hours_posted[v.published_at.hour] += 1

    # Duration analysis
    avg_duration = sum(durations) / len(durations) if durations else 0
    duration_buckets = {"0-15s": 0, "15-30s": 0, "30-60s": 0, "60-180s": 0, "180s+": 0}
    for d in durations:
        if d <= 15: duration_buckets["0-15s"] += 1
        elif d <= 30: duration_buckets["15-30s"] += 1
        elif d <= 60: duration_buckets["30-60s"] += 1
        elif d <= 180: duration_buckets["60-180s"] += 1
        else: duration_buckets["180s+"] += 1

    # Engagement analysis
    avg_views = sum(v.views or 0 for v in videos) / len(videos)
    avg_likes = sum(v.likes or 0 for v in videos) / len(videos)
    avg_comments = sum(v.comments or 0 for v in videos) / len(videos)
    avg_engagement = ((avg_likes + avg_comments) / max(1, avg_views)) * 100

    # Best hours
    best_hours = sorted(hours_posted.items(), key=lambda x: x[1], reverse=True)[:5]

    patterns = {
        "duration": {
            "average_seconds": round(avg_duration),
            "ideal_range": _ideal_duration(duration_buckets),
            "distribution": duration_buckets,
        },
        "formats": {
            "top_formats": sorted(formats.items(), key=lambda x: x[1], reverse=True)[:5],
            "total": sum(formats.values()),
        },
        "hashtags": {
            "top_20": hashtag_counter.most_common(20),
            "total_unique": len(hashtag_counter),
        },
        "hooks": {
            "top_words": hook_words.most_common(15),
        },
        "timing": {
            "best_hours": best_hours,
            "best_hour": best_hours[0][0] if best_hours else 12,
        },
        "engagement": {
            "avg_views": round(avg_views),
            "avg_likes": round(avg_likes),
            "avg_comments": round(avg_comments),
            "avg_engagement_rate": round(avg_engagement, 2),
        },
    }

    return {
        "patterns": patterns,
        "total_analyzed": len(videos),
        "platform": platform or "all",
        "period_days": days,
    }


def generate_script(db: Session, topic: str, platform: str = "tiktok", style: str = "tutorial") -> dict:
    """Generate a video script based on viral patterns and topic."""
    patterns = analyze_viral_patterns(db, platform, days=14)
    p = patterns.get("patterns", {})

    ideal_duration = p.get("duration", {}).get("ideal_range", "15-30 segundos")
    top_hashtags = [h[0] for h in p.get("hashtags", {}).get("top_20", [])][:10]
    best_hour = p.get("timing", {}).get("best_hour", 19)
    top_formats = p.get("formats", {}).get("top_formats", [])

    # Hook templates by style
    hooks = {
        "tutorial": [
            f"Como fazer {topic} em 3 passos simples",
            f"O segredo que ninguem te conta sobre {topic}",
            f"Tutorial rapido de {topic} que funciona de verdade",
        ],
        "pov": [
            f"POV: voce descobriu {topic}",
            f"Quando voce finalmente entende {topic}",
            f"A realidade de quem trabalha com {topic}",
        ],
        "curiosity": [
            f"Voce nao vai acreditar o que acontece com {topic}",
            f"Ninguem fala sobre isso: {topic}",
            f"O lado oculto de {topic} que ninguem mostra",
        ],
        "tips": [
            f"3 dicas de {topic} que vao mudar tudo",
            f"Hack de {topic} que eu queria ter sabido antes",
            f"Se voce faz {topic}, PARE e veja isso",
        ],
        "review": [
            f"Testei {topic} por 30 dias e o resultado...",
            f"Vale a pena? Minha opiniao honesta sobre {topic}",
            f"Comparando os melhores: {topic}",
        ],
    }

    hook_list = hooks.get(style, hooks["tutorial"])

    script = {
        "topic": topic,
        "platform": platform,
        "style": style,
        "ideal_duration": ideal_duration,
        "best_posting_time": f"{best_hour}:00",
        "hooks": hook_list,
        "structure": {
            "hook": f"(0-3s) {hook_list[0]}",
            "problem": f"(3-8s) Apresente o problema/dor relacionado a {topic}",
            "solution": f"(8-20s) Mostre a solucao/conteudo principal",
            "proof": f"(20-25s) Resultado/prova social",
            "cta": f"(25-30s) Salva esse video! Segue pra mais dicas de {topic}",
        },
        "hashtags": [f"#{t}" for t in top_hashtags[:8]] + [f"#{topic.replace(' ', '')}", "#viral", "#fyp"],
        "caption_template": f"{hook_list[0]} 👇\n\nVoce sabia disso? Comenta aqui! 💬\n\n" + " ".join([f"#{t}" for t in top_hashtags[:5]]),
        "tips": [
            "Use texto na tela nos primeiros 2 segundos",
            "Mantenha o ritmo rapido - nao deixe cenas paradas",
            f"Duracao ideal: {ideal_duration}",
            "Responda comentarios para aumentar alcance",
            "Poste em horarios de pico do seu publico",
        ],
    }

    return script


def calculate_viral_probability(db: Session, title: str, hashtags: list[str], platform: str = "tiktok",
                                 duration: int = 0, hour: int = -1) -> dict:
    """Calculate probability of a video going viral based on patterns."""
    patterns = analyze_viral_patterns(db, platform, days=14)
    p = patterns.get("patterns", {})

    score = 50  # Base score
    factors = []

    # 1. Duration check
    dur_dist = p.get("duration", {}).get("distribution", {})
    if dur_dist and duration > 0:
        best_bucket = max(dur_dist.items(), key=lambda x: x[1])[0] if dur_dist else "15-30s"
        if duration <= 15 and "0-15s" in best_bucket:
            score += 10; factors.append({"factor": "Duracao ideal", "impact": "+10", "detail": "Duracao curta funciona bem"})
        elif 15 < duration <= 30:
            score += 8; factors.append({"factor": "Duracao boa", "impact": "+8", "detail": "15-30s e o sweet spot"})
        elif 30 < duration <= 60:
            score += 5; factors.append({"factor": "Duracao ok", "impact": "+5", "detail": "30-60s pode funcionar"})
        elif duration > 180:
            score -= 5; factors.append({"factor": "Video longo", "impact": "-5", "detail": "Videos longos tem menor alcance"})

    # 2. Hashtag overlap
    top_tags = {h[0].lower() for h in p.get("hashtags", {}).get("top_20", [])}
    user_tags = {t.strip("#").lower() for t in hashtags}
    overlap = len(top_tags & user_tags)
    if overlap >= 3:
        score += 15; factors.append({"factor": "Hashtags virais", "impact": "+15", "detail": f"{overlap} hashtags em comum com virais"})
    elif overlap >= 1:
        score += 8; factors.append({"factor": "Hashtags parciais", "impact": "+8", "detail": f"{overlap} hashtag(s) viral"})
    else:
        score -= 5; factors.append({"factor": "Hashtags fracas", "impact": "-5", "detail": "Nenhuma hashtag trending"})

    # 3. Hook analysis
    title_lower = title.lower()
    hook_patterns = [
        (["como", "how to", "tutorial"], "Tutorial hook", 8),
        (["voce nao", "ninguem", "segredo"], "Curiosity gap", 12),
        (["pov", "quando"], "POV/Story", 7),
        (["dica", "hack", "truque"], "Tips hook", 9),
        (["top", "melhor", "ranking"], "Ranking", 6),
    ]
    for words, name, pts in hook_patterns:
        if any(w in title_lower for w in words):
            score += pts; factors.append({"factor": name, "impact": f"+{pts}", "detail": f"Hook tipo '{name}' tem bom desempenho"})
            break

    # 4. Title length
    if 20 <= len(title) <= 100:
        score += 5; factors.append({"factor": "Titulo bom", "impact": "+5", "detail": "Comprimento ideal do titulo"})

    # 5. Best hour
    if hour >= 0:
        best_hours = [h[0] for h in p.get("timing", {}).get("best_hours", [])]
        if hour in best_hours[:3]:
            score += 10; factors.append({"factor": "Horario ideal", "impact": "+10", "detail": f"{hour}h e um dos melhores horarios"})
        elif hour in best_hours:
            score += 5; factors.append({"factor": "Bom horario", "impact": "+5", "detail": f"{hour}h e um horario razoavel"})

    # Clamp score
    score = max(5, min(100, score))

    # Classification
    if score >= 80:
        verdict = "ALTA probabilidade de viralizar! 🔥"
    elif score >= 60:
        verdict = "BOA chance de viralizar 📈"
    elif score >= 40:
        verdict = "Chance moderada - considere ajustar 🤔"
    else:
        verdict = "Baixa probabilidade - recomendo melhorias ⚠️"

    return {
        "score": score,
        "verdict": verdict,
        "factors": factors,
        "suggestions": _get_suggestions(score, factors, p),
        "based_on": patterns.get("total_analyzed", 0),
    }


def _ideal_duration(buckets: dict) -> str:
    if not buckets:
        return "15-30 segundos"
    best = max(buckets.items(), key=lambda x: x[1])
    return best[0].replace("s", " segundos")


def _get_suggestions(score: int, factors: list, patterns: dict) -> list[str]:
    suggestions = []
    factor_names = [f["factor"] for f in factors]

    if "Hashtags fracas" in factor_names:
        top = patterns.get("hashtags", {}).get("top_20", [])[:5]
        if top:
            suggestions.append(f"Use hashtags virais: {', '.join('#' + h[0] for h in top)}")

    if "Video longo" in factor_names:
        suggestions.append("Tente manter o video entre 15-30 segundos para maior alcance")

    if score < 60:
        suggestions.append("Use um hook forte nos primeiros 3 segundos (pergunta, fato chocante, ou 'voce sabia...')")
        suggestions.append("Adicione texto na tela para reter atencao")

    if "Horario ideal" not in factor_names and "Bom horario" not in factor_names:
        best_hour = patterns.get("timing", {}).get("best_hour", 19)
        suggestions.append(f"Poste as {best_hour}:00 para melhor alcance")

    suggestions.append("Responda os primeiros comentarios para aumentar o engajamento")

    return suggestions
