"""LinkedIn API error response mocks.

Reference: https://learn.microsoft.com/en-us/linkedin/shared/api-guide/concepts/error-handling

Common HTTP status codes:
- 400 Bad Request: Invalid request format or parameters
- 401 Unauthorized: Invalid or expired token
- 403 Forbidden: Valid token but insufficient permissions
- 404 Not Found: Resource doesn't exist
- 429 Too Many Requests: Rate limit exceeded
- 500 Internal Server Error: LinkedIn server error
"""

from typing import Any


def mock_rate_limit_response(
    retry_after: int = 60,
    message: str = "Rate limit exceeded. Please retry after the specified time.",
) -> tuple[int, dict[str, str], dict[str, Any]]:
    """Generate a mock 429 rate limit response.

    Args:
        retry_after: Seconds until the client can retry
        message: Error message

    Returns:
        Tuple of (status_code, headers, body)
    """
    return (
        429,
        {
            "Retry-After": str(retry_after),
            "X-RateLimit-Limit": "100",
            "X-RateLimit-Remaining": "0",
            "X-RateLimit-Reset": str(retry_after),
        },
        {
            "status": 429,
            "serviceErrorCode": 65600,
            "code": "RATE_LIMIT_EXCEEDED",
            "message": message,
        },
    )


def mock_unauthorized_response(
    error_code: str = "REVOKED_ACCESS_TOKEN",
    message: str = "The token used in the request has been revoked or has expired.",
) -> tuple[int, dict[str, str], dict[str, Any]]:
    """Generate a mock 401 unauthorized response.

    Common error codes:
    - REVOKED_ACCESS_TOKEN: Token has been revoked
    - EXPIRED_ACCESS_TOKEN: Token has expired
    - INVALID_ACCESS_TOKEN: Token is malformed or invalid

    Args:
        error_code: The specific error code
        message: Error message

    Returns:
        Tuple of (status_code, headers, body)
    """
    return (
        401,
        {"WWW-Authenticate": 'Bearer realm="api.linkedin.com"'},
        {
            "status": 401,
            "serviceErrorCode": 65601,
            "code": error_code,
            "message": message,
        },
    )


def mock_forbidden_response(
    error_code: str = "ACCESS_DENIED",
    message: str = "The user does not have permission to access this resource.",
) -> tuple[int, dict[str, str], dict[str, Any]]:
    """Generate a mock 403 forbidden response.

    This typically happens when:
    - Token doesn't have the required scope
    - User is not an admin of the organization
    - Resource is restricted

    Args:
        error_code: The specific error code
        message: Error message

    Returns:
        Tuple of (status_code, headers, body)
    """
    return (
        403,
        {},
        {
            "status": 403,
            "serviceErrorCode": 65602,
            "code": error_code,
            "message": message,
        },
    )


def mock_not_found_response(
    resource_type: str = "organization",
    resource_id: str = "urn:li:organization:99999",
) -> tuple[int, dict[str, str], dict[str, Any]]:
    """Generate a mock 404 not found response.

    Args:
        resource_type: Type of resource that wasn't found
        resource_id: The ID of the missing resource

    Returns:
        Tuple of (status_code, headers, body)
    """
    return (
        404,
        {},
        {
            "status": 404,
            "serviceErrorCode": 65603,
            "code": "RESOURCE_NOT_FOUND",
            "message": f"The requested {resource_type} ({resource_id}) could not be found.",
        },
    )


def mock_bad_request_response(
    field: str = "organizationUrn",
    message: str = "Invalid URN format",
) -> tuple[int, dict[str, str], dict[str, Any]]:
    """Generate a mock 400 bad request response.

    Args:
        field: The field that caused the error
        message: Error message

    Returns:
        Tuple of (status_code, headers, body)
    """
    return (
        400,
        {},
        {
            "status": 400,
            "serviceErrorCode": 65604,
            "code": "BAD_REQUEST",
            "message": f"Invalid value for field '{field}': {message}",
        },
    )


def mock_server_error_response(
    message: str = "An internal server error occurred. Please try again later.",
) -> tuple[int, dict[str, str], dict[str, Any]]:
    """Generate a mock 500 internal server error response.

    Args:
        message: Error message

    Returns:
        Tuple of (status_code, headers, body)
    """
    return (
        500,
        {},
        {
            "status": 500,
            "serviceErrorCode": 0,
            "code": "INTERNAL_SERVER_ERROR",
            "message": message,
        },
    )


def mock_service_unavailable_response(
    retry_after: int = 120,
    message: str = "Service temporarily unavailable. Please try again later.",
) -> tuple[int, dict[str, str], dict[str, Any]]:
    """Generate a mock 503 service unavailable response.

    Args:
        retry_after: Seconds until the client should retry
        message: Error message

    Returns:
        Tuple of (status_code, headers, body)
    """
    return (
        503,
        {"Retry-After": str(retry_after)},
        {
            "status": 503,
            "serviceErrorCode": 0,
            "code": "SERVICE_UNAVAILABLE",
            "message": message,
        },
    )


# Pre-built error scenarios
ERROR_SCENARIOS = {
    "rate_limit": mock_rate_limit_response(),
    "rate_limit_long": mock_rate_limit_response(retry_after=300),
    "token_expired": mock_unauthorized_response(
        error_code="EXPIRED_ACCESS_TOKEN",
        message="The access token has expired.",
    ),
    "token_revoked": mock_unauthorized_response(
        error_code="REVOKED_ACCESS_TOKEN",
        message="The access token has been revoked by the user.",
    ),
    "token_invalid": mock_unauthorized_response(
        error_code="INVALID_ACCESS_TOKEN",
        message="The access token is invalid or malformed.",
    ),
    "forbidden": mock_forbidden_response(),
    "not_admin": mock_forbidden_response(
        error_code="NOT_ORGANIZATION_ADMIN",
        message="The authenticated user is not an administrator of this organization.",
    ),
    "org_not_found": mock_not_found_response(
        resource_type="organization",
        resource_id="urn:li:organization:99999",
    ),
    "invalid_urn": mock_bad_request_response(
        field="organizationUrn",
        message="Must match pattern urn:li:organization:<number>",
    ),
    "server_error": mock_server_error_response(),
    "service_unavailable": mock_service_unavailable_response(),
}


# Helper function to create responses mock for the requests library
def create_mock_response(
    status_code: int,
    headers: dict[str, str],
    json_body: dict[str, Any],
):
    """Create a mock response object compatible with requests library.

    This is useful when using the responses library or unittest.mock.

    Args:
        status_code: HTTP status code
        headers: Response headers
        json_body: Response body as dict

    Returns:
        A mock response specification
    """
    return {
        "status": status_code,
        "headers": headers,
        "json": json_body,
    }
