"""Reddit resource for Agent Berlin SDK."""

from datetime import datetime
from typing import Any, Dict, Optional

from .._http import HTTPClient
from ..models.reddit import (
    PostCommentsResponse,
    RedditComment,
    RedditPost,
    RedditSearchResponse,
    SubredditInfo,
    SubredditPostsResponse,
)
from ..utils import get_project_domain


def _parse_post(data: Dict[str, Any]) -> RedditPost:
    """Parse a post dict into a RedditPost model."""
    return RedditPost(
        id=data["id"],
        title=data["title"],
        author=data["author"],
        subreddit=data["subreddit"],
        score=data["score"],
        upvote_ratio=data["upvote_ratio"],
        num_comments=data["num_comments"],
        created=datetime.fromtimestamp(data["created"]),
        url=data["url"],
        permalink=data["permalink"],
        is_self=data["is_self"],
        selftext=data.get("selftext"),
        domain=data["domain"],
        nsfw=data["nsfw"],
        spoiler=data["spoiler"],
        locked=data["locked"],
        stickied=data["stickied"],
    )


def _parse_comment(data: Dict[str, Any]) -> RedditComment:
    """Parse a comment dict into a RedditComment model."""
    replies = []
    if data.get("replies"):
        replies = [_parse_comment(r) for r in data["replies"]]

    return RedditComment(
        id=data["id"],
        author=data["author"],
        body=data["body"],
        score=data["score"],
        created=datetime.fromtimestamp(data["created"]),
        permalink=data["permalink"],
        depth=data["depth"],
        is_op=data["is_op"],
        replies=replies,
    )


class RedditResource:
    """Resource for Reddit read-only operations.

    Provides access to Reddit data through the Agent Berlin API.
    The project context is determined by the sandbox's PROJECT_DOMAIN environment
    variable, so methods don't require explicit project parameters.

    Example:
        # Get posts from a subreddit
        posts = client.reddit.get_subreddit_posts(
            subreddit="programming",
            sort="top",
            time_filter="week",
            limit=25
        )
        for post in posts.posts:
            print(f"{post.title}: {post.score} points")

        # Search Reddit
        results = client.reddit.search(
            query="python async",
            subreddit="learnprogramming"
        )
        for post in results.posts:
            print(f"{post.title}")

        # Get comments on a post
        comments = client.reddit.get_post_comments("abc123")
        for comment in comments.comments:
            print(f"{comment.author}: {comment.body[:100]}")
    """

    def __init__(self, http: HTTPClient) -> None:
        self._http = http

    def get_subreddit_posts(
        self,
        subreddit: str,
        *,
        sort: Optional[str] = None,
        time_filter: Optional[str] = None,
        limit: Optional[int] = None,
        after: Optional[str] = None,
    ) -> SubredditPostsResponse:
        """Fetch posts from a subreddit.

        Args:
            subreddit: The subreddit name (without /r/ prefix).
            sort: Sort order. Options: "hot", "new", "top", "rising".
                Defaults to "hot".
            time_filter: Time filter for "top" sort. Options: "hour", "day",
                "week", "month", "year", "all".
            limit: Maximum number of posts (1-100). Defaults to 25.
            after: Pagination cursor from previous response.

        Returns:
            SubredditPostsResponse with posts list and pagination cursor.

        Raises:
            AgentBerlinNotFoundError: If Reddit integration not found.
            AgentBerlinAPIError: If the API returns an error.
        """
        project_domain = get_project_domain()
        payload: Dict[str, Any] = {
            "project_domain": project_domain,
            "subreddit": subreddit,
        }

        if sort is not None:
            payload["sort"] = sort
        if time_filter is not None:
            payload["time_filter"] = time_filter
        if limit is not None:
            payload["limit"] = limit
        if after is not None:
            payload["after"] = after

        data = self._http.post("/reddit/subreddit/posts", json=payload)

        posts = [_parse_post(p) for p in data.get("posts", [])]
        return SubredditPostsResponse(
            posts=posts,
            after=data.get("after"),
        )

    def search(
        self,
        query: str,
        *,
        subreddit: Optional[str] = None,
        sort: Optional[str] = None,
        time_filter: Optional[str] = None,
        limit: Optional[int] = None,
        after: Optional[str] = None,
    ) -> RedditSearchResponse:
        """Search Reddit posts.

        Args:
            query: The search query.
            subreddit: Optional subreddit to restrict search to.
            sort: Sort order. Options: "relevance", "hot", "top", "new",
                "comments". Defaults to "relevance".
            time_filter: Time filter. Options: "hour", "day", "week",
                "month", "year", "all".
            limit: Maximum number of results (1-100). Defaults to 25.
            after: Pagination cursor from previous response.

        Returns:
            RedditSearchResponse with query, posts list, and pagination cursor.

        Raises:
            AgentBerlinNotFoundError: If Reddit integration not found.
            AgentBerlinAPIError: If the API returns an error.
        """
        project_domain = get_project_domain()
        payload: Dict[str, Any] = {
            "project_domain": project_domain,
            "query": query,
        }

        if subreddit is not None:
            payload["subreddit"] = subreddit
        if sort is not None:
            payload["sort"] = sort
        if time_filter is not None:
            payload["time_filter"] = time_filter
        if limit is not None:
            payload["limit"] = limit
        if after is not None:
            payload["after"] = after

        data = self._http.post("/reddit/search", json=payload)

        posts = [_parse_post(p) for p in data.get("posts", [])]
        return RedditSearchResponse(
            query=data.get("query", query),
            posts=posts,
            after=data.get("after"),
        )

    def get_post(self, post_id: str) -> RedditPost:
        """Get a single post by ID.

        Args:
            post_id: The post ID (with or without t3_ prefix).

        Returns:
            RedditPost with full post details.

        Raises:
            AgentBerlinNotFoundError: If post or integration not found.
            AgentBerlinAPIError: If the API returns an error.
        """
        project_domain = get_project_domain()
        payload: Dict[str, Any] = {
            "project_domain": project_domain,
            "post_id": post_id,
        }

        data = self._http.post("/reddit/post", json=payload)
        return _parse_post(data)

    def get_post_comments(
        self,
        post_id: str,
        *,
        sort: Optional[str] = None,
        limit: Optional[int] = None,
    ) -> PostCommentsResponse:
        """Get comments on a post.

        Args:
            post_id: The post ID (with or without t3_ prefix).
            sort: Comment sort order. Options: "best", "top", "new",
                "controversial", "old". Defaults to "best".
            limit: Maximum number of comments (1-500). Defaults to 50.

        Returns:
            PostCommentsResponse with post details and comments list.

        Raises:
            AgentBerlinNotFoundError: If post or integration not found.
            AgentBerlinAPIError: If the API returns an error.
        """
        project_domain = get_project_domain()
        payload: Dict[str, Any] = {
            "project_domain": project_domain,
            "post_id": post_id,
        }

        if sort is not None:
            payload["sort"] = sort
        if limit is not None:
            payload["limit"] = limit

        data = self._http.post("/reddit/post/comments", json=payload)

        post = _parse_post(data["post"])
        comments = [_parse_comment(c) for c in data.get("comments", [])]

        return PostCommentsResponse(
            post=post,
            comments=comments,
        )

    def get_subreddit_info(self, subreddit: str) -> SubredditInfo:
        """Get subreddit metadata.

        Args:
            subreddit: The subreddit name (without /r/ prefix).

        Returns:
            SubredditInfo with subreddit metadata.

        Raises:
            AgentBerlinNotFoundError: If subreddit or integration not found.
            AgentBerlinAPIError: If the API returns an error.
        """
        project_domain = get_project_domain()
        payload: Dict[str, Any] = {
            "project_domain": project_domain,
            "subreddit": subreddit,
        }

        data = self._http.post("/reddit/subreddit/info", json=payload)

        return SubredditInfo(
            name=data["name"],
            title=data["title"],
            description=data["description"],
            public_description=data["public_description"],
            subscribers=data["subscribers"],
            active_users=data["active_users"],
            created=datetime.fromtimestamp(data["created"]),
            nsfw=data["nsfw"],
            icon_url=data.get("icon_url"),
            banner_url=data.get("banner_url"),
        )
