use std::sync::Arc;

use tracing;

use super::super::backend::russh::exec::exec_collect;
use super::{PosixLinuxShell, PosixMacOsShell, RemoteShell, WindowsPowerShell};

pub(crate) async fn detect_remote_shell(
    session: &russh::client::Handle<super::super::backend::russh::connect::ClientHandler>,
) -> Arc<dyn RemoteShell> {
    let shell: Arc<dyn RemoteShell> = 'inner: {
        if let Ok((0, stdout, _)) = exec_collect(session, "uname -s").await {
            let output = String::from_utf8_lossy(&stdout);
            if output.contains("Linux") {
                break 'inner Arc::new(PosixLinuxShell);
            }
            if output.contains("Darwin") {
                break 'inner Arc::new(PosixMacOsShell);
            }
        }

        if let Ok((0, _, _)) = exec_collect(
            session,
            "powershell -Command '$PSVersionTable.PSVersion.Major'",
        )
        .await
        {
            break 'inner Arc::new(WindowsPowerShell);
        }

        Arc::new(PosixLinuxShell)
    };

    tracing::debug!(system_type = ?shell.system_type(), "system type detected");
    shell
}
