from datetime import datetime, timedelta
from collections import Counter
import uuid
import random

from sqlalchemy.orm import Session
from sqlalchemy import desc

from backend.models.video import Video

# ─── PostPilot Smart Queue (in-memory) ────────────────────────
_queue: list[dict] = []
_queue_history: list[dict] = []


def add_to_queue(
    content_type: str = "video",
    title: str = "",
    description: str = "",
    platform: str = "tiktok",
    scheduled_time: str = "",
    hashtags: list = None,
    priority: int = 5,
    metadata: dict = None,
) -> dict:
    """Add content to the smart publishing queue."""
    item = {
        "id": str(uuid.uuid4())[:8],
        "content_type": content_type,
        "title": title,
        "description": description,
        "platform": platform,
        "scheduled_time": scheduled_time or "",
        "hashtags": hashtags or [],
        "priority": max(1, min(10, priority)),
        "status": "queued",
        "created_at": datetime.utcnow().isoformat(),
        "metadata": metadata or {},
    }
    _queue.append(item)
    _queue.sort(key=lambda x: (-x["priority"], x.get("scheduled_time", "")))
    return item


def list_queue(status: str = "", platform: str = "") -> list:
    """List queue items with optional filters."""
    items = _queue[:]
    if status:
        items = [i for i in items if i["status"] == status]
    if platform:
        items = [i for i in items if i["platform"] == platform]
    return items


def update_queue_item(item_id: str, **kwargs) -> dict:
    """Update a queue item."""
    for item in _queue:
        if item["id"] == item_id:
            for k, v in kwargs.items():
                if k in item and k != "id":
                    item[k] = v
            _queue.sort(key=lambda x: (-x["priority"], x.get("scheduled_time", "")))
            return item
    return {"error": "Item nao encontrado"}


def remove_from_queue(item_id: str) -> bool:
    """Remove item from queue."""
    for i, item in enumerate(_queue):
        if item["id"] == item_id:
            removed = _queue.pop(i)
            removed["status"] = "removed"
            _queue_history.append(removed)
            return True
    return False


def reorder_queue(item_ids: list) -> list:
    """Reorder queue by list of item IDs."""
    id_map = {item["id"]: item for item in _queue}
    reordered = []
    for idx, item_id in enumerate(item_ids):
        if item_id in id_map:
            item = id_map[item_id]
            item["priority"] = max(1, 10 - idx)
            reordered.append(item)
    for item in _queue:
        if item["id"] not in {i["id"] for i in reordered}:
            reordered.append(item)
    _queue.clear()
    _queue.extend(reordered)
    return _queue[:]


def publish_item(item_id: str) -> dict:
    """Mark item as published."""
    for item in _queue:
        if item["id"] == item_id:
            item["status"] = "published"
            item["published_at"] = datetime.utcnow().isoformat()
            _queue_history.append(item)
            _queue.remove(item)
            return item
    return {"error": "Item nao encontrado"}


async def auto_schedule_queue(db: Session, platform: str = "", posts_per_day: int = 2) -> dict:
    """AI-powered auto-scheduling based on best times analysis."""
    cal = ContentCalendar()
    times = cal.get_best_times(db, platform)
    best_hours = times.get("best_hours", [])
    best_days = times.get("best_days", [])

    if not best_hours:
        best_hours = [{"hour": h} for h in [10, 14, 18, 20]]

    unscheduled = [i for i in _queue if not i.get("scheduled_time") and i["status"] == "queued"]
    now = datetime.utcnow()
    scheduled_count = 0

    for idx, item in enumerate(unscheduled):
        day_offset = idx // posts_per_day
        hour_idx = idx % min(posts_per_day, len(best_hours))
        target_hour = best_hours[hour_idx]["hour"]
        target_date = now + timedelta(days=day_offset + 1)
        target_date = target_date.replace(hour=target_hour, minute=0, second=0)
        item["scheduled_time"] = target_date.strftime("%Y-%m-%d %H:%M")
        item["auto_scheduled"] = True
        scheduled_count += 1

    _queue.sort(key=lambda x: (-x["priority"], x.get("scheduled_time", "")))
    return {
        "scheduled": scheduled_count,
        "total_in_queue": len(_queue),
        "best_hours_used": [h.get("label", f"{h['hour']:02d}:00") for h in best_hours[:posts_per_day]],
    }


async def suggest_content_recycling(db: Session, days: int = 90, limit: int = 10) -> list:
    """Suggest old high-performing content for recycling."""
    since = datetime.utcnow() - timedelta(days=days)
    cutoff = datetime.utcnow() - timedelta(days=30)

    videos = db.query(Video).filter(
        Video.collected_at >= since,
        Video.collected_at <= cutoff,
        Video.viral_score >= 60,
    ).order_by(desc(Video.viral_score)).limit(limit * 2).all()

    suggestions = []
    for v in videos[:limit]:
        angle = random.choice([
            "Atualizar com dados novos",
            "Criar versao curta (Shorts/Reels)",
            "Fazer versao storytelling",
            "Transformar em carrossel",
            "Adicionar tendencia atual",
            "Criar resposta a comentarios",
        ])
        suggestions.append({
            "video_id": v.id,
            "title": v.title or "",
            "platform": v.platform,
            "original_score": v.viral_score,
            "views": v.views or 0,
            "published_at": v.published_at.isoformat() if v.published_at else "",
            "recycle_angle": angle,
            "estimated_boost": round(random.uniform(1.2, 2.5), 1),
        })
    return suggestions


async def generate_smart_caption(
    title: str, platform: str = "tiktok", tone: str = "engajante", niche: str = ""
) -> dict:
    """Generate AI-powered caption for a post."""
    try:
        from backend.services.local_ai import llm_chat
        prompt = (
            f"Gere uma legenda viral para {platform} sobre: {title}\n"
            f"Tom: {tone}. Nicho: {niche or 'geral'}.\n"
            f"Retorne APENAS JSON: {{\"caption\": \"...\", \"hashtags\": [\"...\"], "
            f"\"cta\": \"...\", \"hook_line\": \"...\", \"emoji_line\": \"...\"}}"
        )
        resp = await llm_chat(prompt, system="Voce e um especialista em social media brasileiro.")
        import json
        try:
            data = json.loads(resp)
        except Exception:
            data = {
                "caption": resp[:300] if resp else f"Confira: {title}",
                "hashtags": ["#viral", "#fyp", "#trending"],
                "cta": "Salve para ver depois!",
                "hook_line": title,
                "emoji_line": "🔥🚀",
            }
        return {"success": True, **data}
    except Exception:
        return {
            "success": True,
            "caption": f"🔥 {title}\n\nVoce precisa ver isso! Salve e compartilhe.",
            "hashtags": ["#viral", "#fyp", "#trending", "#foryou"],
            "cta": "Siga para mais conteudo!",
            "hook_line": title,
            "emoji_line": "🔥✨",
        }


async def ab_test_schedule(
    db: Session, title: str, platform: str = "tiktok", variations: int = 2
) -> dict:
    """Create A/B test schedule with different posting times."""
    cal = ContentCalendar()
    times = cal.get_best_times(db, platform)
    best_hours = times.get("best_hours", [])
    best_days = times.get("best_days", [])

    if len(best_hours) < 2:
        best_hours = [{"hour": 10, "label": "10:00"}, {"hour": 18, "label": "18:00"},
                      {"hour": 14, "label": "14:00"}, {"hour": 20, "label": "20:00"}]

    test_slots = []
    now = datetime.utcnow()
    for i in range(min(variations, 4)):
        h = best_hours[i % len(best_hours)]
        target = now + timedelta(days=i + 1)
        target = target.replace(hour=h["hour"], minute=0)
        slot = {
            "variant": chr(65 + i),
            "scheduled_time": target.strftime("%Y-%m-%d %H:%M"),
            "hour": h.get("label", f"{h['hour']:02d}:00"),
            "expected_score": h.get("avg_score", 50),
            "hypothesis": f"Testar horario {h.get('label', '')} - score medio {h.get('avg_score', 50)}",
        }
        test_slots.append(slot)

    return {
        "title": title,
        "platform": platform,
        "variations": test_slots,
        "recommendation": f"Publique a variante A primeiro e compare engajamento apos 24h",
    }


def get_queue_stats() -> dict:
    """Get queue statistics."""
    queued = [i for i in _queue if i["status"] == "queued"]
    scheduled = [i for i in _queue if i.get("scheduled_time")]
    platforms = Counter(i["platform"] for i in _queue)
    return {
        "total_queued": len(queued),
        "total_scheduled": len(scheduled),
        "total_published": len([i for i in _queue_history if i["status"] == "published"]),
        "total_removed": len([i for i in _queue_history if i["status"] == "removed"]),
        "by_platform": dict(platforms),
        "avg_priority": round(sum(i["priority"] for i in queued) / max(len(queued), 1), 1),
        "next_scheduled": min(
            (i["scheduled_time"] for i in scheduled if i["scheduled_time"]), default=""
        ),
    }


class ContentCalendar:
    """Intelligent content calendar based on viral patterns."""

    WEEKDAYS_PT = {
        0: "Segunda", 1: "Terça", 2: "Quarta",
        3: "Quinta", 4: "Sexta", 5: "Sábado", 6: "Domingo",
    }

    def get_best_times(
        self, db: Session, platform: str = "", days: int = 30
    ) -> dict:
        """Analyze best posting times based on viral video data."""
        since = datetime.utcnow() - timedelta(days=days)
        query = db.query(Video).filter(
            Video.collected_at >= since,
            Video.viral_score >= 40,
            Video.published_at.isnot(None),
        )
        if platform:
            query = query.filter(Video.platform == platform)

        videos = query.all()
        if not videos:
            return self._default_schedule()

        # Analyze by hour and day
        hour_scores: dict[int, list] = {h: [] for h in range(24)}
        day_scores: dict[int, list] = {d: [] for d in range(7)}
        slot_scores: dict[str, list] = {}

        for v in videos:
            if not v.published_at:
                continue
            hour = v.published_at.hour
            day = v.published_at.weekday()
            hour_scores[hour].append(v.viral_score)
            day_scores[day].append(v.viral_score)

            slot_key = f"{day}_{hour}"
            if slot_key not in slot_scores:
                slot_scores[slot_key] = []
            slot_scores[slot_key].append(v.viral_score)

        # Best hours
        best_hours = []
        for hour, scores in hour_scores.items():
            if scores:
                best_hours.append({
                    "hour": hour,
                    "label": f"{hour:02d}:00",
                    "avg_score": round(sum(scores) / len(scores), 1),
                    "count": len(scores),
                })
        best_hours.sort(key=lambda x: x["avg_score"], reverse=True)

        # Best days
        best_days = []
        for day, scores in day_scores.items():
            if scores:
                best_days.append({
                    "day": day,
                    "name": self.WEEKDAYS_PT[day],
                    "avg_score": round(sum(scores) / len(scores), 1),
                    "count": len(scores),
                })
        best_days.sort(key=lambda x: x["avg_score"], reverse=True)

        # Best slots (day + hour combinations)
        best_slots = []
        for slot, scores in slot_scores.items():
            if len(scores) >= 2:
                day, hour = slot.split("_")
                best_slots.append({
                    "day": self.WEEKDAYS_PT[int(day)],
                    "hour": f"{int(hour):02d}:00",
                    "avg_score": round(sum(scores) / len(scores), 1),
                    "count": len(scores),
                })
        best_slots.sort(key=lambda x: x["avg_score"], reverse=True)

        return {
            "total_analyzed": len(videos),
            "best_hours": best_hours[:6],
            "best_days": best_days,
            "best_slots": best_slots[:10],
            "recommendation": self._generate_recommendation(best_hours, best_days),
        }

    def generate_weekly_plan(
        self, db: Session, platform: str = "", posts_per_day: int = 1
    ) -> list[dict]:
        """Generate a weekly posting plan."""
        times = self.get_best_times(db, platform)
        best_hours = times.get("best_hours", [])
        best_days = times.get("best_days", [])

        if not best_hours:
            best_hours = [{"hour": h, "label": f"{h:02d}:00"} for h in [10, 14, 18, 20]]
        if not best_days:
            best_days = [{"day": d, "name": self.WEEKDAYS_PT[d]} for d in range(7)]

        plan = []
        today = datetime.now()
        start_of_week = today - timedelta(days=today.weekday())

        for day_idx in range(7):
            day_date = start_of_week + timedelta(days=day_idx)
            day_info = next((d for d in best_days if d["day"] == day_idx), None)
            day_name = self.WEEKDAYS_PT[day_idx]

            slots = []
            for i in range(min(posts_per_day, len(best_hours))):
                h = best_hours[i % len(best_hours)]
                slots.append({
                    "time": h["label"],
                    "score_potential": h.get("avg_score", 50),
                })

            plan.append({
                "date": day_date.strftime("%Y-%m-%d"),
                "day_name": day_name,
                "day_score": day_info.get("avg_score", 0) if day_info else 0,
                "slots": slots,
            })

        return plan

    def _generate_recommendation(self, best_hours: list, best_days: list) -> str:
        if not best_hours or not best_days:
            return "Colete mais dados para recomendações personalizadas."

        top_hours = ", ".join(h["label"] for h in best_hours[:3])
        top_days = ", ".join(d["name"] for d in best_days[:3])
        return f"Poste preferencialmente às {top_hours} nos dias: {top_days}"

    def _default_schedule(self) -> dict:
        return {
            "total_analyzed": 0,
            "best_hours": [
                {"hour": 10, "label": "10:00", "avg_score": 0, "count": 0},
                {"hour": 14, "label": "14:00", "avg_score": 0, "count": 0},
                {"hour": 18, "label": "18:00", "avg_score": 0, "count": 0},
                {"hour": 20, "label": "20:00", "avg_score": 0, "count": 0},
            ],
            "best_days": [
                {"day": d, "name": self.WEEKDAYS_PT[d], "avg_score": 0, "count": 0}
                for d in range(7)
            ],
            "best_slots": [],
            "recommendation": "Colete vídeos virais para gerar recomendações de horários.",
        }
