@phase2 @a2a @server
Feature: ASGI Server Lifecycle
  As a platform operator
  I want to start, health-check, and shut down the CleverAgents ASGI server
  So that the A2A JSON-RPC 2.0 endpoint is available for client communication

  # -----------------------------------------------------------------------
  # ASGI application creation
  # -----------------------------------------------------------------------

  Scenario: create_asgi_app returns a FastAPI application
    When I create an ASGI application with default settings
    Then the ASGI app should be a FastAPI instance

  Scenario: create_asgi_app accepts a custom facade
    Given an A2aLocalFacade with no services
    When I create an ASGI application with that facade
    Then the ASGI app should be a FastAPI instance

  Scenario: create_asgi_app rejects invalid facade type
    When I try to create an ASGI application with facade "not-a-facade"
    Then a TypeError should be raised for invalid facade

  Scenario: create_asgi_app rejects invalid port
    When I try to create an ASGI application with port 0
    Then a ValueError should be raised for invalid port

  Scenario: create_asgi_app rejects invalid host
    When I try to create an ASGI application with an empty host
    Then a ValueError should be raised for invalid host

  # -----------------------------------------------------------------------
  # Health check endpoint
  # -----------------------------------------------------------------------

  Scenario: Health endpoint returns healthy status
    Given a running ASGI test client
    When I request GET /health
    Then the response status code should be 200
    And the response body should contain "healthy"

  # -----------------------------------------------------------------------
  # Agent Card discovery endpoint
  # -----------------------------------------------------------------------

  Scenario: Agent Card endpoint returns valid agent card
    Given a running ASGI test client
    When I request GET /.well-known/agent.json
    Then the response status code should be 200
    And the response body should contain "CleverAgents"
    And the response body should contain "url"

  # -----------------------------------------------------------------------
  # A2A JSON-RPC endpoint
  # -----------------------------------------------------------------------

  Scenario: A2A endpoint dispatches health check operation
    Given a running ASGI test client
    When I POST a JSON-RPC request to /a2a with operation "_cleveragents/health/check"
    Then the response status code should be 200
    And the A2A response result status should be "healthy"

  Scenario: A2A endpoint returns HTTP 200 with JSON-RPC error for unknown operation
    Given a running ASGI test client
    When I POST a JSON-RPC request to /a2a with operation "nonexistent.operation"
    Then the response status code should be 200
    And the response body should contain "-32601"

  Scenario: A2A endpoint returns HTTP 200 with JSON-RPC error for malformed request
    Given a running ASGI test client
    When I POST a malformed JSON body to /a2a
    Then the response status code should be 200
    And the response body should contain "-32600"

  Scenario: A2A endpoint returns -32700 parse error for invalid JSON bytes
    Given a running ASGI test client
    When I POST invalid JSON bytes to /a2a
    Then the response status code should be 200
    And the response body should contain "-32700"

  Scenario: A2A endpoint returns -32603 internal error when dispatch raises
    Given a running ASGI test client with a failing facade
    When I POST a JSON-RPC request to /a2a with operation "_cleveragents/health/check"
    Then the response status code should be 200
    And the response body should contain "-32603"

  # -----------------------------------------------------------------------
  # ServerLifecycle construction
  # -----------------------------------------------------------------------

  Scenario: ServerLifecycle accepts valid configuration
    When I create a ServerLifecycle with host "127.0.0.1" and port 9000
    Then the lifecycle host should be "127.0.0.1"
    And the lifecycle port should be 9000
    And the lifecycle should not be started
    And the lifecycle should not be stopped

  Scenario: ServerLifecycle rejects empty host
    When I try to create a ServerLifecycle with an empty host
    Then a ValueError should be raised for invalid host

  Scenario: ServerLifecycle rejects invalid port 0
    When I try to create a ServerLifecycle with port 0
    Then a ValueError should be raised for invalid port

  Scenario: ServerLifecycle rejects port above 65535
    When I try to create a ServerLifecycle with port 70000
    Then a ValueError should be raised for invalid port

  Scenario: ServerLifecycle rejects empty log_level
    When I try to create a ServerLifecycle with empty log_level
    Then a ValueError should be raised for invalid log_level

  # -----------------------------------------------------------------------
  # Server configuration from Settings
  # -----------------------------------------------------------------------

  Scenario: Settings provides default server host
    Then the default server host from Settings should be "0.0.0.0"

  Scenario: Settings provides default server port
    Then the default server port from Settings should be 8080

  # -----------------------------------------------------------------------
  # Graceful shutdown
  # -----------------------------------------------------------------------

  Scenario: ServerLifecycle request_shutdown sets flag
    Given a ServerLifecycle with a mock uvicorn server
    When I call request_shutdown on the lifecycle
    Then the mock server should_exit flag should be true

  Scenario: ServerLifecycle cannot be started twice
    Given a ServerLifecycle that has already been started
    When I try to start the lifecycle again
    Then a RuntimeError should be raised for double start

  # -----------------------------------------------------------------------
  # Full start lifecycle (mocked uvicorn)
  # -----------------------------------------------------------------------

  Scenario: ServerLifecycle start runs uvicorn and marks stopped on exit
    Given a ServerLifecycle with mocked uvicorn server run
    When I call start on the lifecycle
    Then the lifecycle should be started
    And the lifecycle should be stopped
    And the mocked uvicorn server run should have been called

  Scenario: ServerLifecycle start installs signal handlers on main thread
    Given a ServerLifecycle with mocked uvicorn and signal handlers
    When I call start on the lifecycle
    Then SIGTERM and SIGINT handlers should have been installed

  Scenario: Signal handler calls request_shutdown with signal name
    Given a ServerLifecycle with mocked uvicorn server run
    When I call start on the lifecycle
    And I invoke the installed SIGTERM handler
    Then the mocked server should_exit should be true

  Scenario: ServerLifecycle request_shutdown is a no-op when server not started
    Given a fresh ServerLifecycle
    When I call request_shutdown on the lifecycle
    Then the lifecycle should not be started

  # -----------------------------------------------------------------------
  # run_server convenience function
  # -----------------------------------------------------------------------

  Scenario: run_server resolves defaults from Settings
    When I call run_server with mocked ServerLifecycle
    Then the lifecycle should have been created with Settings defaults
    And start should have been called on the lifecycle

  Scenario: run_server passes explicit host and port overrides
    When I call run_server with host "10.0.0.1" and port 3000 using mocked lifecycle
    Then the lifecycle should have been created with host "10.0.0.1" and port 3000

  # -----------------------------------------------------------------------
  # Signal handler edge case — non-main thread
  # -----------------------------------------------------------------------

  Scenario: Signal handlers are skipped when not on main thread
    Given a ServerLifecycle with mocked uvicorn and signal tracking
    When I call _install_signal_handlers from a non-main thread
    Then no signal handlers should have been installed
