"""
Creator Baseline Service.

Calculates and caches creator performance baselines
to enable outlier detection in viral scoring.
"""

import logging
import statistics
from datetime import datetime, timedelta

from sqlalchemy.orm import Session
from sqlalchemy import func

from backend.models.video import Video
from backend.models.creator import Creator
from backend.services.viral_detector import ViralDetector

logger = logging.getLogger("viral_social.baseline")


class CreatorBaselineService:
    CACHE_DAYS = 7  # Recalculate baseline every 7 days

    def get_or_update_baseline(self, db: Session, creator: Creator) -> dict:
        """Get creator baseline, updating if stale."""
        if creator.baseline_updated_at:
            age = datetime.utcnow() - creator.baseline_updated_at
            if age < timedelta(days=self.CACHE_DAYS) and creator.avg_views > 0:
                return {
                    "avg_views": creator.avg_views,
                    "median_views": creator.median_views,
                    "followers": creator.followers,
                    "size_tier": creator.size_tier,
                    "avg_engagement": creator.avg_engagement,
                }

        return self.update_baseline(db, creator)

    def update_baseline(self, db: Session, creator: Creator) -> dict:
        """Recalculate baseline from stored videos."""
        videos = (
            db.query(Video)
            .filter(Video.creator_id == creator.id)
            .order_by(Video.published_at.desc())
            .limit(30)
            .all()
        )

        if not videos:
            return {
                "avg_views": 0,
                "median_views": 0,
                "followers": creator.followers,
                "size_tier": creator.size_tier or "unknown",
                "avg_engagement": 0,
            }

        views_list = [v.views for v in videos if v.views > 0]

        if views_list:
            creator.avg_views = statistics.mean(views_list)
            creator.median_views = statistics.median(views_list)
        else:
            creator.avg_views = 0
            creator.median_views = 0

        creator.total_videos = len(videos)

        # Calculate avg engagement
        eng_rates = []
        for v in videos:
            if v.views > 0:
                rate = ((v.likes or 0) + (v.comments or 0) + (v.shares or 0)) / v.views
                eng_rates.append(rate)
        creator.avg_engagement = statistics.mean(eng_rates) * 100 if eng_rates else 0

        # Update size tier
        creator.size_tier = ViralDetector.get_size_tier(creator.followers)
        creator.baseline_updated_at = datetime.utcnow()

        db.commit()

        logger.info(
            f"Updated baseline for @{creator.username} ({creator.platform}): "
            f"avg={creator.avg_views:.0f}, median={creator.median_views:.0f}, "
            f"tier={creator.size_tier}"
        )

        return {
            "avg_views": creator.avg_views,
            "median_views": creator.median_views,
            "followers": creator.followers,
            "size_tier": creator.size_tier,
            "avg_engagement": creator.avg_engagement,
        }

    def update_all_baselines(self, db: Session, force: bool = False):
        """Update baselines for all creators with videos."""
        query = db.query(Creator).filter(Creator.id.in_(
            db.query(Video.creator_id).filter(Video.creator_id.isnot(None)).distinct()
        ))

        if not force:
            stale_threshold = datetime.utcnow() - timedelta(days=self.CACHE_DAYS)
            query = query.filter(
                (Creator.baseline_updated_at.is_(None)) |
                (Creator.baseline_updated_at < stale_threshold)
            )

        creators = query.all()
        updated = 0
        for creator in creators:
            self.update_baseline(db, creator)
            updated += 1

        logger.info(f"Updated baselines for {updated} creators")
        return updated

    def enrich_video_data(self, db: Session, video_data: dict) -> dict:
        """Add creator baseline info to video data before scoring."""
        creator_username = video_data.get("creator_username", "")
        platform = video_data.get("platform", "")

        if not creator_username:
            return video_data

        creator = (
            db.query(Creator)
            .filter_by(platform=platform, username=creator_username)
            .first()
        )

        if creator:
            baseline = self.get_or_update_baseline(db, creator)
            video_data["creator_avg_views"] = baseline["avg_views"]
            video_data["creator_median_views"] = baseline["median_views"]
            video_data["creator_followers"] = baseline["followers"]
        else:
            # Try to get follower count from scraped data
            followers = video_data.get("creator_followers", 0)
            video_data["creator_avg_views"] = 0
            video_data["creator_median_views"] = 0
            video_data["creator_followers"] = followers

        return video_data
