import pytest
import requests
import time
import os

# Define the base URL for the Genesis System API
BASE_URL = os.environ.get("GENESIS_SYSTEM_URL", "http://localhost:8000")  # Default to localhost, allow override

# Helper function to make API requests
def make_api_request(endpoint, method="GET", data=None):
    url = f"{BASE_URL}{endpoint}"
    try:
        if method == "GET":
            response = requests.get(url)
        elif method == "POST":
            response = requests.post(url, json=data)
        elif method == "PUT":
            response = requests.put(url, json=data)
        elif method == "DELETE":
            response = requests.delete(url)
        else:
            raise ValueError(f"Unsupported HTTP method: {method}")

        response.raise_for_status()  # Raise HTTPError for bad responses (4xx or 5xx)
        return response.json(), response.status_code
    except requests.exceptions.RequestException as e:
        pytest.fail(f"API request failed: {e}")
        return None, None


# Test case 1: Successful user creation and retrieval
def test_user_creation_and_retrieval():
    # 1. Create a new user
    user_data = {
        "username": "testuser",
        "email": "test@example.com",
        "password": "password123"
    }
    user_creation_response, user_creation_status_code = make_api_request("/users", method="POST", data=user_data)

    assert user_creation_status_code == 201, f"User creation failed: Status code {user_creation_status_code}"
    assert "id" in user_creation_response, "User ID not returned on creation"
    user_id = user_creation_response["id"]
    print(f"Created user with ID: {user_id}")

    # 2. Retrieve the created user
    retrieved_user, retrieval_status_code = make_api_request(f"/users/{user_id}")

    assert retrieval_status_code == 200, f"User retrieval failed: Status code {retrieval_status_code}"
    assert retrieved_user["username"] == "testuser", "Retrieved username does not match"
    assert retrieved_user["email"] == "test@example.com", "Retrieved email does not match"

    # 3. Clean up: Delete the created user (optional, but good practice)
    deletion_response, deletion_status_code = make_api_request(f"/users/{user_id}", method="DELETE")
    assert deletion_status_code == 204 or deletion_status_code == 200, f"User deletion failed: Status code {deletion_status_code}" # Allow 204 (No Content) or 200 (OK)

# Test case 2: Successful item creation and retrieval
def test_item_creation_and_retrieval():
    # 1. Create a new item
    item_data = {
        "name": "Test Item",
        "description": "A test item for e2e testing",
        "price": 9.99
    }
    item_creation_response, item_creation_status_code = make_api_request("/items", method="POST", data=item_data)

    assert item_creation_status_code == 201, f"Item creation failed: Status code {item_creation_status_code}"
    assert "id" in item_creation_response, "Item ID not returned on creation"
    item_id = item_creation_response["id"]
    print(f"Created item with ID: {item_id}")

    # 2. Retrieve the created item
    retrieved_item, retrieval_status_code = make_api_request(f"/items/{item_id}")

    assert retrieval_status_code == 200, f"Item retrieval failed: Status code {retrieval_status_code}"
    assert retrieved_item["name"] == "Test Item", "Retrieved item name does not match"
    assert retrieved_item["description"] == "A test item for e2e testing", "Retrieved item description does not match"
    assert retrieved_item["price"] == 9.99, "Retrieved item price does not match"

    # 3. Clean up: Delete the created item (optional, but good practice)
    deletion_response, deletion_status_code = make_api_request(f"/items/{item_id}", method="DELETE")
    assert deletion_status_code == 204 or deletion_status_code == 200, f"Item deletion failed: Status code {deletion_status_code}" # Allow 204 (No Content) or 200 (OK)

# Test case 3: Update an item
def test_item_update():
    # 1. Create an item
    item_data = {
        "name": "Original Item",
        "description": "Original description",
        "price": 5.00
    }
    create_response, create_status = make_api_request("/items", method="POST", data=item_data)
    assert create_status == 201
    item_id = create_response["id"]

    # 2. Update the item
    updated_data = {
        "name": "Updated Item",
        "description": "Updated description",
        "price": 10.00
    }
    update_response, update_status = make_api_request(f"/items/{item_id}", method="PUT", data=updated_data)

    assert update_status == 200
    assert update_response["name"] == "Updated Item"
    assert update_response["description"] == "Updated description"
    assert update_response["price"] == 10.00

    # 3. Retrieve and verify
    retrieved_item, retrieve_status = make_api_request(f"/items/{item_id}")
    assert retrieve_status == 200
    assert retrieved_item["name"] == "Updated Item"
    assert retrieved_item["description"] == "Updated description"
    assert retrieved_item["price"] == 10.00

    # 4. Clean up: Delete the created item
    deletion_response, deletion_status_code = make_api_request(f"/items/{item_id}", method="DELETE")
    assert deletion_status_code == 204 or deletion_status_code == 200

# Test case 4:  Error handling - trying to retrieve a non-existent user
def test_nonexistent_user():
    nonexistent_user_id = "999999"  # Assuming this ID doesn't exist
    retrieved_user, retrieval_status_code = make_api_request(f"/users/{nonexistent_user_id}")

    assert retrieval_status_code == 404, f"Expected 404 for nonexistent user, got {retrieval_status_code}"


# Additional test cases can be added here, following the same pattern.