from collections import Counter
from datetime import datetime, timedelta

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

from backend.models.video import Video


class HashtagResearch:
    """Advanced hashtag research and suggestions."""

    def research(
        self, db: Session, seed_hashtag: str = "", platform: str = "", days: int = 30, limit: int = 30
    ) -> dict:
        since = datetime.utcnow() - timedelta(days=days)
        query = db.query(Video).filter(Video.collected_at >= since)
        if platform:
            query = query.filter(Video.platform == platform)

        videos = query.all()
        if not videos:
            return {"results": [], "co_occurrences": [], "seed": seed_hashtag}

        # Build hashtag index
        hashtag_data: dict[str, dict] = {}
        co_occurrence: dict[str, Counter] = {}

        for video in videos:
            tags = video.hashtags or []
            if isinstance(tags, str):
                tags = [t.strip() for t in tags.split(",") if t.strip()]
            tags = [t.lower().strip("#") for t in tags if len(t) > 1]

            for tag in tags:
                if tag not in hashtag_data:
                    hashtag_data[tag] = {
                        "name": tag,
                        "count": 0,
                        "total_views": 0,
                        "total_likes": 0,
                        "scores": [],
                        "platforms": set(),
                        "engagements": [],
                    }
                h = hashtag_data[tag]
                h["count"] += 1
                h["total_views"] += video.views
                h["total_likes"] += video.likes
                h["scores"].append(video.viral_score)
                h["platforms"].add(video.platform)
                h["engagements"].append(video.engagement_rate)

                # Track co-occurrences
                if tag not in co_occurrence:
                    co_occurrence[tag] = Counter()
                for other_tag in tags:
                    if other_tag != tag:
                        co_occurrence[tag][other_tag] += 1

        # Calculate metrics
        results = []
        for tag, data in hashtag_data.items():
            n = max(data["count"], 1)
            scores = data["scores"]
            avg_score = sum(scores) / len(scores) if scores else 0
            avg_engagement = sum(data["engagements"]) / len(data["engagements"]) if data["engagements"] else 0

            # Competitiveness: high count = more competitive
            competitiveness = min(data["count"] / max(len(videos) * 0.3, 1), 1.0)

            # Effectiveness: balance between score and reach
            effectiveness = (avg_score * 0.6 + (1 - competitiveness) * 40 * 0.4)

            results.append({
                "name": tag,
                "count": data["count"],
                "total_views": data["total_views"],
                "avg_views": data["total_views"] // n,
                "avg_viral_score": round(avg_score, 1),
                "avg_engagement": round(avg_engagement, 2),
                "competitiveness": round(competitiveness * 100, 1),
                "effectiveness": round(effectiveness, 1),
                "platforms": list(data["platforms"]),
            })

        # Sort by effectiveness
        results.sort(key=lambda x: x["effectiveness"], reverse=True)

        # Co-occurrences for seed hashtag
        related = []
        seed = seed_hashtag.lower().strip("#")
        if seed and seed in co_occurrence:
            for related_tag, count in co_occurrence[seed].most_common(15):
                if related_tag in hashtag_data:
                    related.append({
                        "name": related_tag,
                        "co_count": count,
                        "avg_score": round(
                            sum(hashtag_data[related_tag]["scores"]) / len(hashtag_data[related_tag]["scores"]), 1
                        ),
                    })

        return {
            "results": results[:limit],
            "co_occurrences": related,
            "seed": seed_hashtag,
            "total_hashtags": len(hashtag_data),
            "total_videos_analyzed": len(videos),
        }

    def suggest_combo(
        self, db: Session, platform: str = "", count: int = 5, days: int = 30
    ) -> list[list[str]]:
        """Suggest effective hashtag combinations."""
        research = self.research(db, platform=platform, days=days, limit=50)
        results = research["results"]
        if len(results) < count:
            return [r["name"] for r in results]

        # Strategy: mix high-effectiveness with medium-competitiveness
        high_eff = [r for r in results if r["effectiveness"] >= 50][:3]
        medium_comp = [r for r in results if 20 <= r["competitiveness"] <= 60][:3]
        low_comp = [r for r in results if r["competitiveness"] < 20][:2]

        seen = set()
        combo = []
        for pool in [high_eff, medium_comp, low_comp]:
            for r in pool:
                if r["name"] not in seen and len(combo) < count:
                    combo.append(r["name"])
                    seen.add(r["name"])

        return combo
