//! Integration tests for session/resume RPC method

use dirigent_acp_api::{
    NoOpConnectorOperations, RpcHandler, SessionManager,
};
use dirigent_acp_api::agent_requests::AgentRequestTracker;
use dirigent_acp_api::sse::SseNotifier;
use serde_json::json;
use std::sync::Arc;

fn create_test_handler() -> RpcHandler<NoOpConnectorOperations> {
    RpcHandler::new(
        SessionManager::new(),
        NoOpConnectorOperations,
        SseNotifier::new(),
        Arc::new(AgentRequestTracker::new()),
    )
}

#[tokio::test]
async fn test_session_resume_returns_session() {
    let handler = create_test_handler();

    let request_body = json!({
        "jsonrpc": "2.0",
        "id": 1,
        "method": "session/resume",
        "params": {
            "sessionId": "sess-123",
            "connectorId": "stub-connector"
        }
    });

    let response = handler.handle_request(&request_body.to_string(), None).await;
    let response_json = serde_json::to_value(&response).unwrap();

    let result = &response_json["result"];
    assert!(result["sessionId"].is_string());
    assert!(result["connectorId"].is_string());
    assert!(result["createdAt"].is_string());
}

#[tokio::test]
async fn test_session_resume_missing_params() {
    let handler = create_test_handler();

    let request_body = json!({
        "jsonrpc": "2.0",
        "id": 1,
        "method": "session/resume"
    });

    let response = handler.handle_request(&request_body.to_string(), None).await;
    let response_json = serde_json::to_value(&response).unwrap();

    // Should return error for missing params
    assert!(response_json["error"].is_object());
}

#[tokio::test]
async fn test_session_resume_creates_mapping() {
    let session_manager = SessionManager::new();
    let handler = RpcHandler::new(
        session_manager.clone(),
        NoOpConnectorOperations,
        SseNotifier::new(),
        Arc::new(AgentRequestTracker::new()),
    );

    let request_body = json!({
        "jsonrpc": "2.0",
        "id": 1,
        "method": "session/resume",
        "params": {
            "sessionId": "sess-456",
            "connectorId": "stub-connector"
        }
    });

    let response = handler.handle_request(&request_body.to_string(), None).await;
    let response_json = serde_json::to_value(&response).unwrap();

    let session_id = response_json["result"]["sessionId"].as_str().unwrap();
    let mapping = session_manager.get_mapping(session_id);
    assert!(mapping.is_some(), "Session mapping should be created for resumed session");
}

#[tokio::test]
async fn test_session_resume_without_connector_id() {
    let handler = create_test_handler();

    // Standard ACP: only sessionId, no connectorId — should resolve via default connector
    let request_body = json!({
        "jsonrpc": "2.0",
        "id": 1,
        "method": "session/resume",
        "params": {
            "sessionId": "sess-789",
            "cwd": "G:\\dev\\projects\\test"
        }
    });

    let response = handler.handle_request(&request_body.to_string(), None).await;
    let response_json = serde_json::to_value(&response).unwrap();

    let result = &response_json["result"];
    assert!(result["sessionId"].is_string(), "Should succeed without connectorId");
    assert!(result["createdAt"].is_string());
}

#[tokio::test]
async fn test_initialize_advertises_session_resume() {
    let handler = create_test_handler();

    let request_body = json!({
        "jsonrpc": "2.0",
        "id": 1,
        "method": "initialize",
        "params": {}
    });

    let response = handler.handle_request(&request_body.to_string(), None).await;
    let response_json = serde_json::to_value(&response).unwrap();

    let caps = &response_json["result"]["agentCapabilities"];
    assert!(
        caps["sessionCapabilities"]["list"].is_object(),
        "sessionCapabilities.list should be advertised as an empty object"
    );
    assert!(
        caps["sessionCapabilities"]["resume"].is_object(),
        "sessionCapabilities.resume should be advertised as an empty object"
    );
}
