use std::{
    fs,
    path::PathBuf,
    time::{SystemTime, UNIX_EPOCH},
};

use dambi::Bytes;
use dope_futures::AsyncRead;
use dope_futures::listener::Listener;
use dope_futures::stream::Stream;
use dope_runtime::{DefaultBackend, block_on, spawn};
use dope_transport::Unix;

fn tmp_sock_path(name: &str) -> PathBuf {
    let ns = SystemTime::now()
        .duration_since(UNIX_EPOCH)
        .unwrap()
        .as_nanos();
    std::env::temp_dir().join(format!("dope-rt-{name}-{ns}.sock"))
}

#[test]
fn unix_stream_bidirectional_roundtrip() {
    let path = tmp_sock_path("uds");
    let mut listener = Listener::<Unix, DefaultBackend>::bind(&path).expect("bind");

    let path2 = path.clone();
    block_on(async move {
        let server = spawn(async move {
            let (mut s, ()) = listener.accept().await.expect("accept");

            let (res, buf) = s.read(vec![0u8; 4]).await;
            let n = res.expect("server read");
            assert_eq!(&buf[..n], b"ping");

            let (res, _) = s.write_all_owned(Bytes::from_static(b"pong")).await;
            res.expect("server write");
        });

        let mut c = Stream::<Unix, DefaultBackend>::connect_with(&path2)
            .await
            .expect("connect");

        let (res, _) = c.write_all_owned(Bytes::from_static(b"ping")).await;
        res.expect("client write");

        let (res, buf) = c.read(vec![0u8; 4]).await;
        let n = res.expect("client read");
        assert_eq!(&buf[..n], b"pong");

        server.await;
    });

    let _ = fs::remove_file(&path);
}
