"""Git utilities for cloning repositories and fetching PRs."""

import os
import subprocess
from pathlib import Path
from typing import Optional
import git
import requests


class GitUtils:
    """Utility class for Git operations."""
    
    def __init__(self, work_dir: str = "./repos"):
        """Initialize GitUtils with a working directory."""
        self.work_dir = Path(work_dir)
        self.work_dir.mkdir(exist_ok=True)
    
    def parse_github_url(self, repo_url: str) -> tuple[str, str]:
        """Parse GitHub URL to extract owner and repo name.
        
        Args:
            repo_url: GitHub repository URL
            
        Returns:
            Tuple of (owner, repo_name)
        """
        # Handle different URL formats
        if repo_url.startswith("https://github.com/"):
            repo_url = repo_url.replace("https://github.com/", "")
        elif repo_url.startswith("git@github.com:"):
            repo_url = repo_url.replace("git@github.com:", "")
        
        if repo_url.endswith(".git"):
            repo_url = repo_url[:-4]
        
        parts = repo_url.split("/")
        if len(parts) != 2:
            raise ValueError(f"Invalid GitHub URL format: {repo_url}")
        
        return parts[0], parts[1]
    
    def get_repo_path(self, owner: str, repo_name: str) -> Path:
        """Get the local path for a repository."""
        return self.work_dir / f"{owner}_{repo_name}"
    
    def clone_or_update_repo(self, repo_url: str) -> Path:
        """Clone repository or update if it already exists.
        
        Args:
            repo_url: GitHub repository URL
            
        Returns:
            Path to the local repository
        """
        owner, repo_name = self.parse_github_url(repo_url)
        repo_path = self.get_repo_path(owner, repo_name)
        
        if repo_path.exists():
            print(f"Repository already exists at {repo_path}, updating...")
            repo = git.Repo(repo_path)
            repo.remotes.origin.fetch()
            print("Repository updated successfully.")
        else:
            print(f"Cloning repository to {repo_path}...")
            repo = git.Repo.clone_from(repo_url, repo_path)
            print("Repository cloned successfully.")
        
        return repo_path
    
    def fetch_and_checkout_pr(self, repo_path: Path, pr_number: int) -> bool:
        """Fetch and checkout a specific PR.
        
        Args:
            repo_path: Path to the local repository
            pr_number: PR number to fetch
            
        Returns:
            True if successful, False otherwise
        """
        try:
            repo = git.Repo(repo_path)
            
            # Fetch the PR ref
            pr_ref = f"pull/{pr_number}/head"
            pr_branch = f"pr-{pr_number}"
            
            print(f"Fetching PR #{pr_number}...")
            repo.remotes.origin.fetch(f"{pr_ref}:{pr_branch}")
            
            # Checkout the PR branch
            print(f"Checking out PR #{pr_number}...")
            repo.git.checkout(pr_branch)
            
            print(f"Successfully checked out PR #{pr_number}")
            return True
            
        except Exception as e:
            print(f"Error fetching PR #{pr_number}: {e}")
            return False
    
    def get_pr_info(self, repo_url: str, pr_number: int) -> Optional[dict]:
        """Get PR information from GitHub API.
        
        Args:
            repo_url: GitHub repository URL
            pr_number: PR number
            
        Returns:
            PR information dict or None if not found
        """
        try:
            owner, repo_name = self.parse_github_url(repo_url)
            api_url = f"https://api.github.com/repos/{owner}/{repo_name}/pulls/{pr_number}"
            
            response = requests.get(api_url)
            if response.status_code == 200:
                return response.json()
            else:
                print(f"PR #{pr_number} not found or API error: {response.status_code}")
                return None
                
        except Exception as e:
            print(f"Error fetching PR info: {e}")
            return None