"""GitHub Discussions operations (#83)."""
from __future__ import annotations

from .core import GitHubError, _graphql


def add_discussion_comment(token: str, discussion_id: str, body: str) -> dict:
    """
    Post a comment to a GitHub Discussion.

    Returns: {"id": str, "url": str}
    """
    if not discussion_id.strip():
        raise ValueError("discussion_id must not be empty.")
    if not body.strip():
        raise ValueError("Comment body must not be empty.")

    query = """
    mutation AddDiscussionComment($discussionId: ID!, $body: String!) {
      addDiscussionComment(input: {discussionId: $discussionId, body: $body}) {
        comment {
          id
          url
        }
      }
    }
    """
    data = _graphql(token, query, {"discussionId": discussion_id, "body": body})
    comment = data["addDiscussionComment"]["comment"]
    return {"id": comment["id"], "url": comment["url"]}


def create_discussion(
    token: str,
    repo_id: str,
    category_id: str,
    title: str,
    body: str,
) -> dict:
    """
    Create a new GitHub Discussion.

    Returns: {"id": str, "number": int, "url": str}
    """
    for name, value in [
        ("repo_id", repo_id),
        ("category_id", category_id),
        ("title", title),
        ("body", body),
    ]:
        if not value.strip():
            raise ValueError(f"{name} must not be empty.")

    query = """
    mutation CreateDiscussion(
      $repositoryId: ID!,
      $categoryId: ID!,
      $title: String!,
      $body: String!
    ) {
      createDiscussion(input: {
        repositoryId: $repositoryId,
        categoryId: $categoryId,
        title: $title,
        body: $body
      }) {
        discussion {
          id
          number
          url
        }
      }
    }
    """
    data = _graphql(
        token,
        query,
        {
            "repositoryId": repo_id,
            "categoryId": category_id,
            "title": title,
            "body": body,
        },
    )
    d = data["createDiscussion"]["discussion"]
    return {"id": d["id"], "number": d["number"], "url": d["url"]}


def get_discussion_body(token: str, discussion_id: str) -> str:
    """Fetch the current opening-post body of a Discussion.

    Raises GitHubError if the Discussion is not found.
    """
    if not discussion_id.strip():
        raise ValueError("discussion_id must not be empty.")

    query = """
    query($id: ID!) {
      node(id: $id) { ... on Discussion { body } }
    }
    """
    data = _graphql(token, query, {"id": discussion_id})
    node = data.get("node") or {}
    body = node.get("body")
    if body is None:
        raise GitHubError(f"Discussion {discussion_id} not found.")
    return body


def update_discussion_body(token: str, discussion_id: str, body: str) -> bool:
    """
    Replace the opening post body of a Discussion.

    Returns True on success. Raises GitHubError on failure.
    """
    if not discussion_id.strip():
        raise ValueError("discussion_id must not be empty.")
    if not body.strip():
        raise ValueError("body must not be empty.")

    query = """
    mutation UpdateDiscussion($discussionId: ID!, $body: String!) {
      updateDiscussion(input: {discussionId: $discussionId, body: $body}) {
        discussion { id }
      }
    }
    """
    _graphql(token, query, {"discussionId": discussion_id, "body": body})
    return True


def get_discussion_comments(
    token: str, discussion_id: str, last_n: int = 20
) -> list[dict]:
    """
    Fetch the last N comments from a Discussion.

    Returns list of {"id": str, "body": str, "createdAt": str}
    """
    if not discussion_id.strip():
        raise ValueError("discussion_id must not be empty.")
    if last_n < 1 or last_n > 100:
        raise ValueError("last_n must be between 1 and 100.")

    query = """
    query GetDiscussionComments($id: ID!, $last: Int!) {
      node(id: $id) {
        ... on Discussion {
          comments(last: $last) {
            nodes {
              id
              body
              createdAt
            }
          }
        }
      }
    }
    """
    data = _graphql(token, query, {"id": discussion_id, "last": last_n})
    node = data.get("node")
    if not node:
        raise GitHubError(f"Discussion {discussion_id} not found.")
    return node["comments"]["nodes"]


def mark_discussion_answer(token: str, comment_id: str) -> bool:
    """
    Mark a Discussion comment as the accepted answer.

    Only works on answerable Discussion categories.
    Returns True on success, raises GitHubError otherwise.
    """
    if not comment_id.strip():
        raise ValueError("comment_id must not be empty.")

    query = """
    mutation MarkAnswer($commentId: ID!) {
      markDiscussionCommentAsAnswer(input: {id: $commentId}) {
        discussion { id }
      }
    }
    """
    _graphql(token, query, {"commentId": comment_id})
    return True
