use monaco_grpc_sdk::monaco::{
    api::health::{health_service_client::HealthServiceClient, PublicHealthCheckRequest},
    api::orders::{
        orders_service_client::OrdersServiceClient, CancelOrderRequest, CreateOrderRequest,
        CreateOrderResponse,
    },
    common::orders::MatchResult,
};
use prost::Message;

// Verify that types from different proto packages compose correctly.
// CreateOrderResponse.match_result is a common::orders::MatchResult — this
// exercises the cross-package type reference in the generated code.
#[test]
fn cross_package_type_composition() {
    let match_result = MatchResult {
        trades_count: 2,
        total_filled: "0.001".to_string(),
        remaining_quantity: "0.0".to_string(),
        average_fill_price: Some("50000.00".to_string()),
        order_status: "FILLED".to_string(),
        actual_slippage_bps: Some(5),
        max_slippage_bps: Some(100),
        execution_price_range: None,
    };

    let response = CreateOrderResponse {
        order_id: "ord-123".to_string(),
        status: "FILLED".to_string(),
        message: "Order executed".to_string(),
        match_result: Some(match_result),
    };

    assert_eq!(response.order_id, "ord-123");
    assert_eq!(response.match_result.unwrap().trades_count, 2);
}

// Prost encode/decode round-trip — verifies the generated field tags are correct.
#[test]
fn prost_round_trip() {
    let original = CreateOrderRequest {
        trading_pair_id: "BTC-USDC".to_string(),
        order_type: "LIMIT".to_string(),
        side: "BUY".to_string(),
        price: Some("50000.00".to_string()),
        quantity: "0.001".to_string(),
        time_in_force: Some("GTC".to_string()),
        ..Default::default()
    };

    let encoded = original.encode_to_vec();
    let decoded = CreateOrderRequest::decode(encoded.as_slice()).expect("decode failed");

    assert_eq!(decoded.trading_pair_id, original.trading_pair_id);
    assert_eq!(decoded.price, original.price);
    assert_eq!(decoded.time_in_force, original.time_in_force);
    assert_eq!(decoded.slippage_tolerance_bps, None);
}

// Verify CancelOrderRequest encodes/decodes correctly.
#[test]
fn cancel_order_round_trip() {
    let original = CancelOrderRequest {
        order_id: "ord-456".to_string(),
    };
    let decoded =
        CancelOrderRequest::decode(original.encode_to_vec().as_slice()).expect("decode failed");
    assert_eq!(decoded.order_id, original.order_id);
}

// Compile-time checks: verify tonic client types exist and expose `connect`.
// These are dead-code functions that exist purely to catch regressions in the
// generated client interface — they are never called.
async fn _orders_client_connect_exists() {
    drop(OrdersServiceClient::connect("http://localhost:9090").await);
}

async fn _health_client_connect_exists() {
    drop(HealthServiceClient::connect("http://localhost:9090").await);
}

// Verify health request type is constructible (it has no fields).
#[test]
fn health_request_default() {
    let req = PublicHealthCheckRequest::default();
    assert_eq!(req.encode_to_vec(), vec![]);
}
