use core::ffi::{c_char, c_int, c_long, c_uint, c_void, CStr};

use crate::{
    env::get_env,
    error::{self, EResult},
    headers::errno::Errno,
    util::PointerExt,
};

#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Debug)]
#[non_exhaustive]
#[repr(C)]
pub enum Sysconf {
    _SC_PAGE_SIZE = 1,
    _SC_GETGR_R_SIZE_MAX,
    _SC_GETPW_R_SIZE_MAX,
    _SC_HOST_NAME_MAX,
    _SC_LINE_MAX,
    _SC_ARG_MAX,
    _SC_NPROCESSORS_ONLN,
}

pub const _CS_PATH: c_int = 1;

#[no_mangle]
unsafe extern "C" fn alarm(value: c_uint) -> c_uint {
    todo!()
}

#[no_mangle]
unsafe extern "C" fn confstr(name: c_int, buf: *mut c_char, size: usize) -> usize {
    match name {
        _CS_PATH => {
            let path = match get_env("PATH".as_bytes()) {
                EResult::Ok(value) => value,
                EResult::Err(err) => {
                    error::set_errno(Errno::EINVAL);
                    return 0;
                }
            };
            let Some(path) = path else {
                return 0;
            };
            let cstr = CStr::from_ptr(path.as_ptr());
            if !buf.is_null() && size > 0 {
                let buf = buf.cast::<u8>().ensure_slice_mut(size);
                let bytes = cstr.to_bytes();
                let len = core::cmp::min(buf.len() - 1, bytes.len());
                buf[..len].copy_from_slice(&bytes[..len]);
                buf[len] = 0;
            }
            cstr.to_bytes().len()
        }
        _ => {
            error::set_errno(Errno::EINVAL);
            0
        }
    }
}

#[no_mangle]
unsafe extern "C" fn gethostid() -> c_long {
    todo!()
}
#[no_mangle]
unsafe extern "C" fn gethostname(name: *mut c_char, namelen: usize) -> c_int {
    todo!()
}
#[no_mangle]
unsafe extern "C" fn getlogin() -> *mut c_char {
    todo!()
}

#[no_mangle]
unsafe extern "C" fn getlogin_r(name: *mut c_char, namelen: usize) -> c_int {
    todo!()
}
#[no_mangle]
unsafe extern "C" fn swab(from: *const c_void, to: *mut c_void, n: isize) {
    todo!()
}
#[no_mangle]
unsafe extern "C" fn sysconf(name: Sysconf) -> c_long {
    match name {
        Sysconf::_SC_ARG_MAX => 4096,
        Sysconf::_SC_PAGE_SIZE => 0x1000,
        _ => todo!("{name:?}"),
    }
}
#[no_mangle]
unsafe extern "C" fn ttyname(fd: c_int) -> *mut c_char {
    todo!()
}
#[no_mangle]
unsafe extern "C" fn ttyname_r(fd: c_int, buf: *mut c_char, len: usize) -> c_int {
    todo!()
}
