"""OCLAWMA Skill: GitHub

Official GitHub skill for OCLAWMA providing comprehensive repository
management, pull request operations, issue tracking, release management,
and GitHub Actions workflow monitoring.

Features:
- Repository operations (list, create, clone, search)
- Pull request management (list, create, review, merge)
- Issue tracking (list, create, update, search, labels)
- GitHub Actions monitoring (workflows, runs, logs, artifacts)
- Release management (list, create, assets)
- Code search and file operations
- Branch management and protection
- Collaboration tools (collaborators, teams)
"""

from __future__ import annotations

import base64
import os
import subprocess
from dataclasses import dataclass
from datetime import datetime
from typing import Any

import httpx
from oclawma.skills import LazySkill, SkillMetadata

__version__ = "1.0.0"
__all__ = ["GitHubSkill"]


@dataclass
class GitHubConfig:
    """GitHub API configuration."""
    token: str | None = None
    base_url: str = "https://api.github.com"
    per_page: int = 30
    timeout: int = 30

    @classmethod
    def from_env(cls) -> GitHubConfig:
        """Create config from environment variables."""
        return cls(
            token=os.environ.get("GITHUB_TOKEN") or os.environ.get("GH_TOKEN"),
            base_url=os.environ.get("GITHUB_API_URL", "https://api.github.com"),
            per_page=int(os.environ.get("GITHUB_PER_PAGE", "30")),
            timeout=int(os.environ.get("GITHUB_TIMEOUT", "30")),
        )


class GitHubSkill(LazySkill):
    """GitHub repository and workflow management skill.

    This skill provides comprehensive GitHub operations including
    repository management, pull requests, issues, releases, and
    GitHub Actions workflow monitoring.

    Features:
    - Repository operations (list, create, search, details)
    - Pull request management (create, review, merge, list)
    - Issue tracking (create, update, search, labels, milestones)
    - GitHub Actions (workflows, runs, logs, artifacts, rerun)
    - Release management (create, assets, notes)
    - Code operations (search, file content, branches)
    - Collaboration (collaborators, teams, permissions)

    Authentication:
        Set GITHUB_TOKEN or GH_TOKEN environment variable with a
        personal access token (classic) or fine-grained token.

        Required scopes for full functionality:
        - repo (full repository access)
        - workflow (Actions access)
        - read:org (organization read)

    Example:
        >>> from oclawma.skills import SkillRegistry
        >>> registry = SkillRegistry()
        >>>
        >>> # List repositories
        >>> result = await registry.execute_tool("github", "list_repos")
        >>>
        >>> # Create a pull request
        >>> result = await registry.execute_tool(
        ...     "github", "create_pr",
        ...     owner="myorg", repo="myrepo",
        ...     title="Fix bug", head="feature-branch", base="main"
        ... )
        >>>
        >>> # Check Actions status
        >>> result = await registry.execute_tool(
        ...     "github", "list_workflow_runs",
        ...     owner="myorg", repo="myrepo"
        ... )
    """

    def __init__(self, metadata: SkillMetadata) -> None:
        """Initialize the GitHub skill.

        Args:
            metadata: Skill metadata from the entry point.
        """
        super().__init__(metadata)
        self._config = GitHubConfig.from_env()
        self._client: httpx.AsyncClient | None = None
        self._gh_cli_path: str | None = None

    def _get_client(self) -> httpx.AsyncClient:
        """Get or create HTTP client with authentication.

        Returns:
            Configured httpx.AsyncClient
        """
        if self._client is None:
            headers = {
                "Accept": "application/vnd.github+json",
                "X-GitHub-Api-Version": "2022-11-28",
                "User-Agent": "OCLAWMA-GitHub-Skill/1.0.0",
            }

            if self._config.token:
                headers["Authorization"] = f"Bearer {self._config.token}"

            self._client = httpx.AsyncClient(
                base_url=self._config.base_url,
                headers=headers,
                timeout=self._config.timeout,
                follow_redirects=True,
            )

        return self._client

    def _find_gh_cli(self) -> str | None:
        """Find the GitHub CLI binary.

        Returns:
            Path to gh CLI or None if not found.
        """
        if self._gh_cli_path is None:
            try:
                result = subprocess.run(
                    ["which", "gh"],
                    capture_output=True,
                    text=True,
                    check=False,
                )
                if result.returncode == 0:
                    self._gh_cli_path = result.stdout.strip()
            except Exception:
                pass
        return self._gh_cli_path

    async def _api_request(
        self,
        method: str,
        endpoint: str,
        params: dict[str, Any] | None = None,
        json_data: dict[str, Any] | None = None,
    ) -> dict[str, Any]:
        """Make an authenticated API request to GitHub.

        Args:
            method: HTTP method (GET, POST, PUT, PATCH, DELETE)
            endpoint: API endpoint path
            params: Query parameters
            json_data: JSON request body

        Returns:
            Standardized result dictionary
        """
        client = self._get_client()

        try:
            response = await client.request(
                method=method,
                url=endpoint,
                params=params,
                json=json_data,
            )

            # Handle rate limiting
            if response.status_code == 403 and "rate limit" in response.text.lower():
                reset_time = response.headers.get("X-RateLimit-Reset")
                if reset_time:
                    reset_dt = datetime.fromtimestamp(int(reset_time))
                    wait_minutes = int((reset_dt - datetime.now()).total_seconds() / 60)
                    return {
                        "success": False,
                        "error": f"GitHub API rate limit exceeded. Resets in {wait_minutes} minutes.",
                        "rate_limited": True,
                        "resets_at": reset_dt.isoformat(),
                    }

            # Handle successful responses
            if response.status_code in (200, 201, 202, 204):
                # Handle empty responses
                if response.status_code == 204 or not response.content:
                    return {"success": True, "data": None}

                return {"success": True, "data": response.json()}

            # Handle errors
            error_data = response.json() if response.content else {}
            error_message = error_data.get("message", f"HTTP {response.status_code}")

            return {
                "success": False,
                "error": error_message,
                "status_code": response.status_code,
            }

        except httpx.TimeoutException:
            return {
                "success": False,
                "error": f"Request timed out after {self._config.timeout} seconds",
            }
        except httpx.RequestError as e:
            return {
                "success": False,
                "error": f"Request failed: {str(e)}",
            }
        except Exception as e:
            return {
                "success": False,
                "error": f"Unexpected error: {str(e)}",
            }

    def _format_repo(self, repo: dict[str, Any]) -> dict[str, Any]:
        """Format repository data for display."""
        return {
            "name": repo.get("name"),
            "full_name": repo.get("full_name"),
            "description": repo.get("description"),
            "url": repo.get("html_url"),
            "private": repo.get("private"),
            "stars": repo.get("stargazers_count", 0),
            "forks": repo.get("forks_count", 0),
            "open_issues": repo.get("open_issues_count", 0),
            "language": repo.get("language"),
            "default_branch": repo.get("default_branch"),
            "updated_at": repo.get("updated_at"),
        }

    def _format_pr(self, pr: dict[str, Any]) -> dict[str, Any]:
        """Format pull request data for display."""
        return {
            "number": pr.get("number"),
            "title": pr.get("title"),
            "state": pr.get("state"),
            "url": pr.get("html_url"),
            "author": pr.get("user", {}).get("login"),
            "branch": pr.get("head", {}).get("ref"),
            "base": pr.get("base", {}).get("ref"),
            "created_at": pr.get("created_at"),
            "updated_at": pr.get("updated_at"),
            "draft": pr.get("draft", False),
            "mergeable": pr.get("mergeable"),
        }

    def _format_issue(self, issue: dict[str, Any]) -> dict[str, Any]:
        """Format issue data for display."""
        return {
            "number": issue.get("number"),
            "title": issue.get("title"),
            "state": issue.get("state"),
            "url": issue.get("html_url"),
            "author": issue.get("user", {}).get("login"),
            "labels": [label.get("name") for label in issue.get("labels", [])],
            "assignees": [a.get("login") for a in issue.get("assignees", [])],
            "milestone": issue.get("milestone", {}).get("title") if issue.get("milestone") else None,
            "created_at": issue.get("created_at"),
            "updated_at": issue.get("updated_at"),
            "comments": issue.get("comments", 0),
        }

    def _format_workflow_run(self, run: dict[str, Any]) -> dict[str, Any]:
        """Format workflow run data for display."""
        return {
            "id": run.get("id"),
            "name": run.get("name"),
            "status": run.get("status"),
            "conclusion": run.get("conclusion"),
            "workflow_id": run.get("workflow_id"),
            "branch": run.get("head_branch"),
            "commit": run.get("head_sha", "")[:7],
            "event": run.get("event"),
            "url": run.get("html_url"),
            "created_at": run.get("created_at"),
            "updated_at": run.get("updated_at"),
            "run_number": run.get("run_number"),
        }

    def _load(self) -> None:
        """Load the skill's tools."""
        self._tools = {
            # Repository operations
            "list_repos": self._list_repos,
            "get_repo": self._get_repo,
            "create_repo": self._create_repo,
            "search_repos": self._search_repos,
            "get_repo_languages": self._get_repo_languages,

            # Pull request operations
            "list_prs": self._list_prs,
            "get_pr": self._get_pr,
            "create_pr": self._create_pr,
            "update_pr": self._update_pr,
            "merge_pr": self._merge_pr,
            "close_pr": self._close_pr,
            "review_pr": self._review_pr,
            "list_pr_files": self._list_pr_files,

            # Issue operations
            "list_issues": self._list_issues,
            "get_issue": self._get_issue,
            "create_issue": self._create_issue,
            "update_issue": self._update_issue,
            "close_issue": self._close_issue,
            "search_issues": self._search_issues,
            "add_issue_comment": self._add_issue_comment,

            # Label operations
            "list_labels": self._list_labels,
            "create_label": self._create_label,
            "add_labels": self._add_labels,
            "remove_label": self._remove_label,

            # GitHub Actions
            "list_workflows": self._list_workflows,
            "list_workflow_runs": self._list_workflow_runs,
            "get_workflow_run": self._get_workflow_run,
            "trigger_workflow": self._trigger_workflow,
            "rerun_workflow": self._rerun_workflow,
            "cancel_workflow": self._cancel_workflow,
            "get_run_logs": self._get_run_logs,
            "list_run_artifacts": self._list_run_artifacts,

            # Release operations
            "list_releases": self._list_releases,
            "get_release": self._get_release,
            "create_release": self._create_release,
            "delete_release": self._delete_release,

            # Code operations
            "get_file": self._get_file,
            "get_readme": self._get_readme,
            "list_branches": self._list_branches,
            "compare_branches": self._compare_branches,
            "search_code": self._search_code,

            # Collaboration
            "list_collaborators": self._list_collaborators,
            "add_collaborator": self._add_collaborator,
            "remove_collaborator": self._remove_collaborator,

            # Utility
            "rate_limit": self._rate_limit,
            "whoami": self._whoami,
        }
        self._loaded = True

    # -------------------------------------------------------------------------
    # Repository Operations
    # -------------------------------------------------------------------------

    async def _list_repos(
        self,
        owner: str | None = None,
        type: str = "owner",
        sort: str = "updated",
        limit: int = 30,
    ) -> dict[str, Any]:
        """List repositories for a user or organization.

        Args:
            owner: Username or org name (defaults to authenticated user)
            type: Filter by type (all, owner, member)
            sort: Sort field (created, updated, pushed, full_name)
            limit: Maximum results to return

        Returns:
            Standardized result with repository list
        """
        if owner:
            endpoint = f"/users/{owner}/repos"
        else:
            endpoint = "/user/repos"

        params = {
            "type": type,
            "sort": sort,
            "per_page": min(limit, 100),
        }

        result = await self._api_request("GET", endpoint, params=params)

        if result["success"]:
            repos = result.get("data", [])
            result["data"] = [self._format_repo(repo) for repo in repos[:limit]]

        return result

    async def _get_repo(self, owner: str, repo: str) -> dict[str, Any]:
        """Get detailed information about a repository.

        Args:
            owner: Repository owner (user or org)
            repo: Repository name

        Returns:
            Standardized result with repository details
        """
        endpoint = f"/repos/{owner}/{repo}"
        result = await self._api_request("GET", endpoint)

        if result["success"] and result.get("data"):
            data = result["data"]
            result["data"] = {
                **self._format_repo(data),
                "topics": data.get("topics", []),
                "archived": data.get("archived", False),
                "disabled": data.get("disabled", False),
                "visibility": data.get("visibility", "public"),
                "permissions": data.get("permissions", {}),
                "allow_forking": data.get("allow_forking", True),
                "is_template": data.get("is_template", False),
                "has_issues": data.get("has_issues", True),
                "has_projects": data.get("has_projects", True),
                "has_wiki": data.get("has_wiki", True),
                "has_pages": data.get("has_pages", False),
                "has_discussions": data.get("has_discussions", False),
            }

        return result

    async def _create_repo(
        self,
        name: str,
        description: str = "",
        private: bool = False,
        auto_init: bool = False,
        gitignore_template: str | None = None,
        license_template: str | None = None,
        org: str | None = None,
    ) -> dict[str, Any]:
        """Create a new repository.

        Args:
            name: Repository name
            description: Repository description
            private: Create as private repository
            auto_init: Initialize with README
            gitignore_template: Gitignore template name
            license_template: License template name
            org: Organization name (creates user repo if not provided)

        Returns:
            Standardized result with created repository
        """
        json_data = {
            "name": name,
            "description": description,
            "private": private,
            "auto_init": auto_init,
        }

        if gitignore_template:
            json_data["gitignore_template"] = gitignore_template
        if license_template:
            json_data["license_template"] = license_template

        if org:
            endpoint = f"/orgs/{org}/repos"
        else:
            endpoint = "/user/repos"

        result = await self._api_request("POST", endpoint, json_data=json_data)

        if result["success"] and result.get("data"):
            result["data"] = self._format_repo(result["data"])

        return result

    async def _search_repos(
        self,
        query: str,
        sort: str = "updated",
        order: str = "desc",
        limit: int = 30,
    ) -> dict[str, Any]:
        """Search repositories on GitHub.

        Args:
            query: Search query (e.g., "language:python stars:>100")
            sort: Sort field (stars, forks, updated)
            order: Sort order (asc, desc)
            limit: Maximum results to return

        Returns:
            Standardized result with search results
        """
        params = {
            "q": query,
            "sort": sort,
            "order": order,
            "per_page": min(limit, 100),
        }

        result = await self._api_request("GET", "/search/repositories", params=params)

        if result["success"]:
            items = result.get("data", {}).get("items", [])
            result["data"] = {
                "total_count": result.get("data", {}).get("total_count", 0),
                "repositories": [self._format_repo(repo) for repo in items[:limit]],
            }

        return result

    async def _get_repo_languages(self, owner: str, repo: str) -> dict[str, Any]:
        """Get language statistics for a repository.

        Args:
            owner: Repository owner
            repo: Repository name

        Returns:
            Standardized result with language breakdown
        """
        endpoint = f"/repos/{owner}/{repo}/languages"
        return await self._api_request("GET", endpoint)

    # -------------------------------------------------------------------------
    # Pull Request Operations
    # -------------------------------------------------------------------------

    async def _list_prs(
        self,
        owner: str,
        repo: str,
        state: str = "open",
        head: str | None = None,
        base: str | None = None,
        sort: str = "updated",
        limit: int = 30,
    ) -> dict[str, Any]:
        """List pull requests for a repository.

        Args:
            owner: Repository owner
            repo: Repository name
            state: Filter by state (open, closed, all)
            head: Filter by head branch
            base: Filter by base branch
            sort: Sort field (created, updated, popularity, long-running)
            limit: Maximum results to return

        Returns:
            Standardized result with PR list
        """
        endpoint = f"/repos/{owner}/{repo}/pulls"
        params = {
            "state": state,
            "sort": sort,
            "per_page": min(limit, 100),
        }

        if head:
            params["head"] = head
        if base:
            params["base"] = base

        result = await self._api_request("GET", endpoint, params=params)

        if result["success"]:
            prs = result.get("data", [])
            result["data"] = [self._format_pr(pr) for pr in prs[:limit]]

        return result

    async def _get_pr(
        self,
        owner: str,
        repo: str,
        number: int,
    ) -> dict[str, Any]:
        """Get detailed information about a pull request.

        Args:
            owner: Repository owner
            repo: Repository name
            number: Pull request number

        Returns:
            Standardized result with PR details
        """
        endpoint = f"/repos/{owner}/{repo}/pulls/{number}"
        result = await self._api_request("GET", endpoint)

        if result["success"] and result.get("data"):
            data = result["data"]
            result["data"] = {
                **self._format_pr(data),
                "body": data.get("body"),
                "additions": data.get("additions"),
                "deletions": data.get("deletions"),
                "changed_files": data.get("changed_files"),
                "commits": data.get("commits"),
                "comments": data.get("comments"),
                "review_comments": data.get("review_comments"),
                "merged": data.get("merged", False),
                "mergeable_state": data.get("mergeable_state"),
                "maintainer_can_modify": data.get("maintainer_can_modify", False),
            }

        return result

    async def _create_pr(
        self,
        owner: str,
        repo: str,
        title: str,
        head: str,
        base: str,
        body: str = "",
        draft: bool = False,
        maintainer_can_modify: bool = True,
    ) -> dict[str, Any]:
        """Create a new pull request.

        Args:
            owner: Repository owner
            repo: Repository name
            title: PR title
            head: Head branch (source)
            base: Base branch (target)
            body: PR description
            draft: Create as draft PR
            maintainer_can_modify: Allow maintainer edits

        Returns:
            Standardized result with created PR
        """
        endpoint = f"/repos/{owner}/{repo}/pulls"
        json_data = {
            "title": title,
            "head": head,
            "base": base,
            "body": body,
            "draft": draft,
            "maintainer_can_modify": maintainer_can_modify,
        }

        result = await self._api_request("POST", endpoint, json_data=json_data)

        if result["success"] and result.get("data"):
            result["data"] = self._format_pr(result["data"])

        return result

    async def _update_pr(
        self,
        owner: str,
        repo: str,
        number: int,
        title: str | None = None,
        body: str | None = None,
        state: str | None = None,
        base: str | None = None,
    ) -> dict[str, Any]:
        """Update a pull request.

        Args:
            owner: Repository owner
            repo: Repository name
            number: PR number
            title: New title
            body: New description
            state: New state (open, closed)
            base: New base branch

        Returns:
            Standardized result with updated PR
        """
        endpoint = f"/repos/{owner}/{repo}/pulls/{number}"
        json_data = {}

        if title is not None:
            json_data["title"] = title
        if body is not None:
            json_data["body"] = body
        if state is not None:
            json_data["state"] = state
        if base is not None:
            json_data["base"] = base

        result = await self._api_request("PATCH", endpoint, json_data=json_data)

        if result["success"] and result.get("data"):
            result["data"] = self._format_pr(result["data"])

        return result

    async def _merge_pr(
        self,
        owner: str,
        repo: str,
        number: int,
        commit_title: str | None = None,
        commit_message: str | None = None,
        sha: str | None = None,
        merge_method: str = "merge",
    ) -> dict[str, Any]:
        """Merge a pull request.

        Args:
            owner: Repository owner
            repo: Repository name
            number: PR number
            commit_title: Custom commit title
            commit_message: Custom commit message
            sha: SHA to verify before merging
            merge_method: Merge method (merge, squash, rebase)

        Returns:
            Standardized result with merge status
        """
        endpoint = f"/repos/{owner}/{repo}/pulls/{number}/merge"
        json_data = {"merge_method": merge_method}

        if commit_title:
            json_data["commit_title"] = commit_title
        if commit_message:
            json_data["commit_message"] = commit_message
        if sha:
            json_data["sha"] = sha

        result = await self._api_request("PUT", endpoint, json_data=json_data)

        if result["success"]:
            result["data"] = {
                "merged": True,
                "message": result.get("data", {}).get("message", "Merged successfully"),
                "sha": result.get("data", {}).get("sha"),
            }

        return result

    async def _close_pr(
        self,
        owner: str,
        repo: str,
        number: int,
    ) -> dict[str, Any]:
        """Close a pull request without merging.

        Args:
            owner: Repository owner
            repo: Repository name
            number: PR number

        Returns:
            Standardized result with closed PR
        """
        return await self._update_pr(owner, repo, number, state="closed")

    async def _review_pr(
        self,
        owner: str,
        repo: str,
        number: int,
        event: str,
        body: str = "",
        comments: list[dict] | None = None,
    ) -> dict[str, Any]:
        """Submit a review for a pull request.

        Args:
            owner: Repository owner
            repo: Repository name
            number: PR number
            event: Review type (APPROVE, REQUEST_CHANGES, COMMENT)
            body: Review comment
            comments: Line-specific comments

        Returns:
            Standardized result with review details
        """
        endpoint = f"/repos/{owner}/{repo}/pulls/{number}/reviews"
        json_data = {
            "event": event,
            "body": body,
        }

        if comments:
            json_data["comments"] = comments

        result = await self._api_request("POST", endpoint, json_data=json_data)

        if result["success"] and result.get("data"):
            data = result["data"]
            result["data"] = {
                "id": data.get("id"),
                "state": data.get("state"),
                "user": data.get("user", {}).get("login"),
                "body": data.get("body"),
                "submitted_at": data.get("submitted_at"),
            }

        return result

    async def _list_pr_files(
        self,
        owner: str,
        repo: str,
        number: int,
        limit: int = 100,
    ) -> dict[str, Any]:
        """List files changed in a pull request.

        Args:
            owner: Repository owner
            repo: Repository name
            number: PR number
            limit: Maximum files to return

        Returns:
            Standardized result with file list
        """
        endpoint = f"/repos/{owner}/{repo}/pulls/{number}/files"
        params = {"per_page": min(limit, 100)}

        result = await self._api_request("GET", endpoint, params=params)

        if result["success"]:
            files = result.get("data", [])
            result["data"] = [
                {
                    "filename": f.get("filename"),
                    "status": f.get("status"),
                    "additions": f.get("additions"),
                    "deletions": f.get("deletions"),
                    "changes": f.get("changes"),
                    "patch": f.get("patch"),
                }
                for f in files[:limit]
            ]

        return result

    # -------------------------------------------------------------------------
    # Issue Operations
    # -------------------------------------------------------------------------

    async def _list_issues(
        self,
        owner: str,
        repo: str,
        state: str = "open",
        labels: str | None = None,
        assignee: str | None = None,
        creator: str | None = None,
        milestone: str | None = None,
        sort: str = "updated",
        limit: int = 30,
    ) -> dict[str, Any]:
        """List issues for a repository.

        Args:
            owner: Repository owner
            repo: Repository name
            state: Filter by state (open, closed, all)
            labels: Comma-separated label names
            assignee: Filter by assignee
            creator: Filter by creator
            milestone: Filter by milestone
            sort: Sort field (created, updated, comments)
            limit: Maximum results to return

        Returns:
            Standardized result with issue list
        """
        endpoint = f"/repos/{owner}/{repo}/issues"
        params = {
            "state": state,
            "sort": sort,
            "per_page": min(limit, 100),
        }

        if labels:
            params["labels"] = labels
        if assignee:
            params["assignee"] = assignee
        if creator:
            params["creator"] = creator
        if milestone:
            params["milestone"] = milestone

        result = await self._api_request("GET", endpoint, params=params)

        if result["success"]:
            issues = result.get("data", [])
            # Filter out pull requests (GitHub returns PRs as issues)
            issues = [i for i in issues if "pull_request" not in i]
            result["data"] = [self._format_issue(issue) for issue in issues[:limit]]

        return result

    async def _get_issue(
        self,
        owner: str,
        repo: str,
        number: int,
    ) -> dict[str, Any]:
        """Get detailed information about an issue.

        Args:
            owner: Repository owner
            repo: Repository name
            number: Issue number

        Returns:
            Standardized result with issue details
        """
        endpoint = f"/repos/{owner}/{repo}/issues/{number}"
        result = await self._api_request("GET", endpoint)

        if result["success"] and result.get("data"):
            data = result["data"]
            result["data"] = {
                **self._format_issue(data),
                "body": data.get("body"),
                "locked": data.get("locked", False),
                "html_url": data.get("html_url"),
            }

        return result

    async def _create_issue(
        self,
        owner: str,
        repo: str,
        title: str,
        body: str = "",
        labels: list[str] | None = None,
        assignees: list[str] | None = None,
        milestone: int | None = None,
    ) -> dict[str, Any]:
        """Create a new issue.

        Args:
            owner: Repository owner
            repo: Repository name
            title: Issue title
            body: Issue description
            labels: List of label names
            assignees: List of usernames to assign
            milestone: Milestone number

        Returns:
            Standardized result with created issue
        """
        endpoint = f"/repos/{owner}/{repo}/issues"
        json_data = {"title": title, "body": body}

        if labels:
            json_data["labels"] = labels
        if assignees:
            json_data["assignees"] = assignees
        if milestone:
            json_data["milestone"] = milestone

        result = await self._api_request("POST", endpoint, json_data=json_data)

        if result["success"] and result.get("data"):
            result["data"] = self._format_issue(result["data"])

        return result

    async def _update_issue(
        self,
        owner: str,
        repo: str,
        number: int,
        title: str | None = None,
        body: str | None = None,
        state: str | None = None,
        labels: list[str] | None = None,
        assignees: list[str] | None = None,
        milestone: int | None = None,
    ) -> dict[str, Any]:
        """Update an existing issue.

        Args:
            owner: Repository owner
            repo: Repository name
            number: Issue number
            title: New title
            body: New description
            state: New state (open, closed)
            labels: Replace labels with these
            assignees: Replace assignees with these
            milestone: New milestone number

        Returns:
            Standardized result with updated issue
        """
        endpoint = f"/repos/{owner}/{repo}/issues/{number}"
        json_data = {}

        if title is not None:
            json_data["title"] = title
        if body is not None:
            json_data["body"] = body
        if state is not None:
            json_data["state"] = state
        if labels is not None:
            json_data["labels"] = labels
        if assignees is not None:
            json_data["assignees"] = assignees
        if milestone is not None:
            json_data["milestone"] = milestone

        result = await self._api_request("PATCH", endpoint, json_data=json_data)

        if result["success"] and result.get("data"):
            result["data"] = self._format_issue(result["data"])

        return result

    async def _close_issue(
        self,
        owner: str,
        repo: str,
        number: int,
    ) -> dict[str, Any]:
        """Close an issue.

        Args:
            owner: Repository owner
            repo: Repository name
            number: Issue number

        Returns:
            Standardized result with closed issue
        """
        return await self._update_issue(owner, repo, number, state="closed")

    async def _search_issues(
        self,
        query: str,
        sort: str = "updated",
        order: str = "desc",
        limit: int = 30,
    ) -> dict[str, Any]:
        """Search issues and pull requests across GitHub.

        Args:
            query: Search query (supports GitHub search syntax)
            sort: Sort field (comments, reactions, created, updated)
            order: Sort order (asc, desc)
            limit: Maximum results to return

        Returns:
            Standardized result with search results

        Example query: "is:open is:issue label:bug repo:owner/repo"
        """
        params = {
            "q": query,
            "sort": sort,
            "order": order,
            "per_page": min(limit, 100),
        }

        result = await self._api_request("GET", "/search/issues", params=params)

        if result["success"]:
            items = result.get("data", {}).get("items", [])
            result["data"] = {
                "total_count": result.get("data", {}).get("total_count", 0),
                "issues": [self._format_issue(item) for item in items[:limit]],
            }

        return result

    async def _add_issue_comment(
        self,
        owner: str,
        repo: str,
        number: int,
        body: str,
    ) -> dict[str, Any]:
        """Add a comment to an issue or pull request.

        Args:
            owner: Repository owner
            repo: Repository name
            number: Issue/PR number
            body: Comment text

        Returns:
            Standardized result with created comment
        """
        endpoint = f"/repos/{owner}/{repo}/issues/{number}/comments"
        json_data = {"body": body}

        result = await self._api_request("POST", endpoint, json_data=json_data)

        if result["success"] and result.get("data"):
            data = result["data"]
            result["data"] = {
                "id": data.get("id"),
                "url": data.get("html_url"),
                "body": data.get("body"),
                "user": data.get("user", {}).get("login"),
                "created_at": data.get("created_at"),
            }

        return result

    # -------------------------------------------------------------------------
    # Label Operations
    # -------------------------------------------------------------------------

    async def _list_labels(
        self,
        owner: str,
        repo: str,
        limit: int = 100,
    ) -> dict[str, Any]:
        """List labels for a repository.

        Args:
            owner: Repository owner
            repo: Repository name
            limit: Maximum labels to return

        Returns:
            Standardized result with label list
        """
        endpoint = f"/repos/{owner}/{repo}/labels"
        params = {"per_page": min(limit, 100)}

        result = await self._api_request("GET", endpoint, params=params)

        if result["success"]:
            labels = result.get("data", [])
            result["data"] = [
                {
                    "name": label.get("name"),
                    "color": label.get("color"),
                    "description": label.get("description"),
                }
                for label in labels[:limit]
            ]

        return result

    async def _create_label(
        self,
        owner: str,
        repo: str,
        name: str,
        color: str,
        description: str = "",
    ) -> dict[str, Any]:
        """Create a new label.

        Args:
            owner: Repository owner
            repo: Repository name
            name: Label name
            color: Hex color (without #)
            description: Label description

        Returns:
            Standardized result with created label
        """
        endpoint = f"/repos/{owner}/{repo}/labels"
        json_data = {
            "name": name,
            "color": color.lstrip("#"),
            "description": description,
        }

        return await self._api_request("POST", endpoint, json_data=json_data)

    async def _add_labels(
        self,
        owner: str,
        repo: str,
        number: int,
        labels: list[str],
    ) -> dict[str, Any]:
        """Add labels to an issue or pull request.

        Args:
            owner: Repository owner
            repo: Repository name
            number: Issue/PR number
            labels: List of label names to add

        Returns:
            Standardized result with updated labels
        """
        endpoint = f"/repos/{owner}/{repo}/issues/{number}/labels"
        json_data = {"labels": labels}

        result = await self._api_request("POST", endpoint, json_data=json_data)

        if result["success"]:
            labels = result.get("data", [])
            result["data"] = [label.get("name") for label in labels]

        return result

    async def _remove_label(
        self,
        owner: str,
        repo: str,
        number: int,
        label: str,
    ) -> dict[str, Any]:
        """Remove a label from an issue or pull request.

        Args:
            owner: Repository owner
            repo: Repository name
            number: Issue/PR number
            label: Label name to remove

        Returns:
            Standardized result
        """
        endpoint = f"/repos/{owner}/{repo}/issues/{number}/labels/{label}"
        return await self._api_request("DELETE", endpoint)

    # -------------------------------------------------------------------------
    # GitHub Actions
    # -------------------------------------------------------------------------

    async def _list_workflows(
        self,
        owner: str,
        repo: str,
    ) -> dict[str, Any]:
        """List GitHub Actions workflows for a repository.

        Args:
            owner: Repository owner
            repo: Repository name

        Returns:
            Standardized result with workflow list
        """
        endpoint = f"/repos/{owner}/{repo}/actions/workflows"
        result = await self._api_request("GET", endpoint)

        if result["success"]:
            workflows = result.get("data", {}).get("workflows", [])
            result["data"] = [
                {
                    "id": w.get("id"),
                    "name": w.get("name"),
                    "path": w.get("path"),
                    "state": w.get("state"),
                    "created_at": w.get("created_at"),
                    "updated_at": w.get("updated_at"),
                    "url": w.get("html_url"),
                }
                for w in workflows
            ]

        return result

    async def _list_workflow_runs(
        self,
        owner: str,
        repo: str,
        workflow_id: str | int | None = None,
        branch: str | None = None,
        event: str | None = None,
        status: str | None = None,
        limit: int = 30,
    ) -> dict[str, Any]:
        """List workflow runs for a repository or specific workflow.

        Args:
            owner: Repository owner
            repo: Repository name
            workflow_id: Filter by workflow ID or filename
            branch: Filter by branch
            event: Filter by event type (push, pull_request, etc.)
            status: Filter by status (queued, completed, in_progress)
            limit: Maximum results to return

        Returns:
            Standardized result with run list
        """
        if workflow_id:
            endpoint = f"/repos/{owner}/{repo}/actions/workflows/{workflow_id}/runs"
        else:
            endpoint = f"/repos/{owner}/{repo}/actions/runs"

        params = {"per_page": min(limit, 100)}

        if branch:
            params["branch"] = branch
        if event:
            params["event"] = event
        if status:
            params["status"] = status

        result = await self._api_request("GET", endpoint, params=params)

        if result["success"]:
            runs = result.get("data", {}).get("workflow_runs", [])
            result["data"] = [self._format_workflow_run(run) for run in runs[:limit]]

        return result

    async def _get_workflow_run(
        self,
        owner: str,
        repo: str,
        run_id: int,
    ) -> dict[str, Any]:
        """Get detailed information about a workflow run.

        Args:
            owner: Repository owner
            repo: Repository name
            run_id: Workflow run ID

        Returns:
            Standardized result with run details
        """
        endpoint = f"/repos/{owner}/{repo}/actions/runs/{run_id}"
        result = await self._api_request("GET", endpoint)

        if result["success"] and result.get("data"):
            data = result["data"]
            result["data"] = {
                **self._format_workflow_run(data),
                "run_attempt": data.get("run_attempt"),
                "run_started_at": data.get("run_started_at"),
                "triggering_actor": data.get("triggering_actor", {}).get("login"),
                "jobs_url": data.get("jobs_url"),
                "logs_url": data.get("logs_url"),
                "check_suite_url": data.get("check_suite_url"),
                "artifacts_url": data.get("artifacts_url"),
            }

        return result

    async def _trigger_workflow(
        self,
        owner: str,
        repo: str,
        workflow_id: str,
        ref: str,
        inputs: dict[str, Any] | None = None,
    ) -> dict[str, Any]:
        """Trigger a workflow run.

        Args:
            owner: Repository owner
            repo: Repository name
            workflow_id: Workflow ID or filename (e.g., "main.yml")
            ref: Git reference (branch, tag, or SHA)
            inputs: Workflow input parameters

        Returns:
            Standardized result
        """
        endpoint = f"/repos/{owner}/{repo}/actions/workflows/{workflow_id}/dispatches"
        json_data = {"ref": ref}

        if inputs:
            json_data["inputs"] = inputs

        result = await self._api_request("POST", endpoint, json_data=json_data)

        if result["success"]:
            result["data"] = {"triggered": True, "ref": ref}

        return result

    async def _rerun_workflow(
        self,
        owner: str,
        repo: str,
        run_id: int,
        failed_only: bool = False,
    ) -> dict[str, Any]:
        """Rerun a workflow run.

        Args:
            owner: Repository owner
            repo: Repository name
            run_id: Workflow run ID to rerun
            failed_only: Only rerun failed jobs

        Returns:
            Standardized result
        """
        if failed_only:
            endpoint = f"/repos/{owner}/{repo}/actions/runs/{run_id}/rerun-failed-jobs"
        else:
            endpoint = f"/repos/{owner}/{repo}/actions/runs/{run_id}/rerun"

        result = await self._api_request("POST", endpoint)

        if result["success"]:
            result["data"] = {"rerun_requested": True}

        return result

    async def _cancel_workflow(
        self,
        owner: str,
        repo: str,
        run_id: int,
    ) -> dict[str, Any]:
        """Cancel a workflow run.

        Args:
            owner: Repository owner
            repo: Repository name
            run_id: Workflow run ID to cancel

        Returns:
            Standardized result
        """
        endpoint = f"/repos/{owner}/{repo}/actions/runs/{run_id}/cancel"
        result = await self._api_request("POST", endpoint)

        if result["success"]:
            result["data"] = {"cancelled": True}

        return result

    async def _get_run_logs(
        self,
        owner: str,
        repo: str,
        run_id: int,
    ) -> dict[str, Any]:
        """Get logs for a workflow run.

        Note: This returns the log download URL. You'll need to download
        and extract the logs separately.

        Args:
            owner: Repository owner
            repo: Repository name
            run_id: Workflow run ID

        Returns:
            Standardized result with log URL
        """
        endpoint = f"/repos/{owner}/{repo}/actions/runs/{run_id}/logs"

        # This endpoint returns a redirect to the log archive
        client = self._get_client()
        response = await client.get(endpoint, follow_redirects=False)

        if response.status_code == 302:
            log_url = response.headers.get("Location")
            return {
                "success": True,
                "data": {
                    "log_url": log_url,
                    "note": "Download this URL to get the log archive (zip)",
                },
            }

        return {
            "success": False,
            "error": f"Failed to get logs: HTTP {response.status_code}",
        }

    async def _list_run_artifacts(
        self,
        owner: str,
        repo: str,
        run_id: int,
    ) -> dict[str, Any]:
        """List artifacts from a workflow run.

        Args:
            owner: Repository owner
            repo: Repository name
            run_id: Workflow run ID

        Returns:
            Standardized result with artifact list
        """
        endpoint = f"/repos/{owner}/{repo}/actions/runs/{run_id}/artifacts"
        result = await self._api_request("GET", endpoint)

        if result["success"]:
            artifacts = result.get("data", {}).get("artifacts", [])
            result["data"] = [
                {
                    "id": a.get("id"),
                    "name": a.get("name"),
                    "size": a.get("size_in_bytes"),
                    "expired": a.get("expired", False),
                    "expires_at": a.get("expires_at"),
                    "download_url": a.get("archive_download_url"),
                }
                for a in artifacts
            ]

        return result

    # -------------------------------------------------------------------------
    # Release Operations
    # -------------------------------------------------------------------------

    async def _list_releases(
        self,
        owner: str,
        repo: str,
        limit: int = 30,
    ) -> dict[str, Any]:
        """List releases for a repository.

        Args:
            owner: Repository owner
            repo: Repository name
            limit: Maximum releases to return

        Returns:
            Standardized result with release list
        """
        endpoint = f"/repos/{owner}/{repo}/releases"
        params = {"per_page": min(limit, 100)}

        result = await self._api_request("GET", endpoint, params=params)

        if result["success"]:
            releases = result.get("data", [])
            result["data"] = [
                {
                    "id": r.get("id"),
                    "tag_name": r.get("tag_name"),
                    "name": r.get("name"),
                    "body": r.get("body"),
                    "draft": r.get("draft", False),
                    "prerelease": r.get("prerelease", False),
                    "created_at": r.get("created_at"),
                    "published_at": r.get("published_at"),
                    "author": r.get("author", {}).get("login"),
                    "url": r.get("html_url"),
                    "assets": [
                        {
                            "name": a.get("name"),
                            "size": a.get("size"),
                            "download_count": a.get("download_count"),
                            "download_url": a.get("browser_download_url"),
                        }
                        for a in r.get("assets", [])
                    ],
                }
                for r in releases[:limit]
            ]

        return result

    async def _get_release(
        self,
        owner: str,
        repo: str,
        tag: str | None = None,
        release_id: int | None = None,
    ) -> dict[str, Any]:
        """Get a specific release by tag or ID.

        Args:
            owner: Repository owner
            repo: Repository name
            tag: Release tag name
            release_id: Release ID

        Returns:
            Standardized result with release details
        """
        if release_id:
            endpoint = f"/repos/{owner}/{repo}/releases/{release_id}"
        elif tag:
            endpoint = f"/repos/{owner}/{repo}/releases/tags/{tag}"
        else:
            return {
                "success": False,
                "error": "Must provide either tag or release_id",
            }

        result = await self._api_request("GET", endpoint)

        if result["success"] and result.get("data"):
            r = result["data"]
            result["data"] = {
                "id": r.get("id"),
                "tag_name": r.get("tag_name"),
                "name": r.get("name"),
                "body": r.get("body"),
                "draft": r.get("draft", False),
                "prerelease": r.get("prerelease", False),
                "created_at": r.get("created_at"),
                "published_at": r.get("published_at"),
                "author": r.get("author", {}).get("login"),
                "url": r.get("html_url"),
                "assets": [
                    {
                        "name": a.get("name"),
                        "size": a.get("size"),
                        "download_count": a.get("download_count"),
                        "download_url": a.get("browser_download_url"),
                    }
                    for a in r.get("assets", [])
                ],
            }

        return result

    async def _create_release(
        self,
        owner: str,
        repo: str,
        tag_name: str,
        name: str | None = None,
        body: str = "",
        target_commitish: str = "main",
        draft: bool = False,
        prerelease: bool = False,
        generate_release_notes: bool = False,
    ) -> dict[str, Any]:
        """Create a new release.

        Args:
            owner: Repository owner
            repo: Repository name
            tag_name: Git tag for the release
            name: Release title
            body: Release description
            target_commitish: Commitish value (branch or SHA)
            draft: Create as draft release
            prerelease: Mark as prerelease
            generate_release_notes: Auto-generate release notes

        Returns:
            Standardized result with created release
        """
        endpoint = f"/repos/{owner}/{repo}/releases"
        json_data = {
            "tag_name": tag_name,
            "target_commitish": target_commitish,
            "name": name or tag_name,
            "body": body,
            "draft": draft,
            "prerelease": prerelease,
            "generate_release_notes": generate_release_notes,
        }

        result = await self._api_request("POST", endpoint, json_data=json_data)

        if result["success"] and result.get("data"):
            r = result["data"]
            result["data"] = {
                "id": r.get("id"),
                "tag_name": r.get("tag_name"),
                "name": r.get("name"),
                "draft": r.get("draft", False),
                "prerelease": r.get("prerelease", False),
                "url": r.get("html_url"),
                "upload_url": r.get("upload_url"),
            }

        return result

    async def _delete_release(
        self,
        owner: str,
        repo: str,
        release_id: int,
    ) -> dict[str, Any]:
        """Delete a release.

        Args:
            owner: Repository owner
            repo: Repository name
            release_id: Release ID to delete

        Returns:
            Standardized result
        """
        endpoint = f"/repos/{owner}/{repo}/releases/{release_id}"
        result = await self._api_request("DELETE", endpoint)

        if result["success"]:
            result["data"] = {"deleted": True}

        return result

    # -------------------------------------------------------------------------
    # Code Operations
    # -------------------------------------------------------------------------

    async def _get_file(
        self,
        owner: str,
        repo: str,
        path: str,
        ref: str = "main",
    ) -> dict[str, Any]:
        """Get the contents of a file.

        Args:
            owner: Repository owner
            repo: Repository name
            path: File path in the repository
            ref: Git reference (branch, tag, or SHA)

        Returns:
            Standardized result with file content
        """
        endpoint = f"/repos/{owner}/{repo}/contents/{path}"
        params = {"ref": ref}

        result = await self._api_request("GET", endpoint, params=params)

        if result["success"] and result.get("data"):
            data = result["data"]
            content = data.get("content", "")
            encoding = data.get("encoding", "")

            # Decode base64 content
            if encoding == "base64" and content:
                try:
                    decoded = base64.b64decode(content).decode("utf-8")
                except Exception:
                    decoded = content
            else:
                decoded = content

            result["data"] = {
                "name": data.get("name"),
                "path": data.get("path"),
                "sha": data.get("sha"),
                "size": data.get("size"),
                "url": data.get("html_url"),
                "content": decoded,
                "encoding": encoding,
            }

        return result

    async def _get_readme(
        self,
        owner: str,
        repo: str,
        ref: str = "main",
    ) -> dict[str, Any]:
        """Get the README file for a repository.

        Args:
            owner: Repository owner
            repo: Repository name
            ref: Git reference

        Returns:
            Standardized result with README content
        """
        endpoint = f"/repos/{owner}/{repo}/readme"
        params = {"ref": ref}

        result = await self._api_request("GET", endpoint, params=params)

        if result["success"] and result.get("data"):
            data = result["data"]
            content = data.get("content", "")

            # Decode base64 content
            if data.get("encoding") == "base64" and content:
                try:
                    decoded = base64.b64decode(content).decode("utf-8")
                except Exception:
                    decoded = content
            else:
                decoded = content

            result["data"] = {
                "name": data.get("name"),
                "path": data.get("path"),
                "sha": data.get("sha"),
                "size": data.get("size"),
                "url": data.get("html_url"),
                "content": decoded,
            }

        return result

    async def _list_branches(
        self,
        owner: str,
        repo: str,
        protected_only: bool = False,
        limit: int = 100,
    ) -> dict[str, Any]:
        """List branches for a repository.

        Args:
            owner: Repository owner
            repo: Repository name
            protected_only: Only show protected branches
            limit: Maximum branches to return

        Returns:
            Standardized result with branch list
        """
        endpoint = f"/repos/{owner}/{repo}/branches"
        params = {"per_page": min(limit, 100)}

        if protected_only:
            params["protected"] = "true"

        result = await self._api_request("GET", endpoint, params=params)

        if result["success"]:
            branches = result.get("data", [])
            result["data"] = [
                {
                    "name": b.get("name"),
                    "protected": b.get("protected", False),
                    "commit": b.get("commit", {}).get("sha", "")[:7],
                }
                for b in branches[:limit]
            ]

        return result

    async def _compare_branches(
        self,
        owner: str,
        repo: str,
        base: str,
        head: str,
    ) -> dict[str, Any]:
        """Compare two branches or commits.

        Args:
            owner: Repository owner
            repo: Repository name
            base: Base branch/commit
            head: Head branch/commit

        Returns:
            Standardized result with comparison
        """
        endpoint = f"/repos/{owner}/{repo}/compare/{base}...{head}"
        result = await self._api_request("GET", endpoint)

        if result["success"] and result.get("data"):
            data = result["data"]
            result["data"] = {
                "status": data.get("status"),
                "ahead_by": data.get("ahead_by"),
                "behind_by": data.get("behind_by"),
                "total_commits": data.get("total_commits"),
                "commits": [
                    {
                        "sha": c.get("sha", "")[:7],
                        "message": c.get("commit", {}).get("message", "").split("\n")[0],
                        "author": c.get("commit", {}).get("author", {}).get("name"),
                        "date": c.get("commit", {}).get("author", {}).get("date"),
                    }
                    for c in data.get("commits", [])[:10]
                ],
                "files": [
                    {
                        "filename": f.get("filename"),
                        "status": f.get("status"),
                        "additions": f.get("additions"),
                        "deletions": f.get("deletions"),
                    }
                    for f in data.get("files", [])
                ],
            }

        return result

    async def _search_code(
        self,
        query: str,
        sort: str = "indexed",
        order: str = "desc",
        limit: int = 30,
    ) -> dict[str, Any]:
        """Search code across GitHub repositories.

        Args:
            query: Search query (supports GitHub search syntax)
            sort: Sort field (indexed, best-match)
            order: Sort order (asc, desc)
            limit: Maximum results to return

        Returns:
            Standardized result with search results

        Example query: "filename:dockerfile repo:owner/repo"
        """
        params = {
            "q": query,
            "sort": sort,
            "order": order,
            "per_page": min(limit, 100),
        }

        result = await self._api_request("GET", "/search/code", params=params)

        if result["success"]:
            items = result.get("data", {}).get("items", [])
            result["data"] = {
                "total_count": result.get("data", {}).get("total_count", 0),
                "results": [
                    {
                        "name": item.get("name"),
                        "path": item.get("path"),
                        "repository": item.get("repository", {}).get("full_name"),
                        "url": item.get("html_url"),
                        "score": item.get("score"),
                    }
                    for item in items[:limit]
                ],
            }

        return result

    # -------------------------------------------------------------------------
    # Collaboration
    # -------------------------------------------------------------------------

    async def _list_collaborators(
        self,
        owner: str,
        repo: str,
        affiliation: str = "all",
        permission: str | None = None,
        limit: int = 100,
    ) -> dict[str, Any]:
        """List collaborators for a repository.

        Args:
            owner: Repository owner
            repo: Repository name
            affiliation: Filter by affiliation (outside, direct, all)
            permission: Filter by permission (pull, push, admin)
            limit: Maximum collaborators to return

        Returns:
            Standardized result with collaborator list
        """
        endpoint = f"/repos/{owner}/{repo}/collaborators"
        params = {
            "affiliation": affiliation,
            "per_page": min(limit, 100),
        }

        if permission:
            params["permission"] = permission

        result = await self._api_request("GET", endpoint, params=params)

        if result["success"]:
            collaborators = result.get("data", [])
            result["data"] = [
                {
                    "login": c.get("login"),
                    "id": c.get("id"),
                    "permissions": c.get("permissions"),
                }
                for c in collaborators[:limit]
            ]

        return result

    async def _add_collaborator(
        self,
        owner: str,
        repo: str,
        username: str,
        permission: str = "push",
    ) -> dict[str, Any]:
        """Add a collaborator to a repository.

        Args:
            owner: Repository owner
            repo: Repository name
            username: Username to add
            permission: Permission level (pull, push, admin, maintain, triage)

        Returns:
            Standardized result
        """
        endpoint = f"/repos/{owner}/{repo}/collaborators/{username}"
        json_data = {"permission": permission}

        result = await self._api_request("PUT", endpoint, json_data=json_data)

        if result["success"]:
            result["data"] = {"added": True, "username": username}

        return result

    async def _remove_collaborator(
        self,
        owner: str,
        repo: str,
        username: str,
    ) -> dict[str, Any]:
        """Remove a collaborator from a repository.

        Args:
            owner: Repository owner
            repo: Repository name
            username: Username to remove

        Returns:
            Standardized result
        """
        endpoint = f"/repos/{owner}/{repo}/collaborators/{username}"
        result = await self._api_request("DELETE", endpoint)

        if result["success"]:
            result["data"] = {"removed": True, "username": username}

        return result

    # -------------------------------------------------------------------------
    # Utility
    # -------------------------------------------------------------------------

    async def _rate_limit(self) -> dict[str, Any]:
        """Check current rate limit status.

        Returns:
            Standardized result with rate limit info
        """
        result = await self._api_request("GET", "/rate_limit")

        if result["success"] and result.get("data"):
            resources = result["data"].get("resources", {})
            core = resources.get("core", {})

            reset_time = datetime.fromtimestamp(core.get("reset", 0))
            remaining = core.get("remaining", 0)
            limit = core.get("limit", 0)

            result["data"] = {
                "limit": limit,
                "remaining": remaining,
                "used": core.get("used", 0),
                "reset_at": reset_time.isoformat(),
                "reset_in_minutes": max(0, int((reset_time - datetime.now()).total_seconds() / 60)),
                "percentage_used": round((core.get("used", 0) / limit * 100), 1) if limit else 0,
            }

        return result

    async def _whoami(self) -> dict[str, Any]:
        """Get information about the authenticated user.

        Returns:
            Standardized result with user info
        """
        result = await self._api_request("GET", "/user")

        if result["success"] and result.get("data"):
            data = result["data"]
            result["data"] = {
                "login": data.get("login"),
                "id": data.get("id"),
                "name": data.get("name"),
                "email": data.get("email"),
                "company": data.get("company"),
                "location": data.get("location"),
                "bio": data.get("bio"),
                "public_repos": data.get("public_repos"),
                "private_repos": data.get("total_private_repos"),
                "followers": data.get("followers"),
                "following": data.get("following"),
                "created_at": data.get("created_at"),
                "url": data.get("html_url"),
            }

        return result

    async def _on_unload(self) -> None:
        """Cleanup when skill is unloaded."""
        if self._client:
            await self._client.aclose()
            self._client = None
