"""Base trait definition for repository handlers."""

from abc import ABC, abstractmethod

# Import schema types for type hints
from .github.schema import GitHubReviewComment
from .gitlab.schema import GitLabReviewComment
from .schema import BasicReviewOutput, DiscussionItem, MergeRequest

# Union type for all platform review types
PlatformReview = GitHubReviewComment | GitLabReviewComment | BasicReviewOutput


class RepositoryHandler(ABC):
    """
    Abstract base class defining the interface for repository operations.
    This allows the workflow to be platform-agnostic for repository operations.
    """

    @abstractmethod
    async def fetch_merge_request(self, repo: str, merge_id: str) -> MergeRequest:
        """
        Fetch merge request/pull request information.

        Args:
            repo: Repository identifier (e.g., "owner/repo")
            merge_id: Merge request/pull request ID

        Returns:
            MergeRequest object with all details
        """
        pass

    @abstractmethod
    async def fetch_discussions(self, repo: str, merge_id: str) -> list[DiscussionItem]:
        """
        Fetch all discussions (comments and review threads) for a merge request.
        This method handles pagination internally and returns all discussions.

        Returns discussions sorted by updated_at desc, filtered to only human comments.

        Args:
            repo: Repository identifier
            merge_id: Merge request/pull request ID

        Returns:
            list of discussion items
        """
        pass

    @abstractmethod
    async def post_comment(self, repo: str, merge_id: str, content: str) -> None:
        """
        Post a comment on the merge request.

        Args:
            repo: Repository identifier
            merge_id: Merge request/pull request ID
            content: Comment content in Markdown format
        """
        pass

    @abstractmethod
    async def post_review(
        self, merge_request: MergeRequest, reviews: list[PlatformReview]
    ) -> tuple[int, int]:
        """
        Post review comments/discussions.

        Each platform adaptor extracts what it needs from the MergeRequest
        (e.g., commit SHA, base SHA) and combines it with the review data.

        Args:
            merge_request: The merge request being reviewed
            reviews: List of platform-specific review comments
                - GitHub: list[GitHubReviewComment]
                - GitLab: list[GitLabReviewComment]

        Returns:
            Tuple of (successful, failed) comment counts
        """
        pass

    @abstractmethod
    def platform_name(self) -> str:
        """Get platform name (e.g., 'GitHub', 'GitLab')."""
        pass

    @abstractmethod
    async def fetch_archive(self, repo: str, ref: str) -> bytes:
        """
        Download repository archive as a ZIP file.

        Args:
            repo: Repository identifier (e.g., "owner/repo")
            ref: Git reference (branch, tag, or commit SHA)

        Returns:
            ZIP file content as bytes
        """
        pass

    @abstractmethod
    async def fetch_file(self, repo: str, ref: str, path: str) -> str | None:
        """
        Fetch a file from the repository.

        Args:
            repo: Repository identifier (e.g., "owner/repo")
            ref: Git reference (branch, tag, or commit SHA)
            path: Path to the file in the repository

        Returns:
            File content as string, or None if file not found
        """
        pass

    @staticmethod
    @abstractmethod
    def output_format() -> str:
        """Get platform-specific output format instructions for LLM."""
        pass

    @abstractmethod
    async def close(self) -> None:
        """Close the HTTP client."""
        pass
