# flake8: noqa
# The Okta software accompanied by this notice is provided pursuant to the following terms:
# Copyright © 2025-Present, Okta, Inc.
# Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the
# License.
# You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0.
# Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS
# IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and limitations under the License.
# coding: utf-8

from http import HTTPStatus

import pytest

import okta.models as models
from okta.errors.okta_api_error import OktaAPIError
from tests.mocks import MockOktaClient


class TestPoliciesResource:
    """
    Integration Tests for the Policies Resource
    """

    SDK_PREFIX = "python_sdk"

    @pytest.mark.vcr()
    @pytest.mark.asyncio
    async def test_create_get_sign_on_policy(self, fs):
        # Instantiate Mock Client
        client = MockOktaClient(fs)

        # Create Policy
        policy_model = models.OktaSignOnPolicy(
            **{
                "name": f"{TestPoliciesResource.SDK_PREFIX} Test-Sign-On",
                "status": "ACTIVE",
                "description": "Test policy applies for tests only",
            }
        )

        try:
            created_policy, _, err = await client.create_policy(policy_model)
            assert err is None
            assert isinstance(created_policy, models.OktaSignOnPolicy)
            assert created_policy.name == policy_model.name
            assert created_policy.description == policy_model.description
            assert created_policy.status == "ACTIVE"
            assert created_policy.type == models.PolicyType.OKTA_SIGN_ON

            # Retrieve
            retrieved_policy, _, err = await client.get_policy(created_policy.id)
            assert err is None
            assert retrieved_policy.id == created_policy.id
            assert retrieved_policy.name == created_policy.name
            assert retrieved_policy.description == created_policy.description
            assert retrieved_policy.status == created_policy.status
            assert retrieved_policy.type == created_policy.type

        finally:
            # Delete
            _, _, err = await client.delete_policy(created_policy.id)
            assert err is None

    @pytest.mark.vcr()
    @pytest.mark.asyncio
    async def test_create_password_policy(self, fs):
        # Instantiate Mock Client
        client = MockOktaClient(fs)

        # Create Policy
        policy_model = models.PasswordPolicy(
            **{
                "name": f"{TestPoliciesResource.SDK_PREFIX} Test-Password",
                "status": "ACTIVE",
                "description": "Test policy applies for tests only",
            }
        )

        try:
            created_policy, _, err = await client.create_policy(policy_model)
            assert err is None
            assert isinstance(created_policy, models.PasswordPolicy)
            assert created_policy.name == policy_model.name
            assert created_policy.description == policy_model.description
            assert created_policy.status == "ACTIVE"
            assert created_policy.type == models.PolicyType.PASSWORD

            # Retrieve
            retrieved_policy, _, err = await client.get_policy(created_policy.id)
            assert err is None
            assert retrieved_policy.id == created_policy.id
            assert retrieved_policy.name == created_policy.name
            assert retrieved_policy.description == created_policy.description
            assert retrieved_policy.status == created_policy.status
            assert retrieved_policy.type == created_policy.type

        finally:
            # Delete
            _, _, err = await client.delete_policy(created_policy.id)
            assert err is None

    @pytest.mark.vcr()
    @pytest.mark.asyncio
    async def test_create_get_policy(self, fs):
        # Instantiate Mock Client
        client = MockOktaClient(fs)

        # Create Policy
        policy_model = models.Policy(
            **{
                "name": f"{TestPoliciesResource.SDK_PREFIX} Test-Sign-On",
                "type": models.PolicyType.OKTA_SIGN_ON,
                "status": "ACTIVE",
                "description": "Test policy applies for tests only",
            }
        )

        try:
            created_policy, _, err = await client.create_policy(policy_model)
            assert err is None
            assert isinstance(created_policy, models.OktaSignOnPolicy)
            assert created_policy.name == policy_model.name
            assert created_policy.description == policy_model.description
            assert created_policy.status == "ACTIVE"
            assert created_policy.type == models.PolicyType.OKTA_SIGN_ON

            # Retrieve
            retrieved_policy, _, err = await client.get_policy(created_policy.id)
            assert err is None
            assert retrieved_policy.id == created_policy.id
            assert retrieved_policy.name == created_policy.name
            assert retrieved_policy.description == created_policy.description
            assert retrieved_policy.status == created_policy.status
            assert retrieved_policy.type == created_policy.type

        finally:
            # Delete
            _, _, err = await client.delete_policy(created_policy.id)
            assert err is None

    @pytest.mark.vcr()
    @pytest.mark.asyncio
    async def test_create_get_sign_on_policy_with_group_conditions(self, fs):
        # Instantiate Mock Client
        client = MockOktaClient(fs)

        # Create Group
        GROUP_NAME = "Group-Target-Test"
        group_obj = models.Group(
            **{"profile": models.GroupProfile(**{"name": GROUP_NAME})}
        )

        try:
            created_group, _, err = await client.create_group(group_obj)
            assert err is None
            assert isinstance(created_group, models.Group)

            # Create Policy & Conditions
            policy_model = models.OktaSignOnPolicy(
                **{
                    "name": f"{TestPoliciesResource.SDK_PREFIX} Test-Sign-On",
                    "status": "ACTIVE",
                    "description": "Test policy applies for tests only",
                }
            )

            policy_conditions = models.OktaSignOnPolicyConditions(
                **{
                    "people": models.PolicyPeopleCondition(
                        **{
                            "groups": models.GroupCondition(
                                **{"include": [created_group.id]}
                            )
                        }
                    )
                }
            )

            policy_model.conditions = policy_conditions

            created_policy, _, err = await client.create_policy(policy_model)
            assert err is None
            assert isinstance(created_policy, models.OktaSignOnPolicy)
            assert created_policy.name == policy_model.name
            assert created_policy.description == policy_model.description
            assert created_policy.status == "ACTIVE"
            assert created_policy.type == models.PolicyType.OKTA_SIGN_ON
            assert len(created_policy.conditions.people.groups.include) == 1
            assert created_group.id in created_policy.conditions.people.groups.include

            # Retrieve
            retrieved_policy, _, err = await client.get_policy(created_policy.id)
            assert err is None
            assert retrieved_policy.id == created_policy.id
            assert retrieved_policy.name == created_policy.name
            assert retrieved_policy.description == created_policy.description
            assert retrieved_policy.status == created_policy.status
            assert retrieved_policy.type == created_policy.type
            assert len(retrieved_policy.conditions.people.groups.include) == 1
            assert created_group.id in retrieved_policy.conditions.people.groups.include

        finally:
            errors = []
            # Delete Policy + Group
            try:
                _, _, err = await client.delete_policy(created_policy.id)
                assert err is None
            except Exception as exc:
                errors.append(exc)
            try:
                _, _, err = await client.delete_group(created_group.id)
                assert err is None
            except Exception as exc:
                errors.append(exc)
            assert len(errors) == 0

    @pytest.mark.vcr()
    @pytest.mark.asyncio
    async def test_list_policies_by_type(self, fs):
        # Instantiate Mock Client
        client = MockOktaClient(fs)

        # Create Policies
        policy_model = models.OktaSignOnPolicy(
            **{
                "name": f"{TestPoliciesResource.SDK_PREFIX} Test-Sign-On",
                "status": "ACTIVE",
                "description": "Test sign on policy applies for tests only",
            }
        )

        policy_model_2 = models.PasswordPolicy(
            **{
                "name": f"{TestPoliciesResource.SDK_PREFIX} Test-Password",
                "status": "ACTIVE",
                "description": "Test password policy applies for tests only",
            }
        )

        try:
            created_oss_policy, _, err = await client.create_policy(policy_model)
            assert err is None
            assert isinstance(created_oss_policy, models.OktaSignOnPolicy)
            assert created_oss_policy.name == policy_model.name
            assert created_oss_policy.description == policy_model.description
            assert created_oss_policy.status == "ACTIVE"
            assert created_oss_policy.type == models.PolicyType.OKTA_SIGN_ON

            created_pw_policy, _, err = await client.create_policy(policy_model_2)
            assert err is None
            assert isinstance(created_pw_policy, models.PasswordPolicy)
            assert created_pw_policy.name == policy_model_2.name
            assert created_pw_policy.description == policy_model_2.description
            assert created_pw_policy.status == "ACTIVE"
            assert created_pw_policy.type == models.PolicyType.PASSWORD

            # List by type
            query_params_list_sign_on = {"type": "OKTA_SIGN_ON"}
            sign_on_policies, _, err = await client.list_policies(type="OKTA_SIGN_ON")
            assert err is None
            assert isinstance(sign_on_policies, list)
            assert next(
                (plcy for plcy in sign_on_policies if plcy.id == created_oss_policy.id)
            )

            query_params_list_pw = {"type": "PASSWORD"}
            sign_on_policies, _, err = await client.list_policies(type="PASSWORD")
            assert err is None
            assert isinstance(sign_on_policies, list)
            assert next(
                (plcy for plcy in sign_on_policies if plcy.id == created_pw_policy.id)
            )

        finally:
            errors = []
            # Delete
            try:
                _, _, err = await client.delete_policy(created_oss_policy.id)
                assert err is None
            except Exception as exc:
                errors.append(exc)
            try:
                _, _, err = await client.delete_policy(created_pw_policy.id)
                assert err is None
            except Exception as exc:
                errors.append(exc)
            assert len(errors) == 0

    @pytest.mark.vcr()
    @pytest.mark.asyncio
    async def test_delete_policy(self, fs):
        # Instantiate Mock Client
        client = MockOktaClient(fs)

        # Create Policy
        policy_model = models.OktaSignOnPolicy(
            **{
                "name": f"{TestPoliciesResource.SDK_PREFIX} Test-Sign-On",
                "status": "ACTIVE",
                "description": "Test policy applies for tests only",
            }
        )

        try:
            created_policy, _, err = await client.create_policy(policy_model)
            assert err is None
            assert isinstance(created_policy, models.OktaSignOnPolicy)
            assert created_policy.name == policy_model.name
            assert created_policy.description == policy_model.description
            assert created_policy.status == "ACTIVE"
            assert created_policy.type == models.PolicyType.OKTA_SIGN_ON

            # Retrieve
            retrieved_policy, _, err = await client.get_policy(created_policy.id)
            assert err is None
            assert retrieved_policy.id == created_policy.id
            assert retrieved_policy.name == created_policy.name
            assert retrieved_policy.description == created_policy.description
            assert retrieved_policy.status == created_policy.status
            assert retrieved_policy.type == created_policy.type

            # Delete
            _, _, err = await client.delete_policy(created_policy.id)
            assert err is None

            # Retrieve
            retrieved_policy, resp, err = await client.get_policy(created_policy.id)
            assert err is not None
            assert isinstance(err, OktaAPIError)
            assert resp.status == HTTPStatus.NOT_FOUND
            assert retrieved_policy is None
        finally:
            try:
                _, _, err = await client.delete_policy(created_policy.id)
            except Exception:
                pass

    @pytest.mark.vcr()
    @pytest.mark.asyncio
    async def test_update_policy(self, fs):
        # Instantiate Mock Client
        client = MockOktaClient(fs)

        # Create Policy
        policy_model = models.OktaSignOnPolicy(
            **{
                "name": f"{TestPoliciesResource.SDK_PREFIX} Test-Sign-On",
                "status": "ACTIVE",
                "description": "Test policy applies for tests only",
            }
        )

        try:
            created_policy, _, err = await client.create_policy(policy_model)
            assert err is None
            assert isinstance(created_policy, models.OktaSignOnPolicy)
            assert created_policy.name == policy_model.name
            assert created_policy.description == policy_model.description
            assert created_policy.status == "ACTIVE"
            assert created_policy.type == models.PolicyType.OKTA_SIGN_ON

            # Retrieve
            retrieved_policy, _, err = await client.get_policy(created_policy.id)
            assert err is None
            assert retrieved_policy.id == created_policy.id
            assert retrieved_policy.name == created_policy.name
            assert retrieved_policy.description == created_policy.description
            assert retrieved_policy.status == created_policy.status
            assert retrieved_policy.type == created_policy.type

            # Update
            NEW_NAME = policy_model.name + "UPDATED"
            NEW_DESC = policy_model.description + "UPDATED"
            created_policy.name = NEW_NAME
            created_policy.description = NEW_DESC
            updated_policy, _, err = await client.replace_policy(
                created_policy.id, created_policy
            )
            assert err is None
            assert updated_policy.id == created_policy.id
            assert updated_policy.name == NEW_NAME
            assert updated_policy.description == NEW_DESC

            # Retrieve
            retrieved_policy, _, err = await client.get_policy(created_policy.id)
            assert err is None
            assert retrieved_policy.id == created_policy.id
            assert retrieved_policy.name == NEW_NAME
            assert retrieved_policy.description == NEW_DESC
            assert retrieved_policy.status == created_policy.status
            assert retrieved_policy.type == created_policy.type

        finally:
            # Delete
            _, _, err = await client.delete_policy(created_policy.id)
            assert err is None

    @pytest.mark.vcr()
    @pytest.mark.asyncio
    async def test_activate_deactivate_policy(self, fs):
        # Instantiate Mock Client
        client = MockOktaClient(fs)

        # Create Policy
        policy_model = models.OktaSignOnPolicy(
            **{
                "name": f"{TestPoliciesResource.SDK_PREFIX} Test-Sign-On",
                "status": "ACTIVE",
                "description": "Test policy applies for tests only",
            }
        )

        try:
            created_policy, _, err = await client.create_policy(policy_model)
            assert err is None
            assert isinstance(created_policy, models.OktaSignOnPolicy)
            assert created_policy.name == policy_model.name
            assert created_policy.description == policy_model.description
            assert created_policy.status == "ACTIVE"
            assert created_policy.type == models.PolicyType.OKTA_SIGN_ON

            # Deactivate
            _, _, err = await client.deactivate_policy(created_policy.id)
            assert err is None

            # Retrieve
            retrieved_policy, _, err = await client.get_policy(created_policy.id)
            assert err is None
            assert retrieved_policy.id == created_policy.id
            assert retrieved_policy.name == created_policy.name
            assert retrieved_policy.description == created_policy.description
            assert retrieved_policy.status == "INACTIVE"
            assert retrieved_policy.type == created_policy.type

            # Reactivate
            _, _, err = await client.activate_policy(created_policy.id)
            assert err is None

        finally:
            # Delete
            _, _, err = await client.delete_policy(created_policy.id)
            assert err is None

    """
    POLICY RULES TESTS BELOW
    """

    @pytest.mark.vcr()
    @pytest.mark.asyncio
    async def test_create_get_sign_on_policy_rule(self, fs):
        # Instantiate Mock Client
        client = MockOktaClient(fs)

        # Create Policy
        policy_model = models.OktaSignOnPolicy(
            **{
                "name": f"{TestPoliciesResource.SDK_PREFIX} Test-Sign-On",
                "status": "ACTIVE",
                "description": "Test policy applies for tests only",
            }
        )

        try:
            created_policy, _, err = await client.create_policy(policy_model)
            assert err is None
            assert isinstance(created_policy, models.OktaSignOnPolicy)
            assert created_policy.name == policy_model.name
            assert created_policy.description == policy_model.description
            assert created_policy.status == "ACTIVE"
            assert created_policy.type == models.PolicyType.OKTA_SIGN_ON

            # Create Policy Rule
            policy_rule_model = models.PolicyRule(
                **{
                    "name": f"{TestPoliciesResource.SDK_PREFIX} Test-Sign-On-Rule",
                    "actions": models.OktaSignOnPolicyRuleActions(
                        **{
                            "signon": models.OktaSignOnPolicyRuleSignonActions(
                                **{
                                    "access": "ALLOW",
                                    "require_factor": False,
                                    "remember_device_by_default": False,
                                    "session": models.OktaSignOnPolicyRuleSignonSessionActions(
                                        **{
                                            "use_persistent_cookie": False,
                                            "max_session_idle_minutes": 720,
                                            "max_session_lifetime_minutes": 0,
                                        }
                                    ),
                                }
                            )
                        }
                    ),
                    "conditions": models.OktaSignOnPolicyRuleConditions(
                        **{
                            "auth_context": models.PolicyRuleAuthContextCondition(
                                **{"auth_type": "ANY"}
                            )
                        }
                    ),
                }
            )
            created_policy_rule, _, err = await client.create_policy_rule(
                created_policy.id, policy_rule_model
            )
            assert err is None
            assert isinstance(created_policy_rule, models.OktaSignOnPolicyRule)
            assert created_policy_rule.name == policy_rule_model.name
            assert created_policy_rule.type == "SIGN_ON"
            assert created_policy_rule.actions.signon.access == "ALLOW"
            assert created_policy_rule.actions.signon.require_factor is False
            assert (
                    created_policy_rule.actions.signon.remember_device_by_default is False
            )
            assert (
                    created_policy_rule.actions.signon.session.use_persistent_cookie
                    is False
            )
            assert (
                    created_policy_rule.actions.signon.session.max_session_idle_minutes
                    == 720
            )
            assert (
                    created_policy_rule.actions.signon.session.max_session_lifetime_minutes
                    == 0
            )
            assert created_policy_rule.conditions.auth_context.auth_type == "ANY"

            # Retrieve
            retrieved_policy_rule, _, err = await client.get_policy_rule(
                created_policy.id, created_policy_rule.id
            )
            assert err is None
            assert retrieved_policy_rule.id == created_policy_rule.id
            assert retrieved_policy_rule.name == created_policy_rule.name
            assert isinstance(retrieved_policy_rule, models.OktaSignOnPolicyRule)

        finally:
            errors = []
            # Delete
            try:
                _, _, err = await client.delete_policy_rule(
                    created_policy.id, created_policy_rule.id
                )
                assert err is None
            except Exception as exc:
                errors.append(exc)
            try:
                _, _, err = await client.delete_policy(created_policy.id)
                assert err is None
            except Exception as exc:
                errors.append(exc)
            assert len(errors) == 0

    @pytest.mark.vcr()
    @pytest.mark.asyncio
    async def test_create_get_password_policy_rule(self, fs):
        # Instantiate Mock Client
        client = MockOktaClient(fs)

        # Create Policy
        policy_model = models.PasswordPolicy(
            **{
                "name": f"{TestPoliciesResource.SDK_PREFIX} Test-Password",
                "status": "ACTIVE",
                "description": "Test policy applies for tests only",
            }
        )

        try:
            created_policy, _, err = await client.create_policy(policy_model)
            assert err is None
            assert isinstance(created_policy, models.PasswordPolicy)
            assert created_policy.name == policy_model.name
            assert created_policy.description == policy_model.description
            assert created_policy.status == "ACTIVE"
            assert created_policy.type == models.PolicyType.PASSWORD

            # Create Policy Rule
            policy_rule_model = models.PolicyRule(
                **{
                    "name": f"{TestPoliciesResource.SDK_PREFIX} Test-Password-Rule",
                    "type": "PASSWORD",
                    "actions": models.PasswordPolicyRuleActions(
                        **{
                            "password_change": models.PasswordPolicyRuleAction(
                                **{"access": "ALLOW"}
                            ),
                            "self_service_password_reset": models.SelfServicePasswordResetAction(
                                **{"access": "ALLOW"}
                            ),
                            "self_service_unlock": models.PasswordPolicyRuleAction(
                                **{"access": "ALLOW"}
                            ),
                        }
                    ),
                    "conditions": models.PasswordPolicyRuleConditions(
                        **{
                            "people": models.PolicyPeopleCondition(
                                **{"users": models.UserCondition(**{"exclude": []})}
                            ),
                            "network": models.PolicyNetworkCondition(
                                **{"connection": "ANYWHERE"}
                            ),
                        }
                    ),
                }
            )
            created_policy_rule, _, err = await client.create_policy_rule(
                created_policy.id, policy_rule_model
            )
            assert err is None
            assert isinstance(created_policy_rule, models.PasswordPolicyRule)
            assert created_policy_rule.name == policy_rule_model.name
            assert created_policy_rule.type == "PASSWORD"
            assert created_policy_rule.status == "ACTIVE"
            assert created_policy_rule.conditions.people.users.exclude == []
            assert created_policy_rule.conditions.network.connection == "ANYWHERE"
            assert created_policy_rule.actions.password_change.access == "ALLOW"
            assert (
                    created_policy_rule.actions.self_service_password_reset.access
                    == "ALLOW"
            )
            assert created_policy_rule.actions.self_service_unlock.access == "ALLOW"

            # Retrieve
            retrieved_policy_rule, _, err = await client.get_policy_rule(
                created_policy.id, created_policy_rule.id
            )
            assert err is None
            assert retrieved_policy_rule.id == created_policy_rule.id
            assert retrieved_policy_rule.name == created_policy_rule.name
            assert isinstance(retrieved_policy_rule, models.PasswordPolicyRule)

        finally:
            errors = []
            # Delete
            try:
                _, _, err = await client.delete_policy_rule(
                    created_policy.id, created_policy_rule.id
                )
                assert err is None
            except Exception as exc:
                errors.append(exc)
            try:
                _, _, err = await client.delete_policy(created_policy.id)
                assert err is None
            except Exception as exc:
                errors.append(exc)
            assert len(errors) == 0

    @pytest.mark.vcr()
    @pytest.mark.asyncio
    async def test_update_policy_rule(self, fs):
        # Instantiate Mock Client
        client = MockOktaClient(fs)

        # Create Policy
        policy_model = models.OktaSignOnPolicy(
            **{
                "name": f"{TestPoliciesResource.SDK_PREFIX} Test-Sign-On",
                "status": "ACTIVE",
                "description": "Test policy applies for tests only",
            }
        )

        try:
            created_policy, _, err = await client.create_policy(policy_model)
            assert err is None
            assert isinstance(created_policy, models.OktaSignOnPolicy)
            assert created_policy.name == policy_model.name
            assert created_policy.description == policy_model.description
            assert created_policy.status == "ACTIVE"
            assert created_policy.type == models.PolicyType.OKTA_SIGN_ON

            # Create Policy Rule
            policy_rule_model = models.OktaSignOnPolicyRule(
                **{
                    "name": f"{TestPoliciesResource.SDK_PREFIX} Test-Sign-On-Rule",
                    "actions": models.OktaSignOnPolicyRuleActions(
                        **{
                            "signon": models.OktaSignOnPolicyRuleSignonActions(
                                **{
                                    "access": "ALLOW",
                                    "requireFactor": False,
                                    "rememberDeviceByDefault": False,
                                    "session": models.OktaSignOnPolicyRuleSignonSessionActions(
                                        **{
                                            "usePersistentCookie": False,
                                            "maxSessionIdleMinutes": 720,
                                            "maxSessionLifetimeMinutes": 0,
                                        }
                                    ),
                                }
                            )
                        }
                    ),
                    "conditions": models.OktaSignOnPolicyRuleConditions(
                        **{
                            "authContext": models.PolicyRuleAuthContextCondition(
                                **{"authType": "ANY"}
                            )
                        }
                    ),
                }
            )
            created_policy_rule, _, err = await client.create_policy_rule(
                created_policy.id, policy_rule_model
            )
            assert err is None
            assert isinstance(created_policy_rule, models.OktaSignOnPolicyRule)
            assert created_policy_rule.name == policy_rule_model.name
            assert created_policy_rule.type == "SIGN_ON"
            assert created_policy_rule.actions.signon.access == "ALLOW"
            assert created_policy_rule.actions.signon.require_factor is False
            assert (
                    created_policy_rule.actions.signon.remember_device_by_default is False
            )
            assert (
                    created_policy_rule.actions.signon.session.use_persistent_cookie
                    is False
            )
            assert (
                    created_policy_rule.actions.signon.session.max_session_idle_minutes
                    == 720
            )
            assert (
                    created_policy_rule.actions.signon.session.max_session_lifetime_minutes
                    == 0
            )
            assert created_policy_rule.conditions.auth_context.auth_type == "ANY"

            # Retrieve
            retrieved_policy_rule, _, err = await client.get_policy_rule(
                created_policy.id, created_policy_rule.id
            )
            assert err is None
            assert retrieved_policy_rule.id == created_policy_rule.id
            assert retrieved_policy_rule.name == created_policy_rule.name
            assert isinstance(retrieved_policy_rule, models.OktaSignOnPolicyRule)

            # Update
            created_policy_rule.name = policy_rule_model.name + "UPDATED"
            created_policy_rule.conditions.network.connection = "ANYWHERE"
            updated_policy_rule, _, err = await client.replace_policy_rule(
                created_policy.id, created_policy_rule.id, created_policy_rule
            )
            assert err is None
            assert isinstance(updated_policy_rule, models.OktaSignOnPolicyRule)
            assert updated_policy_rule.name == created_policy_rule.name
            assert (
                    updated_policy_rule.conditions.network.connection
                    == created_policy_rule.conditions.network.connection
            )

            # Retrieve
            retrieved_policy_rule, _, err = await client.get_policy_rule(
                created_policy.id, created_policy_rule.id
            )
            assert err is None
            assert retrieved_policy_rule.id == created_policy_rule.id
            assert retrieved_policy_rule.name == created_policy_rule.name
            assert (
                    retrieved_policy_rule.conditions.network.connection
                    == created_policy_rule.conditions.network.connection
            )
            assert isinstance(retrieved_policy_rule, models.OktaSignOnPolicyRule)

        finally:
            errors = []
            # Delete
            try:
                _, _, err = await client.delete_policy_rule(
                    created_policy.id, created_policy_rule.id
                )
                assert err is None
            except Exception as exc:
                errors.append(exc)
            try:
                _, _, err = await client.delete_policy(created_policy.id)
                assert err is None
            except Exception as exc:
                errors.append(exc)
            assert len(errors) == 0

    @pytest.mark.vcr()
    @pytest.mark.asyncio
    async def test_list_policy_rules(self, fs):
        # Instantiate Mock Client
        client = MockOktaClient(fs)

        # Create Policy
        policy_model = models.OktaSignOnPolicy(
            **{
                "name": f"{TestPoliciesResource.SDK_PREFIX} Test-Sign-On",
                "status": "ACTIVE",
                "description": "Test policy applies for tests only",
            }
        )

        try:
            created_policy, _, err = await client.create_policy(policy_model)
            assert err is None
            assert isinstance(created_policy, models.OktaSignOnPolicy)
            assert created_policy.name == policy_model.name
            assert created_policy.description == policy_model.description
            assert created_policy.status == "ACTIVE"
            assert created_policy.type == models.PolicyType.OKTA_SIGN_ON

            # Create Policy Rule
            policy_rule_model = models.OktaSignOnPolicyRule(
                **{
                    "name": f"{TestPoliciesResource.SDK_PREFIX} Test-Sign-On-Rule",
                    "actions": models.OktaSignOnPolicyRuleActions(
                        **{
                            "signon": models.OktaSignOnPolicyRuleSignonActions(
                                **{
                                    "access": "ALLOW",
                                    "requireFactor": False,
                                    "rememberDeviceByDefault": False,
                                    "session": models.OktaSignOnPolicyRuleSignonSessionActions(
                                        **{
                                            "usePersistentCookie": False,
                                            "maxSessionIdleMinutes": 720,
                                            "maxSessionLifetimeMinutes": 0,
                                        }
                                    ),
                                }
                            )
                        }
                    ),
                    "conditions": models.OktaSignOnPolicyRuleConditions(
                        **{
                            "authContext": models.PolicyRuleAuthContextCondition(
                                **{"authType": "ANY"}
                            )
                        }
                    ),
                }
            )
            created_policy_rule, _, err = await client.create_policy_rule(
                created_policy.id, policy_rule_model
            )
            assert err is None
            assert isinstance(created_policy_rule, models.OktaSignOnPolicyRule)
            assert created_policy_rule.name == policy_rule_model.name
            assert created_policy_rule.type == "SIGN_ON"
            assert created_policy_rule.actions.signon.access == "ALLOW"
            assert created_policy_rule.actions.signon.require_factor is False
            assert (
                    created_policy_rule.actions.signon.remember_device_by_default is False
            )
            assert (
                    created_policy_rule.actions.signon.session.use_persistent_cookie
                    is False
            )
            assert (
                    created_policy_rule.actions.signon.session.max_session_idle_minutes
                    == 720
            )
            assert (
                    created_policy_rule.actions.signon.session.max_session_lifetime_minutes
                    == 0
            )
            assert created_policy_rule.conditions.auth_context.auth_type == "ANY"

            # List
            policy_rules, _, err = await client.list_policy_rules(created_policy.id)
            assert err is None
            assert isinstance(policy_rules, list)
            assert next(
                (
                    plcy_rule
                    for plcy_rule in policy_rules
                    if plcy_rule.id == created_policy_rule.id
                )
            )
            assert len(policy_rules) == 1

        finally:
            errors = []
            # Delete
            try:
                _, _, err = await client.delete_policy_rule(
                    created_policy.id, created_policy_rule.id
                )
                assert err is None
            except Exception as exc:
                errors.append(exc)
            try:
                _, _, err = await client.delete_policy(created_policy.id)
                assert err is None
            except Exception as exc:
                errors.append(exc)
            assert len(errors) == 0

    @pytest.mark.vcr()
    @pytest.mark.asyncio
    async def test_delete_policy_rules(self, fs):
        # Instantiate Mock Client
        client = MockOktaClient(fs)

        # Create Policy
        policy_model = models.OktaSignOnPolicy(
            **{
                "name": f"{TestPoliciesResource.SDK_PREFIX} Test-Sign-On",
                "status": "ACTIVE",
                "description": "Test policy applies for tests only",
            }
        )

        try:
            created_policy, _, err = await client.create_policy(policy_model)
            assert err is None
            assert isinstance(created_policy, models.OktaSignOnPolicy)
            assert created_policy.name == policy_model.name
            assert created_policy.description == policy_model.description
            assert created_policy.status == "ACTIVE"
            assert created_policy.type == models.PolicyType.OKTA_SIGN_ON

            # Create Policy Rule
            policy_rule_model = models.OktaSignOnPolicyRule(
                **{
                    "name": f"{TestPoliciesResource.SDK_PREFIX} Test-Sign-On-Rule",
                    "actions": models.OktaSignOnPolicyRuleActions(
                        **{
                            "signon": models.OktaSignOnPolicyRuleSignonActions(
                                **{
                                    "access": "ALLOW",
                                    "requireFactor": False,
                                    "rememberDeviceByDefault": False,
                                    "session": models.OktaSignOnPolicyRuleSignonSessionActions(
                                        **{
                                            "usePersistentCookie": False,
                                            "maxSessionIdleMinutes": 720,
                                            "maxSessionLifetimeMinutes": 0,
                                        }
                                    ),
                                }
                            )
                        }
                    ),
                    "conditions": models.OktaSignOnPolicyRuleConditions(
                        **{
                            "authContext": models.PolicyRuleAuthContextCondition(
                                **{"authType": "ANY"}
                            )
                        }
                    ),
                }
            )
            created_policy_rule, _, err = await client.create_policy_rule(
                created_policy.id, policy_rule_model
            )
            assert err is None
            assert isinstance(created_policy_rule, models.OktaSignOnPolicyRule)
            assert created_policy_rule.name == policy_rule_model.name
            assert created_policy_rule.type == "SIGN_ON"
            assert created_policy_rule.actions.signon.access == "ALLOW"
            assert created_policy_rule.actions.signon.require_factor is False
            assert (
                    created_policy_rule.actions.signon.remember_device_by_default is False
            )
            assert (
                    created_policy_rule.actions.signon.session.use_persistent_cookie
                    is False
            )
            assert (
                    created_policy_rule.actions.signon.session.max_session_idle_minutes
                    == 720
            )
            assert (
                    created_policy_rule.actions.signon.session.max_session_lifetime_minutes
                    == 0
            )
            assert created_policy_rule.conditions.auth_context.auth_type == "ANY"

            # Retrieve
            retrieved_policy_rule, _, err = await client.get_policy_rule(
                created_policy.id, created_policy_rule.id
            )
            assert err is None
            assert retrieved_policy_rule.id == created_policy_rule.id
            assert retrieved_policy_rule.name == created_policy_rule.name
            assert isinstance(retrieved_policy_rule, models.OktaSignOnPolicyRule)

            # Delete
            _, _, err = await client.delete_policy_rule(
                created_policy.id, created_policy_rule.id
            )
            assert err is None
            _, _, err = await client.delete_policy(created_policy.id)
            assert err is None

            # Retrieve
            retrieved_policy_rule, resp, err = await client.get_policy_rule(
                created_policy.id, created_policy_rule.id
            )
            assert err is not None
            assert isinstance(err, OktaAPIError)
            assert resp.status == HTTPStatus.NOT_FOUND
            assert retrieved_policy_rule is None
        finally:
            # Delete
            try:
                _, _, err = await client.delete_policy_rule(
                    created_policy.id, created_policy_rule.id
                )
            except Exception:
                pass
            try:
                _, _, err = await client.delete_policy(created_policy.id)
            except Exception:
                pass

    @pytest.mark.vcr()
    @pytest.mark.asyncio
    async def test_activate_deactivate_policy_rule(self, fs):
        # Instantiate Mock Client
        client = MockOktaClient(fs)

        # Create Policy
        policy_model = models.OktaSignOnPolicy(
            **{
                "name": f"{TestPoliciesResource.SDK_PREFIX} Test-Sign-On",
                "status": "ACTIVE",
                "description": "Test policy applies for tests only",
            }
        )

        try:
            created_policy, _, err = await client.create_policy(policy_model)
            assert err is None
            assert isinstance(created_policy, models.OktaSignOnPolicy)
            assert created_policy.name == policy_model.name
            assert created_policy.description == policy_model.description
            assert created_policy.status == "ACTIVE"
            assert created_policy.type == models.PolicyType.OKTA_SIGN_ON

            # Create Policy Rule
            policy_rule_model = models.PolicyRule(
                **{
                    "name": f"{TestPoliciesResource.SDK_PREFIX} Test-Sign-On-Rule",
                    "actions": models.OktaSignOnPolicyRuleActions(
                        **{
                            "signon": models.OktaSignOnPolicyRuleSignonActions(
                                **{
                                    "access": "ALLOW",
                                    "requireFactor": False,
                                    "rememberDeviceByDefault": False,
                                    "session": models.OktaSignOnPolicyRuleSignonSessionActions(
                                        **{
                                            "usePersistentCookie": False,
                                            "maxSessionIdleMinutes": 720,
                                            "maxSessionLifetimeMinutes": 0,
                                        }
                                    ),
                                }
                            )
                        }
                    ),
                    "conditions": models.OktaSignOnPolicyRuleConditions(
                        **{
                            "authContext": models.PolicyRuleAuthContextCondition(
                                **{"authType": "ANY"}
                            )
                        }
                    ),
                }
            )
            created_policy_rule, _, err = await client.create_policy_rule(
                created_policy.id, policy_rule_model
            )
            assert err is None
            assert isinstance(created_policy_rule, models.OktaSignOnPolicyRule)
            assert created_policy_rule.name == policy_rule_model.name
            assert created_policy_rule.type == "SIGN_ON"
            assert created_policy_rule.status == "ACTIVE"
            assert created_policy_rule.actions.signon.access == "ALLOW"
            assert created_policy_rule.actions.signon.require_factor is False
            assert (
                    created_policy_rule.actions.signon.remember_device_by_default is False
            )
            assert (
                    created_policy_rule.actions.signon.session.use_persistent_cookie
                    is False
            )
            assert (
                    created_policy_rule.actions.signon.session.max_session_idle_minutes
                    == 720
            )
            assert (
                    created_policy_rule.actions.signon.session.max_session_lifetime_minutes
                    == 0
            )
            assert created_policy_rule.conditions.auth_context.auth_type == "ANY"

            # Retrieve
            retrieved_policy_rule, _, err = await client.get_policy_rule(
                created_policy.id, created_policy_rule.id
            )
            assert err is None
            assert retrieved_policy_rule.id == created_policy_rule.id
            assert retrieved_policy_rule.name == created_policy_rule.name
            assert retrieved_policy_rule.status == "ACTIVE"
            assert isinstance(retrieved_policy_rule, models.OktaSignOnPolicyRule)

            # Deactivate
            _, _, err = await client.deactivate_policy_rule(
                created_policy.id, created_policy_rule.id
            )
            assert err is None

            # Retrieve
            retrieved_policy_rule, _, err = await client.get_policy_rule(
                created_policy.id, created_policy_rule.id
            )
            assert err is None
            assert retrieved_policy_rule.id == created_policy_rule.id
            assert retrieved_policy_rule.name == created_policy_rule.name
            assert retrieved_policy_rule.status == "INACTIVE"
            assert isinstance(retrieved_policy_rule, models.OktaSignOnPolicyRule)

            # Reactivate
            _, _, err = await client.activate_policy_rule(
                created_policy.id, created_policy_rule.id
            )
            assert err is None

            # Retrieve
            retrieved_policy_rule, _, err = await client.get_policy_rule(
                created_policy.id, created_policy_rule.id
            )
            assert err is None
            assert retrieved_policy_rule.id == created_policy_rule.id
            assert retrieved_policy_rule.name == created_policy_rule.name
            assert retrieved_policy_rule.status == "ACTIVE"
            assert isinstance(retrieved_policy_rule, models.OktaSignOnPolicyRule)

        finally:
            errors = []
            # Delete
            try:
                _, _, err = await client.delete_policy_rule(
                    created_policy.id, created_policy_rule.id
                )
                assert err is None
            except Exception as exc:
                errors.append(exc)
            try:
                _, _, err = await client.delete_policy(created_policy.id)
                assert err is None
            except Exception as exc:
                errors.append(exc)
            assert len(errors) == 0
