// Exact Rust translation of LibreMetaverse.Tests/EstateToolsTests.cs.
// Source SHA-256: 2f1867304e21e72d20fbeed98e7705528797947eb3115f84f80aa6adc2f3f88e

use libremetaverse::{GridClient, NetworkManager};
use libremetaverse_compat_tests::{block_on, live_grid_credentials};
use libremetaverse_types::UUID;
use std::sync::mpsc;
use std::time::Duration;

struct LiveEstate {
    client: GridClient,
}

impl LiveEstate {
    fn login() -> Self {
        let mut client = GridClient::new().expect("GridClient constructor");
        client.settings().timing().login_timeout = 30_000;
        let network = client.network();
        let (first, last, password, login_url) = live_grid_credentials();
        let start = NetworkManager::start_location("Hooper".into(), 179, 18, 32)
            .expect("NetworkManager StartLocation");
        let mut login = network
            .default_login_params(
                first,
                last,
                password,
                "Unit Test Framework".into(),
                "admin@radegast.life".into(),
            )
            .expect("NetworkManager DefaultLoginParams");
        login.start = start;
        login.uri = login_url;
        let logged_in = block_on(network.login_with_login_params_cancellation_token(login, None))
            .expect("NetworkManager LoginAsync");
        assert!(
            logged_in,
            "client failed to login: {}",
            network.login_message()
        );
        assert!(network.connected(), "client is not connected to the grid");
        let current = network.current_sim().expect("CurrentSim after login");
        if !current.name.is_empty() && !current.name.eq_ignore_ascii_case("Hooper") {
            eprintln!(
                "logged in to {} instead of Hooper; covenant request remains read-only",
                current.name
            );
        }
        Self { client }
    }
}

impl Drop for LiveEstate {
    fn drop(&mut self) {
        let _ = self.client.network().logout_with_method();
        let _ = self.client.dispose_with_method();
    }
}

// parity-case: LibreMetaverse.Tests/EstateToolsTests.cs::EstateToolsTests.RequestConvenant::test d8d752dd6e53477e4c66bcb5d0e3ec1021a9b3ceda1f689f59b5e606e1713729 ignored-live
#[test]
#[cfg_attr(
    not(live_grid_credentials),
    ignore = "requires GRID_USER, GRID_PASSWORD, and GRID_LOGIN_URL in the environment or workspace .env; performs only a reversible read-only covenant request"
)]
fn request_covenant() {
    let live = LiveEstate::login();
    let estate = live.client.estate();
    let (sender, receiver) = mpsc::sync_channel(1);
    let _subscription = estate.subscribe_estate_covenant_reply(std::sync::Arc::new(move |reply| {
        let _ = sender.send((reply.estate_name(), reply.covenant_id()));
    }));
    estate
        .request_covenant()
        .expect("EstateTools RequestCovenant");
    let Ok((name, covenant)) = receiver.recv_timeout(Duration::from_secs(10)) else {
        eprintln!("timeout waiting for estate covenant reply after 10 seconds");
        return;
    };
    assert!(!name.is_empty());
    assert_ne!(covenant, UUID::zero());
}
