"""Reddit data provider for social sentiment."""

from typing import Any

from .base import Provider, ProviderData


class RedditData(ProviderData):
    """Reddit specific data."""

    provider: str = "reddit"
    post_count_24h: int | None = None
    comment_count_24h: int | None = None
    avg_score: float | None = None
    sentiment_score: float | None = None
    top_subreddits: list[str] | None = None
    mention_velocity: float | None = None


class RedditProvider(Provider):
    """Reddit API provider for social sentiment data."""

    name = "reddit"
    base_url = "https://oauth.reddit.com"
    requires_auth = True

    def __init__(self, client_id: str | None = None, client_secret: str | None = None):
        """Initialize Reddit provider with OAuth credentials."""
        super().__init__(client_id)
        self.client_secret = client_secret
        self._access_token: str | None = None

    async def _get_access_token(self) -> str | None:
        """Get OAuth access token."""
        if self._access_token:
            return self._access_token

        if not self.api_key or not self.client_secret:
            return None

        import base64

        auth = base64.b64encode(
            f"{self.api_key}:{self.client_secret}".encode()
        ).decode()

        # Use a separate client for auth
        import httpx

        async with httpx.AsyncClient() as client:
            response = await client.post(
                "https://www.reddit.com/api/v1/access_token",
                headers={
                    "Authorization": f"Basic {auth}",
                    "User-Agent": "FOMO-Guard/0.1.0",
                },
                data={
                    "grant_type": "client_credentials",
                },
            )

            if response.status_code == 200:
                data = response.json()
                self._access_token = data.get("access_token")
                return self._access_token

        return None

    def _get_auth_headers(self) -> dict[str, str]:
        """Get authentication headers."""
        # Note: This is called before we have the token
        # Real implementation would handle this async
        return {}

    async def fetch_data(self, symbol: str) -> RedditData:
        """Fetch Reddit posts and sentiment for a coin."""
        token = await self._get_access_token()
        if not token:
            return RedditData(symbol=symbol.upper(), raw_data={})

        try:
            # Search cryptocurrency subreddits
            subreddits = [
                "cryptocurrency",
                "bitcoin" if symbol.upper() == "BTC" else symbol.lower(),
                "CryptoMarkets",
                "altcoin",
            ]

            all_posts = []
            for subreddit in subreddits:
                try:
                    posts = await self._search_subreddit(token, subreddit, symbol)
                    all_posts.extend(posts)
                except Exception:
                    continue

            if not all_posts:
                return RedditData(symbol=symbol.upper(), raw_data={})

            # Analyze posts
            sentiment = self._analyze_sentiment(all_posts)
            avg_score = (
                sum(p.get("score", 0) for p in all_posts) / len(all_posts)
                if all_posts
                else 0
            )

            return RedditData(
                symbol=symbol.upper(),
                post_count_24h=len(all_posts),
                avg_score=avg_score,
                sentiment_score=sentiment["score"],
                top_subreddits=list(set(p.get("subreddit", "") for p in all_posts[:5])),
                mention_velocity=len(all_posts) / 24.0,  # Posts per hour
                raw_data={"post_count": len(all_posts)},
            )

        except Exception:
            return RedditData(symbol=symbol.upper(), raw_data={})

    async def _search_subreddit(
        self, token: str, subreddit: str, symbol: str
    ) -> list[dict]:
        """Search a subreddit for coin mentions."""
        import httpx

        async with httpx.AsyncClient() as client:
            response = await client.get(
                f"https://oauth.reddit.com/r/{subreddit}/search",
                headers={
                    "Authorization": f"Bearer {token}",
                    "User-Agent": "FOMO-Guard/0.1.0",
                },
                params={
                    "q": symbol,
                    "sort": "new",
                    "time_filter": "day",
                    "limit": 25,
                },
            )

            if response.status_code == 200:
                data = response.json()
                posts = data.get("data", {}).get("children", [])
                return [p.get("data", {}) for p in posts]

        return []

    def _analyze_sentiment(self, posts: list[dict]) -> dict[str, float]:
        """Simple sentiment analysis based on post content and scores."""
        bullish_keywords = [
            "moon", "bullish", "buy", "pump", "breakout", "undervalued",
            "gem", "hodl", "accumulate", "dip", "opportunity",
        ]
        bearish_keywords = [
            "dump", "bearish", "sell", "crash", "scam", "rug", "dead",
            "overvalued", "bubble", "avoid", "warning", "careful",
        ]

        bullish_count = 0
        bearish_count = 0

        for post in posts:
            title = post.get("title", "").lower()
            text = post.get("selftext", "").lower()
            content = title + " " + text

            is_bullish = any(word in content for word in bullish_keywords)
            is_bearish = any(word in content for word in bearish_keywords)

            # Also consider upvote ratio
            upvote_ratio = post.get("upvote_ratio", 0.5)

            if is_bullish:
                bullish_count += 1 * upvote_ratio
            if is_bearish:
                bearish_count += 1 * upvote_ratio

        total = bullish_count + bearish_count
        if total == 0:
            return {"score": 0.0, "bullish_ratio": 0.5}

        bullish_ratio = bullish_count / total
        score = (bullish_ratio - 0.5) * 2

        return {"score": score, "bullish_ratio": bullish_ratio}
