"""
Data Populator - Extract maximum information from collected videos
to populate all platform sections WITHOUT spending API credits.

Populates: Creators, Trends, Hashtags, Trend Lifecycle, Sounds (from raw data)
"""

import logging
from datetime import datetime, timedelta
from collections import Counter

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

from backend.models.video import Video
from backend.models.creator import Creator
from backend.models.trend import Trend
from backend.models.competitor import TrendLifecycle, SoundTracker
from backend.services.viral_detector import ViralDetector

logger = logging.getLogger("viral_social.populator")
detector = ViralDetector()


def populate_all(db: Session) -> dict:
    """Run all population tasks. Returns summary."""
    results = {}
    results["creators"] = populate_creators(db)
    results["trends"] = populate_trends(db)
    results["lifecycle"] = populate_trend_lifecycle(db)
    results["sounds"] = populate_sounds_from_videos(db)
    return results


def populate_creators(db: Session) -> dict:
    """Update all creator stats from their videos."""
    creators = db.query(Creator).all()
    updated = 0

    for c in creators:
        videos = db.query(Video).filter(Video.creator_id == c.id).all()
        if not videos:
            continue

        total_views = sum(v.views for v in videos)
        total_engagement = sum(v.engagement_rate for v in videos)
        n = len(videos)

        # Update followers from videos if creator has 0
        if (c.followers or 0) == 0:
            max_followers = max((v.creator_followers or 0) for v in videos)
            if max_followers > 0:
                c.followers = max_followers
                c.size_tier = ViralDetector.get_size_tier(max_followers)

        c.total_videos = n
        c.avg_views = total_views / n
        c.avg_engagement = total_engagement / n
        c.updated_at = datetime.utcnow()
        updated += 1

    db.commit()
    logger.info(f"[Populator] Updated {updated} creators")
    return {"updated": updated, "total": len(creators)}


def populate_trends(db: Session) -> dict:
    """Extract hashtag trends from videos and save to Trend table."""
    videos = db.query(Video).filter(Video.collected_at >= datetime.utcnow() - timedelta(days=30)).all()

    hashtag_stats = {}
    for video in videos:
        tags = video.hashtags or []
        if isinstance(tags, str):
            tags = [t.strip() for t in tags.split(",") if t.strip()]

        for tag in tags:
            tag = tag.lower().strip("#")
            if not tag or len(tag) < 2:
                continue
            if tag not in hashtag_stats:
                hashtag_stats[tag] = {
                    "count": 0, "total_views": 0, "scores": [],
                    "platforms": set(), "videos": [],
                }
            h = hashtag_stats[tag]
            h["count"] += 1
            h["total_views"] += video.views
            h["scores"].append(video.viral_score)
            h["platforms"].add(video.platform)
            h["videos"].append(video.id)

    saved = 0
    for tag, stats in hashtag_stats.items():
        if stats["count"] < 2:
            continue

        avg_score = sum(stats["scores"]) / len(stats["scores"]) if stats["scores"] else 0
        platforms = list(stats["platforms"])

        existing = db.query(Trend).filter_by(trend_type="hashtag", name=tag).first()
        if existing:
            existing.volume = stats["total_views"]
            existing.video_count = stats["count"]
            existing.growth_rate = round(avg_score, 1)
            existing.last_updated = datetime.utcnow()
        else:
            db.add(Trend(
                platform=platforms[0] if len(platforms) == 1 else "multi",
                trend_type="hashtag",
                name=tag,
                volume=stats["total_views"],
                video_count=stats["count"],
                growth_rate=round(avg_score, 1),
            ))
        saved += 1

    db.commit()
    logger.info(f"[Populator] Saved {saved} hashtag trends")
    return {"saved": saved, "total_hashtags": len(hashtag_stats)}


def populate_trend_lifecycle(db: Session) -> dict:
    """Create trend lifecycle entries from video keywords/hashtags."""
    videos = db.query(Video).filter(
        Video.collected_at >= datetime.utcnow() - timedelta(days=30)
    ).all()

    # Collect hashtag stats with time info
    hashtag_data = {}
    for v in videos:
        tags = v.hashtags or []
        if isinstance(tags, str):
            tags = [t.strip() for t in tags.split(",") if t.strip()]

        for tag in tags:
            tag = tag.lower().strip("#")
            if not tag or len(tag) < 3:
                continue
            if tag not in hashtag_data:
                hashtag_data[tag] = {
                    "videos": [],
                    "total_views": 0,
                    "total_engagement": 0,
                    "creators": Counter(),
                    "platforms": set(),
                }
            h = hashtag_data[tag]
            h["videos"].append(v)
            h["total_views"] += v.views
            h["total_engagement"] += v.engagement_rate
            h["platforms"].add(v.platform)
            if v.creator and v.creator.username:
                h["creators"][v.creator.username] += 1

    created = 0
    for tag, data in hashtag_data.items():
        if len(data["videos"]) < 3:
            continue

        n = len(data["videos"])
        avg_views = data["total_views"] / n
        avg_engagement = data["total_engagement"] / n
        platform = list(data["platforms"])[0] if len(data["platforms"]) == 1 else "tiktok"

        top_creators = [
            {"username": c, "videos": count}
            for c, count in data["creators"].most_common(5)
        ]

        # Classify phase based on video recency
        recent_vids = [v for v in data["videos"]
                       if v.published_at and v.published_at > datetime.utcnow() - timedelta(days=7)]
        older_vids = [v for v in data["videos"]
                      if v.published_at and v.published_at <= datetime.utcnow() - timedelta(days=7)]

        if len(recent_vids) > len(older_vids):
            phase = "growing"
        elif len(recent_vids) > 0 and avg_views > 50000:
            phase = "peak"
        elif len(recent_vids) == 0 and n > 5:
            phase = "declining"
        else:
            phase = "emerging"

        existing = db.query(TrendLifecycle).filter(
            TrendLifecycle.keyword == tag,
            TrendLifecycle.platform == platform,
        ).first()

        if existing:
            existing.video_count = n
            existing.avg_views = round(avg_views)
            existing.avg_engagement = round(avg_engagement, 2)
            existing.top_creators = top_creators
            existing.phase = phase
            existing.last_checked = datetime.utcnow()
            history = existing.history or []
            history.append({
                "date": datetime.utcnow().strftime("%d/%m %H:%M"),
                "video_count": n,
                "avg_views": round(avg_views),
                "phase": phase,
            })
            existing.history = history[-50:]
        else:
            db.add(TrendLifecycle(
                keyword=tag,
                platform=platform,
                phase=phase,
                video_count=n,
                avg_views=round(avg_views),
                avg_engagement=round(avg_engagement, 2),
                top_creators=top_creators,
                history=[{
                    "date": datetime.utcnow().strftime("%d/%m %H:%M"),
                    "video_count": n,
                    "avg_views": round(avg_views),
                    "phase": phase,
                }],
            ))
        created += 1

    db.commit()
    logger.info(f"[Populator] Created/updated {created} trend lifecycle entries")
    return {"created": created}


def populate_sounds_from_videos(db: Session) -> dict:
    """Extract sound/music data from raw video API responses stored in DB.
    Since parsers now include music data, process any videos that have it."""
    # For existing videos, we need to extract from description patterns
    # TikTok videos often mention the sound in their description
    videos = db.query(Video).filter(
        Video.platform == "tiktok",
        Video.collected_at >= datetime.utcnow() - timedelta(days=30),
    ).all()

    # Extract music mentions from hashtags (common patterns like "som original")
    sound_mentions = Counter()
    for v in videos:
        tags = v.hashtags or []
        if isinstance(tags, str):
            tags = [t.strip() for t in tags.split(",") if t.strip()]

        for tag in tags:
            tag_lower = tag.lower()
            # Common sound-related hashtags
            if any(kw in tag_lower for kw in ["som", "sound", "musica", "music", "audio",
                                                "remix", "beat", "funk", "sertanejo"]):
                sound_mentions[tag_lower] += 1

    # Create sound entries from frequently mentioned audio-related hashtags
    created = 0
    for sound_tag, count in sound_mentions.most_common(50):
        if count < 2:
            continue

        existing = db.query(SoundTracker).filter(
            SoundTracker.title == sound_tag
        ).first()

        if not existing:
            phase = "emerging" if count < 5 else "growing" if count < 15 else "peak"
            db.add(SoundTracker(
                sound_id=f"hashtag_{sound_tag}",
                title=sound_tag,
                author="",
                url="",
                video_count=count,
                phase=phase,
                growth_rate=count * 10.0,
            ))
            created += 1

    db.commit()
    logger.info(f"[Populator] Created {created} sound entries from hashtags")
    return {"created": created, "total_mentions": len(sound_mentions)}


def recalculate_video_scores(db: Session) -> dict:
    """Recalculate viral scores for videos that have creator_followers=0
    but whose creator now has followers data."""
    creators_with_followers = db.query(Creator).filter(Creator.followers > 0).all()
    creator_map = {c.id: c.followers for c in creators_with_followers}

    updated = 0
    for cid, followers in creator_map.items():
        videos = db.query(Video).filter(
            Video.creator_id == cid,
            Video.creator_followers == 0,
        ).all()

        for v in videos:
            v.creator_followers = followers
            video_data = {
                "platform": v.platform,
                "views": v.views,
                "likes": v.likes,
                "comments": v.comments,
                "shares": v.shares,
                "duration": v.duration,
                "hashtags": v.hashtags or [],
                "published_at": v.published_at,
                "creator_followers": followers,
                "creator_avg_views": v.creator_avg_views or 0,
            }
            score_data = detector.calculate_score(video_data)
            replicability = detector.calculate_replicability(video_data, score_data)

            v.viral_score = score_data["viral_score"]
            v.engagement_rate = score_data["engagement_rate"]
            v.outlier_ratio = score_data["outlier_ratio"]
            v.views_per_follower = score_data.get("views_per_follower", 0)
            v.is_small_creator = score_data.get("is_small_creator", False)
            v.replicability_score = replicability
            updated += 1

    db.commit()
    logger.info(f"[Populator] Recalculated scores for {updated} videos")
    return {"updated": updated}
