use ssh2::Session;
use std::{
    io::Read,
    net::{TcpStream, ToSocketAddrs},
    time::Duration,
};

fn run_vps_command(
    password: &str,
    command: &str,
) -> Result<String, String> {
    let address = "146.59.230.190:22";

    let socket_address = address
        .to_socket_addrs()
        .map_err(|error| {
            format!(
                "failed to resolve VPS address: {}",
                error
            )
        })?
        .next()
        .ok_or_else(|| {
            format!(
                "failed to resolve VPS address {}",
                address
            )
        })?;

    let tcp = TcpStream::connect_timeout(
        &socket_address,
        Duration::from_secs(8),
    )
    .map_err(|error| {
        format!(
            "failed to connect to VPS SSH: {}",
            error
        )
    })?;

    let _ = tcp.set_read_timeout(Some(
        Duration::from_secs(30),
    ));

    let _ = tcp.set_write_timeout(Some(
        Duration::from_secs(30),
    ));

    let mut session = Session::new()
        .map_err(|error| {
            format!(
                "failed to create VPS SSH session: {}",
                error
            )
        })?;

    session.set_tcp_stream(tcp);

    session.handshake().map_err(|error| {
        format!(
            "VPS SSH handshake failed: {}",
            error
        )
    })?;

    session
        .userauth_password("lr-vpn", password)
        .map_err(|error| {
            format!(
                "VPS SSH authentication failed: {}",
                error
            )
        })?;

    if !session.authenticated() {
        return Err(
            "VPS SSH authentication failed"
                .into(),
        );
    }

    let mut channel = session
        .channel_session()
        .map_err(|error| {
            format!(
                "failed to open VPS SSH channel: {}",
                error
            )
        })?;

    channel
        .exec(command)
        .map_err(|error| {
            format!(
                "failed to execute VPS command: {}",
                error
            )
        })?;

    let mut stdout = String::new();

    channel
        .read_to_string(&mut stdout)
        .map_err(|error| {
            format!(
                "failed to read VPS command output: {}",
                error
            )
        })?;

    channel.wait_close().ok();

    let exit_status = channel
        .exit_status()
        .map_err(|error| {
            format!(
                "failed to read VPS command exit status: {}",
                error
            )
        })?;

    if exit_status != 0 {
        return Err(format!(
            "VPS command failed with exit code {}:\n{}",
            exit_status,
            stdout
        ));
    }

    Ok(stdout)
}

#[tauri::command]
pub async fn list_controller_clients(
    password: String,
) -> Result<String, String> {
    if password.trim().is_empty() {
        return Err(
            "VPS password is required".into(),
        );
    }

    run_vps_command(
        &password,
        "sudo /usr/local/sbin/lr-controllers-list",
    )
}