"""
Base storage interfaces for the news system.
"""

from abc import ABC, abstractmethod
from typing import List, Optional, Dict, Any
from datetime import datetime
import uuid


class BaseStorage(ABC):
    """Abstract base class for all storage interfaces"""

    @abstractmethod
    def create(self, data: Dict[str, Any]) -> str:
        """Create a new record and return its ID"""
        pass

    @abstractmethod
    def get(self, id: str) -> Optional[Dict[str, Any]]:
        """Get a record by ID"""
        pass

    @abstractmethod
    def update(self, id: str, data: Dict[str, Any]) -> bool:
        """Update a record, return True if successful"""
        pass

    @abstractmethod
    def delete(self, id: str) -> bool:
        """Delete a record, return True if successful"""
        pass

    @abstractmethod
    def list(
        self,
        filters: Optional[Dict[str, Any]] = None,
        limit: int = 100,
        offset: int = 0,
    ) -> List[Dict[str, Any]]:
        """List records with optional filtering"""
        pass

    def generate_id(self) -> str:
        """Generate a unique ID"""
        return str(uuid.uuid4())


class CardStorage(BaseStorage):
    """Interface for news card storage"""

    @abstractmethod
    def get_by_user(
        self, user_id: str, limit: int = 50, offset: int = 0
    ) -> List[Dict[str, Any]]:
        """Get cards for a specific user"""
        pass

    @abstractmethod
    def get_latest_version(self, card_id: str) -> Optional[Dict[str, Any]]:
        """Get the latest version of a card"""
        pass

    @abstractmethod
    def add_version(self, card_id: str, version_data: Dict[str, Any]) -> str:
        """Add a new version to a card"""
        pass

    @abstractmethod
    def update_latest_info(
        self, card_id: str, version_data: Dict[str, Any]
    ) -> bool:
        """Update the denormalized latest version info on the card"""
        pass

    @abstractmethod
    def archive_card(self, card_id: str) -> bool:
        """Archive a card"""
        pass

    @abstractmethod
    def pin_card(self, card_id: str, pinned: bool = True) -> bool:
        """Pin or unpin a card"""
        pass


class SubscriptionStorage(BaseStorage):
    """Interface for subscription storage"""

    @abstractmethod
    def get_active_subscriptions(
        self, user_id: Optional[str] = None
    ) -> List[Dict[str, Any]]:
        """Get all active subscriptions, optionally filtered by user"""
        pass

    @abstractmethod
    def get_due_subscriptions(self, limit: int = 100) -> List[Dict[str, Any]]:
        """Get subscriptions that are due for refresh"""
        pass

    @abstractmethod
    def update_refresh_time(
        self,
        subscription_id: str,
        last_refresh: datetime,
        next_refresh: datetime,
    ) -> bool:
        """Update refresh timestamps after processing"""
        pass

    @abstractmethod
    def increment_stats(self, subscription_id: str, results_count: int) -> bool:
        """Increment refresh count and update results count"""
        pass

    @abstractmethod
    def pause_subscription(self, subscription_id: str) -> bool:
        """Pause a subscription"""
        pass

    @abstractmethod
    def resume_subscription(self, subscription_id: str) -> bool:
        """Resume a paused subscription"""
        pass

    @abstractmethod
    def expire_subscription(self, subscription_id: str) -> bool:
        """Mark a subscription as expired"""
        pass


class RatingStorage(BaseStorage):
    """Interface for rating storage"""

    @abstractmethod
    def get_user_rating(
        self, user_id: str, item_id: str, rating_type: str
    ) -> Optional[Dict[str, Any]]:
        """Get a user's rating for a specific item"""
        pass

    @abstractmethod
    def upsert_rating(
        self,
        user_id: str,
        item_id: str,
        rating_type: str,
        rating_value: str,
        item_type: str = "card",
    ) -> str:
        """Create or update a rating"""
        pass

    @abstractmethod
    def get_ratings_summary(
        self, item_id: str, item_type: str = "card"
    ) -> Dict[str, Any]:
        """Get aggregated ratings for an item"""
        pass

    @abstractmethod
    def get_user_ratings(
        self, user_id: str, rating_type: Optional[str] = None, limit: int = 100
    ) -> List[Dict[str, Any]]:
        """Get all ratings by a user"""
        pass


class PreferenceStorage(BaseStorage):
    """Interface for user preference storage"""

    @abstractmethod
    def get_user_preferences(self, user_id: str) -> Optional[Dict[str, Any]]:
        """Get preferences for a user"""
        pass

    @abstractmethod
    def upsert_preferences(
        self, user_id: str, preferences: Dict[str, Any]
    ) -> str:
        """Create or update user preferences"""
        pass

    @abstractmethod
    def add_liked_item(
        self, user_id: str, item_id: str, item_type: str = "news"
    ) -> bool:
        """Add an item to liked list"""
        pass

    @abstractmethod
    def add_disliked_item(
        self, user_id: str, item_id: str, item_type: str = "news"
    ) -> bool:
        """Add an item to disliked list"""
        pass

    @abstractmethod
    def update_preference_embedding(
        self, user_id: str, embedding: List[float]
    ) -> bool:
        """Update the user's preference embedding"""
        pass


class SearchHistoryStorage(BaseStorage):
    """Interface for search history storage (if tracking enabled)"""

    @abstractmethod
    def record_search(
        self, user_id: str, query: str, search_data: Dict[str, Any]
    ) -> str:
        """Record a search query"""
        pass

    @abstractmethod
    def get_recent_searches(
        self, user_id: str, hours: int = 48, limit: int = 50
    ) -> List[Dict[str, Any]]:
        """Get recent searches for a user"""
        pass

    @abstractmethod
    def link_to_subscription(
        self, search_id: str, subscription_id: str
    ) -> bool:
        """Link a search to a subscription created from it"""
        pass

    @abstractmethod
    def get_popular_searches(
        self, hours: int = 24, limit: int = 20
    ) -> List[Dict[str, Any]]:
        """Get popular searches across all users"""
        pass


class NewsItemStorage(BaseStorage):
    """Interface for news item storage (the raw news data)"""

    @abstractmethod
    def get_recent(
        self, hours: int = 24, limit: int = 50
    ) -> List[Dict[str, Any]]:
        """Get recent news items"""
        pass

    @abstractmethod
    def store_batch(self, news_items: List[Dict[str, Any]]) -> List[str]:
        """Store multiple news items at once"""
        pass

    @abstractmethod
    def update_votes(self, news_id: str, vote_type: str) -> bool:
        """Update vote counts"""
        pass

    @abstractmethod
    def get_by_category(
        self, category: str, limit: int = 50
    ) -> List[Dict[str, Any]]:
        """Get news items by category"""
        pass

    @abstractmethod
    def cleanup_old_items(self, days: int = 7) -> int:
        """Remove old news items, return count deleted"""
        pass
