use core::{
    ffi::{c_char, c_int, c_uint},
    time::Duration,
};

use crate::{
    error::{self, CIntCountResult, CIntZeroResult, ResultExt},
    headers::{
        errno::Errno,
        sys_types::{gid_t, pid_t, uid_t},
    },
    process,
};

#[no_mangle]
unsafe extern "C" fn _exit(status: c_int) -> ! {
    process::c_exit_immediately(status)
}

#[no_mangle]
unsafe extern "C" fn fork() -> pid_t {
    todo!()
}

#[no_mangle]
unsafe extern "C" fn getegid() -> gid_t {
    todo!()
}

#[no_mangle]
unsafe extern "C" fn geteuid() -> uid_t {
    todo!()
}

#[no_mangle]
unsafe extern "C" fn getgid() -> gid_t {
    todo!()
}

#[no_mangle]
unsafe extern "C" fn getgroups(gidsetsize: c_int, grouplist: *mut gid_t) -> c_int {
    todo!()
}

#[no_mangle]
unsafe extern "C" fn getpgid(pid: pid_t) -> pid_t {
    todo!()
}

#[no_mangle]
unsafe extern "C" fn getpgrp() -> pid_t {
    process::getpgrp()
}

#[no_mangle]
unsafe extern "C" fn getpid() -> pid_t {
    process::getpid()
}

#[no_mangle]
unsafe extern "C" fn getppid() -> pid_t {
    todo!()
}

#[no_mangle]
unsafe extern "C" fn getsid(pid: pid_t) -> pid_t {
    todo!()
}

#[no_mangle]
unsafe extern "C" fn getuid() -> uid_t {
    todo!()
}

#[no_mangle]
unsafe extern "C" fn nice(incr: c_int) -> CIntCountResult {
    log::error!("TODO: nice()");
    CIntCountResult::success(0)
}

#[no_mangle]
unsafe extern "C" fn pause() -> CIntZeroResult {
    todo!()
}

#[no_mangle]
unsafe extern "C" fn setegid(gid: gid_t) -> c_int {
    todo!()
}

#[no_mangle]
unsafe extern "C" fn seteuid(uid: uid_t) -> c_int {
    todo!()
}

#[no_mangle]
unsafe extern "C" fn setgid(gid: gid_t) -> c_int {
    todo!()
}
#[no_mangle]
unsafe extern "C" fn setpgid(pid: pid_t, pgid: pid_t) -> c_int {
    todo!()
}

#[no_mangle]
unsafe extern "C" fn setpgrp() -> pid_t {
    todo!()
}

#[no_mangle]
unsafe extern "C" fn setregid(rgid: gid_t, egid: gid_t) -> c_int {
    todo!()
}

#[no_mangle]
unsafe extern "C" fn setreuid(ruid: uid_t, euid: uid_t) -> c_int {
    todo!()
}

#[no_mangle]
unsafe extern "C" fn setsid() -> pid_t {
    todo!()
}

#[no_mangle]
unsafe extern "C" fn setuid(uid: uid_t) -> c_int {
    todo!()
}

#[no_mangle]
unsafe extern "C" fn sleep(seconds: c_uint) -> c_uint {
    let duration = Duration::from_secs(seconds.try_into().unwrap());
    match process::sleep(duration) {
        Ok(()) => 0,
        Err(remaining) => {
            error::set_errno(Errno::EINTR);
            remaining.as_secs() as c_uint + (remaining.subsec_nanos() != 0) as c_uint
        }
    }
}

#[no_mangle]
unsafe extern "C" fn usleep(millis: c_uint) -> CIntZeroResult {
    let duration = Duration::from_millis(millis.try_into().unwrap());
    process::sleep(duration).e_map_err(|_| Errno::EINTR)?;
    CIntZeroResult::SUCCESS
}

#[no_mangle]
unsafe extern "C" fn getpagesize() -> usize {
    4096
}
