use std::env;
use std::process;

use kordophone::{
    api::{HTTPAPIClient, InMemoryAuthenticationStore, EventSocket},
    model::{ConversationID, event::EventData},
    APIInterface,
};
use kordophone::api::http_client::Credentials;
use kordophone::api::AuthenticationStore;

use futures_util::StreamExt;
use hyper::Uri;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    env_logger::init();

    let args: Vec<String> = env::args().collect();
    if args.len() < 2 {
        eprintln!("Usage: {} <conversation_id1> [conversation_id2] [conversation_id3] ...", args[0]);
        eprintln!("Environment variables required:");
        eprintln!("  KORDOPHONE_API_URL - Server URL");
        eprintln!("  KORDOPHONE_USERNAME - Username for authentication");
        eprintln!("  KORDOPHONE_PASSWORD - Password for authentication");
        process::exit(1);
    }

    // Read environment variables
    let server_url: Uri = env::var("KORDOPHONE_API_URL")
        .map_err(|_| "KORDOPHONE_API_URL environment variable not set")?
        .parse()?;
    
    let username = env::var("KORDOPHONE_USERNAME")
        .map_err(|_| "KORDOPHONE_USERNAME environment variable not set")?;
    
    let password = env::var("KORDOPHONE_PASSWORD")
        .map_err(|_| "KORDOPHONE_PASSWORD environment variable not set")?;
    
    let credentials = Credentials { username, password };
    
    // Collect all conversation IDs from command line arguments
    let target_conversation_ids: Vec<ConversationID> = args[1..].iter()
        .map(|id| id.clone())
        .collect();
    
    println!("Monitoring {} conversation(s) for updates: {:?}", 
             target_conversation_ids.len(), target_conversation_ids);
    
    let auth_store = InMemoryAuthenticationStore::new(Some(credentials.clone()));
    let mut client = HTTPAPIClient::new(server_url, auth_store);
    let _ = client.authenticate(credentials).await?;
    
    // Open event socket
    let event_socket = client.open_event_socket(None).await?;
    let (mut stream, _sink) = event_socket.events().await;
    
    println!("Connected to event stream, waiting for updates...");
    
    // Process events
    while let Some(event_result) = stream.next().await {
        match event_result {
            Ok(socket_event) => {
                match socket_event {
                    kordophone::api::event_socket::SocketEvent::Update(event) => {
                        match event.data {
                            EventData::MessageReceived(conversation, _message) => {
                                if target_conversation_ids.contains(&conversation.guid) {
                                    println!("Message update detected for conversation {}, marking as read...", conversation.guid);
                                    match client.mark_conversation_as_read(&conversation.guid).await {
                                        Ok(_) => println!("Successfully marked conversation {} as read", conversation.guid),
                                        Err(e) => eprintln!("Failed to mark conversation {} as read: {:?}", conversation.guid, e),
                                    }
                                }
                            },

                            _ => {}
                        }
                    },
                    kordophone::api::event_socket::SocketEvent::Pong => {
                        // Ignore pong messages
                    }
                }
            },
            Err(e) => {
                eprintln!("Error receiving event: {:?}", e);
                break;
            }
        }
    }
    
    println!("Event stream ended");
    Ok(())
}
