# This file is auto-generated by oagen. Do not edit.

import json

import pytest
from workos import WorkOSClient, AsyncWorkOSClient
from tests.generated_helpers import load_fixture

from workos.common.models import (
    AuthenticationChallenge,
    AuthenticationFactor,
    AuthenticationFactorEnrolled,
    AuthenticationFactorsCreateRequestType,
    PaginationOrder,
)
from workos.multi_factor_auth.models import (
    AuthenticationChallengeVerifyResponse,
    UserAuthenticationFactorEnrollResponse,
)
from workos._pagination import AsyncPage, SyncPage
from workos._errors import (
    AuthenticationError,
    BadRequestError,
    NotFoundError,
    RateLimitExceededError,
    ServerError,
    UnprocessableEntityError,
)


class TestMultiFactorAuth:
    def test_verify_challenge(self, workos, httpx_mock):
        httpx_mock.add_response(
            json=load_fixture("authentication_challenge_verify_response.json"),
        )
        result = workos.multi_factor_auth.verify_challenge("test_id", code="test_code")
        assert isinstance(result, AuthenticationChallengeVerifyResponse)
        assert result.valid is True
        request = httpx_mock.get_request()
        assert request.method == "POST"
        assert request.url.path.endswith("/auth/challenges/test_id/verify")
        body = json.loads(request.content)
        assert body["code"] == "test_code"

    def test_enroll_factor(self, workos, httpx_mock):
        httpx_mock.add_response(
            json=load_fixture("authentication_factor_enrolled.json"),
        )
        result = workos.multi_factor_auth.enroll_factor(
            type=AuthenticationFactorsCreateRequestType("generic_otp")
        )
        assert isinstance(result, AuthenticationFactorEnrolled)
        assert result.object == "authentication_factor"
        assert result.id == "auth_factor_01FVYZ5QM8N98T9ME5BCB2BBMJ"
        request = httpx_mock.get_request()
        assert request.method == "POST"
        assert request.url.path.endswith("/auth/factors/enroll")
        body = json.loads(request.content)
        assert body["type"] == AuthenticationFactorsCreateRequestType("generic_otp")

    def test_get_factor(self, workos, httpx_mock):
        httpx_mock.add_response(
            json=load_fixture("authentication_factor.json"),
        )
        result = workos.multi_factor_auth.get_factor("test_id")
        assert isinstance(result, AuthenticationFactor)
        assert result.object == "authentication_factor"
        assert result.id == "auth_factor_01FVYZ5QM8N98T9ME5BCB2BBMJ"
        request = httpx_mock.get_request()
        assert request.method == "GET"
        assert request.url.path.endswith("/auth/factors/test_id")

    def test_delete_factor(self, workos, httpx_mock):
        httpx_mock.add_response(status_code=200, content=b"\n")
        result = workos.multi_factor_auth.delete_factor("test_id")
        assert result is None
        request = httpx_mock.get_request()
        assert request.method == "DELETE"
        assert request.url.path.endswith("/auth/factors/test_id")

    def test_challenge_factor(self, workos, httpx_mock):
        httpx_mock.add_response(
            json=load_fixture("authentication_challenge.json"),
        )
        result = workos.multi_factor_auth.challenge_factor("test_id")
        assert isinstance(result, AuthenticationChallenge)
        assert result.object == "authentication_challenge"
        assert result.id == "auth_challenge_01FVYZ5QM8N98T9ME5BCB2BBMJ"
        request = httpx_mock.get_request()
        assert request.method == "POST"
        assert request.url.path.endswith("/auth/factors/test_id/challenge")

    def test_list_user_auth_factors(self, workos, httpx_mock):
        httpx_mock.add_response(
            json=load_fixture("list_authentication_factor.json"),
        )
        page = workos.multi_factor_auth.list_user_auth_factors("test_userlandUserId")
        assert isinstance(page, SyncPage)
        assert len(page.data) == 1
        assert isinstance(page.data[0], AuthenticationFactor)

    def test_list_user_auth_factors_empty_page(self, workos, httpx_mock):
        httpx_mock.add_response(json={"data": [], "list_metadata": {}})
        page = workos.multi_factor_auth.list_user_auth_factors("test_userlandUserId")
        assert isinstance(page, SyncPage)
        assert page.data == []

    def test_list_user_auth_factors_encodes_query_params(self, workos, httpx_mock):
        httpx_mock.add_response(json={"data": [], "list_metadata": {}})
        workos.multi_factor_auth.list_user_auth_factors(
            "test_userlandUserId",
            limit=10,
            before="cursor before",
            after="cursor/after",
            order=PaginationOrder("value_order"),
        )
        request = httpx_mock.get_request()
        assert request.url.params["limit"] == "10"
        assert request.url.params["before"] == "cursor before"
        assert request.url.params["after"] == "cursor/after"
        assert request.url.params["order"] == "value_order"

    def test_create_user_auth_factor(self, workos, httpx_mock):
        httpx_mock.add_response(
            json=load_fixture("user_authentication_factor_enroll_response.json"),
        )
        result = workos.multi_factor_auth.create_user_auth_factor(
            "test_userlandUserId", type="totp"
        )
        assert isinstance(result, UserAuthenticationFactorEnrollResponse)
        request = httpx_mock.get_request()
        assert request.method == "POST"
        assert request.url.path.endswith(
            "/user_management/users/test_userlandUserId/auth_factors"
        )
        body = json.loads(request.content)
        assert body["type"] == "totp"

    def test_verify_challenge_with_request_options(self, workos, httpx_mock):
        httpx_mock.add_response(
            json=load_fixture("authentication_challenge_verify_response.json")
        )
        workos.multi_factor_auth.verify_challenge(
            "test_id",
            code="test_code",
            request_options={"extra_headers": {"X-Custom": "value"}},
        )
        request = httpx_mock.get_request()
        assert request.headers["X-Custom"] == "value"

    def test_verify_challenge_unauthorized(self, workos, httpx_mock):
        httpx_mock.add_response(
            status_code=401,
            json={"message": "Unauthorized"},
        )
        with pytest.raises(AuthenticationError):
            workos.multi_factor_auth.verify_challenge("test_id", code="test_code")

    def test_verify_challenge_not_found(self, httpx_mock):
        workos = WorkOSClient(
            api_key="sk_test_123", client_id="client_test", max_retries=0
        )
        try:
            httpx_mock.add_response(status_code=404, json={"message": "Not found"})
            with pytest.raises(NotFoundError):
                workos.multi_factor_auth.verify_challenge("test_id", code="test_code")
        finally:
            workos.close()

    def test_verify_challenge_rate_limited(self, httpx_mock):
        workos = WorkOSClient(
            api_key="sk_test_123", client_id="client_test", max_retries=0
        )
        try:
            httpx_mock.add_response(
                status_code=429,
                headers={"Retry-After": "0"},
                json={"message": "Slow down"},
            )
            with pytest.raises(RateLimitExceededError):
                workos.multi_factor_auth.verify_challenge("test_id", code="test_code")
        finally:
            workos.close()

    def test_verify_challenge_server_error(self, httpx_mock):
        workos = WorkOSClient(
            api_key="sk_test_123", client_id="client_test", max_retries=0
        )
        try:
            httpx_mock.add_response(status_code=500, json={"message": "Server error"})
            with pytest.raises(ServerError):
                workos.multi_factor_auth.verify_challenge("test_id", code="test_code")
        finally:
            workos.close()

    def test_verify_challenge_bad_request(self, httpx_mock):
        workos = WorkOSClient(
            api_key="sk_test_123", client_id="client_test", max_retries=0
        )
        try:
            httpx_mock.add_response(status_code=400, json={"message": "Bad request"})
            with pytest.raises(BadRequestError):
                workos.multi_factor_auth.verify_challenge("test_id", code="test_code")
        finally:
            workos.close()

    def test_verify_challenge_unprocessable(self, httpx_mock):
        workos = WorkOSClient(
            api_key="sk_test_123", client_id="client_test", max_retries=0
        )
        try:
            httpx_mock.add_response(status_code=422, json={"message": "Unprocessable"})
            with pytest.raises(UnprocessableEntityError):
                workos.multi_factor_auth.verify_challenge("test_id", code="test_code")
        finally:
            workos.close()


class TestAsyncMultiFactorAuth:
    @pytest.mark.asyncio
    async def test_verify_challenge(self, async_workos, httpx_mock):
        httpx_mock.add_response(
            json=load_fixture("authentication_challenge_verify_response.json")
        )
        result = await async_workos.multi_factor_auth.verify_challenge(
            "test_id", code="test_code"
        )
        assert isinstance(result, AuthenticationChallengeVerifyResponse)
        assert result.valid is True
        request = httpx_mock.get_request()
        assert request.method == "POST"
        assert request.url.path.endswith("/auth/challenges/test_id/verify")

    @pytest.mark.asyncio
    async def test_enroll_factor(self, async_workos, httpx_mock):
        httpx_mock.add_response(
            json=load_fixture("authentication_factor_enrolled.json")
        )
        result = await async_workos.multi_factor_auth.enroll_factor(
            type=AuthenticationFactorsCreateRequestType("generic_otp")
        )
        assert isinstance(result, AuthenticationFactorEnrolled)
        assert result.object == "authentication_factor"
        assert result.id == "auth_factor_01FVYZ5QM8N98T9ME5BCB2BBMJ"
        request = httpx_mock.get_request()
        assert request.method == "POST"
        assert request.url.path.endswith("/auth/factors/enroll")

    @pytest.mark.asyncio
    async def test_get_factor(self, async_workos, httpx_mock):
        httpx_mock.add_response(json=load_fixture("authentication_factor.json"))
        result = await async_workos.multi_factor_auth.get_factor("test_id")
        assert isinstance(result, AuthenticationFactor)
        assert result.object == "authentication_factor"
        assert result.id == "auth_factor_01FVYZ5QM8N98T9ME5BCB2BBMJ"
        request = httpx_mock.get_request()
        assert request.method == "GET"
        assert request.url.path.endswith("/auth/factors/test_id")

    @pytest.mark.asyncio
    async def test_delete_factor(self, async_workos, httpx_mock):
        httpx_mock.add_response(status_code=200, content=b"\n")
        result = await async_workos.multi_factor_auth.delete_factor("test_id")
        assert result is None
        request = httpx_mock.get_request()
        assert request.method == "DELETE"
        assert request.url.path.endswith("/auth/factors/test_id")

    @pytest.mark.asyncio
    async def test_challenge_factor(self, async_workos, httpx_mock):
        httpx_mock.add_response(json=load_fixture("authentication_challenge.json"))
        result = await async_workos.multi_factor_auth.challenge_factor("test_id")
        assert isinstance(result, AuthenticationChallenge)
        assert result.object == "authentication_challenge"
        assert result.id == "auth_challenge_01FVYZ5QM8N98T9ME5BCB2BBMJ"
        request = httpx_mock.get_request()
        assert request.method == "POST"
        assert request.url.path.endswith("/auth/factors/test_id/challenge")

    @pytest.mark.asyncio
    async def test_list_user_auth_factors(self, async_workos, httpx_mock):
        httpx_mock.add_response(json=load_fixture("list_authentication_factor.json"))
        page = await async_workos.multi_factor_auth.list_user_auth_factors(
            "test_userlandUserId"
        )
        assert isinstance(page, AsyncPage)
        assert len(page.data) == 1
        assert isinstance(page.data[0], AuthenticationFactor)

    @pytest.mark.asyncio
    async def test_list_user_auth_factors_empty_page(self, async_workos, httpx_mock):
        httpx_mock.add_response(json={"data": [], "list_metadata": {}})
        page = await async_workos.multi_factor_auth.list_user_auth_factors(
            "test_userlandUserId"
        )
        assert isinstance(page, AsyncPage)
        assert page.data == []

    @pytest.mark.asyncio
    async def test_list_user_auth_factors_encodes_query_params(
        self, async_workos, httpx_mock
    ):
        httpx_mock.add_response(json={"data": [], "list_metadata": {}})
        await async_workos.multi_factor_auth.list_user_auth_factors(
            "test_userlandUserId",
            limit=10,
            before="cursor before",
            after="cursor/after",
            order=PaginationOrder("value_order"),
        )
        request = httpx_mock.get_request()
        assert request.url.params["limit"] == "10"
        assert request.url.params["before"] == "cursor before"
        assert request.url.params["after"] == "cursor/after"
        assert request.url.params["order"] == "value_order"

    @pytest.mark.asyncio
    async def test_create_user_auth_factor(self, async_workos, httpx_mock):
        httpx_mock.add_response(
            json=load_fixture("user_authentication_factor_enroll_response.json")
        )
        result = await async_workos.multi_factor_auth.create_user_auth_factor(
            "test_userlandUserId", type="totp"
        )
        assert isinstance(result, UserAuthenticationFactorEnrollResponse)
        request = httpx_mock.get_request()
        assert request.method == "POST"
        assert request.url.path.endswith(
            "/user_management/users/test_userlandUserId/auth_factors"
        )

    @pytest.mark.asyncio
    async def test_verify_challenge_with_request_options(
        self, async_workos, httpx_mock
    ):
        httpx_mock.add_response(
            json=load_fixture("authentication_challenge_verify_response.json")
        )
        await async_workos.multi_factor_auth.verify_challenge(
            "test_id",
            code="test_code",
            request_options={"extra_headers": {"X-Custom": "value"}},
        )
        request = httpx_mock.get_request()
        assert request.headers["X-Custom"] == "value"

    @pytest.mark.asyncio
    async def test_verify_challenge_unauthorized(self, async_workos, httpx_mock):
        httpx_mock.add_response(status_code=401, json={"message": "Unauthorized"})
        with pytest.raises(AuthenticationError):
            await async_workos.multi_factor_auth.verify_challenge(
                "test_id", code="test_code"
            )

    @pytest.mark.asyncio
    async def test_verify_challenge_not_found(self, httpx_mock):
        workos = AsyncWorkOSClient(
            api_key="sk_test_123", client_id="client_test", max_retries=0
        )
        try:
            httpx_mock.add_response(status_code=404, json={"message": "Not found"})
            with pytest.raises(NotFoundError):
                await workos.multi_factor_auth.verify_challenge(
                    "test_id", code="test_code"
                )
        finally:
            await workos.close()

    @pytest.mark.asyncio
    async def test_verify_challenge_rate_limited(self, httpx_mock):
        workos = AsyncWorkOSClient(
            api_key="sk_test_123", client_id="client_test", max_retries=0
        )
        try:
            httpx_mock.add_response(
                status_code=429,
                headers={"Retry-After": "0"},
                json={"message": "Slow down"},
            )
            with pytest.raises(RateLimitExceededError):
                await workos.multi_factor_auth.verify_challenge(
                    "test_id", code="test_code"
                )
        finally:
            await workos.close()

    @pytest.mark.asyncio
    async def test_verify_challenge_server_error(self, httpx_mock):
        workos = AsyncWorkOSClient(
            api_key="sk_test_123", client_id="client_test", max_retries=0
        )
        try:
            httpx_mock.add_response(status_code=500, json={"message": "Server error"})
            with pytest.raises(ServerError):
                await workos.multi_factor_auth.verify_challenge(
                    "test_id", code="test_code"
                )
        finally:
            await workos.close()

    @pytest.mark.asyncio
    async def test_verify_challenge_bad_request(self, httpx_mock):
        workos = AsyncWorkOSClient(
            api_key="sk_test_123", client_id="client_test", max_retries=0
        )
        try:
            httpx_mock.add_response(status_code=400, json={"message": "Bad request"})
            with pytest.raises(BadRequestError):
                await workos.multi_factor_auth.verify_challenge(
                    "test_id", code="test_code"
                )
        finally:
            await workos.close()

    @pytest.mark.asyncio
    async def test_verify_challenge_unprocessable(self, httpx_mock):
        workos = AsyncWorkOSClient(
            api_key="sk_test_123", client_id="client_test", max_retries=0
        )
        try:
            httpx_mock.add_response(status_code=422, json={"message": "Unprocessable"})
            with pytest.raises(UnprocessableEntityError):
                await workos.multi_factor_auth.verify_challenge(
                    "test_id", code="test_code"
                )
        finally:
            await workos.close()
