"""Contract tests for async operation Pydantic models.

These tests validate that AsyncOperation and OperationStatus models correctly parse
live Graph API responses from /admin/teams/telephoneNumberManagement/operations.

Note: Testing async operations is challenging because:
1. Operations are created by assign/unassign actions (destructive)
2. Operations may complete quickly and become unavailable
3. There is no "list operations" endpoint to discover existing operations

This test file validates the model structure when an operation can be found,
but gracefully skips when no test data is available.
"""

from __future__ import annotations

import pytest

from teams_phone.models import (
    AsyncOperation,
    OperationStatus,
)


@pytest.mark.contract
@pytest.mark.asyncio
async def test_operation_status_enum_values() -> None:
    """Verify OperationStatus enum contains expected values.

    This is a static test that validates the enum definition matches
    documented Graph API values. Since we cannot easily trigger or
    discover async operations without destructive actions, we validate
    the enum structure directly.
    """
    # Expected values from Graph API documentation
    expected_values = {
        "notStarted",
        "running",
        "succeeded",
        "failed",
        "skipped",
        "unknownFutureValue",
    }

    enum_values = {e.value for e in OperationStatus}
    assert enum_values == expected_values, (
        f"OperationStatus enum values mismatch. "
        f"Expected: {expected_values}, Got: {enum_values}"
    )


@pytest.mark.contract
@pytest.mark.asyncio
async def test_async_operation_model_structure() -> None:
    """Validate AsyncOperation model structure with synthetic data.

    Since async operations cannot be easily discovered without performing
    destructive assign/unassign operations, this test validates the model
    can parse the expected response structure using synthetic data matching
    the documented API contract.

    Note: The AsyncOperation model includes @odata.context and @odata.type
    as explicit fields (unlike other models that strip OData metadata),
    because polling responses include these fields consistently.
    """
    # Synthetic data matching documented Graph API response structure
    # Based on: /admin/teams/telephoneNumberManagement/operations/{id}
    sample_response = {
        "@odata.context": "https://graph.microsoft.com/beta/$metadata#admin/teams/telephoneNumberManagement/operations/$entity",
        "@odata.type": "#microsoft.graph.telephoneNumberManagementOperation",
        "id": "00000000-0000-0000-0000-000000000001",
        "createdDateTime": "2024-01-15T10:30:00Z",
        "status": "succeeded",
        "numbers": [
            {
                "resourceLocation": "/admin/teams/telephoneNumberManagement/numberAssignments/%2B14255551234",
                "status": "succeeded",
            }
        ],
    }

    # Validate model can parse the response
    operation = AsyncOperation.model_validate(sample_response)

    assert operation.id == "00000000-0000-0000-0000-000000000001"
    assert operation.status == OperationStatus.SUCCEEDED
    assert operation.odata_context is not None
    assert operation.odata_type is not None
    assert len(operation.numbers) == 1
    assert operation.numbers[0].status == OperationStatus.SUCCEEDED


@pytest.mark.contract
@pytest.mark.asyncio
async def test_async_operation_minimal_response() -> None:
    """Validate AsyncOperation model with minimal response structure.

    Tests that the model handles responses with minimal fields (empty numbers list).
    """
    # Minimal response without optional fields
    minimal_response = {
        "createdDateTime": "2024-01-15T10:30:00Z",
        "status": "running",
        "numbers": [],
    }

    # Validate model can parse minimal response
    operation = AsyncOperation.model_validate(minimal_response)

    assert operation.status == OperationStatus.RUNNING
    assert operation.id is None  # id is optional
    assert operation.odata_context is None
    assert operation.odata_type is None
    assert operation.numbers == []


@pytest.mark.contract
@pytest.mark.asyncio
async def test_async_operation_all_status_values() -> None:
    """Validate AsyncOperation model accepts all OperationStatus values.

    Ensures the model can parse operations in any valid status state.
    """
    base_response = {
        "createdDateTime": "2024-01-15T10:30:00Z",
        "numbers": [],
    }

    # Test each status value
    for status in OperationStatus:
        response = {**base_response, "status": status.value}
        operation = AsyncOperation.model_validate(response)
        assert operation.status == status
