from typing import Optional


class GitProviderUnavailable(Exception):
    pass


class GqlRateLimitExceededException(Exception):
    pass


class GqlPageTimeoutException(Exception):
    pass


class GitAuthenticationException(Exception):
    def __init__(self, *args, original_exception: Optional[Exception] = None):
        self.original_exception = original_exception
        super().__init__(*args)


class GitAuthorizationException(Exception):
    pass


class GitCircuitBreakerException(Exception):
    """Raised when the percentage of repos that failed to retrieve commits or PRs
    exceeds the circuit breaker threshold. This indicates a systemic issue (e.g.,
    permissions) rather than individual repo-level failures.

    The circuit breaker triggers independently for commits and PRs -- if either
    data type exceeds the failure threshold, the exception is raised."""

    FAILURE_THRESHOLD = 0.80  # 80% failure rate triggers the circuit breaker

    def __init__(
        self,
        commit_failure_count: int,
        commit_total_count: int,
        commit_failure_rate: float,
        pr_failure_count: int,
        pr_total_count: int,
        pr_failure_rate: float,
    ):
        self.commit_failure_count = commit_failure_count
        self.commit_total_count = commit_total_count
        self.commit_failure_rate = commit_failure_rate
        self.pr_failure_count = pr_failure_count
        self.pr_total_count = pr_total_count
        self.pr_failure_rate = pr_failure_rate

        parts = []
        if commit_total_count > 0 and commit_failure_rate > self.FAILURE_THRESHOLD:
            parts.append(
                f'commits: {commit_failure_count}/{commit_total_count} repos '
                f'({commit_failure_rate:.1%}) failed'
            )
        if pr_total_count > 0 and pr_failure_rate > self.FAILURE_THRESHOLD:
            parts.append(
                f'PRs/MRs: {pr_failure_count}/{pr_total_count} repos '
                f'({pr_failure_rate:.1%}) failed'
            )
        super().__init__(f'Circuit breaker triggered: {"; ".join(parts)}')
