"""
GitHub Integration Utility for Code Assistant Bot
Author: RSK World (https://rskworld.in)
Founder: Molla Samser
Designer & Tester: Rima Khatun
Contact: help@rskworld.in, +91 93305 39277
Year: 2026
"""

import requests
import json
from typing import Dict, List, Any, Optional

class GitHubIntegration:
    """
    Utility class for integrating with GitHub API
    """
    
    def __init__(self):
        self.base_url = "https://api.github.com"
        self.token = None  # Set this with GitHub personal access token for higher rate limits
        self.headers = {
            "Accept": "application/vnd.github.v3+json",
            "User-Agent": "Code-Assistant-Bot/1.0"
        }
        
        if self.token:
            self.headers["Authorization"] = f"token {self.token}"
    
    def search_repositories(self, query: str, language: Optional[str] = None, sort: str = "stars", order: str = "desc") -> Dict[str, Any]:
        """
        Search GitHub repositories
        """
        try:
            # Build search query
            search_query = query
            if language:
                search_query += f" language:{language}"
            
            # Make API request
            url = f"{self.base_url}/search/repositories"
            params = {
                "q": search_query,
                "sort": sort,
                "order": order,
                "per_page": 20
            }
            
            response = requests.get(url, headers=self.headers, params=params)
            response.raise_for_status()
            
            data = response.json()
            
            # Process results
            repositories = []
            for repo in data.get("items", []):
                repositories.append({
                    "id": repo["id"],
                    "name": repo["name"],
                    "full_name": repo["full_name"],
                    "description": repo["description"],
                    "html_url": repo["html_url"],
                    "clone_url": repo["clone_url"],
                    "ssh_url": repo["ssh_url"],
                    "stars": repo["stargazers_count"],
                    "forks": repo["forks_count"],
                    "language": repo["language"],
                    "updated_at": repo["updated_at"],
                    "created_at": repo["created_at"],
                    "size": repo["size"],
                    "open_issues": repo["open_issues_count"],
                    "watchers": repo.get("watchers_count", 0),
                    "license": repo.get("license", {}).get("name") if repo.get("license") else None,
                    "topics": repo.get("topics", []),
                    "owner": {
                        "login": repo["owner"]["login"],
                        "type": repo["owner"]["type"],
                        "avatar_url": repo["owner"]["avatar_url"]
                    }
                })
            
            return {
                "total_count": data.get("total_count", 0),
                "incomplete_results": data.get("incomplete_results", False),
                "repositories": repositories
            }
            
        except requests.exceptions.RequestException as e:
            return {
                "error": f"GitHub API request failed: {str(e)}",
                "repositories": []
            }
        except Exception as e:
            return {
                "error": f"Unexpected error: {str(e)}",
                "repositories": []
            }
    
    def get_repository_details(self, owner: str, repo: str) -> Dict[str, Any]:
        """
        Get detailed information about a specific repository
        """
        try:
            url = f"{self.base_url}/repos/{owner}/{repo}"
            response = requests.get(url, headers=self.headers)
            response.raise_for_status()
            
            data = response.json()
            
            return {
                "id": data["id"],
                "name": data["name"],
                "full_name": data["full_name"],
                "description": data["description"],
                "html_url": data["html_url"],
                "clone_url": data["clone_url"],
                "ssh_url": data["ssh_url"],
                "stars": data["stargazers_count"],
                "forks": data["forks_count"],
                "language": data["language"],
                "updated_at": data["updated_at"],
                "created_at": data["created_at"],
                "pushed_at": data["pushed_at"],
                "size": data["size"],
                "open_issues": data["open_issues_count"],
                "watchers": data["watchers_count"],
                "network_count": data["network_count"],
                "subscribers_count": data["subscribers_count"],
                "license": data.get("license", {}).get("name") if data.get("license") else None,
                "topics": data.get("topics", []),
                "has_issues": data["has_issues"],
                "has_projects": data["has_projects"],
                "has_wiki": data["has_wiki"],
                "has_pages": data["has_pages"],
                "has_downloads": data["has_downloads"],
                "archived": data["archived"],
                "disabled": data["disabled"],
                "visibility": data.get("visibility", "public"),
                "default_branch": data["default_branch"],
                "owner": {
                    "login": data["owner"]["login"],
                    "id": data["owner"]["id"],
                    "type": data["owner"]["type"],
                    "avatar_url": data["owner"]["avatar_url"]
                }
            }
            
        except requests.exceptions.RequestException as e:
            return {"error": f"GitHub API request failed: {str(e)}"}
        except Exception as e:
            return {"error": f"Unexpected error: {str(e)}"}
    
    def get_repository_contents(self, owner: str, repo: str, path: str = "", ref: Optional[str] = None) -> Dict[str, Any]:
        """
        Get contents of a repository directory or file
        """
        try:
            url = f"{self.base_url}/repos/{owner}/{repo}/contents/{path}"
            params = {}
            if ref:
                params["ref"] = ref
            
            response = requests.get(url, headers=self.headers, params=params)
            response.raise_for_status()
            
            data = response.json()
            
            if isinstance(data, list):
                # Directory contents
                contents = []
                for item in data:
                    contents.append({
                        "name": item["name"],
                        "path": item["path"],
                        "type": item["type"],
                        "size": item.get("size", 0),
                        "download_url": item.get("download_url"),
                        "html_url": item.get("html_url"),
                        "git_url": item.get("git_url"),
                        "_links": item.get("_links", {})
                    })
                return {"type": "dir", "contents": contents}
            else:
                # File contents
                if data["type"] == "file":
                    import base64
                    content = base64.b64decode(data["content"]).decode('utf-8')
                    return {
                        "type": "file",
                        "name": data["name"],
                        "path": data["path"],
                        "size": data["size"],
                        "content": content,
                        "encoding": data["encoding"],
                        "download_url": data.get("download_url"),
                        "html_url": data.get("html_url")
                    }
                else:
                    return {"type": data["type"], "name": data["name"]}
            
        except requests.exceptions.RequestException as e:
            return {"error": f"GitHub API request failed: {str(e)}"}
        except Exception as e:
            return {"error": f"Unexpected error: {str(e)}"}
    
    def get_repository_commits(self, owner: str, repo: str, sha: Optional[str] = None, per_page: int = 20) -> Dict[str, Any]:
        """
        Get commit history for a repository
        """
        try:
            url = f"{self.base_url}/repos/{owner}/{repo}/commits"
            params = {"per_page": per_page}
            if sha:
                params["sha"] = sha
            
            response = requests.get(url, headers=self.headers, params=params)
            response.raise_for_status()
            
            data = response.json()
            
            commits = []
            for commit in data:
                commits.append({
                    "sha": commit["sha"],
                    "message": commit["commit"]["message"],
                    "author": {
                        "name": commit["commit"]["author"]["name"],
                        "email": commit["commit"]["author"]["email"],
                        "date": commit["commit"]["author"]["date"]
                    },
                    "committer": {
                        "name": commit["commit"]["committer"]["name"],
                        "email": commit["commit"]["committer"]["email"],
                        "date": commit["commit"]["committer"]["date"]
                    },
                    "url": commit["url"],
                    "html_url": commit["html_url"],
                    "parents": [parent["sha"] for parent in commit.get("parents", [])]
                })
            
            return {"commits": commits}
            
        except requests.exceptions.RequestException as e:
            return {"error": f"GitHub API request failed: {str(e)}"}
        except Exception as e:
            return {"error": f"Unexpected error: {str(e)}"}
    
    def get_repository_languages(self, owner: str, repo: str) -> Dict[str, Any]:
        """
        Get language breakdown for a repository
        """
        try:
            url = f"{self.base_url}/repos/{owner}/{repo}/languages"
            response = requests.get(url, headers=self.headers)
            response.raise_for_status()
            
            data = response.json()
            
            # Calculate percentages
            total_bytes = sum(data.values())
            languages = {}
            for language, bytes_count in data.items():
                languages[language] = {
                    "bytes": bytes_count,
                    "percentage": round((bytes_count / total_bytes) * 100, 2) if total_bytes > 0 else 0
                }
            
            return {
                "languages": languages,
                "total_bytes": total_bytes
            }
            
        except requests.exceptions.RequestException as e:
            return {"error": f"GitHub API request failed: {str(e)}"}
        except Exception as e:
            return {"error": f"Unexpected error: {str(e)}"}
    
    def get_repository_contributors(self, owner: str, repo: str) -> Dict[str, Any]:
        """
        Get contributors for a repository
        """
        try:
            url = f"{self.base_url}/repos/{owner}/{repo}/contributors"
            response = requests.get(url, headers=self.headers)
            response.raise_for_status()
            
            data = response.json()
            
            contributors = []
            for contributor in data:
                contributors.append({
                    "login": contributor["login"],
                    "id": contributor["id"],
                    "type": contributor["type"],
                    "contributions": contributor["contributions"],
                    "avatar_url": contributor["avatar_url"],
                    "html_url": contributor["html_url"]
                })
            
            return {"contributors": contributors}
            
        except requests.exceptions.RequestException as e:
            return {"error": f"GitHub API request failed: {str(e)}"}
        except Exception as e:
            return {"error": f"Unexpected error: {str(e)}"}
    
    def search_code(self, query: str, language: Optional[str] = None, sort: str = "indexed", order: str = "desc") -> Dict[str, Any]:
        """
        Search for code across GitHub
        """
        try:
            # Build search query
            search_query = query
            if language:
                search_query += f" language:{language}"
            
            # Make API request
            url = f"{self.base_url}/search/code"
            params = {
                "q": search_query,
                "sort": sort,
                "order": order,
                "per_page": 20
            }
            
            response = requests.get(url, headers=self.headers, params=params)
            response.raise_for_status()
            
            data = response.json()
            
            # Process results
            code_items = []
            for item in data.get("items", []):
                code_items.append({
                    "name": item["name"],
                    "path": item["path"],
                    "sha": item["sha"],
                    "url": item["url"],
                    "git_url": item["git_url"],
                    "html_url": item["html_url"],
                    "repository": {
                        "id": item["repository"]["id"],
                        "name": item["repository"]["name"],
                        "full_name": item["repository"]["full_name"],
                        "html_url": item["repository"]["html_url"]
                    },
                    "score": item["score"]
                })
            
            return {
                "total_count": data.get("total_count", 0),
                "incomplete_results": data.get("incomplete_results", False),
                "items": code_items
            }
            
        except requests.exceptions.RequestException as e:
            return {
                "error": f"GitHub API request failed: {str(e)}",
                "items": []
            }
        except Exception as e:
            return {
                "error": f"Unexpected error: {str(e)}",
                "items": []
            }
