"""
Topic subscription - allows users to subscribe to specific news topics.
Topics are extracted from news analysis and can evolve over time.
"""

from typing import Optional, Dict, Any, List
from datetime import datetime, UTC
from loguru import logger

from .base_subscription import BaseSubscription
from ..core.base_card import CardSource
from ..core.utils import utc_now


class TopicSubscription(BaseSubscription):
    """
    Subscription to a specific news topic.
    Topics can be extracted from news or manually created.
    """

    def __init__(
        self,
        topic: str,
        user_id: str,
        refresh_interval_minutes: int = 240,  # Default 4 hours
        source: Optional[CardSource] = None,
        related_topics: Optional[List[str]] = None,
        subscription_id: Optional[str] = None,
    ):
        """
        Initialize a topic subscription.

        Args:
            user_id: ID of the user
            topic: The topic to follow
            source: Source information (auto-created if not provided)
            refresh_interval_minutes: How often to check for updates in minutes
            related_topics: Other topics related to this one
            subscription_id: Optional ID
        """
        # Create source if not provided
        if source is None:
            source = CardSource(
                type="news_topic", created_from=f"Topic subscription: {topic}"
            )

        super().__init__(
            user_id, source, topic, refresh_interval_minutes, subscription_id
        )

        self.topic = topic
        self.related_topics = related_topics or []

        # Set subscription type
        self.subscription_type = "topic"

        # Track topic evolution
        self.topic_history = [topic]
        self.current_topic = topic

        # Track when topic was last significantly active
        self.last_significant_activity = utc_now()
        self.activity_threshold = 3  # Min news items to be "active"

        # Metadata specific to topic subscriptions
        self.metadata.update(
            {
                "subscription_type": "topic",
                "original_topic": topic,
                "is_trending": False,
                "topic_category": None,  # Will be set by analyzer
            }
        )

        logger.info(f"Created topic subscription for: {topic}")

    def get_subscription_type(self) -> str:
        """Return the subscription type identifier."""
        return "topic_subscription"

    def generate_search_query(self) -> str:
        """
        Generate a search query for this topic.

        Returns:
            str: The search query for finding news about this topic
        """
        # Build query with main topic and related topics
        query_parts = [self.current_topic]

        # Add some related topics for broader coverage
        if self.related_topics:
            # Add up to 2 related topics
            query_parts.extend(self.related_topics[:2])

        # Combine with news-specific terms
        base_query = " OR ".join(f'"{part}"' for part in query_parts)
        news_query = f"{base_query} latest news today developments breaking"

        # Update any date placeholders with current date
        current_date = datetime.now(UTC).date().isoformat()

        # Replace YYYY-MM-DD placeholder ONLY (not all dates)
        news_query = news_query.replace("YYYY-MM-DD", current_date)

        logger.debug(f"Generated topic query: {news_query}")
        return news_query

    def update_activity(
        self, news_count: int, significant_news: bool = False
    ) -> None:
        """
        Update activity tracking for this topic.

        Args:
            news_count: Number of news items found
            significant_news: Whether any news was particularly significant
        """
        if news_count >= self.activity_threshold or significant_news:
            self.last_significant_activity = utc_now()
            self.metadata["is_trending"] = True
        else:
            # Check if topic is becoming stale
            hours_since_activity = (
                utc_now() - self.last_significant_activity
            ).total_seconds() / 3600

            if hours_since_activity > 72:  # 3 days
                self.metadata["is_trending"] = False

    def evolve_topic(
        self, new_form: str, reason: str = "natural evolution"
    ) -> None:
        """
        Evolve the topic to a new form.

        Args:
            new_form: The new form of the topic
            reason: Why the topic evolved
        """
        if new_form != self.current_topic:
            self.topic_history.append(new_form)
            self.current_topic = new_form

            self.metadata["last_evolution"] = {
                "from": self.topic_history[-2],
                "to": new_form,
                "reason": reason,
                "timestamp": utc_now().isoformat(),
            }

            logger.info(
                f"Topic evolved from '{self.topic_history[-2]}' to '{new_form}' - {reason}"
            )

    def add_related_topic(self, topic: str) -> None:
        """
        Add a related topic.

        Args:
            topic: Related topic to add
        """
        if topic not in self.related_topics and topic != self.current_topic:
            self.related_topics.append(topic)
            logger.debug(
                f"Added related topic '{topic}' to '{self.current_topic}'"
            )

    def merge_with(self, other_subscription: "TopicSubscription") -> None:
        """
        Merge another topic subscription into this one.
        Useful when topics converge.

        Args:
            other_subscription: The subscription to merge
        """
        # Add the other topic as related
        self.add_related_topic(other_subscription.current_topic)

        # Merge related topics
        for topic in other_subscription.related_topics:
            self.add_related_topic(topic)

        # Update metadata
        self.metadata["merged_from"] = {
            "topic": other_subscription.current_topic,
            "subscription_id": other_subscription.id,
            "timestamp": utc_now().isoformat(),
        }

        logger.info(
            f"Merged topic '{other_subscription.current_topic}' into '{self.current_topic}'"
        )

    def should_auto_expire(self) -> bool:
        """
        Check if this subscription should auto-expire due to inactivity.

        Returns:
            bool: True if subscription should expire
        """
        # Don't expire if actively refreshing successfully
        if self.error_count == 0 and self.refresh_count > 0:
            # Check activity
            days_inactive = (
                utc_now() - self.last_significant_activity
            ).total_seconds() / (24 * 3600)

            # Expire after 30 days of no significant activity
            return days_inactive > 30

        return False

    def get_statistics(self) -> Dict[str, Any]:
        """Get statistics about this topic subscription."""
        return {
            "original_topic": self.topic,
            "current_topic": self.current_topic,
            "evolution_count": len(self.topic_history) - 1,
            "related_topics_count": len(self.related_topics),
            "is_trending": self.metadata.get("is_trending", False),
            "days_since_activity": (
                utc_now() - self.last_significant_activity
            ).total_seconds()
            / (24 * 3600),
            "total_refreshes": self.refresh_count,
        }

    def to_dict(self) -> Dict[str, Any]:
        """Convert to dictionary representation."""
        data = super().to_dict()
        data.update(
            {
                "topic": self.topic,
                "current_topic": self.current_topic,
                "related_topics": self.related_topics,
                "topic_history": self.topic_history,
                "last_significant_activity": self.last_significant_activity.isoformat(),
                "statistics": self.get_statistics(),
            }
        )
        return data


class TopicSubscriptionFactory:
    """
    Factory for creating topic subscriptions from various sources.
    """

    @staticmethod
    def from_news_extraction(
        user_id: str,
        topic: str,
        source_news_id: str,
        related_topics: Optional[List[str]] = None,
        **kwargs,
    ) -> TopicSubscription:
        """
        Create a subscription from an extracted news topic.

        Args:
            user_id: The user creating the subscription
            topic: The extracted topic
            source_news_id: ID of the news item it came from
            related_topics: Other related topics
            **kwargs: Additional arguments

        Returns:
            TopicSubscription instance
        """
        source = CardSource(
            type="news_topic",
            source_id=source_news_id,
            created_from=f"Topic from news analysis: {topic}",
            metadata={
                "extraction_timestamp": utc_now().isoformat(),
                "extraction_method": kwargs.get("extraction_method", "llm"),
            },
        )

        return TopicSubscription(
            user_id=user_id,
            topic=topic,
            source=source,
            related_topics=related_topics,
            **kwargs,
        )

    @staticmethod
    def from_user_interest(
        user_id: str, topic: str, **kwargs
    ) -> TopicSubscription:
        """
        Create a subscription from direct user interest.

        Args:
            user_id: The user
            topic: Topic they're interested in
            **kwargs: Additional arguments

        Returns:
            TopicSubscription instance
        """
        source = CardSource(
            type="user_interest",
            created_from=f"Your interest: {topic}",
            metadata={"created_via": kwargs.get("created_via", "manual")},
        )

        return TopicSubscription(
            user_id=user_id, topic=topic, source=source, **kwargs
        )
