def test_should_make_request_to_mpi_using_transformed_identifier_and_return_va_profile_id(
            self, mpi_client, rmock, mocker,
            sample_notification_model_with_organization):
        notification = sample_notification_model_with_organization
        recipient_identifier = sample_recipient_identifier()
        notification.recipient_identifiers.set(recipient_identifier)

        rmock.get(ANY,
                  json=response_with_one_active_va_profile_id(),
                  status_code=200)

        mocker.patch('app.va.mpi.mpi.is_fhir_format', return_value=False)
        mocked_transform_to_fhir_format = mocker.patch(
            'app.va.mpi.mpi.transform_to_fhir_format',
            return_value='some-transformed-fhir-identifier')

        expected_url = (f"{mpi_client.base_url}/psim_webservice/fhir/Patient/"
                        f"{quote('some-transformed-fhir-identifier')}"
                        f"?-sender={MpiClient.SYSTEM_IDENTIFIER}")

        actual_va_profile_id = mpi_client.get_va_profile_id(notification)

        mocked_transform_to_fhir_format.assert_called_with(
            recipient_identifier)
        assert rmock.called
        assert rmock.request_history[0].url == expected_url
        assert actual_va_profile_id == EXPECTED_VA_PROFILE_ID
class TestGetVaProfileId:
    @pytest.mark.parametrize("recipient_identifiers", [
        None,
        [
            sample_recipient_identifier(IdentifierType.ICN),
            sample_recipient_identifier(IdentifierType.PID)
        ]
    ])
    def test_should_raise_exception_if_not_exactly_one_identifier(
            self, mpi_client, sample_notification_model_with_organization,
            recipient_identifiers):
        notification = sample_notification_model_with_organization
        if recipient_identifiers:
            for identifier in recipient_identifiers:
                notification.recipient_identifiers.set(identifier)
        with pytest.raises(IncorrectNumberOfIdentifiersException) as e:
            mpi_client.get_va_profile_id(notification)
        assert "Unexpected number of recipient_identifiers" in str(e.value)

    def test_should_make_request_to_mpi_using_non_transformed_identifier_and_return_va_profile_id(
            self, mpi_client, rmock, mocker,
            sample_notification_model_with_organization):
        notification = sample_notification_model_with_organization
        recipient_identifier = sample_recipient_identifier()
        notification.recipient_identifiers.set(recipient_identifier)

        rmock.get(ANY,
                  json=response_with_one_active_va_profile_id(),
                  status_code=200)

        mocked_is_fhir_format = mocker.patch('app.va.mpi.mpi.is_fhir_format',
                                             return_value=True)

        expected_url = (f"{mpi_client.base_url}/psim_webservice/fhir/Patient/"
                        f"{quote(recipient_identifier.id_value)}"
                        f"?-sender={MpiClient.SYSTEM_IDENTIFIER}")

        actual_va_profile_id = mpi_client.get_va_profile_id(notification)

        mocked_is_fhir_format.assert_called_with(recipient_identifier.id_value)
        assert rmock.called
        assert rmock.request_history[0].url == expected_url
        assert actual_va_profile_id == EXPECTED_VA_PROFILE_ID

    def test_should_make_request_to_mpi_using_transformed_identifier_and_return_va_profile_id(
            self, mpi_client, rmock, mocker,
            sample_notification_model_with_organization):
        notification = sample_notification_model_with_organization
        recipient_identifier = sample_recipient_identifier()
        notification.recipient_identifiers.set(recipient_identifier)

        rmock.get(ANY,
                  json=response_with_one_active_va_profile_id(),
                  status_code=200)

        mocker.patch('app.va.mpi.mpi.is_fhir_format', return_value=False)
        mocked_transform_to_fhir_format = mocker.patch(
            'app.va.mpi.mpi.transform_to_fhir_format',
            return_value='some-transformed-fhir-identifier')

        expected_url = (f"{mpi_client.base_url}/psim_webservice/fhir/Patient/"
                        f"{quote('some-transformed-fhir-identifier')}"
                        f"?-sender={MpiClient.SYSTEM_IDENTIFIER}")

        actual_va_profile_id = mpi_client.get_va_profile_id(notification)

        mocked_transform_to_fhir_format.assert_called_with(
            recipient_identifier)
        assert rmock.called
        assert rmock.request_history[0].url == expected_url
        assert actual_va_profile_id == EXPECTED_VA_PROFILE_ID

    def test_should_throw_error_when_multiple_active_va_profile_ids_exist(
            self, mpi_client, rmock, notification_with_recipient_identifier):
        rmock.get(ANY,
                  json=response_with_two_active_va_profile_ids(),
                  status_code=200)

        with pytest.raises(MultipleActiveVaProfileIdsException):
            mpi_client.get_va_profile_id(
                notification_with_recipient_identifier)

    def test_should_throw_error_when_no_active_va_profile_id(
            self, mpi_client, rmock, notification_with_recipient_identifier):
        rmock.get(ANY,
                  json=MPI_RESPONSE_WITH_NO_VA_PROFILE_ID,
                  status_code=200)

        with pytest.raises(IdentifierNotFound):
            mpi_client.get_va_profile_id(
                notification_with_recipient_identifier)

    def test_should_throw_error_when_mpi_returns_error_response(
            self, mpi_client, rmock, notification_with_recipient_identifier):
        rmock.get(ANY, json=MPI_ERROR_RESPONSE, status_code=200)

        with pytest.raises(MpiNonRetryableException):
            mpi_client.get_va_profile_id(
                notification_with_recipient_identifier)

    @pytest.mark.parametrize("http_status_code", [429, 500, 502, 503, 504])
    def test_should_throw_mpi_retryable_exception_when_mpi_returns_retryable_http_errors(
            self, mpi_client, rmock, notification_with_recipient_identifier,
            http_status_code):
        rmock.get(ANY, status_code=http_status_code)

        with pytest.raises(MpiRetryableException):
            mpi_client.get_va_profile_id(
                notification_with_recipient_identifier)

    @pytest.mark.parametrize("http_status_code", [400, 401, 403, 404, 501])
    def test_should_throw_mpi_non_retryable_exception_when_mpi_returns_non_retryable_http_errors(
            self, mpi_client, rmock, notification_with_recipient_identifier,
            http_status_code):
        rmock.get(ANY, status_code=http_status_code)

        with pytest.raises(MpiNonRetryableException):
            mpi_client.get_va_profile_id(
                notification_with_recipient_identifier)

    def test_should_throw_exception_when_beneficiary_deceased(
            self, mpi_client, rmock, notification_with_recipient_identifier):
        rmock.get(ANY,
                  json=response_with_deceased_beneficiary(),
                  status_code=200)

        with pytest.raises(BeneficiaryDeceasedException):
            mpi_client.get_va_profile_id(
                notification_with_recipient_identifier)

    def test_should_handle_security_exception(
            self, mpi_client, rmock, notification_with_recipient_identifier):
        rmock.get(ANY, json=MPI_SECURITY_ERROR_RESPONSE, status_code=200)

        with pytest.raises(MpiNonRetryableException):
            mpi_client.get_va_profile_id(
                notification_with_recipient_identifier)

    def test_should_treat_beneficiary_deceased_as_successful_call_to_mpi(
            self, mpi_client, rmock, notification_with_recipient_identifier):
        rmock.get(ANY,
                  json=response_with_deceased_beneficiary(),
                  status_code=200)

        with pytest.raises(BeneficiaryDeceasedException):
            mpi_client.get_va_profile_id(
                notification_with_recipient_identifier)

        mpi_client.statsd_client.incr.assert_any_call("clients.mpi.success")
        mpi_client.statsd_client.incr.assert_called_with(
            "clients.mpi.get_va_profile_id.beneficiary_deceased")

    def test_should_throw_mpi_retryable_exception_when_request_exception_is_thrown(
            self, mpi_client, notification_with_recipient_identifier, mocker):
        mocker.patch('app.va.mpi.mpi.requests.get',
                     side_effect=RequestException)

        with pytest.raises(MpiRetryableException) as e:
            mpi_client.get_va_profile_id(
                notification_with_recipient_identifier)

            assert (
                e.value.failure_reason ==
                'MPI returned RequestException while querying for FHIR identifier'
            )
def notification_with_recipient_identifier(
        sample_notification_model_with_organization):
    notification = sample_notification_model_with_organization
    recipient_identifier = sample_recipient_identifier()
    notification.recipient_identifiers.set(recipient_identifier)
    return notification