# Kemoverse - a gacha-style bot for the Fediverse.
# Copyright © 2025 Moon and contributors.

# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.

# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU Affero General Public License for more details.

# You should have received a copy of the GNU Affero General Public License
# along with this program.  If not, see https://www.gnu.org/licenses/.

from abc import ABC, abstractmethod
from typing import List, Optional, Union, BinaryIO
from fediverse_types import FediverseNotification, FediversePost, FediverseFile, Visibility


class FediverseService(ABC):
    """Abstract interface for Fediverse platform services (Misskey, Pleroma, etc.)"""
    
    @abstractmethod
    def get_notifications(self, since_id: Optional[str] = None) -> List[FediverseNotification]:
        """
        Retrieve notifications from the Fediverse instance.
        
        Args:
            since_id: Optional ID to get notifications newer than this ID
            
        Returns:
            List of FediverseNotification objects
        """
        pass
    
    @abstractmethod
    def create_post(
        self,
        text: str,
        reply_to_id: Optional[str] = None,
        visibility: Visibility = Visibility.HOME,
        file_ids: Optional[List[str]] = None,
        visible_user_ids: Optional[List[str]] = None
    ) -> str:
        """
        Create a new post on the Fediverse instance.
        
        Args:
            text: The text content of the post
            reply_to_id: Optional ID of post to reply to
            visibility: Visibility level for the post
            file_ids: Optional list of file IDs to attach
            visible_user_ids: Optional list of user IDs who can see the post (for specified visibility)
            
        Returns:
            ID of the created post
        """
        pass
    
    @abstractmethod
    def get_post_by_id(self, post_id: str) -> Optional[FediversePost]:
        """
        Retrieve a specific post by its ID.
        
        Args:
            post_id: The ID of the post to retrieve
            
        Returns:
            FediversePost object if found, None otherwise
        """
        pass
    
    @abstractmethod
    def upload_file(self, file_data: Union[BinaryIO, bytes], filename: Optional[str] = None) -> FediverseFile:
        """
        Upload a file to the Fediverse instance.
        
        Args:
            file_data: File data as binary stream or bytes
            filename: Optional filename for the uploaded file
            
        Returns:
            FediverseFile object with ID, URL, and other metadata
            
        Raises:
            RuntimeError: If file upload fails
        """
        pass