"""GitHub API client for fetching commits."""

from datetime import datetime, timedelta
from typing import List, Dict, Any
from github import Github, GithubException
import logging

logger = logging.getLogger(__name__)


class CommitInfo:
    """Information about a single commit."""
    
    def __init__(self, sha: str, message: str, author: str, date: datetime,
                 files_changed: List[Dict[str, Any]], pr_number: int = None,
                 pr_url: str = None):
        self.sha = sha
        self.message = message
        self.author = author
        self.date = date
        self.files_changed = files_changed
        self.pr_number = pr_number
        self.pr_url = pr_url


class GitHubClient:
    """Client for interacting with GitHub API."""
    
    def __init__(self, token: str):
        """Initialize GitHub client.
        
        Args:
            token: GitHub personal access token
        """
        self.github = Github(token)
    
    def get_commits_last_24h(self, repo_name: str, branch: str) -> List[CommitInfo]:
        """Get all commits from the last 24 hours for a repository branch.
        
        Args:
            repo_name: Repository name (owner/repo)
            branch: Branch name
            
        Returns:
            List of CommitInfo objects
        """
        try:
            repo = self.github.get_repo(repo_name)
            since = datetime.now() - timedelta(days=1)
            
            commits = repo.get_commits(sha=branch, since=since)
            
            commit_infos = []
            for commit in commits:
                # Get file changes
                files_changed = []
                for file in commit.files:
                    files_changed.append({
                        'filename': file.filename,
                        'status': file.status,  # 'added', 'modified', 'removed', etc.
                        'additions': file.additions,
                        'deletions': file.deletions,
                        'changes': file.changes,
                        'patch': file.patch if hasattr(file, 'patch') else None
                    })
                
                # Try to find associated PR
                pr_number = None
                pr_url = None
                try:
                    prs = repo.get_pulls(state='closed', sort='updated', direction='desc')
                    for pr in prs:
                        if pr.merge_commit_sha == commit.sha:
                            pr_number = pr.number
                            pr_url = pr.html_url
                            break
                except GithubException as e:
                    logger.warning(f"Could not fetch PR info for commit {commit.sha}: {e}")
                
                commit_info = CommitInfo(
                    sha=commit.sha,
                    message=commit.commit.message,
                    author=commit.commit.author.name,
                    date=commit.commit.author.date,
                    files_changed=files_changed,
                    pr_number=pr_number,
                    pr_url=pr_url
                )
                commit_infos.append(commit_info)
            
            return commit_infos
            
        except GithubException as e:
            logger.error(f"Error fetching commits from {repo_name}/{branch}: {e}")
            raise
    
    def get_pr_files_url(self, repo_name: str, pr_number: int) -> str:
        """Get the URL for PR file changes.
        
        Args:
            repo_name: Repository name (owner/repo)
            pr_number: PR number
            
        Returns:
            URL to PR files changed page
        """
        return f"https://github.com/{repo_name}/pull/{pr_number}/files"
