// Copyright (c) Subzero Labs, Inc.
// SPDX-License-Identifier: Apache-2.0

//! Integration tests for validation

#[cfg(test)]
mod tests {
    use crate::{
        messages::send_transaction::{SendTransactionConfig, TransactionEncoding},
        requests::SendTransactionRequest,
        validation::{validate_request, ValidationError},
    };

    #[test]
    fn test_send_transaction_validation_success() {
        let config = SendTransactionConfig {
            encoding: TransactionEncoding::Base64,
            max_retries: Some(5),
            min_context_slot: Some(0),
            skip_preflight: false,
            wait_for_execution: false,
        };

        let request = SendTransactionRequest {
            transaction: "ATyWkIxOhtyIydyX6UNAGB9L2izqYuMJUAM9KhuyoidE06Zw2sMmECpZXeLNOwluhUEZN45gqpvz4sW5dytb+gyAAQABA+oY70IUxzeFet4jGXfnglexgCVAa3Tz4KkCnL9Tzqf/AAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQICAAEMAgAAAAAAAAAAAAAA".to_string(),
            config,
        };

        let result = validate_request(request);
        assert!(result.is_ok());
    }

    #[test]
    fn test_send_transaction_validation_empty_transaction() {
        let config = SendTransactionConfig {
            encoding: TransactionEncoding::Base64,
            max_retries: Some(5),
            min_context_slot: Some(0),
            skip_preflight: false,
            wait_for_execution: false,
        };

        let request = SendTransactionRequest {
            transaction: "".to_string(), // Empty transaction should fail
            config,
        };

        let result = validate_request(request);
        assert!(result.is_err());

        match result {
            Err(ValidationError::InvalidFormat(msg)) => {
                assert!(msg.contains("Transaction cannot be empty"));
            }
            Err(other_error) => {
                panic!(
                    "Expected ValidationError::InvalidFormat, but got: {:?}",
                    other_error
                );
            }
            Ok(_) => {
                panic!("Expected error but got Ok");
            }
        }
    }

    #[test]
    fn test_send_transaction_validation_invalid_transaction_structure() {
        let config = SendTransactionConfig {
            encoding: TransactionEncoding::Base64,
            max_retries: Some(5),
            min_context_slot: Some(0),
            skip_preflight: false,
            wait_for_execution: false,
        };

        // Valid base64 but not a valid transaction structure ("Hello World" in base64)
        let request = SendTransactionRequest {
            transaction: "SGVsbG8gV29ybGQ=".to_string(),
            config,
        };

        let result = validate_request(request);
        assert!(result.is_err());

        if let Err(ValidationError::InvalidFormat(msg)) = result {
            // Should contain error about invalid transaction structure
            assert!(
                msg.contains("validation failed") || msg.contains("invalid_transaction_structure")
            );
        } else {
            panic!("Expected ValidationError::InvalidFormat for invalid transaction structure");
        }
    }

    #[test]
    fn test_send_transaction_validation_invalid_encoding() {
        let config = SendTransactionConfig {
            encoding: TransactionEncoding::Base64,
            max_retries: Some(5),
            min_context_slot: Some(0),
            skip_preflight: false,
            wait_for_execution: false,
        };

        // Invalid encoding (not base64 or base58)
        let request = SendTransactionRequest {
            transaction: "This is not base64 or base58!@#$".to_string(),
            config,
        };

        let result = validate_request(request);
        assert!(result.is_err());

        if let Err(ValidationError::InvalidFormat(msg)) = result {
            // Should contain error about invalid encoding
            assert!(
                msg.contains("validation failed") || msg.contains("invalid_transaction_encoding")
            );
        } else {
            panic!("Expected ValidationError::InvalidFormat for invalid encoding");
        }
    }

    #[test]
    fn test_send_transaction_validation_max_retries_out_of_range() {
        let config = SendTransactionConfig {
            encoding: TransactionEncoding::Base64,
            max_retries: Some(150), // Out of range (0-100)
            min_context_slot: Some(0),
            skip_preflight: false,
            wait_for_execution: false,
        };

        let request = SendTransactionRequest {
            transaction: "AYGRg0cjRLKsdIRL9U02mNvV1zVqhtoIu/k7aB0S4BeRYNQHCxxq3la1NBNszCCrzY6J/l56Of7NF8w+Kpix+w2AAQABAxhn60cWnkU7ME/pRUG79JUP5F376Z7mp0GHp+nzhwYQAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQICAAEMAgAAAAAAAAAAAAAA".to_string(),
            config,
        };

        let result = validate_request(request);
        assert!(result.is_err());
        // Verify the error message contains the expected validation details
        if let Err(e) = result {
            let err_msg = e.to_string();
            assert!(
                err_msg.contains("config.max_retries") && err_msg.contains("Max retries must be between 0 and 100"),
                "Expected error to contain 'config.max_retries' and 'Max retries must be between 0 and 100', but got: {}",
                err_msg
            );
        }
    }
}
