import httpx
from typing import List, Dict
from datetime import datetime, timedelta
from textblob import TextBlob
import hashlib
from app.config import settings
from app.schemas.schemas import (
    NewsArticle,
    NewsFeedResponse,
    Sentiment,
    EconomicEvent,
    EconomicCalendarResponse,
)


class NewsService:
    def __init__(self):
        self.alpha_vantage_key = settings.ALPHA_VANTAGE_API_KEY
        self.finnhub_key = settings.FINNHUB_API_KEY
        self.news_api_key = settings.NEWS_API_KEY

        # Gold-related keywords for relevance scoring
        self.gold_keywords = {
            "high_relevance": [
                "gold", "xau", "precious metals", "bullion", "gold price",
                "gold market", "gold trading", "gold miners", "gold etf"
            ],
            "medium_relevance": [
                "federal reserve", "fed", "inflation", "interest rates",
                "dollar", "usd", "monetary policy", "central bank",
                "jerome powell", "treasury", "bonds"
            ],
            "context_relevance": [
                "geopolitics", "war", "sanctions", "recession",
                "crisis", "safe haven", "risk off", "uncertainty"
            ]
        }

        # Impact categories
        self.impact_categories = {
            "MONETARY_POLICY": ["federal reserve", "fed", "interest rate", "monetary policy", "central bank"],
            "GEOPOLITICS": ["war", "conflict", "sanctions", "tension", "geopolitical"],
            "ECONOMIC_DATA": ["inflation", "cpi", "gdp", "employment", "jobs", "unemployment"],
            "MARKET_SENTIMENT": ["risk", "sentiment", "volatility", "safe haven"],
            "COMMODITY": ["gold", "precious metals", "bullion", "commodities"],
        }

    def _calculate_relevance_score(self, text: str) -> float:
        """Calculate how relevant a news article is to gold trading"""
        text_lower = text.lower()
        score = 0.0

        # High relevance keywords
        for keyword in self.gold_keywords["high_relevance"]:
            if keyword in text_lower:
                score += 0.4

        # Medium relevance keywords
        for keyword in self.gold_keywords["medium_relevance"]:
            if keyword in text_lower:
                score += 0.2

        # Context relevance keywords
        for keyword in self.gold_keywords["context_relevance"]:
            if keyword in text_lower:
                score += 0.1

        return min(score, 1.0)

    def _categorize_news(self, text: str) -> str:
        """Categorize news based on content"""
        text_lower = text.lower()

        for category, keywords in self.impact_categories.items():
            for keyword in keywords:
                if keyword in text_lower:
                    return category

        return "OTHER"

    def _analyze_sentiment(self, text: str) -> tuple[Sentiment, float]:
        """Analyze sentiment using TextBlob"""
        try:
            analysis = TextBlob(text)
            polarity = analysis.sentiment.polarity

            if polarity > 0.1:
                sentiment = Sentiment.POSITIVE
            elif polarity < -0.1:
                sentiment = Sentiment.NEGATIVE
            else:
                sentiment = Sentiment.NEUTRAL

            return sentiment, polarity
        except Exception:
            return Sentiment.NEUTRAL, 0.0

    def _assess_gold_impact(self, sentiment: Sentiment, category: str, relevance: float) -> str:
        """Assess impact level on gold prices"""
        # High impact categories
        high_impact_cats = ["MONETARY_POLICY", "ECONOMIC_DATA"]

        if relevance > 0.7:
            if category in high_impact_cats:
                return "HIGH"
            return "MEDIUM"
        elif relevance > 0.4:
            return "MEDIUM"
        else:
            return "LOW"

    async def fetch_alpha_vantage_news(self, topics: str = "economy_monetary,finance") -> List[NewsArticle]:
        """Fetch news from Alpha Vantage News Sentiment API"""
        try:
            params = {
                "function": "NEWS_SENTIMENT",
                "topics": topics,
                "limit": 50,
                "apikey": self.alpha_vantage_key,
            }

            async with httpx.AsyncClient(timeout=30.0) as client:
                response = await client.get(
                    settings.ALPHA_VANTAGE_BASE_URL,
                    params=params
                )
                response.raise_for_status()
                data = response.json()

            if "feed" not in data:
                return []

            articles = []
            for item in data["feed"]:
                title = item.get("title", "")
                summary = item.get("summary", "")
                full_text = f"{title} {summary}"

                relevance = self._calculate_relevance_score(full_text)

                # Filter only gold-relevant news
                if relevance < 0.3:
                    continue

                sentiment, score = self._analyze_sentiment(full_text)
                category = self._categorize_news(full_text)
                impact = self._assess_gold_impact(sentiment, category, relevance)

                # Parse published date
                published_str = item.get("time_published", "")
                try:
                    published_at = datetime.strptime(published_str, "%Y%m%dT%H%M%S")
                except:
                    published_at = datetime.now()

                article_id = hashlib.md5(f"{title}{published_str}".encode()).hexdigest()

                articles.append(
                    NewsArticle(
                        id=article_id,
                        source=item.get("source", "Alpha Vantage"),
                        title=title,
                        description=summary,
                        url=item.get("url", ""),
                        published_at=published_at,
                        sentiment=sentiment,
                        sentiment_score=score,
                        impact_on_gold=impact,
                        relevance_score=relevance,
                        category=category,
                    )
                )

            return articles

        except Exception as e:
            print(f"Error fetching Alpha Vantage news: {e}")
            return []

    async def fetch_finnhub_news(self) -> List[NewsArticle]:
        """Fetch gold-related news from Finnhub"""
        if not self.finnhub_key:
            return []

        try:
            # Get general market news
            params = {
                "category": "forex",
                "token": self.finnhub_key,
            }

            async with httpx.AsyncClient(timeout=30.0) as client:
                response = await client.get(
                    f"{settings.FINNHUB_BASE_URL}/news",
                    params=params
                )
                response.raise_for_status()
                data = response.json()

            articles = []
            for item in data[:50]:  # Limit to 50 articles
                title = item.get("headline", "")
                summary = item.get("summary", "")
                full_text = f"{title} {summary}"

                relevance = self._calculate_relevance_score(full_text)

                # Filter only gold-relevant news
                if relevance < 0.3:
                    continue

                sentiment, score = self._analyze_sentiment(full_text)
                category = self._categorize_news(full_text)
                impact = self._assess_gold_impact(sentiment, category, relevance)

                published_at = datetime.fromtimestamp(item.get("datetime", 0))
                article_id = hashlib.md5(f"{title}{item.get('id', '')}".encode()).hexdigest()

                articles.append(
                    NewsArticle(
                        id=article_id,
                        source=item.get("source", "Finnhub"),
                        title=title,
                        description=summary,
                        url=item.get("url", ""),
                        published_at=published_at,
                        sentiment=sentiment,
                        sentiment_score=score,
                        impact_on_gold=impact,
                        relevance_score=relevance,
                        category=category,
                    )
                )

            return articles

        except Exception as e:
            print(f"Error fetching Finnhub news: {e}")
            return []

    async def get_aggregated_news_feed(self) -> NewsFeedResponse:
        """Get aggregated news from all sources"""
        # Fetch from multiple sources
        alpha_news = await self.fetch_alpha_vantage_news()
        finnhub_news = await self.fetch_finnhub_news() if self.finnhub_key else []

        # Combine and deduplicate
        all_articles = alpha_news + finnhub_news

        # Remove duplicates based on similar titles
        unique_articles = []
        seen_titles = set()

        for article in all_articles:
            title_key = article.title.lower()[:50]  # First 50 chars
            if title_key not in seen_titles:
                seen_titles.add(title_key)
                unique_articles.append(article)

        # Sort by published date (newest first)
        unique_articles.sort(key=lambda x: x.published_at, reverse=True)

        # Limit to most recent 50
        unique_articles = unique_articles[:50]

        # Calculate statistics
        bullish_count = sum(1 for a in unique_articles if a.sentiment == Sentiment.POSITIVE)
        bearish_count = sum(1 for a in unique_articles if a.sentiment == Sentiment.NEGATIVE)
        neutral_count = sum(1 for a in unique_articles if a.sentiment == Sentiment.NEUTRAL)

        avg_sentiment = (
            sum(a.sentiment_score for a in unique_articles) / len(unique_articles)
            if unique_articles else 0.0
        )

        # Determine overall sentiment
        if avg_sentiment > 0.1:
            overall_sentiment = Sentiment.POSITIVE
        elif avg_sentiment < -0.1:
            overall_sentiment = Sentiment.NEGATIVE
        else:
            overall_sentiment = Sentiment.NEUTRAL

        return NewsFeedResponse(
            articles=unique_articles,
            total_count=len(unique_articles),
            bullish_count=bullish_count,
            bearish_count=bearish_count,
            neutral_count=neutral_count,
            overall_sentiment=overall_sentiment,
            avg_sentiment_score=avg_sentiment,
        )

    async def get_economic_calendar(self) -> EconomicCalendarResponse:
        """Get upcoming economic events that impact gold"""
        # This would integrate with economic calendar APIs
        # For MVP, return curated list of upcoming events

        # In production, integrate with:
        # - Forex Factory API
        # - Investing.com Economic Calendar
        # - Alpha Vantage Economic Indicators

        # For now, return empty with structure
        events = []

        # Count high-impact upcoming events
        now = datetime.now()
        upcoming_high_impact = sum(
            1 for e in events
            if e.importance == "HIGH" and e.event_date > now
        )

        return EconomicCalendarResponse(
            events=events,
            upcoming_high_impact=upcoming_high_impact,
        )


news_service = NewsService()
