use core::ffi::c_char;

use ax_errno::AxError;
use ax_posix_api::{ctypes::stat, utils::char_ptr_to_str};
use log::info;

use crate::err;

#[unsafe(no_mangle)]
pub fn sys_stat(name: *const c_char, stat: *mut stat) -> i32 {
    info!("called sys_stat");
    unsafe { ax_posix_api::sys_stat(name, stat as _) }
}

#[unsafe(no_mangle)]
pub fn sys_lstat(name: *const c_char, stat: *mut stat) -> i32 {
    info!("called sys_lstat");
    unsafe { ax_posix_api::sys_lstat(name, stat as _) as _ }
}

#[unsafe(no_mangle)]
pub fn sys_fstat(fd: i32, stat: *mut stat) -> i32 {
    info!("called sys_fstat");
    unsafe { ax_posix_api::sys_fstat(fd, stat as _) as _ }
}

#[unsafe(no_mangle)]
pub fn sys_unlink(name: *const c_char) -> i32 {
    info!("called sys_unlink");
    // get name as &str
    let name = match char_ptr_to_str(name) {
        Ok(s) => s,
        Err(e) => return err(e),
    };

    if let Err(e) = ax_api::fs::ax_remove_file(name) {
        if e != AxError::IsADirectory {
            return err(e.into());
        }
        if let Err(e) = ax_api::fs::ax_remove_dir(name) {
            return err(e.into());
        }
    }
    0
}

#[unsafe(no_mangle)]
pub fn sys_mkdir(name: *const c_char, _mode: u32) -> i32 {
    let name = match char_ptr_to_str(name) {
        Ok(s) => s,
        Err(e) => return err(e),
    };
    if let Err(e) = ax_api::fs::ax_create_dir(name) {
        return err(e.into());
    }
    0
}

#[unsafe(no_mangle)]
pub fn sys_getdents64(fd: i32, buf: *mut u8, len: usize) -> isize {
    info!("called sys_getdents64");
    unsafe { ax_posix_api::sys_getdents64(fd, buf, len) as _ }
}
