#[cfg(unix)]
use std::os::unix::net::{
    UnixListener,
    UnixStream,
};
#[cfg(unix)]
use std::{
    fs,
    io::{
        Read,
        Write,
    },
};
use std::{
    path::PathBuf,
    sync::Arc,
    time::Duration,
};

#[cfg(unix)]
use kftray_commons::utils::config_dir;
use log::{
    debug,
    error,
    info,
    warn,
};
#[cfg(windows)]
use tokio::net::windows::named_pipe::{
    NamedPipeServer,
    PipeMode,
    ServerOptions,
};
use tokio::{
    sync::mpsc,
    task,
};

#[cfg(unix)]
use crate::auth::validate_peer_credentials;
use crate::{
    address_pool::AddressPoolManager,
    auth::validate_request,
    error::HelperError,
    hostfile::HostfileManager,
    messages::{
        AddressCommand,
        HelperRequest,
        HelperResponse,
        HostCommand,
        NetworkCommand,
        RequestCommand,
        ServiceCommand,
    },
    network::NetworkConfigManager,
};

#[cfg(target_os = "linux")]
pub const SOCKET_FILENAME: &str = "kftray-helper.sock";

#[cfg(target_os = "macos")]
pub const SOCKET_FILENAME: &str = "com.hcavarsan.kftray.helper.sock";

#[cfg(target_os = "windows")]
pub const DEFAULT_NAMED_PIPE: &str = r"\\.\pipe\kftray-helper";

#[cfg(unix)]
fn is_running_as_root() -> bool {
    unsafe { libc::geteuid() == 0 }
}

#[cfg(target_os = "macos")]
fn get_user_config_dir() -> Option<PathBuf> {
    if let Ok(socket_path) = std::env::var("SOCKET_PATH")
        && !socket_path.is_empty()
    {
        info!("Using explicit SOCKET_PATH from environment: {socket_path}");
        return Some(PathBuf::from(socket_path).parent()?.to_path_buf());
    }

    if let Ok(config_dir) = std::env::var("KFTRAY_CONFIG")
        && !config_dir.is_empty()
    {
        info!("Using KFTRAY_CONFIG from environment: {config_dir}");
        return Some(PathBuf::from(config_dir));
    }

    if let Ok(config_dir) = std::env::var("CONFIG_DIR")
        && !config_dir.is_empty()
    {
        info!("Using CONFIG_DIR from environment: {config_dir}");
        return Some(PathBuf::from(config_dir));
    }

    if let Ok(home) = std::env::var("HOME")
        && !home.is_empty()
    {
        if let Ok(user) = std::env::var("USER")
            && user != "root"
        {
            info!("Using home directory for user '{user}': {home}");
            let mut path = PathBuf::from(home);
            path.push(".kftray");
            return Some(path);
        }

        if home.starts_with("/Users/") || home.starts_with("/home/") {
            let mut path = PathBuf::from(home);
            path.push(".kftray");
            info!("Using user's home directory: {}", path.display());
            return Some(path);
        }

        if let Ok(sudo_user) = std::env::var("SUDO_USER")
            && !sudo_user.is_empty()
            && sudo_user != "root"
        {
            info!("Using SUDO_USER's home directory for: {sudo_user}");
            let user_home = if cfg!(target_os = "macos") {
                format!("/Users/{sudo_user}")
            } else {
                format!("/home/{sudo_user}")
            };
            let mut path = PathBuf::from(user_home);
            path.push(".kftray");
            return Some(path);
        }
    }

    None
}

pub fn get_default_socket_path() -> Result<PathBuf, HelperError> {
    #[cfg(target_os = "macos")]
    {
        debug!("Getting socket path from user config directory");

        let socket_path = if let Some(mut user_dir) = get_user_config_dir() {
            user_dir.push(SOCKET_FILENAME);
            user_dir
        } else {
            match config_dir::get_config_dir() {
                Ok(mut path) => {
                    path.push(SOCKET_FILENAME);
                    path
                }
                Err(_) => {
                    warn!("Could not get config directory, falling back to /tmp");
                    PathBuf::from(format!("/tmp/{SOCKET_FILENAME}"))
                }
            }
        };

        if let Some(parent) = socket_path.parent()
            && !parent.exists()
        {
            info!("Creating socket parent directory: {parent:?}");
            if let Err(e) = fs::create_dir_all(parent) {
                error!("Failed to create socket directory: {e}");
                return Err(HelperError::Communication(format!(
                    "Failed to create socket directory: {parent:?}, error: {e}"
                )));
            }

            #[cfg(unix)]
            if is_running_as_root()
                && let (Ok(user_id), Ok(group_id)) =
                    (std::env::var("SUDO_UID"), std::env::var("SUDO_GID"))
            {
                info!("Fixing directory ownership for socket directory");
                if let Err(e) = std::process::Command::new("chown")
                    .arg(format!("{user_id}:{group_id}"))
                    .arg(parent.as_os_str())
                    .status()
                {
                    warn!("Failed to fix directory ownership: {e}");
                }
            }
        }

        if let Some(parent) = socket_path.parent() {
            match parent.metadata() {
                Ok(_) => {
                    info!("Socket parent directory exists at: {}", parent.display());
                }
                Err(e) => {
                    warn!("Couldn't check socket parent directory: {e}");
                }
            }
        }

        info!("Using socket path: {}", socket_path.display());
        Ok(socket_path)
    }

    #[cfg(target_os = "linux")]
    {
        let socket_path = if let Ok(path) = std::env::var("SOCKET_PATH") {
            if !path.is_empty() {
                info!("Using explicit SOCKET_PATH from environment: {}", path);
                PathBuf::from(path)
            } else {
                find_linux_socket_path()
            }
        } else if let Ok(config_dir) = std::env::var("KFTRAY_CONFIG") {
            if !config_dir.is_empty() {
                info!("Using KFTRAY_CONFIG from environment: {}", config_dir);
                let mut path = PathBuf::from(config_dir);
                path.push(SOCKET_FILENAME);
                path
            } else {
                find_linux_socket_path()
            }
        } else if let Ok(config_dir) = std::env::var("CONFIG_DIR") {
            if !config_dir.is_empty() {
                info!("Using CONFIG_DIR from environment: {}", config_dir);
                let mut path = PathBuf::from(config_dir);
                path.push(SOCKET_FILENAME);
                path
            } else {
                find_linux_socket_path()
            }
        } else {
            find_linux_socket_path()
        };

        fn find_linux_socket_path() -> PathBuf {
            if let Ok(user) = std::env::var("USER")
                && user != "root"
                && let Ok(home) = std::env::var("HOME")
                && !home.is_empty()
                && (home.starts_with("/home/") || home.starts_with("/Users/"))
            {
                info!("Using home directory for user '{}': {}", user, home);
                let mut path = PathBuf::from(home);
                path.push(".kftray");
                path.push(SOCKET_FILENAME);
                return path;
            }

            if is_running_as_root()
                && let Ok(sudo_user) = std::env::var("SUDO_USER")
                && !sudo_user.is_empty()
                && sudo_user != "root"
            {
                info!("Using SUDO_USER's home directory for: {}", sudo_user);
                let user_home = format!("/home/{}", sudo_user);
                let mut path = PathBuf::from(user_home);
                path.push(".kftray");
                path.push(SOCKET_FILENAME);
                return path;
            }

            if let Ok(home) = std::env::var("HOME")
                && !home.is_empty()
                && (home.starts_with("/home/") || home.starts_with("/Users/"))
            {
                info!("Using home directory: {}", home);
                let mut path = PathBuf::from(home);
                path.push(".kftray");
                path.push(SOCKET_FILENAME);
                return path;
            }

            match config_dir::get_config_dir() {
                Ok(mut path) => {
                    path.push(SOCKET_FILENAME);
                    path
                }
                Err(_) => PathBuf::from(format!("/tmp/{}", SOCKET_FILENAME)),
            }
        }

        if let Some(parent) = socket_path.parent()
            && !parent.exists()
        {
            info!("Creating socket parent directory: {:?}", parent);
            if let Err(e) = fs::create_dir_all(parent) {
                error!("Failed to create socket directory: {}", e);
                return Err(HelperError::Communication(format!(
                    "Failed to create socket directory: {:?}, error: {}",
                    parent, e
                )));
            }

            if is_running_as_root()
                && let (Ok(user_id), Ok(group_id)) =
                    (std::env::var("SUDO_UID"), std::env::var("SUDO_GID"))
            {
                info!("Fixing directory ownership for socket directory");
                if let Err(e) = std::process::Command::new("chown")
                    .arg(format!("{}:{}", user_id, group_id))
                    .arg(parent.as_os_str())
                    .status()
                {
                    warn!("Failed to fix directory ownership: {}", e);
                }
            }
        }

        info!("Using socket path: {}", socket_path.display());
        Ok(socket_path)
    }

    #[cfg(target_os = "windows")]
    {
        Ok(PathBuf::from(DEFAULT_NAMED_PIPE))
    }

    #[cfg(not(any(target_os = "macos", target_os = "linux", target_os = "windows")))]
    {
        Err(HelperError::UnsupportedPlatform)
    }
}

pub async fn start_communication_server(
    socket_path: PathBuf, pool_manager: AddressPoolManager, network_manager: NetworkConfigManager,
    hostfile_manager: HostfileManager,
) -> Result<(), HelperError> {
    #[cfg(any(target_os = "macos", target_os = "linux"))]
    {
        start_unix_socket_server(socket_path, pool_manager, network_manager, hostfile_manager).await
    }

    #[cfg(target_os = "windows")]
    {
        start_named_pipe_server(socket_path, pool_manager, network_manager, hostfile_manager).await
    }

    #[cfg(not(any(target_os = "macos", target_os = "linux", target_os = "windows")))]
    {
        Err(HelperError::UnsupportedPlatform)
    }
}

#[cfg(any(target_os = "macos", target_os = "linux"))]
async fn start_unix_socket_server(
    socket_path: PathBuf, pool_manager: AddressPoolManager, network_manager: NetworkConfigManager,
    hostfile_manager: HostfileManager,
) -> Result<(), HelperError> {
    info!("Starting Unix socket server on: {}", socket_path.display());

    if socket_path.exists() {
        info!("Removing existing socket file");
        fs::remove_file(&socket_path).map_err(|e| {
            HelperError::Communication(format!("Failed to remove existing socket: {e}"))
        })?;
    }

    if let Some(parent) = socket_path.parent() {
        if !parent.exists() {
            info!("Creating socket directory: {}", parent.display());
            fs::create_dir_all(parent).map_err(|e| {
                HelperError::Communication(format!("Failed to create socket directory: {e}"))
            })?;
        }

        #[cfg(unix)]
        {
            if is_running_as_root() {
                debug!("Running as root, proceeding with socket creation");
            } else if !parent.exists() {
                info!("Creating socket directory: {}", parent.display());
                if let Err(e) = fs::create_dir_all(parent) {
                    warn!("Couldn't create socket directory: {e}");
                }
            }
        }
    }

    let listener = UnixListener::bind(&socket_path)
        .map_err(|e| HelperError::Communication(format!("Failed to bind Unix socket: {e}")))?;

    #[cfg(unix)]
    {
        use std::os::unix::fs::PermissionsExt;
        if let Err(e) = fs::set_permissions(&socket_path, fs::Permissions::from_mode(0o666)) {
            warn!("Failed to set socket permissions: {e}");
        } else {
            info!("Set socket permissions to 666 (rw-rw-rw-)");
        }

        if is_running_as_root()
            && let (Ok(user_id), Ok(group_id)) =
                (std::env::var("SUDO_UID"), std::env::var("SUDO_GID"))
        {
            info!("Fixing socket ownership for user access");
            match std::process::Command::new("chown")
                .arg(format!("{user_id}:{group_id}"))
                .arg(&socket_path)
                .status()
            {
                Err(e) => {
                    warn!("Failed to fix socket ownership: {e}");
                }
                _ => {
                    info!("Set socket ownership to {user_id}:{group_id}");
                }
            }
        }

        if socket_path.exists() {
            info!("Socket file exists at: {}", socket_path.display());
        }
    }

    info!(
        "Unix socket bound successfully at: {}",
        socket_path.display()
    );

    let pool_manager = Arc::new(pool_manager);
    let network_manager = Arc::new(network_manager);
    let hostfile_manager = Arc::new(hostfile_manager);

    let (_shutdown_tx, mut shutdown_rx) = mpsc::channel::<()>(1);

    let socket_path_clone = socket_path.clone();
    let listener_task = task::spawn(async move {
        info!("Listening on Unix socket: {socket_path_clone:?}");

        listener.set_nonblocking(true).map_err(|e| {
            HelperError::Communication(format!("Failed to set non-blocking mode: {e}"))
        })?;

        loop {
            match listener.accept() {
                Ok((stream, _addr)) => {
                    let pool_manager = Arc::clone(&pool_manager);
                    let network_manager = Arc::clone(&network_manager);
                    let hostfile_manager = Arc::clone(&hostfile_manager);

                    task::spawn(async move {
                        if let Err(e) = handle_connection(
                            stream,
                            pool_manager,
                            network_manager,
                            hostfile_manager,
                        )
                        .await
                        {
                            error!("Error handling connection: {e}");
                        }
                    });
                }
                Err(ref e) if e.kind() == std::io::ErrorKind::WouldBlock => {
                    tokio::time::sleep(Duration::from_millis(100)).await;
                }
                Err(e) => {
                    return Err(HelperError::Communication(format!(
                        "Error accepting connection: {e}"
                    )));
                }
            }

            if shutdown_rx.try_recv().is_ok() {
                info!("Shutting down Unix socket server");
                break;
            }
        }

        if socket_path_clone.exists() {
            fs::remove_file(&socket_path_clone).ok();
        }

        Ok::<(), HelperError>(())
    });

    match listener_task.await {
        Ok(result) => result,
        Err(e) => Err(HelperError::Communication(format!(
            "Listener task panicked: {e}"
        ))),
    }
}

#[cfg(any(target_os = "macos", target_os = "linux"))]
async fn handle_connection(
    mut stream: UnixStream, pool_manager: Arc<AddressPoolManager>,
    network_manager: Arc<NetworkConfigManager>, hostfile_manager: Arc<HostfileManager>,
) -> Result<(), HelperError> {
    info!("New connection received");

    #[cfg(any(target_os = "linux", target_os = "macos"))]
    {
        if let Err(e) = validate_peer_credentials(&stream) {
            error!("Peer credential validation failed: {e}");
            return Err(e);
        }
        debug!("Peer credentials validated successfully");
    }

    stream
        .set_read_timeout(Some(Duration::from_secs(5)))
        .map_err(|e| HelperError::Communication(format!("Failed to set socket timeout: {e}")))?;

    let mut buffer = Vec::new();
    let mut tmp_buf = [0u8; 4096];

    loop {
        match stream.read(&mut tmp_buf) {
            Ok(0) => {
                info!("Client closed connection (0 bytes read)");
                break;
            }
            Ok(n) => {
                debug!("Read {n} bytes from client");
                buffer.extend_from_slice(&tmp_buf[..n]);

                if n < tmp_buf.len() {
                    debug!("Read less than buffer size, assuming message is complete");
                    break;
                }
            }
            Err(e) if e.kind() == std::io::ErrorKind::WouldBlock => {
                debug!("Socket would block, waiting briefly");
                std::thread::sleep(Duration::from_millis(50));
                continue;
            }
            Err(e) if e.kind() == std::io::ErrorKind::Interrupted => {
                debug!("Socket read interrupted, continuing");
                continue;
            }
            Err(e) if e.kind() == std::io::ErrorKind::TimedOut => {
                debug!("Socket read timed out, ending read loop");
                break;
            }
            Err(e) => {
                error!("Error reading from client: {e}");
                return Err(HelperError::Communication(format!(
                    "Failed to read from socket: {e}"
                )));
            }
        }
    }

    if buffer.is_empty() {
        debug!("Empty request received, will wait for more data");
        std::thread::sleep(std::time::Duration::from_millis(500));

        match stream.read(&mut tmp_buf) {
            Ok(0) => {
                info!("Client still sent 0 bytes, closing connection");
                return Ok(());
            }
            Ok(n) => {
                debug!("Read {n} bytes from client after wait");
                buffer.extend_from_slice(&tmp_buf[..n]);
            }
            Err(e) => {
                warn!("Error reading more data: {e}");
                return Ok(());
            }
        }

        if buffer.is_empty() {
            warn!("Request is still empty after retry, cannot process");
            return Ok(());
        }
    }

    let request = match serde_json::from_slice::<HelperRequest>(&buffer) {
        Ok(req) => {
            debug!("Request parsed successfully");

            if let Err(e) = validate_request(&req) {
                error!("Request validation failed: {e}");
                return Err(e);
            }
            debug!("Request validation passed");

            req
        }
        Err(e) => {
            error!("Failed to parse request: {e}");
            return Err(HelperError::Communication(format!(
                "Failed to parse request: {e}"
            )));
        }
    };

    debug!("Processing request...");
    let response =
        process_request(request, pool_manager, network_manager, hostfile_manager).await?;
    debug!("Request processed successfully");

    let response_bytes = match serde_json::to_vec(&response) {
        Ok(bytes) => {
            debug!(
                "Response serialized ({} bytes), result={:?}",
                bytes.len(),
                response.result
            );
            bytes
        }
        Err(e) => {
            error!("Failed to serialize response: {e}");
            return Err(HelperError::Communication(format!(
                "Failed to serialize response: {e}"
            )));
        }
    };

    stream
        .set_write_timeout(Some(Duration::from_secs(5)))
        .map_err(|e| {
            warn!("Failed to set write timeout: {e}");
            HelperError::Communication(format!("Failed to set socket write timeout: {e}"))
        })?;

    debug!(
        "Writing response directly to client socket ({} bytes)",
        response_bytes.len()
    );
    match stream.write_all(&response_bytes) {
        Ok(_) => debug!("Response written successfully"),
        Err(e) => {
            error!("Failed to write response: {e}");
            if e.kind() == std::io::ErrorKind::BrokenPipe {
                info!("Client disconnected (broken pipe), ignoring error");
                return Ok(());
            }
            return Err(HelperError::Communication(format!(
                "Failed to write response: {e}"
            )));
        }
    }

    debug!("Flushing socket output");
    match stream.flush() {
        Ok(_) => debug!("Response flushed successfully"),
        Err(e) => {
            error!("Failed to flush response: {e}");
            if e.kind() == std::io::ErrorKind::BrokenPipe {
                info!("Client disconnected (broken pipe), ignoring error");
                return Ok(());
            }
            return Err(HelperError::Communication(format!(
                "Failed to flush response: {e}"
            )));
        }
    }

    std::thread::sleep(std::time::Duration::from_millis(100));

    info!("Connection handled successfully");
    Ok(())
}

#[cfg(target_os = "windows")]
fn create_secure_pipe(pipe_name: &str) -> Result<NamedPipeServer, std::io::Error> {
    ServerOptions::new()
        .pipe_mode(PipeMode::Byte)
        .access_inbound(true)
        .access_outbound(true)
        .create(pipe_name)
}

#[cfg(target_os = "windows")]
async fn start_named_pipe_server(
    _pipe_path: PathBuf, _pool_manager: AddressPoolManager, _network_manager: NetworkConfigManager,
    _hostfile_manager: HostfileManager,
) -> Result<(), HelperError> {
    info!(
        "Starting Windows named pipe server on: {}",
        _pipe_path.display()
    );

    let pipe_name = _pipe_path.to_string_lossy();

    let pool_manager = Arc::new(_pool_manager);
    let network_manager = Arc::new(_network_manager);
    let hostfile_manager = Arc::new(_hostfile_manager);

    let (_shutdown_tx, mut shutdown_rx) = mpsc::channel::<()>(1);

    let pipe_name_clone = pipe_name.to_string();
    let listener_task = task::spawn(async move {
        info!("Listening on Windows named pipe: {}", pipe_name_clone);

        loop {
            let pipe = match create_secure_pipe(&pipe_name_clone) {
                Ok(pipe) => pipe,
                Err(e) => {
                    error!("Failed to create named pipe: {}", e);
                    tokio::time::sleep(Duration::from_millis(1000)).await;
                    continue;
                }
            };

            debug!("Named pipe created, waiting for connection");

            match pipe.connect().await {
                Ok(()) => {
                    info!("Client connected to named pipe");
                    let pool_manager_clone = Arc::clone(&pool_manager);
                    let network_manager_clone = Arc::clone(&network_manager);
                    let hostfile_manager_clone = Arc::clone(&hostfile_manager);

                    task::spawn(async move {
                        if let Err(e) = handle_windows_connection(
                            pipe,
                            pool_manager_clone,
                            network_manager_clone,
                            hostfile_manager_clone,
                        )
                        .await
                        {
                            error!("Error handling Windows pipe connection: {}", e);
                        }
                    });
                }
                Err(e) => {
                    error!("Failed to connect client to named pipe: {}", e);
                    tokio::time::sleep(Duration::from_millis(100)).await;
                    continue;
                }
            }

            if shutdown_rx.try_recv().is_ok() {
                info!("Shutting down Windows named pipe server");
                break;
            }

            tokio::time::sleep(Duration::from_millis(100)).await;
        }

        Ok::<(), HelperError>(())
    });

    match listener_task.await {
        Ok(result) => result,
        Err(e) => Err(HelperError::Communication(format!(
            "Listener task panicked: {}",
            e
        ))),
    }
}

#[cfg(target_os = "windows")]
async fn handle_windows_connection(
    mut pipe: NamedPipeServer, pool_manager: Arc<AddressPoolManager>,
    network_manager: Arc<NetworkConfigManager>, hostfile_manager: Arc<HostfileManager>,
) -> Result<(), HelperError> {
    use tokio::io::{
        AsyncReadExt,
        AsyncWriteExt,
    };
    info!("New connection received on Windows named pipe");

    let mut buffer = Vec::new();
    let mut tmp_buf = [0u8; 4096];

    let mut total_read = 0;
    let timeout = Duration::from_secs(30);
    let start_time = std::time::Instant::now();

    loop {
        if start_time.elapsed() > timeout {
            warn!(
                "Read operation timed out after {} seconds",
                timeout.as_secs()
            );
            break;
        }

        match tokio::time::timeout(Duration::from_secs(5), pipe.read(&mut tmp_buf)).await {
            Ok(read_result) => match read_result {
                Ok(0) => {
                    info!("Client closed connection (0 bytes read)");
                    break;
                }
                Ok(n) => {
                    debug!("Read {} bytes from client", n);
                    buffer.extend_from_slice(&tmp_buf[..n]);
                    total_read += n;

                    if n < tmp_buf.len() {
                        debug!("Read less than buffer size, assuming message is complete");
                        break;
                    }
                }
                Err(e) if e.kind() == std::io::ErrorKind::WouldBlock => {
                    debug!("Pipe would block, waiting briefly");
                    tokio::time::sleep(Duration::from_millis(50)).await;
                    continue;
                }
                Err(e) if e.kind() == std::io::ErrorKind::Interrupted => {
                    debug!("Pipe read interrupted, continuing");
                    continue;
                }
                Err(e) => {
                    error!("Error reading from client: {}", e);
                    if total_read > 0 {
                        debug!(
                            "Have partial data ({} bytes), continuing with processing",
                            total_read
                        );
                        break;
                    }
                    return Err(HelperError::Communication(format!(
                        "Failed to read from pipe: {}",
                        e
                    )));
                }
            },
            Err(_) => {
                debug!("Read operation timed out");
                if total_read > 0 {
                    debug!(
                        "Have partial data ({} bytes), continuing with processing",
                        total_read
                    );
                    break;
                }
                tokio::time::sleep(Duration::from_millis(100)).await;
            }
        }
    }

    if buffer.is_empty() {
        debug!("Empty request received, will wait for more data");
        tokio::time::sleep(Duration::from_millis(500)).await;

        match tokio::time::timeout(Duration::from_secs(5), pipe.read(&mut tmp_buf)).await {
            Ok(result) => match result {
                Ok(0) => {
                    info!("Client still sent 0 bytes, closing connection");
                    return Ok(());
                }
                Ok(n) => {
                    debug!("Read {} bytes from client after wait", n);
                    buffer.extend_from_slice(&tmp_buf[..n]);
                }
                Err(e) => {
                    warn!("Error reading more data: {}", e);
                    return Ok(());
                }
            },
            Err(_) => {
                info!("Additional read timed out, closing connection");
                return Ok(());
            }
        }

        if buffer.is_empty() {
            warn!("Request is still empty after retry, cannot process");
            return Ok(());
        }
    }

    let request = match serde_json::from_slice::<HelperRequest>(&buffer) {
        Ok(req) => {
            debug!("Request parsed successfully");

            if let Err(e) = validate_request(&req) {
                error!("Request validation failed: {}", e);
                return Err(e);
            }
            debug!("Request validation passed");

            req
        }
        Err(e) => {
            error!("Failed to parse request: {}", e);
            return Err(HelperError::Communication(format!(
                "Failed to parse request: {}",
                e
            )));
        }
    };

    debug!("Processing request...");
    let response =
        process_request(request, pool_manager, network_manager, hostfile_manager).await?;
    debug!("Request processed successfully");

    let response_bytes = match serde_json::to_vec(&response) {
        Ok(bytes) => {
            debug!(
                "Response serialized ({} bytes), result={:?}",
                bytes.len(),
                response.result
            );
            bytes
        }
        Err(e) => {
            error!("Failed to serialize response: {}", e);
            return Err(HelperError::Communication(format!(
                "Failed to serialize response: {}",
                e
            )));
        }
    };

    debug!(
        "Writing response directly to client pipe ({} bytes)",
        response_bytes.len()
    );

    match pipe.write_all(&response_bytes).await {
        Ok(_) => debug!("Response written successfully"),
        Err(e) => {
            error!("Failed to write response: {}", e);
            if e.kind() == std::io::ErrorKind::BrokenPipe {
                info!("Client disconnected (broken pipe), ignoring error");
                return Ok(());
            }
            return Err(HelperError::Communication(format!(
                "Failed to write response: {}",
                e
            )));
        }
    }

    debug!("Flushing pipe output");
    match pipe.flush().await {
        Ok(_) => debug!("Response flushed successfully"),
        Err(e) => {
            error!("Failed to flush response: {}", e);
            if e.kind() == std::io::ErrorKind::BrokenPipe {
                info!("Client disconnected (broken pipe), ignoring error");
                return Ok(());
            }
            return Err(HelperError::Communication(format!(
                "Failed to flush response: {}",
                e
            )));
        }
    }

    tokio::time::sleep(Duration::from_millis(100)).await;

    info!("Connection handled successfully");
    Ok(())
}

async fn process_request(
    request: HelperRequest, pool_manager: Arc<AddressPoolManager>,
    network_manager: Arc<NetworkConfigManager>, hostfile_manager: Arc<HostfileManager>,
) -> Result<HelperResponse, HelperError> {
    let request_id = request.request_id.clone();

    debug!("Processing request: {:?}", request.command);

    match request.command {
        RequestCommand::Network(cmd) => match cmd {
            NetworkCommand::Add { address } => {
                debug!("Processing Add request for address: {address}");
                match network_manager.add_loopback_address(&address).await {
                    Ok(_) => {
                        info!("Add request successful for address: {address}");
                        Ok(HelperResponse::success(request_id))
                    }
                    Err(e) => {
                        error!("Add request failed for address {address}: {e}");
                        Ok(HelperResponse::error(request_id, format!("Error: {e}")))
                    }
                }
            }
            NetworkCommand::Remove { address } => {
                debug!("Processing Remove request for address: {address}");

                let result = match network_manager.remove_loopback_address(&address).await {
                    Ok(_) => {
                        info!("Remove request successful for address: {address}");
                        info!("Successfully removed loopback address: {address}");
                        HelperResponse::success(request_id.clone())
                    }
                    Err(e) => {
                        error!("Remove request failed for address {address}: {e}");

                        if e.to_string().contains("not found")
                            || e.to_string().contains("No such process")
                        {
                            info!("Address already removed, considering operation successful");
                            HelperResponse::success(request_id.clone())
                        } else {
                            debug!("Returning error response for failed removal");
                            HelperResponse::error(request_id.clone(), format!("Error: {e}"))
                        }
                    }
                };

                debug!(
                    "Prepared response for address removal: result={:?}",
                    result.result
                );

                match serde_json::to_vec(&result) {
                    Ok(bytes) => {
                        debug!("Serialized response: {} bytes", bytes.len());
                        Ok(result)
                    }
                    Err(e) => {
                        error!("Failed to serialize response: {e}");
                        Ok(HelperResponse::error(
                            request_id.clone(),
                            format!("Error serializing response: {e}"),
                        ))
                    }
                }
            }
            NetworkCommand::List => {
                debug!("Processing List request");
                match network_manager.list_loopback_addresses().await {
                    Ok(addresses) => {
                        info!(
                            "List request successful, found {} addresses",
                            addresses.len()
                        );
                        Ok(HelperResponse::list_success(request_id, addresses))
                    }
                    Err(e) => {
                        error!("List request failed: {e}");
                        Ok(HelperResponse::list_success(request_id, vec![]))
                    }
                }
            }
        },
        RequestCommand::Address(cmd) => match cmd {
            AddressCommand::Allocate { service_name } => {
                debug!("Processing Allocate request for service: {service_name}");
                match pool_manager.allocate_address(&service_name).await {
                    Ok(address) => {
                        info!(
                            "Address pool allocation successful for service {service_name}: {address}"
                        );

                        match network_manager.add_loopback_address(&address).await {
                            Ok(_) => {
                                info!(
                                    "Network interface addition successful for address: {address}"
                                );
                                Ok(HelperResponse::string_success(request_id, address))
                            }
                            Err(e) => {
                                error!(
                                    "Network interface addition failed for address {address}: {e}"
                                );
                                if let Err(release_err) =
                                    pool_manager.release_address(&address).await
                                {
                                    warn!(
                                        "Failed to release address from pool after network error: {release_err}"
                                    );
                                }
                                Ok(HelperResponse::string_success(
                                    request_id,
                                    "127.0.0.1".to_string(),
                                ))
                            }
                        }
                    }
                    Err(e) => {
                        error!("Address pool allocation failed for service {service_name}: {e}");

                        Ok(HelperResponse::string_success(
                            request_id,
                            "127.0.0.1".to_string(),
                        ))
                    }
                }
            }
            AddressCommand::Release { address } => {
                debug!("Processing Release request for address: {address}");

                let pool_result = pool_manager.release_address(&address).await;
                match pool_result {
                    Ok(_) => info!("Address pool release successful for address: {address}"),
                    Err(e) => error!("Address pool release failed for address {address}: {e}"),
                }

                let network_result = network_manager.remove_loopback_address(&address).await;
                match network_result {
                    Ok(_) => {
                        info!("Network interface removal successful for address: {address}");
                        Ok(HelperResponse::success(request_id))
                    }
                    Err(e) => {
                        error!("Network interface removal failed for address {address}: {e}");

                        if e.to_string().contains("not found")
                            || e.to_string().contains("No such process")
                        {
                            info!(
                                "Address already removed from interface, considering operation successful"
                            );
                            Ok(HelperResponse::success(request_id))
                        } else {
                            debug!("Returning error response for failed network removal");
                            Ok(HelperResponse::error(request_id, format!("Error: {e}")))
                        }
                    }
                }
            }
            AddressCommand::List => {
                debug!("Processing List request");
                match pool_manager.list_allocations().await {
                    Ok(allocations) => {
                        info!(
                            "List request successful, found {} allocations",
                            allocations.len()
                        );
                        Ok(HelperResponse::allocations_success(request_id, allocations))
                    }
                    Err(e) => {
                        error!("List request failed: {e}");

                        Ok(HelperResponse::allocations_success(request_id, vec![]))
                    }
                }
            }
        },
        RequestCommand::Service(cmd) => match cmd {
            ServiceCommand::Status => {
                debug!("Processing Status request");

                Ok(HelperResponse::string_success(request_id, "running".into()))
            }
            ServiceCommand::Stop => {
                debug!("Processing Stop request");
                info!("Received stop command, shutting down helper service");

                // Send success response before shutting down
                let response = HelperResponse::success(request_id);

                // Schedule shutdown after a short delay to allow response to be sent
                tokio::spawn(async {
                    tokio::time::sleep(tokio::time::Duration::from_millis(100)).await;
                    info!("Shutting down helper service");
                    std::process::exit(0);
                });

                Ok(response)
            }
            ServiceCommand::Restart => {
                debug!("Processing Restart request");
                Ok(HelperResponse::success(request_id))
            }
        },
        RequestCommand::Host(cmd) => match cmd {
            HostCommand::Add { id, entry } => {
                debug!("Processing Host Add request for ID: {id}");
                match hostfile_manager.add_entry(id, entry) {
                    Ok(_) => {
                        info!("Host Add request successful");
                        Ok(HelperResponse::success(request_id))
                    }
                    Err(e) => {
                        error!("Host Add request failed: {e}");
                        Ok(HelperResponse::error(request_id, format!("Error: {e}")))
                    }
                }
            }
            HostCommand::Remove { id } => {
                debug!("Processing Host Remove request for ID: {id}");
                match hostfile_manager.remove_entry(&id) {
                    Ok(_) => {
                        info!("Host Remove request successful");
                        Ok(HelperResponse::success(request_id))
                    }
                    Err(e) => {
                        error!("Host Remove request failed: {e}");
                        Ok(HelperResponse::error(request_id, format!("Error: {e}")))
                    }
                }
            }
            HostCommand::RemoveAll => {
                debug!("Processing Host RemoveAll request");
                match hostfile_manager.remove_all_entries() {
                    Ok(_) => {
                        info!("Host RemoveAll request successful");
                        Ok(HelperResponse::success(request_id))
                    }
                    Err(e) => {
                        error!("Host RemoveAll request failed: {e}");
                        Ok(HelperResponse::error(request_id, format!("Error: {e}")))
                    }
                }
            }
            HostCommand::List => {
                debug!("Processing Host List request");
                match hostfile_manager.list_entries() {
                    Ok(entries) => {
                        info!(
                            "Host List request successful, found {} entries",
                            entries.len()
                        );
                        Ok(HelperResponse::host_entries_success(request_id, entries))
                    }
                    Err(e) => {
                        error!("Host List request failed: {e}");
                        Ok(HelperResponse::error(request_id, format!("Error: {e}")))
                    }
                }
            }
        },
        RequestCommand::Ping => {
            debug!("Processing Ping request");
            Ok(HelperResponse::string_success(request_id, "pong".into()))
        }
    }
}
