import os
import pytest
import requests
from jsonschema import validate  # pip install jsonschema


BASE_URL = os.environ.get("API_BASE_URL", "http://localhost:8000")


class TestUpdatePet:
    """Tests for PUT /pet"""

    def test_happy_path(self):
        """Happy path — expects 2xx response"""
        response = requests.put(url=BASE_URL + "/pet", headers={"Authorization": "Bearer <YOUR_TOKEN>"})
        assert response.status_code in (200, 201, 204)

    def test_missing_auth(self):
        """Missing auth token — expects 401"""
        response = requests.put(url=BASE_URL + "/pet")
        assert response.status_code == 401

    def test_response_matches_schema(self):
        """Successful response body matches the documented schema"""
        response = requests.put(url=BASE_URL + "/pet", headers={"Authorization": "Bearer <YOUR_TOKEN>"})
        if response.status_code not in (200, 201):
            pytest.skip("no successful response to validate")
        schema = {'required': ['name', 'photoUrls'], 'type': 'object', 'properties': {'id': {'type': 'integer', 'format': 'int64', 'example': 10}, 'name': {'type': 'string', 'example': 'doggie'}, 'category': {'type': 'object', 'properties': {'id': {'type': 'integer', 'format': 'int64', 'example': 1}, 'name': {'type': 'string', 'example': 'Dogs'}}, 'xml': {'name': 'category'}}, 'photoUrls': {'type': 'array', 'xml': {'wrapped': True}, 'items': {'type': 'string', 'xml': {'name': 'photoUrl'}}}, 'tags': {'type': 'array', 'xml': {'wrapped': True}, 'items': {'type': 'object', 'properties': {'id': {'type': 'integer', 'format': 'int64'}, 'name': {'type': 'string'}}, 'xml': {'name': 'tag'}}}, 'status': {'type': 'string', 'description': 'pet status in the store', 'enum': ['available', 'pending', 'sold']}}, 'xml': {'name': 'pet'}}
        validate(instance=response.json(), schema=schema)

class TestAddPet:
    """Tests for POST /pet"""

    def test_happy_path(self):
        """Happy path — expects 2xx response"""
        response = requests.post(url=BASE_URL + "/pet", headers={"Authorization": "Bearer <YOUR_TOKEN>"})
        assert response.status_code in (200, 201, 204)

    def test_missing_auth(self):
        """Missing auth token — expects 401"""
        response = requests.post(url=BASE_URL + "/pet")
        assert response.status_code == 401

    def test_response_matches_schema(self):
        """Successful response body matches the documented schema"""
        response = requests.post(url=BASE_URL + "/pet", headers={"Authorization": "Bearer <YOUR_TOKEN>"})
        if response.status_code not in (200, 201):
            pytest.skip("no successful response to validate")
        schema = {'required': ['name', 'photoUrls'], 'type': 'object', 'properties': {'id': {'type': 'integer', 'format': 'int64', 'example': 10}, 'name': {'type': 'string', 'example': 'doggie'}, 'category': {'type': 'object', 'properties': {'id': {'type': 'integer', 'format': 'int64', 'example': 1}, 'name': {'type': 'string', 'example': 'Dogs'}}, 'xml': {'name': 'category'}}, 'photoUrls': {'type': 'array', 'xml': {'wrapped': True}, 'items': {'type': 'string', 'xml': {'name': 'photoUrl'}}}, 'tags': {'type': 'array', 'xml': {'wrapped': True}, 'items': {'type': 'object', 'properties': {'id': {'type': 'integer', 'format': 'int64'}, 'name': {'type': 'string'}}, 'xml': {'name': 'tag'}}}, 'status': {'type': 'string', 'description': 'pet status in the store', 'enum': ['available', 'pending', 'sold']}}, 'xml': {'name': 'pet'}}
        validate(instance=response.json(), schema=schema)

class TestFindPetsByStatus:
    """Tests for GET /pet/findByStatus"""

    def test_happy_path(self):
        """Happy path — expects 2xx response"""
        response = requests.get(url=BASE_URL + "/pet/findByStatus", params={'status': 'example'}, headers={"Authorization": "Bearer <YOUR_TOKEN>"})
        assert response.status_code in (200, 201, 204)

    def test_missing_auth(self):
        """Missing auth token — expects 401"""
        response = requests.get(url=BASE_URL + "/pet/findByStatus", params={'status': 'example'})
        assert response.status_code == 401

    def test_missing_status(self):
        """Missing required param 'status' — expects 400 or 422"""
        response = requests.get(url=BASE_URL + "/pet/findByStatus", headers={"Authorization": "Bearer <YOUR_TOKEN>"})
        assert response.status_code in (400, 422)

    def test_invalid_types(self):
        """Invalid field types — expects 400 or 422"""
        response = requests.get(url=BASE_URL + "/pet/findByStatus", params={'status': 'INVALID_TYPE_$$'}, headers={"Authorization": "Bearer <YOUR_TOKEN>"})
        assert response.status_code in (400, 422)

    def test_response_matches_schema(self):
        """Successful response body matches the documented schema"""
        response = requests.get(url=BASE_URL + "/pet/findByStatus", params={'status': 'example'}, headers={"Authorization": "Bearer <YOUR_TOKEN>"})
        if response.status_code not in (200, 201):
            pytest.skip("no successful response to validate")
        schema = {'type': 'array', 'items': {'required': ['name', 'photoUrls'], 'type': 'object', 'properties': {'id': {'type': 'integer', 'format': 'int64', 'example': 10}, 'name': {'type': 'string', 'example': 'doggie'}, 'category': {'type': 'object', 'properties': {'id': {'type': 'integer', 'format': 'int64', 'example': 1}, 'name': {'type': 'string', 'example': 'Dogs'}}, 'xml': {'name': 'category'}}, 'photoUrls': {'type': 'array', 'xml': {'wrapped': True}, 'items': {'type': 'string', 'xml': {'name': 'photoUrl'}}}, 'tags': {'type': 'array', 'xml': {'wrapped': True}, 'items': {'type': 'object', 'properties': {'id': {'type': 'integer', 'format': 'int64'}, 'name': {'type': 'string'}}, 'xml': {'name': 'tag'}}}, 'status': {'type': 'string', 'description': 'pet status in the store', 'enum': ['available', 'pending', 'sold']}}, 'xml': {'name': 'pet'}}}
        validate(instance=response.json(), schema=schema)

class TestFindPetsByTags:
    """Tests for GET /pet/findByTags"""

    def test_happy_path(self):
        """Happy path — expects 2xx response"""
        response = requests.get(url=BASE_URL + "/pet/findByTags", params={'tags': 'example'}, headers={"Authorization": "Bearer <YOUR_TOKEN>"})
        assert response.status_code in (200, 201, 204)

    def test_missing_auth(self):
        """Missing auth token — expects 401"""
        response = requests.get(url=BASE_URL + "/pet/findByTags", params={'tags': 'example'})
        assert response.status_code == 401

    def test_missing_tags(self):
        """Missing required param 'tags' — expects 400 or 422"""
        response = requests.get(url=BASE_URL + "/pet/findByTags", headers={"Authorization": "Bearer <YOUR_TOKEN>"})
        assert response.status_code in (400, 422)

    def test_invalid_types(self):
        """Invalid field types — expects 400 or 422"""
        response = requests.get(url=BASE_URL + "/pet/findByTags", params={'tags': 'INVALID_TYPE_$$'}, headers={"Authorization": "Bearer <YOUR_TOKEN>"})
        assert response.status_code in (400, 422)

    def test_response_matches_schema(self):
        """Successful response body matches the documented schema"""
        response = requests.get(url=BASE_URL + "/pet/findByTags", params={'tags': 'example'}, headers={"Authorization": "Bearer <YOUR_TOKEN>"})
        if response.status_code not in (200, 201):
            pytest.skip("no successful response to validate")
        schema = {'type': 'array', 'items': {'required': ['name', 'photoUrls'], 'type': 'object', 'properties': {'id': {'type': 'integer', 'format': 'int64', 'example': 10}, 'name': {'type': 'string', 'example': 'doggie'}, 'category': {'type': 'object', 'properties': {'id': {'type': 'integer', 'format': 'int64', 'example': 1}, 'name': {'type': 'string', 'example': 'Dogs'}}, 'xml': {'name': 'category'}}, 'photoUrls': {'type': 'array', 'xml': {'wrapped': True}, 'items': {'type': 'string', 'xml': {'name': 'photoUrl'}}}, 'tags': {'type': 'array', 'xml': {'wrapped': True}, 'items': {'type': 'object', 'properties': {'id': {'type': 'integer', 'format': 'int64'}, 'name': {'type': 'string'}}, 'xml': {'name': 'tag'}}}, 'status': {'type': 'string', 'description': 'pet status in the store', 'enum': ['available', 'pending', 'sold']}}, 'xml': {'name': 'pet'}}}
        validate(instance=response.json(), schema=schema)

class TestGetPetById:
    """Tests for GET /pet/{petId}"""

    def test_happy_path(self):
        """Happy path — expects 2xx response"""
        response = requests.get(url=BASE_URL + "/pet/1", headers={"Authorization": "Bearer <YOUR_TOKEN>"})
        assert response.status_code in (200, 201, 204)

    def test_missing_auth(self):
        """Missing auth token — expects 401"""
        response = requests.get(url=BASE_URL + "/pet/1")
        assert response.status_code == 401

    def test_missing_petId(self):
        """Missing required param 'petId' — expects 400 or 422"""
        response = requests.get(url=BASE_URL + "/pet/1", headers={"Authorization": "Bearer <YOUR_TOKEN>"})
        assert response.status_code in (400, 422)

    def test_response_matches_schema(self):
        """Successful response body matches the documented schema"""
        response = requests.get(url=BASE_URL + "/pet/1", headers={"Authorization": "Bearer <YOUR_TOKEN>"})
        if response.status_code not in (200, 201):
            pytest.skip("no successful response to validate")
        schema = {'required': ['name', 'photoUrls'], 'type': 'object', 'properties': {'id': {'type': 'integer', 'format': 'int64', 'example': 10}, 'name': {'type': 'string', 'example': 'doggie'}, 'category': {'type': 'object', 'properties': {'id': {'type': 'integer', 'format': 'int64', 'example': 1}, 'name': {'type': 'string', 'example': 'Dogs'}}, 'xml': {'name': 'category'}}, 'photoUrls': {'type': 'array', 'xml': {'wrapped': True}, 'items': {'type': 'string', 'xml': {'name': 'photoUrl'}}}, 'tags': {'type': 'array', 'xml': {'wrapped': True}, 'items': {'type': 'object', 'properties': {'id': {'type': 'integer', 'format': 'int64'}, 'name': {'type': 'string'}}, 'xml': {'name': 'tag'}}}, 'status': {'type': 'string', 'description': 'pet status in the store', 'enum': ['available', 'pending', 'sold']}}, 'xml': {'name': 'pet'}}
        validate(instance=response.json(), schema=schema)

class TestUpdatePetWithForm:
    """Tests for POST /pet/{petId}"""

    def test_happy_path(self):
        """Happy path — expects 2xx response"""
        response = requests.post(url=BASE_URL + "/pet/1", params={'name': 'example', 'status': 'example'}, headers={"Authorization": "Bearer <YOUR_TOKEN>"})
        assert response.status_code in (200, 201, 204)

    def test_missing_auth(self):
        """Missing auth token — expects 401"""
        response = requests.post(url=BASE_URL + "/pet/1", params={'name': 'example', 'status': 'example'})
        assert response.status_code == 401

    def test_missing_petId(self):
        """Missing required param 'petId' — expects 400 or 422"""
        response = requests.post(url=BASE_URL + "/pet/1", params={'name': 'example', 'status': 'example'}, headers={"Authorization": "Bearer <YOUR_TOKEN>"})
        assert response.status_code in (400, 422)

    def test_invalid_types(self):
        """Invalid field types — expects 400 or 422"""
        response = requests.post(url=BASE_URL + "/pet/1", params={'name': 'INVALID_TYPE_$$', 'status': 'INVALID_TYPE_$$'}, headers={"Authorization": "Bearer <YOUR_TOKEN>"})
        assert response.status_code in (400, 422)

    def test_response_matches_schema(self):
        """Successful response body matches the documented schema"""
        response = requests.post(url=BASE_URL + "/pet/1", params={'name': 'example', 'status': 'example'}, headers={"Authorization": "Bearer <YOUR_TOKEN>"})
        if response.status_code not in (200, 201):
            pytest.skip("no successful response to validate")
        schema = {'required': ['name', 'photoUrls'], 'type': 'object', 'properties': {'id': {'type': 'integer', 'format': 'int64', 'example': 10}, 'name': {'type': 'string', 'example': 'doggie'}, 'category': {'type': 'object', 'properties': {'id': {'type': 'integer', 'format': 'int64', 'example': 1}, 'name': {'type': 'string', 'example': 'Dogs'}}, 'xml': {'name': 'category'}}, 'photoUrls': {'type': 'array', 'xml': {'wrapped': True}, 'items': {'type': 'string', 'xml': {'name': 'photoUrl'}}}, 'tags': {'type': 'array', 'xml': {'wrapped': True}, 'items': {'type': 'object', 'properties': {'id': {'type': 'integer', 'format': 'int64'}, 'name': {'type': 'string'}}, 'xml': {'name': 'tag'}}}, 'status': {'type': 'string', 'description': 'pet status in the store', 'enum': ['available', 'pending', 'sold']}}, 'xml': {'name': 'pet'}}
        validate(instance=response.json(), schema=schema)

class TestDeletePet:
    """Tests for DELETE /pet/{petId}"""

    def test_happy_path(self):
        """Happy path — expects 2xx response"""
        response = requests.delete(url=BASE_URL + "/pet/1", headers={"Authorization": "Bearer <YOUR_TOKEN>"})
        assert response.status_code in (200, 201, 204)

    def test_missing_auth(self):
        """Missing auth token — expects 401"""
        response = requests.delete(url=BASE_URL + "/pet/1")
        assert response.status_code == 401

    def test_missing_petId(self):
        """Missing required param 'petId' — expects 400 or 422"""
        response = requests.delete(url=BASE_URL + "/pet/1", headers={"Authorization": "Bearer <YOUR_TOKEN>"})
        assert response.status_code in (400, 422)

class TestUploadFile:
    """Tests for POST /pet/{petId}/uploadImage"""

    def test_happy_path(self):
        """Happy path — expects 2xx response"""
        response = requests.post(url=BASE_URL + "/pet/1/uploadImage", params={'additionalMetadata': 'example'}, headers={"Authorization": "Bearer <YOUR_TOKEN>"})
        assert response.status_code in (200, 201, 204)

    def test_missing_auth(self):
        """Missing auth token — expects 401"""
        response = requests.post(url=BASE_URL + "/pet/1/uploadImage", params={'additionalMetadata': 'example'})
        assert response.status_code == 401

    def test_missing_petId(self):
        """Missing required param 'petId' — expects 400 or 422"""
        response = requests.post(url=BASE_URL + "/pet/1/uploadImage", params={'additionalMetadata': 'example'}, headers={"Authorization": "Bearer <YOUR_TOKEN>"})
        assert response.status_code in (400, 422)

    def test_invalid_types(self):
        """Invalid field types — expects 400 or 422"""
        response = requests.post(url=BASE_URL + "/pet/1/uploadImage", params={'additionalMetadata': 'INVALID_TYPE_$$'}, headers={"Authorization": "Bearer <YOUR_TOKEN>"})
        assert response.status_code in (400, 422)

    def test_response_matches_schema(self):
        """Successful response body matches the documented schema"""
        response = requests.post(url=BASE_URL + "/pet/1/uploadImage", params={'additionalMetadata': 'example'}, headers={"Authorization": "Bearer <YOUR_TOKEN>"})
        if response.status_code not in (200, 201):
            pytest.skip("no successful response to validate")
        schema = {'type': 'object', 'properties': {'code': {'type': 'integer', 'format': 'int32'}, 'type': {'type': 'string'}, 'message': {'type': 'string'}}, 'xml': {'name': '##default'}}
        validate(instance=response.json(), schema=schema)

class TestGetInventory:
    """Tests for GET /store/inventory"""

    def test_happy_path(self):
        """Happy path — expects 2xx response"""
        response = requests.get(url=BASE_URL + "/store/inventory", headers={"Authorization": "Bearer <YOUR_TOKEN>"})
        assert response.status_code in (200, 201, 204)

    def test_missing_auth(self):
        """Missing auth token — expects 401"""
        response = requests.get(url=BASE_URL + "/store/inventory")
        assert response.status_code == 401

    def test_response_matches_schema(self):
        """Successful response body matches the documented schema"""
        response = requests.get(url=BASE_URL + "/store/inventory", headers={"Authorization": "Bearer <YOUR_TOKEN>"})
        if response.status_code not in (200, 201):
            pytest.skip("no successful response to validate")
        schema = {'type': 'object', 'additionalProperties': {'type': 'integer', 'format': 'int32'}}
        validate(instance=response.json(), schema=schema)

class TestPlaceOrder:
    """Tests for POST /store/order"""

    def test_happy_path(self):
        """Happy path — expects 2xx response"""
        response = requests.post(url=BASE_URL + "/store/order")
        assert response.status_code in (200, 201, 204)

    def test_response_matches_schema(self):
        """Successful response body matches the documented schema"""
        response = requests.post(url=BASE_URL + "/store/order")
        if response.status_code not in (200, 201):
            pytest.skip("no successful response to validate")
        schema = {'type': 'object', 'properties': {'id': {'type': 'integer', 'format': 'int64', 'example': 10}, 'petId': {'type': 'integer', 'format': 'int64', 'example': 198772}, 'quantity': {'type': 'integer', 'format': 'int32', 'example': 7}, 'shipDate': {'type': 'string', 'format': 'date-time'}, 'status': {'type': 'string', 'description': 'Order Status', 'example': 'approved', 'enum': ['placed', 'approved', 'delivered']}, 'complete': {'type': 'boolean'}}, 'xml': {'name': 'order'}}
        validate(instance=response.json(), schema=schema)

class TestGetOrderById:
    """Tests for GET /store/order/{orderId}"""

    def test_happy_path(self):
        """Happy path — expects 2xx response"""
        response = requests.get(url=BASE_URL + "/store/order/1")
        assert response.status_code in (200, 201, 204)

    def test_missing_orderId(self):
        """Missing required param 'orderId' — expects 400 or 422"""
        response = requests.get(url=BASE_URL + "/store/order/1")
        assert response.status_code in (400, 422)

    def test_response_matches_schema(self):
        """Successful response body matches the documented schema"""
        response = requests.get(url=BASE_URL + "/store/order/1")
        if response.status_code not in (200, 201):
            pytest.skip("no successful response to validate")
        schema = {'type': 'object', 'properties': {'id': {'type': 'integer', 'format': 'int64', 'example': 10}, 'petId': {'type': 'integer', 'format': 'int64', 'example': 198772}, 'quantity': {'type': 'integer', 'format': 'int32', 'example': 7}, 'shipDate': {'type': 'string', 'format': 'date-time'}, 'status': {'type': 'string', 'description': 'Order Status', 'example': 'approved', 'enum': ['placed', 'approved', 'delivered']}, 'complete': {'type': 'boolean'}}, 'xml': {'name': 'order'}}
        validate(instance=response.json(), schema=schema)

class TestDeleteOrder:
    """Tests for DELETE /store/order/{orderId}"""

    def test_happy_path(self):
        """Happy path — expects 2xx response"""
        response = requests.delete(url=BASE_URL + "/store/order/1")
        assert response.status_code in (200, 201, 204)

    def test_missing_orderId(self):
        """Missing required param 'orderId' — expects 400 or 422"""
        response = requests.delete(url=BASE_URL + "/store/order/1")
        assert response.status_code in (400, 422)

class TestCreateUser:
    """Tests for POST /user"""

    def test_happy_path(self):
        """Happy path — expects 2xx response"""
        response = requests.post(url=BASE_URL + "/user")
        assert response.status_code in (200, 201, 204)

    def test_response_matches_schema(self):
        """Successful response body matches the documented schema"""
        response = requests.post(url=BASE_URL + "/user")
        if response.status_code not in (200, 201):
            pytest.skip("no successful response to validate")
        schema = {'type': 'object', 'properties': {'id': {'type': 'integer', 'format': 'int64', 'example': 10}, 'username': {'type': 'string', 'example': 'theUser'}, 'firstName': {'type': 'string', 'example': 'John'}, 'lastName': {'type': 'string', 'example': 'James'}, 'email': {'type': 'string', 'example': 'john@email.com'}, 'password': {'type': 'string', 'example': '12345'}, 'phone': {'type': 'string', 'example': '12345'}, 'userStatus': {'type': 'integer', 'description': 'User Status', 'format': 'int32', 'example': 1}}, 'xml': {'name': 'user'}}
        validate(instance=response.json(), schema=schema)

class TestCreateUsersWithListInput:
    """Tests for POST /user/createWithList"""

    def test_happy_path(self):
        """Happy path — expects 2xx response"""
        response = requests.post(url=BASE_URL + "/user/createWithList")
        assert response.status_code in (200, 201, 204)

    def test_response_matches_schema(self):
        """Successful response body matches the documented schema"""
        response = requests.post(url=BASE_URL + "/user/createWithList")
        if response.status_code not in (200, 201):
            pytest.skip("no successful response to validate")
        schema = {'type': 'object', 'properties': {'id': {'type': 'integer', 'format': 'int64', 'example': 10}, 'username': {'type': 'string', 'example': 'theUser'}, 'firstName': {'type': 'string', 'example': 'John'}, 'lastName': {'type': 'string', 'example': 'James'}, 'email': {'type': 'string', 'example': 'john@email.com'}, 'password': {'type': 'string', 'example': '12345'}, 'phone': {'type': 'string', 'example': '12345'}, 'userStatus': {'type': 'integer', 'description': 'User Status', 'format': 'int32', 'example': 1}}, 'xml': {'name': 'user'}}
        validate(instance=response.json(), schema=schema)

class TestLoginUser:
    """Tests for GET /user/login"""

    def test_happy_path(self):
        """Happy path — expects 2xx response"""
        response = requests.get(url=BASE_URL + "/user/login", params={'username': 'example', 'password': 'example'})
        assert response.status_code in (200, 201, 204)

    def test_invalid_types(self):
        """Invalid field types — expects 400 or 422"""
        response = requests.get(url=BASE_URL + "/user/login", params={'username': 'INVALID_TYPE_$$', 'password': 'INVALID_TYPE_$$'})
        assert response.status_code in (400, 422)

    def test_response_matches_schema(self):
        """Successful response body matches the documented schema"""
        response = requests.get(url=BASE_URL + "/user/login", params={'username': 'example', 'password': 'example'})
        if response.status_code not in (200, 201):
            pytest.skip("no successful response to validate")
        schema = {'type': 'string'}
        validate(instance=response.json(), schema=schema)

class TestLogoutUser:
    """Tests for GET /user/logout"""

    def test_happy_path(self):
        """Happy path — expects 2xx response"""
        response = requests.get(url=BASE_URL + "/user/logout")
        assert response.status_code in (200, 201, 204)

class TestGetUserByName:
    """Tests for GET /user/{username}"""

    def test_happy_path(self):
        """Happy path — expects 2xx response"""
        response = requests.get(url=BASE_URL + "/user/example")
        assert response.status_code in (200, 201, 204)

    def test_missing_username(self):
        """Missing required param 'username' — expects 400 or 422"""
        response = requests.get(url=BASE_URL + "/user/example")
        assert response.status_code in (400, 422)

    def test_response_matches_schema(self):
        """Successful response body matches the documented schema"""
        response = requests.get(url=BASE_URL + "/user/example")
        if response.status_code not in (200, 201):
            pytest.skip("no successful response to validate")
        schema = {'type': 'object', 'properties': {'id': {'type': 'integer', 'format': 'int64', 'example': 10}, 'username': {'type': 'string', 'example': 'theUser'}, 'firstName': {'type': 'string', 'example': 'John'}, 'lastName': {'type': 'string', 'example': 'James'}, 'email': {'type': 'string', 'example': 'john@email.com'}, 'password': {'type': 'string', 'example': '12345'}, 'phone': {'type': 'string', 'example': '12345'}, 'userStatus': {'type': 'integer', 'description': 'User Status', 'format': 'int32', 'example': 1}}, 'xml': {'name': 'user'}}
        validate(instance=response.json(), schema=schema)

class TestUpdateUser:
    """Tests for PUT /user/{username}"""

    def test_happy_path(self):
        """Happy path — expects 2xx response"""
        response = requests.put(url=BASE_URL + "/user/example")
        assert response.status_code in (200, 201, 204)

    def test_missing_username(self):
        """Missing required param 'username' — expects 400 or 422"""
        response = requests.put(url=BASE_URL + "/user/example")
        assert response.status_code in (400, 422)

class TestDeleteUser:
    """Tests for DELETE /user/{username}"""

    def test_happy_path(self):
        """Happy path — expects 2xx response"""
        response = requests.delete(url=BASE_URL + "/user/example")
        assert response.status_code in (200, 201, 204)

    def test_missing_username(self):
        """Missing required param 'username' — expects 400 or 422"""
        response = requests.delete(url=BASE_URL + "/user/example")
        assert response.status_code in (400, 422)


# ---- Multi-step flows: each test creates a resource and passes its id to the next calls ----

def _flow_value(body, path):
    """Read a value from a JSON body by key path (None when absent)."""
    for key in path:
        if not isinstance(body, dict) or key not in body:
            return None
        body = body[key]
    return body


class TestUserFlow:
    """Multi-step flow /user: create → read → update → delete"""

    def test_crud_flow(self):
        created = requests.post(url=BASE_URL + "/user", json={'id': 10, 'username': 'theUser', 'firstName': 'John', 'lastName': 'James', 'email': 'john@email.com', 'password': '12345', 'phone': '12345', 'userStatus': 1})
        assert created.status_code in (200, 201), created.text[:300]
        try:
            body = created.json()
        except ValueError:
            body = {}
        item_id = _flow_value(body, ['username'])
        if item_id is None:
            pytest.skip("create response has no username field to pass to the next steps")
        item_url = BASE_URL + "/user/" + str(item_id)
        deleted = False
        try:
            response = requests.get(url=item_url)
            assert response.status_code == 200, response.text[:300]
            validate(instance=response.json(), schema={'type': 'object', 'properties': {'id': {'type': 'integer', 'format': 'int64', 'example': 10}, 'username': {'type': 'string', 'example': 'theUser'}, 'firstName': {'type': 'string', 'example': 'John'}, 'lastName': {'type': 'string', 'example': 'James'}, 'email': {'type': 'string', 'example': 'john@email.com'}, 'password': {'type': 'string', 'example': '12345'}, 'phone': {'type': 'string', 'example': '12345'}, 'userStatus': {'type': 'integer', 'description': 'User Status', 'format': 'int32', 'example': 1}}, 'xml': {'name': 'user'}})
            response = requests.put(url=item_url, json={'id': 10, 'username': 'theUser-updated', 'firstName': 'John', 'lastName': 'James', 'email': 'john@email.com', 'password': '12345', 'phone': '12345', 'userStatus': 1})
            assert response.status_code in (200, 204), response.text[:300]
            response = requests.delete(url=item_url)
            assert response.status_code in (200, 202, 204), response.text[:300]
            deleted = True
            response = requests.get(url=item_url)
            assert response.status_code in (404, 410), "deleted resource is still readable"
        finally:
            if not deleted:  # leave no test data behind when a step fails
                requests.delete(url=item_url)


class TestPetFlow:
    """Multi-step flow /pet: create → read → delete"""

    def test_crud_flow(self):
        created = requests.post(url=BASE_URL + "/pet", json={'name': 'doggie', 'photoUrls': [], 'id': 10}, headers={"Authorization": "Bearer <YOUR_TOKEN>"})
        assert created.status_code in (200, 201), created.text[:300]
        try:
            body = created.json()
        except ValueError:
            body = {}
        item_id = _flow_value(body, ['id'])
        if item_id is None:
            pytest.skip("create response has no id field to pass to the next steps")
        item_url = BASE_URL + "/pet/" + str(item_id)
        deleted = False
        try:
            response = requests.get(url=item_url, headers={"Authorization": "Bearer <YOUR_TOKEN>"})
            assert response.status_code == 200, response.text[:300]
            validate(instance=response.json(), schema={'required': ['name', 'photoUrls'], 'type': 'object', 'properties': {'id': {'type': 'integer', 'format': 'int64', 'example': 10}, 'name': {'type': 'string', 'example': 'doggie'}, 'category': {'type': 'object', 'properties': {'id': {'type': 'integer', 'format': 'int64', 'example': 1}, 'name': {'type': 'string', 'example': 'Dogs'}}, 'xml': {'name': 'category'}}, 'photoUrls': {'type': 'array', 'xml': {'wrapped': True}, 'items': {'type': 'string', 'xml': {'name': 'photoUrl'}}}, 'tags': {'type': 'array', 'xml': {'wrapped': True}, 'items': {'type': 'object', 'properties': {'id': {'type': 'integer', 'format': 'int64'}, 'name': {'type': 'string'}}, 'xml': {'name': 'tag'}}}, 'status': {'type': 'string', 'description': 'pet status in the store', 'enum': ['available', 'pending', 'sold']}}, 'xml': {'name': 'pet'}})
            response = requests.delete(url=item_url, headers={"Authorization": "Bearer <YOUR_TOKEN>"})
            assert response.status_code in (200, 202, 204), response.text[:300]
            deleted = True
            response = requests.get(url=item_url, headers={"Authorization": "Bearer <YOUR_TOKEN>"})
            assert response.status_code in (404, 410), "deleted resource is still readable"
        finally:
            if not deleted:  # leave no test data behind when a step fails
                requests.delete(url=item_url, headers={"Authorization": "Bearer <YOUR_TOKEN>"})


class TestOrderFlow:
    """Multi-step flow /store/order: create → read → delete"""

    def test_crud_flow(self):
        created = requests.post(url=BASE_URL + "/store/order", json={'id': 10, 'petId': 198772, 'quantity': 7, 'status': 'approved'})
        assert created.status_code in (200, 201), created.text[:300]
        try:
            body = created.json()
        except ValueError:
            body = {}
        item_id = _flow_value(body, ['id'])
        if item_id is None:
            pytest.skip("create response has no id field to pass to the next steps")
        item_url = BASE_URL + "/store/order/" + str(item_id)
        deleted = False
        try:
            response = requests.get(url=item_url)
            assert response.status_code == 200, response.text[:300]
            validate(instance=response.json(), schema={'type': 'object', 'properties': {'id': {'type': 'integer', 'format': 'int64', 'example': 10}, 'petId': {'type': 'integer', 'format': 'int64', 'example': 198772}, 'quantity': {'type': 'integer', 'format': 'int32', 'example': 7}, 'shipDate': {'type': 'string', 'format': 'date-time'}, 'status': {'type': 'string', 'description': 'Order Status', 'example': 'approved', 'enum': ['placed', 'approved', 'delivered']}, 'complete': {'type': 'boolean'}}, 'xml': {'name': 'order'}})
            response = requests.delete(url=item_url)
            assert response.status_code in (200, 202, 204), response.text[:300]
            deleted = True
            response = requests.get(url=item_url)
            assert response.status_code in (404, 410), "deleted resource is still readable"
        finally:
            if not deleted:  # leave no test data behind when a step fails
                requests.delete(url=item_url)

