//! File I/O — the ONLY place in `service/file_io/` that may perform
//! filesystem reads, writes, shell execution, or other side effects.
//!
//! Every function here is a thin adapter that converts lower-level
//! `String` errors into the typed [`super::Error`] variants.

use super::Error;
use crate::io::fs::FileEntry;
use crate::io::search::SearchResult;
use crate::io::shell::CommandOutput;
use crate::state::SessionState;

pub(super) async fn read_file(path: String, state: &SessionState) -> Result<String, Error> {
    crate::io::fs::read_file(path, state)
        .await
        .map_err(Error::Filesystem)
}

#[allow(dead_code)]
pub(super) async fn write_file(
    path: String,
    content: String,
    state: &SessionState,
) -> Result<(), Error> {
    crate::io::fs::write_file(path, content, state)
        .await
        .map_err(Error::Filesystem)
}

#[allow(dead_code)]
pub(super) async fn list_directory(
    path: String,
    state: &SessionState,
) -> Result<Vec<FileEntry>, Error> {
    crate::io::fs::list_directory(path, state)
        .await
        .map_err(Error::Filesystem)
}

pub(super) async fn list_directory_absolute(path: String) -> Result<Vec<FileEntry>, Error> {
    crate::io::fs::list_directory_absolute(path)
        .await
        .map_err(Error::Filesystem)
}

#[allow(dead_code)]
pub(super) async fn create_directory_absolute(path: String) -> Result<(), Error> {
    crate::io::fs::create_directory_absolute(path)
        .await
        .map_err(Error::Filesystem)
        .map(|_| ())
}

pub(super) fn get_home_directory() -> Result<String, Error> {
    crate::io::fs::get_home_directory().map_err(Error::Filesystem)
}

pub(super) async fn list_project_files(state: &SessionState) -> Result<Vec<String>, Error> {
    crate::io::fs::list_project_files(state)
        .await
        .map_err(Error::Filesystem)
}

#[allow(dead_code)]
pub(super) async fn search_files(
    query: String,
    state: &SessionState,
) -> Result<Vec<SearchResult>, Error> {
    crate::io::search::search_files(query, state)
        .await
        .map_err(Error::Filesystem)
}

#[allow(dead_code)]
pub(super) async fn exec_shell(
    command: String,
    args: Vec<String>,
    state: &SessionState,
) -> Result<CommandOutput, Error> {
    crate::io::shell::exec_shell(command, args, state)
        .await
        .map_err(|e| {
            if e.contains("not in the allowlist") {
                Error::Validation(e)
            } else {
                Error::Filesystem(e)
            }
        })
}
