"""API client for Prismor security scanning service."""

import os
import requests
from typing import Optional, Dict, Any


class PrismorAPIError(Exception):
    """Custom exception for Prismor API errors."""
    pass


class PrismorClient:
    """Client for interacting with Prismor API."""
    
    def __init__(self, api_key: Optional[str] = None):
        """Initialize the Prismor API client.
        
        Args:
            api_key: Prismor API key. If not provided, will look for PRISMOR_API_KEY env var.
        """
        self.api_key = api_key or os.environ.get("PRISMOR_API_KEY")
        if not self.api_key:
            raise PrismorAPIError(
                "PRISMOR_API_KEY environment variable is not set. "
                "Please set it with: export PRISMOR_API_KEY=your_api_key"
            )
        
        # self.base_url = "http://localhost:3000"
        self.base_url = "https://prismor.dev"
        self.headers = {
            "Authorization": f"Bearer {self.api_key}",
            "Content-Type": "application/json"
        }
    
    def authenticate(self) -> Dict[str, Any]:
        """Authenticate with the Prismor API using the API key.
        
        Returns:
            Dictionary containing user information and repositories
            
        Raises:
            PrismorAPIError: If authentication fails
        """
        try:
            response = requests.post(
                f"{self.base_url}/api/cli/auth",
                json={"apiKey": self.api_key},
                headers={"Content-Type": "application/json"},
                timeout=30
            )
            
            if response.status_code == 401:
                raise PrismorAPIError("Invalid API key. Please check your PRISMOR_API_KEY.")
            
            if response.status_code == 400:
                raise PrismorAPIError("API key is required.")
            
            if response.status_code >= 400:
                error_msg = response.json().get("error", "Authentication failed")
                raise PrismorAPIError(f"Authentication error: {error_msg}")
            
            response.raise_for_status()
            return response.json()
            
        except requests.exceptions.Timeout:
            raise PrismorAPIError("Authentication request timed out.")
        except requests.exceptions.ConnectionError:
            raise PrismorAPIError(
                "Failed to connect to Prismor API. Please check your internet connection."
            )
        except requests.exceptions.RequestException as e:
            raise PrismorAPIError(f"Authentication request failed: {str(e)}")
    
    def normalize_repo_url(self, repo: str) -> str:
        """Normalize repository input to a full GitHub URL.
        
        Args:
            repo: Repository in format 'username/repo' or full GitHub URL
            
        Returns:
            Full GitHub repository URL
        """
        if repo.startswith("http://") or repo.startswith("https://"):
            return repo
        
        # Assume it's in username/repo format
        if "/" in repo:
            return f"https://github.com/{repo}"
        
        raise PrismorAPIError(
            f"Invalid repository format: {repo}. "
            "Please use 'username/repo' or full GitHub URL"
        )
    
    def scan(
        self,
        repo: str,
        vex: bool = False,
        sbom: bool = False,
        detect_secret: bool = False,
        fullscan: bool = False,
        branch: Optional[str] = None
    ) -> Dict[str, Any]:
        """Perform security scan on a GitHub repository.
        
        Args:
            repo: Repository URL or username/repo format
            vex: Enable vulnerability scanning
            sbom: Enable SBOM generation
            detect_secret: Enable secret detection
            fullscan: Enable all scan types
            branch: Specific branch to scan (defaults to main/master)
            
        Returns:
            Dictionary containing scan results
        """
        repo_url = self.normalize_repo_url(repo)
        
        # First authenticate to get user info
        auth_response = self.authenticate()
        user_info = auth_response.get("user", {})
        
        # Prepare request payload for CLI scan
        payload = {
            "repo_url": repo_url,
            "api_key": self.api_key,
            "vex": vex or fullscan,
            "sbom": sbom or fullscan,
            "detect_secret": detect_secret or fullscan,
            "fullscan": fullscan,
            "branch": branch
        }
        
        try:
            response = requests.post(
                f"{self.base_url}/api/cli/scan",
                json=payload,
                headers={"Content-Type": "application/json"},
                timeout=300  # 5 minute timeout
            )
            
            if response.status_code == 401:
                error_data = response.json()
                if error_data.get("action") == "integrate_github":
                    raise PrismorAPIError(
                        f"{error_data.get('message', 'GitHub integration required')}\n"
                        f"Please visit: {error_data.get('integration_url', 'https://prismor.dev/dashboard')}"
                    )
                raise PrismorAPIError("Invalid API key. Please check your PRISMOR_API_KEY.")
            
            if response.status_code == 404:
                raise PrismorAPIError("CLI scan endpoint not found. Please check if CLI endpoints are available.")
            
            if response.status_code >= 400:
                error_msg = response.json().get("error", "Unknown error")
                raise PrismorAPIError(f"API error: {error_msg}")
            
            response.raise_for_status()
            result = response.json()
            
            # Handle the new response format from CLI endpoint
            if result.get("ok") and "results" in result:
                return result["results"]
            return result
            
        except requests.exceptions.Timeout:
            raise PrismorAPIError(
                "Request timed out. The repository scan is taking longer than expected."
            )
        except requests.exceptions.ConnectionError:
            raise PrismorAPIError(
                "Failed to connect to Prismor API. Please check your internet connection."
            )
        except requests.exceptions.RequestException as e:
            raise PrismorAPIError(f"Request failed: {str(e)}")
    
    def get_repositories(self) -> Dict[str, Any]:
        """Get user's repositories.
        
        Returns:
            Dictionary containing user repositories
            
        Raises:
            PrismorAPIError: If request fails
        """
        auth_response = self.authenticate()
        user_info = auth_response.get("user", {})
        return {
            "repositories": user_info.get("repositories", []),
            "user": {
                "id": user_info.get("id"),
                "email": user_info.get("email"),
                "name": user_info.get("name")
            }
        }

