"""Test list_services with include_app_services parameter."""

import pytest
import asyncio
from hypha_rpc import connect_to_server
from . import SERVER_URL, find_item

# All test coroutines will be treated as marked.
pytestmark = pytest.mark.asyncio


async def test_list_services_with_app_services_simple(
    minio_server, fastapi_server, test_user_token
):
    """Test that list_services can discover services from running applications."""
    
    # Connect to server
    api = await connect_to_server(
        {
            "name": "test client",
            "server_url": SERVER_URL,
            "token": test_user_token,
        }
    )
    
    # Get the apps controller
    apps = await api.get_service("public/server-apps")
    
    # Create a test application with JavaScript code that exports services
    # The services must be generated by actual running code, not declared in manifest
    source_code = f"""
<config lang="json">
{{
    "name": "Test Discovery App",
    "type": "window",
    "version": "1.0.0"
}}
</config>

<script lang="javascript">
// This app registers services by running actual code
// The api variable is already available from the template

// Register test services dynamically using registerService
api.registerService({{
    "id": "test-service-1",
    "name": "Test Service 1",
    "type": "computation",
    "description": "Test service for discovery",
    "config": {{
        "visibility": "public"
    }},
    // Service implementation
    "test_function_1": function(x) {{
        return x * 2;
    }}
}}).then(() => {{
    console.log("Test Service 1 registered");
}});

api.registerService({{
    "id": "test-service-2",
    "name": "Test Service 2",
    "type": "data-processing",
    "description": "Another test service",
    "config": {{
        "visibility": "protected",
        "authorized_workspaces": ["{api.config.workspace}"]
    }},
    // Service implementation
    "test_function_2": function(x, y) {{
        return x + y;
    }}
}}).then(() => {{
    console.log("Test Service 2 registered");
}});
</script>

<body>
    <h1>Test Discovery App</h1>
    <p>This app exports services through actual JavaScript code.</p>
</body>
"""
    
    app_info = await apps.install(
        source=source_code,
        wait_for_service=False,  # Don't wait for service during install
        overwrite=True
    )
    
    app_id = app_info["id"] if isinstance(app_info, dict) else app_info.id
    
    # Start the app to register services at runtime
    # Services are exported by running code, not declared in manifests
    print("Starting app to register services...")
    session = await apps.start(app_id, wait_for_service=False, timeout=20)
    session_id = session["id"]
    
    # Give the app time to export its services
    await asyncio.sleep(2)
    
    # Test 1: List services (should find the running app services)
    services = await api.list_services(
        query={"workspace": api.config.workspace}
    )
    
    # Debug: Print all services found
    print(f"Found {len(services)} services")
    for svc in services:
        print(f"  - Service: {svc.get('id')}")
    
    # Should find the exported services
    test_svc_1 = find_item(
        services, 
        lambda s: ":test-service-1" in s.get("id", "")
    )
    assert test_svc_1 is not None, f"Should find test-service-1. Found services: {[s.get('id') for s in services]}"
    assert test_svc_1.get("name") == "Test Service 1"
    
    # Should find the second service
    test_svc_2 = find_item(
        services,
        lambda s: ":test-service-2" in s.get("id", "")
    )
    assert test_svc_2 is not None, "Should find test-service-2"
    assert test_svc_2.get("name") == "Test Service 2"
    
    # Test 2: Query with type filter
    computation_services = await api.list_services(
        query={"workspace": api.config.workspace, "type": "computation"}
    )
    
    # Should find test-service-1 which has type "computation"
    test_svc_1_filtered = find_item(
        computation_services,
        lambda s: ":test-service-1" in s.get("id", "")
    )
    assert test_svc_1_filtered is not None, "Should find test-service-1 with type filter"
    
    # Should not find test-service-2 which has type "data-processing"
    test_svc_2_filtered = find_item(
        computation_services,
        lambda s: ":test-service-2" in s.get("id", "")
    )
    assert test_svc_2_filtered is None, "Should not find test-service-2 with computation type filter"
    
    # Stop the app session
    await apps.stop(session_id)
    
    # Clean up - uninstall the app
    await apps.uninstall(app_id)
    
    print("✅ All tests passed successfully!")
    
    await api.disconnect()