"""
News Router - THE Crypto News Aggregator Feed
=============================================
200+ sources. Real data only. No fake articles.

Endpoints:
  GET /api/v1/news/feed       - Full aggregated feed with filters
  GET /api/v1/news/sources    - Active sources list with counts
  GET /api/v1/news/sentiment  - Real-time sentiment overview
  GET /api/v1/news/headlines  - Top headlines only
  GET /api/v1/news/stats      - Source/category statistics
  POST /api/v1/news/comment   - Comment on article (social)
  GET /api/v1/news/comments/:article_id - Get comments for article
"""

import asyncio
import hashlib
import logging
from datetime import UTC, datetime, timedelta

from fastapi import APIRouter, Depends, HTTPException, Query
from pydantic import BaseModel

from app.auth import require_public_profile

logger = logging.getLogger(__name__)

router = APIRouter(prefix="/api/v1/news", tags=["news"])


# ─── Models ───────────────────────────────────────────────────────
class NewsArticle(BaseModel):
    id: str | None = None
    title: str = ""
    url: str = ""
    description: str | None = None
    source: str = ""
    published_at: str | None = None
    image_url: str | None = None
    category: str | None = None
    sentiment: str | None = None
    kind: str | None = None
    tier: str | None = None
    reddit_score: int | None = None
    reddit_comments: int | None = None
    risk_score: float | None = None
    token_address: str | None = None
    chain: str | None = None
    comment_count: int | None = 0


class NewsFeedResponse(BaseModel):
    status: str = "success"
    articles: list[NewsArticle] = []
    total: int = 0
    sources: list[str] = []
    source_count: int = 0
    sentiment_summary: dict[str, int] = {}
    tiers: list[str] = []
    cached: bool = False
    fetched_at: str = ""


class CommentRequest(BaseModel):
    article_id: str
    author: str = "anon"
    content: str
    parent_id: str | None = None


class CommentResponse(BaseModel):
    id: str
    article_id: str
    author: str
    content: str
    created_at: str
    parent_id: str | None = None
    likes: int = 0


# ─── In-memory cache ──────────────────────────────────────────────
_NEWS_CACHE = []
_CACHE_TS: datetime | None = None
_CACHE_TTL = timedelta(minutes=3)

# In-memory comments store (ephemeral - persists via Redis later)
_COMMENTS: dict[str, list[dict]] = {}

# ─── Helpers ──────────────────────────────────────────────────────


def _make_comment_id(article_id: str, content: str) -> str:
    h = hashlib.md5(f"{article_id}:{content}:{datetime.now(UTC).isoformat()}".encode()).hexdigest()
    return f"comment-{h[:12]}"


async def _refresh_cache(include_rss: bool, include_reddit: bool, include_internal: bool):
    """Background cache refresh task."""
    global _NEWS_CACHE, _CACHE_TS
    try:
        from app.news_service import get_news_service

        svc = get_news_service()
        result = await svc.fetch_all(
            limit=200,
            include_rss=include_rss,
            include_reddit=include_reddit,
            include_internal=include_internal,
        )
        _NEWS_CACHE = result
        _CACHE_TS = datetime.now(UTC)
        logger.info(
            f"News cache refreshed: {result.get('total', 0)} articles from {result.get('source_count', 0)} sources"
        )
    except Exception as e:
        logger.warning(f"Background news refresh failed: {e}")


# ─── Main Feed ────────────────────────────────────────────────────


@router.get("/feed", response_model=NewsFeedResponse)
async def get_news_feed(
    limit: int = Query(50, ge=1, le=200),
    sentiment: str | None = Query(None, description="bullish, bearish, neutral, slightly_bullish, slightly_bearish"),
    source: str | None = Query(None),
    category: str | None = Query(None),
    tier: str | None = Query(None, description="news, social, market, rmi, api"),
    kind: str | None = Query(None, description="external, internal, social, api"),
    include_rss: bool = Query(True),
    include_reddit: bool = Query(True),
    include_internal: bool = Query(True),
    refresh: bool = Query(False, description="Force refresh, bypass cache"),
):
    """Full aggregated news feed from all sources."""
    global _NEWS_CACHE, _CACHE_TS

    # Return cache if fresh
    if not refresh and _NEWS_CACHE and _CACHE_TS and (datetime.now(UTC) - _CACHE_TS) < _CACHE_TTL:
        result = _NEWS_CACHE
    else:
        # Serve stale cache immediately while refreshing in background
        if _NEWS_CACHE and not refresh:
            result = _NEWS_CACHE
            # Background refresh
            asyncio.create_task(_refresh_cache(include_rss, include_reddit, include_internal))
        else:
            # First load or forced refresh - fetch inline but with limits
            try:
                from app.news_service import get_news_service

                svc = get_news_service()
                result = await svc.fetch_all(
                    limit=200,
                    include_rss=include_rss,
                    include_reddit=include_reddit,
                    include_internal=include_internal,
                )
                _NEWS_CACHE = result
                _CACHE_TS = datetime.now(UTC)
            except Exception as e:
                logger.error(f"News fetch failed: {e}")
                if _NEWS_CACHE:
                    result = _NEWS_CACHE
                else:
                    raise HTTPException(status_code=500, detail=f"News aggregation failed: {e!s}") from e

    articles = result.get("articles", [])

    # Apply filters
    if sentiment:
        articles = [a for a in articles if a.get("sentiment", "").lower() == sentiment.lower()]
    if source:
        articles = [a for a in articles if source.lower() in a.get("source", "").lower()]
    if category:
        articles = [a for a in articles if a.get("category", "").lower() == category.lower()]
    if tier:
        articles = [a for a in articles if a.get("tier", "").lower() == tier.lower()]
    if kind:
        articles = [a for a in articles if a.get("kind", "").lower() == kind.lower()]

    articles = articles[:limit]

    # Enrich with comment counts
    for a in articles:
        aid = a.get("id", "")
        a["comment_count"] = len(_COMMENTS.get(aid, []))

    return NewsFeedResponse(
        status="success",
        articles=[NewsArticle(**a) for a in articles],
        total=len(articles),
        sources=result.get("sources", []),
        source_count=result.get("source_count", 0),
        sentiment_summary=result.get("sentiment_summary", {}),
        tiers=result.get("tiers", []),
        cached=bool(_NEWS_CACHE),
        fetched_at=(_CACHE_TS or datetime.now(UTC)).isoformat(),
    )


# ─── Headlines ────────────────────────────────────────────────────


@router.get("/headlines")
async def get_headlines(
    count: int = Query(10, ge=1, le=50),
    category: str | None = Query(None),
):
    """Top headlines only - fast, lightweight."""
    feed = await get_news_feed(limit=count, category=category, include_reddit=False)
    return {
        "headlines": [
            {
                "title": a.title,
                "url": a.url,
                "source": a.source,
                "published_at": a.published_at,
                "category": a.category,
                "sentiment": a.sentiment,
                "kind": a.kind,
            }
            for a in feed.articles[:count]
        ],
        "count": len(feed.articles[:count]),
    }


# ─── Sources ──────────────────────────────────────────────────────


@router.get("/sources")
async def get_news_sources():
    """Get all active news sources."""
    feed = await get_news_feed(limit=200, refresh=False)
    sources = {}
    for a in feed.articles:
        src = a.source
        sources[src] = sources.get(src, 0) + 1

    return {
        "sources": [
            {
                "name": name,
                "article_count": count,
                "tier": a.tier if hasattr(a, "tier") else "unknown",
            }
            for name, count in sorted(sources.items(), key=lambda x: -x[1])
            for a in [next((art for art in feed.articles if art.source == name), None)]
        ],
        "total_sources": len(sources),
    }


# ─── Sentiment ────────────────────────────────────────────────────


@router.get("/sentiment")
async def get_sentiment():
    """Real-time sentiment overview from current news feed."""
    feed = await get_news_feed(limit=200, refresh=False)
    return {
        "sentiment": feed.sentiment_summary,
        "sample_size": feed.total,
        "fetched_at": feed.fetched_at,
        "trending": [a.title for a in feed.articles[:5] if a.sentiment in ("bullish", "bearish")],
    }


# ─── Categories ───────────────────────────────────────────────────


@router.get("/categories")
async def get_categories():
    """Get all news categories with counts."""
    feed = await get_news_feed(limit=200, refresh=False)
    cats = {}
    for a in feed.articles:
        cat = a.category or "general"
        cats[cat] = cats.get(cat, 0) + 1
    return {
        "categories": [{"name": n, "count": c} for n, c in sorted(cats.items(), key=lambda x: -x[1])],
    }


# ─── Stats ────────────────────────────────────────────────────────


@router.get("/stats")
async def get_stats():
    """Aggregate statistics about the news pipeline."""
    feed = await get_news_feed(limit=200, refresh=False)
    source_counts = {}
    tier_counts = {}
    for a in feed.articles:
        src = a.source or "unknown"
        source_counts[src] = source_counts.get(src, 0) + 1
        t = a.tier or "unknown"
        tier_counts[t] = tier_counts.get(t, 0) + 1

    return {
        "total_articles": feed.total,
        "total_sources": feed.source_count,
        "sentiment": feed.sentiment_summary,
        "source_breakdown": dict(sorted(source_counts.items(), key=lambda x: -x[1])[:20]),
        "tier_breakdown": tier_counts,
        "fetched_at": feed.fetched_at,
    }


# ─── Comments / Social ────────────────────────────────────────────


@router.post("/comment", response_model=CommentResponse)
async def post_comment(req: CommentRequest, user: dict = Depends(require_public_profile)):
    """Post a comment on any news article. Requires public profile."""
    if not req.article_id or not req.content.strip():
        raise HTTPException(status_code=400, detail="article_id and content required")

    comment = {
        "id": _make_comment_id(req.article_id, req.content),
        "article_id": req.article_id,
        "author": user.get("display_name") or user.get("email", "anon")[:50],
        "content": req.content[:2000],
        "created_at": datetime.now(UTC).isoformat(),
        "parent_id": req.parent_id,
        "likes": 0,
    }

    if req.article_id not in _COMMENTS:
        _COMMENTS[req.article_id] = []
    _COMMENTS[req.article_id].append(comment)

    return CommentResponse(**comment)


@router.get("/comments/{article_id}", response_model=list[CommentResponse])
async def get_comments(article_id: str):
    """Get comments for a specific article."""
    comments = _COMMENTS.get(article_id, [])
    return [CommentResponse(**c) for c in sorted(comments, key=lambda x: x["created_at"])]


# ─── Internal: for cron jobs to post scanner findings as news ─────


@router.post("/internal/scanner-alert")
async def post_scanner_alert(token_name: str, chain: str, risk_score: float, address: str, flags: str = ""):
    """Internal endpoint for cron jobs to inject scanner findings into news feed."""
    global _NEWS_CACHE
    content_hash = hashlib.md5(f"internal:{address}:{chain}".encode()).hexdigest()
    article = {
        "id": f"rmi-{content_hash[:12]}",
        "title": f"RMI Scanner: {token_name} ({chain.upper()}) - Risk {risk_score}/100",
        "url": f"https://rugmunch.io/scanner?address={address}&chain={chain}",
        "description": f"Scanner detected {token_name} on {chain}. Risk: {risk_score}/100. Flags: {flags}. Address: {address}",
        "source": "RMI Scanner",
        "published_at": datetime.now(UTC).isoformat(),
        "category": "security",
        "sentiment": "bearish" if risk_score > 50 else "neutral",
        "kind": "internal",
        "tier": "rmi",
        "risk_score": risk_score,
        "token_address": address,
        "chain": chain,
    }
    # Prepend to cache
    if _NEWS_CACHE:
        _NEWS_CACHE["articles"] = [article, *_NEWS_CACHE.get("articles", [])]
        _NEWS_CACHE["total"] = len(_NEWS_CACHE["articles"])
    return {"status": "injected", "id": article["id"]}
