//! Integration Tests for Broker Gateway Service Metrics
//!
//! Tests Prometheus metrics collection, recording, and HTTP endpoint.

#![allow(
    clippy::tests_outside_test_module,
    clippy::unwrap_used,
    clippy::expect_used,
    unused_imports,
    dead_code,
)]

use broker_gateway_service::metrics;
use prometheus::{Encoder, TextEncoder};

#[test]
fn test_order_submitted_metric() {
    // Record order submission
    metrics::record_order_submitted("ES.FUT", "MARKET", "BUY");

    // Verify metric is recorded
    let metric_families = prometheus::gather();
    let encoder = TextEncoder::new();
    let mut buffer = vec![];
    encoder.encode(&metric_families, &mut buffer).unwrap();
    let output = String::from_utf8(buffer).unwrap();

    assert!(
        output.contains("broker_gateway_orders_submitted_total"),
        "Metric not found in output"
    );
    assert!(
        output.contains("ES.FUT"),
        "Symbol label not found in metric"
    );
    assert!(
        output.contains("MARKET"),
        "Order type label not found in metric"
    );
    assert!(
        output.contains("BUY"),
        "Side label not found in metric"
    );
}

#[test]
fn test_order_filled_metric() {
    // Record order fill
    metrics::record_order_filled("NQ.FUT", "LIMIT", "SELL", 0.125);

    // Verify metric is recorded
    let metric_families = prometheus::gather();
    let encoder = TextEncoder::new();
    let mut buffer = vec![];
    encoder.encode(&metric_families, &mut buffer).unwrap();
    let output = String::from_utf8(buffer).unwrap();

    assert!(
        output.contains("broker_gateway_orders_filled_total"),
        "Filled metric not found"
    );
    assert!(
        output.contains("broker_gateway_order_fill_latency_seconds"),
        "Fill latency metric not found"
    );
    assert!(
        output.contains("NQ.FUT"),
        "Symbol not found in filled metric"
    );
}

#[test]
fn test_order_rejected_metric() {
    // Record order rejection
    metrics::record_order_rejected("ZN.FUT", "LIMIT", "RISK_LIMIT");

    // Verify metric is recorded
    let metric_families = prometheus::gather();
    let encoder = TextEncoder::new();
    let mut buffer = vec![];
    encoder.encode(&metric_families, &mut buffer).unwrap();
    let output = String::from_utf8(buffer).unwrap();

    assert!(
        output.contains("broker_gateway_orders_rejected_total"),
        "Rejected metric not found"
    );
    assert!(
        output.contains("RISK_LIMIT"),
        "Rejection reason not found"
    );
}

#[test]
fn test_order_cancelled_metric() {
    // Record order cancellation
    metrics::record_order_cancelled("6E.FUT", "CANCEL_SUCCESS");

    // Verify metric is recorded
    let metric_families = prometheus::gather();
    let encoder = TextEncoder::new();
    let mut buffer = vec![];
    encoder.encode(&metric_families, &mut buffer).unwrap();
    let output = String::from_utf8(buffer).unwrap();

    assert!(
        output.contains("broker_gateway_orders_cancelled_total"),
        "Cancelled metric not found"
    );
    assert!(
        output.contains("CANCEL_SUCCESS"),
        "Cancellation status not found"
    );
}

#[test]
fn test_partial_fill_metric() {
    // Record partial fill
    metrics::record_partial_fill("ES.FUT");

    // Verify metric is recorded
    let metric_families = prometheus::gather();
    let encoder = TextEncoder::new();
    let mut buffer = vec![];
    encoder.encode(&metric_families, &mut buffer).unwrap();
    let output = String::from_utf8(buffer).unwrap();

    assert!(
        output.contains("broker_gateway_orders_partial_fills_total"),
        "Partial fill metric not found"
    );
}

#[test]
fn test_order_latency_metric() {
    // Record order latency
    metrics::record_order_latency("MARKET", 0.025); // 25ms

    // Verify metric is recorded
    let metric_families = prometheus::gather();
    let encoder = TextEncoder::new();
    let mut buffer = vec![];
    encoder.encode(&metric_families, &mut buffer).unwrap();
    let output = String::from_utf8(buffer).unwrap();

    assert!(
        output.contains("broker_gateway_order_latency_seconds"),
        "Order latency metric not found"
    );
}

#[test]
fn test_position_metrics() {
    // Update position
    metrics::update_position(
        "ES.FUT",
        "TEST_ACCOUNT",
        10.0,      // quantity
        50000.0,   // value USD
        1250.0,    // unrealized PnL
    );

    // Verify metrics are recorded
    let metric_families = prometheus::gather();
    let encoder = TextEncoder::new();
    let mut buffer = vec![];
    encoder.encode(&metric_families, &mut buffer).unwrap();
    let output = String::from_utf8(buffer).unwrap();

    assert!(
        output.contains("broker_gateway_position_quantity"),
        "Position quantity metric not found"
    );
    assert!(
        output.contains("broker_gateway_position_value_usd"),
        "Position value metric not found"
    );
    assert!(
        output.contains("broker_gateway_unrealized_pnl_usd"),
        "Unrealized PnL metric not found"
    );
    assert!(
        output.contains("TEST_ACCOUNT"),
        "Account ID not found in metrics"
    );
}

#[test]
fn test_account_metrics() {
    // Update account
    metrics::update_account(
        "TEST_ACCOUNT",
        100000.0,  // cash balance
        25000.0,   // margin used
    );

    // Verify metrics are recorded
    let metric_families = prometheus::gather();
    let encoder = TextEncoder::new();
    let mut buffer = vec![];
    encoder.encode(&metric_families, &mut buffer).unwrap();
    let output = String::from_utf8(buffer).unwrap();

    assert!(
        output.contains("broker_gateway_cash_balance_usd"),
        "Cash balance metric not found"
    );
    assert!(
        output.contains("broker_gateway_margin_used_usd"),
        "Margin used metric not found"
    );
}

#[test]
fn test_fix_session_status_metric() {
    // Update FIX session status
    metrics::update_fix_session_status("FOXHUNT-CQG", 1.0); // Connected

    // Verify metric is recorded
    let metric_families = prometheus::gather();
    let encoder = TextEncoder::new();
    let mut buffer = vec![];
    encoder.encode(&metric_families, &mut buffer).unwrap();
    let output = String::from_utf8(buffer).unwrap();

    assert!(
        output.contains("broker_gateway_fix_session_status"),
        "FIX session status metric not found"
    );
    assert!(
        output.contains("FOXHUNT-CQG"),
        "Session ID not found in metric"
    );
}

#[test]
fn test_sequence_gap_metric() {
    // Record sequence gap
    metrics::record_sequence_gap("FOXHUNT-CQG");

    // Verify metric is recorded
    let metric_families = prometheus::gather();
    let encoder = TextEncoder::new();
    let mut buffer = vec![];
    encoder.encode(&metric_families, &mut buffer).unwrap();
    let output = String::from_utf8(buffer).unwrap();

    assert!(
        output.contains("broker_gateway_sequence_number_gap_total"),
        "Sequence gap metric not found"
    );
}

#[test]
fn test_heartbeat_rtt_metric() {
    // Update heartbeat RTT
    metrics::update_heartbeat_rtt("FOXHUNT-CQG", 12.5);

    // Verify metric is recorded
    let metric_families = prometheus::gather();
    let encoder = TextEncoder::new();
    let mut buffer = vec![];
    encoder.encode(&metric_families, &mut buffer).unwrap();
    let output = String::from_utf8(buffer).unwrap();

    assert!(
        output.contains("broker_gateway_fix_heartbeat_rtt_ms"),
        "Heartbeat RTT metric not found"
    );
}

#[test]
fn test_sequence_numbers_metric() {
    // Update sequence numbers
    metrics::update_sequence_numbers("FOXHUNT-CQG", 1234, 5678);

    // Verify metrics are recorded
    let metric_families = prometheus::gather();
    let encoder = TextEncoder::new();
    let mut buffer = vec![];
    encoder.encode(&metric_families, &mut buffer).unwrap();
    let output = String::from_utf8(buffer).unwrap();

    assert!(
        output.contains("broker_gateway_fix_sender_seq_num"),
        "Sender sequence number metric not found"
    );
    assert!(
        output.contains("broker_gateway_fix_target_seq_num"),
        "Target sequence number metric not found"
    );
}

#[test]
fn test_fix_message_sent_metric() {
    // Record FIX message sent
    metrics::record_fix_message_sent("FOXHUNT-CQG", "NewOrderSingle", 2.5);

    // Verify metrics are recorded
    let metric_families = prometheus::gather();
    let encoder = TextEncoder::new();
    let mut buffer = vec![];
    encoder.encode(&metric_families, &mut buffer).unwrap();
    let output = String::from_utf8(buffer).unwrap();

    assert!(
        output.contains("broker_gateway_fix_messages_sent_total"),
        "FIX messages sent metric not found"
    );
    assert!(
        output.contains("broker_gateway_fix_message_latency_ms"),
        "FIX message latency metric not found"
    );
    assert!(
        output.contains("NewOrderSingle"),
        "Message type not found in metric"
    );
}

#[test]
fn test_fix_message_received_metric() {
    // Record FIX message received
    metrics::record_fix_message_received("FOXHUNT-CQG", "ExecutionReport");

    // Verify metric is recorded
    let metric_families = prometheus::gather();
    let encoder = TextEncoder::new();
    let mut buffer = vec![];
    encoder.encode(&metric_families, &mut buffer).unwrap();
    let output = String::from_utf8(buffer).unwrap();

    assert!(
        output.contains("broker_gateway_fix_messages_received_total"),
        "FIX messages received metric not found"
    );
    assert!(
        output.contains("ExecutionReport"),
        "Message type not found in metric"
    );
}

#[test]
fn test_error_metrics() {
    // Record error
    metrics::record_error("VALIDATION_ERROR", "WARNING");

    // Verify metric is recorded
    let metric_families = prometheus::gather();
    let encoder = TextEncoder::new();
    let mut buffer = vec![];
    encoder.encode(&metric_families, &mut buffer).unwrap();
    let output = String::from_utf8(buffer).unwrap();

    assert!(
        output.contains("broker_gateway_error_total"),
        "Error metric not found"
    );
    assert!(
        output.contains("VALIDATION_ERROR"),
        "Error type not found"
    );
    assert!(
        output.contains("WARNING"),
        "Severity not found"
    );
}

#[test]
fn test_database_error_metric() {
    // Record database error
    metrics::record_db_error("INSERT");

    // Verify metrics are recorded
    let metric_families = prometheus::gather();
    let encoder = TextEncoder::new();
    let mut buffer = vec![];
    encoder.encode(&metric_families, &mut buffer).unwrap();
    let output = String::from_utf8(buffer).unwrap();

    assert!(
        output.contains("broker_gateway_db_errors_total"),
        "Database error metric not found"
    );
    assert!(
        output.contains("INSERT"),
        "Database operation not found"
    );
}

#[test]
fn test_active_orders_metric() {
    // Update active orders
    metrics::update_active_orders("PENDING_SUBMIT", 5.0);
    metrics::update_active_orders("SUBMITTED", 3.0);
    metrics::update_active_orders("PARTIALLY_FILLED", 2.0);

    // Verify metric is recorded
    let metric_families = prometheus::gather();
    let encoder = TextEncoder::new();
    let mut buffer = vec![];
    encoder.encode(&metric_families, &mut buffer).unwrap();
    let output = String::from_utf8(buffer).unwrap();

    assert!(
        output.contains("broker_gateway_active_orders"),
        "Active orders metric not found"
    );
    assert!(
        output.contains("PENDING_SUBMIT"),
        "PENDING_SUBMIT status not found"
    );
    assert!(
        output.contains("SUBMITTED"),
        "SUBMITTED status not found"
    );
    assert!(
        output.contains("PARTIALLY_FILLED"),
        "PARTIALLY_FILLED status not found"
    );
}

#[test]
fn test_last_order_time_metric() {
    // Record order submission (updates last order time)
    metrics::record_order_submitted("ES.FUT", "MARKET", "BUY");

    // Verify metric is recorded
    let metric_families = prometheus::gather();
    let encoder = TextEncoder::new();
    let mut buffer = vec![];
    encoder.encode(&metric_families, &mut buffer).unwrap();
    let output = String::from_utf8(buffer).unwrap();

    assert!(
        output.contains("broker_gateway_last_order_time"),
        "Last order time metric not found"
    );

    // Verify timestamp is recent (within last 60 seconds)
    let now = std::time::SystemTime::now()
        .duration_since(std::time::UNIX_EPOCH)
        .unwrap()
        .as_secs() as f64;

    let last_order_time = metrics::BROKER_GATEWAY_LAST_ORDER_TIME.get();
    assert!(
        now - last_order_time < 60.0,
        "Last order time is not recent"
    );
}
