use futures::Future;
use nostr_rs_client::Pool;
use nostr_rs_relayer::Relayer;
use nostr_rs_rocksdb::RocksDb;
use nostr_rs_types::{types::Filter, Request, Response};
use std::{env, fs, pin::Pin, sync::Arc};
use tokio::{net::TcpListener, sync::mpsc};
use url::Url;

mod config;

use config::Config;

fn on_connection(
    host: Url,
    _socket: mpsc::Sender<Request>,
) -> Pin<Box<dyn Future<Output = ()> + Send>> {
    Box::pin(async move {})
}

pub struct Connection {
    connection_to_relayers: Arc<nostr_rs_client::Pool>,
    receive_from_relayer: mpsc::Receiver<Response>,
}

/*
fn create_listener(relayer: Arc<nostr_rs_relayer::Relayer>) -> nostr_rs_client::Pool {
    let (clients, mut client_receiver) = nostr_rs_client::Pool::new();

    tokio::spawn(async move {
        loop {
            let (event, _url) = client_receiver.recv().await.unwrap();
            match &event {
                Event::Response(Response::Event(event)) => {
                    let _ = relayer.store_and_broadcast(&event.event);
                }
                Event::Disconnected => break,
                _ => {}
            }
        }
    });

    clients
}
*/

#[tokio::main]
async fn main() {
    env_logger::init();

    let args: Vec<String> = env::args().collect();
    let config_path = if args.len() > 1 {
        &args[1]
    } else {
        "config.toml"
    };

    let config_content = fs::read_to_string(config_path).expect("Failed to read the config file");

    let config: Config = toml::from_str(&config_content).expect("Failed to parse the config file");
    println!("{:#?}", config);

    let db = RocksDb::new(&config.db_path).expect("db");
    let mut client_pool = Pool::new_with_clients(config.relayers);

    let initial_subscription = vec![Filter::default()];

    let _ = client_pool.subscribe(initial_subscription.into()).await;

    let relayer = Relayer::new(Some(db), Some(client_pool)).expect("relayer");

    let addr = "127.0.0.1:3000";
    let listener: TcpListener = TcpListener::bind(&addr).await.unwrap();

    let _ = relayer.main(listener).expect("valid main").await;

    /*
    loop {
        tokio::select! {
            Some((event, url)) = client_pool.recv() => {
                println!("Recv: {} from {}", serde_json::to_string(&event).expect("valid json"), url);
            }
        }
    }

    let db = RocksDb::new("./relayer-db").expect("db");
    let (relayer, mut server_receiver) = nostr_rs_relayer::Relayer::new(Some(db));
    let mut clients = nostr_rs_client::Pool::new()
        .connect_to("wss://relay.damus.io/", Some(on_connection))
        .expect("valid url")
        .connect_to("wss://brb.io", Some(on_connection))
        .expect("valid url")
        .connect_to("wss://nos.lol", Some(on_connection))
        .expect("valid url")
        .connect_to("wss://relay.current.fyi", Some(on_connection))
        .expect("valid url")
        .connect_to("wss://eden.nostr.land", Some(on_connection))
        .expect("valid url")
        .connect_to("wss://relay.snort.social", Some(on_connection))
        .expect("valid url");

    let addr = "127.0.0.1:3000";
    let listener: TcpListener = TcpListener::bind(&addr).await.unwrap();

    clients.send(Request::Request(Default::default())).await;

    loop {
        tokio::select! {
            Some((event, url)) = clients.recv() => {
                println!("Recv: {:?} from {}", event, url);
            }
        }
    }
    let relayer_for_recv = relayer.clone();
    let relayer_for_client = relayer.clone();
    let relayer_for_republisher = relayer.clone();

        tokio::spawn(async move {
            loop {
                if let Ok(events) = relayer_for_republisher.get_db().get_local_events() {
                    println!("Rebroadcast: {:?} ", events);
                    for event in events.into_iter() {
                        println!("Rebroadcasting: {}", serde_json::to_string(&event).unwrap());
                        let _ = clients_for_republisher.send(event.into()).await;
                    }
                }
                sleep(Duration::from_secs(360)).await;
            }
        });

        tokio::spawn(async move {
            loop {
                let (event, url) = client_receiver.recv().await.unwrap();
                match &event {
                    Event::Response(Response::Event(event)) => {
                        let _ = relayer_for_client.store_and_broadcast(&event.event);
                    }
                    _msg => {
                        //println!("Sending message: {:?}", msg);
                        //let _ = relayer_for_client.send(msg).await;
                    }
                }
            }
        });

        tokio::spawn(async move {
            loop {
                let x = relayer_for_recv.recv(&mut server_receiver).await.unwrap();
                if let Some(x) = x {
                    println!(
                        "received event: {}",
                        serde_json::to_string(&x).expect("valid json")
                    );
                    clients.send(x).await;
                }
            }
        });

        let mut clients = HashMap::<u128, nostr_rs_client::Pool>::new();

        loop {
            let (stream, _) = listener.accept().await.unwrap();
            let addr = stream.peer_addr().unwrap();

            println!("Client {} connected", addr);

            let _ = relayer.add_connection(None, stream).await;
        }
        */
}
