use core::intrinsics::unlikely;

use crate::arch::interrupt::TrapFrame;
use crate::arch::ipc::signal::MAX_SIG_NUM;
use crate::arch::MMArch;
use crate::mm::{MemoryManagementArch, VirtAddr};
use crate::process::fork::{CloneFlags, KernelCloneArgs, MAX_PID_NS_LEVEL};
use crate::process::pid::PidType;
use crate::process::{KernelStack, ProcessControlBlock, ProcessManager};
use crate::sched::completion::Completion;
use crate::syscall::user_access::{write_one_to_user_protected, UserBufferReader};
use alloc::{string::ToString, sync::Arc};
use system_error::SystemError;

#[repr(C)]
#[derive(Clone, Copy)]
struct PosixCloneArgs {
    pub flags: u64,
    pub pidfd: u64,
    pub child_tid: u64,
    pub parent_tid: u64,
    pub exit_signal: u64,
    pub stack: u64,
    pub stack_size: u64,
    pub tls: u64,
    pub set_tid: u64,
    pub set_tid_size: u64,
    pub cgroup: u64,
}

impl PosixCloneArgs {
    const CLONE_ARGS_SIZE_VER0: usize = 64; /* sizeof first published struct */
    const CLONE_ARGS_SIZE_VER1: usize = 80; /* sizeof second published struct */
    const CLONE_ARGS_SIZE_VER2: usize = 88; /* sizeof third published struct */

    pub fn check_valid(&self, size: usize) -> Result<(), SystemError> {
        if self.set_tid_size > MAX_PID_NS_LEVEL as u64 {
            return Err(SystemError::EINVAL);
        }
        if self.set_tid == 0 && self.set_tid_size > 0 {
            return Err(SystemError::EINVAL);
        }
        if self.set_tid > 0 && self.set_tid_size == 0 {
            return Err(SystemError::EINVAL);
        }
        if self.exit_signal >= MAX_SIG_NUM as u64 {
            return Err(SystemError::EINVAL);
        }
        if self.flags & CloneFlags::CLONE_INTO_CGROUP.bits() != 0
            && (self.cgroup > i32::MAX as u64 || size < Self::CLONE_ARGS_SIZE_VER2)
        {
            return Err(SystemError::EINVAL);
        }
        Ok(())
    }
}

pub fn do_clone(
    mut clone_args: KernelCloneArgs,
    frame: &mut TrapFrame,
) -> Result<usize, SystemError> {
    clone_args.normalize_exit_signal();
    clone_args.verify()?;
    let flags = clone_args.flags;
    let parent_tid = clone_args.parent_tid;

    let vfork = Arc::new(Completion::new());

    if flags.contains(CloneFlags::CLONE_PIDFD)
        && flags.intersects(CloneFlags::CLONE_PARENT_SETTID | CloneFlags::CLONE_THREAD)
    {
        return Err(SystemError::EINVAL);
    }

    let current_pcb = ProcessManager::current_pcb();
    let new_kstack = KernelStack::new()?;
    let name = current_pcb.basic().name().to_string();

    let pcb = ProcessControlBlock::new(name, new_kstack);
    // 克隆pcb
    let ptrace_fork_session = ProcessManager::copy_process(&current_pcb, &pcb, clone_args, frame)?;

    let child_vpid = pcb
        .task_pid_nr_ns(PidType::PID, Some(current_pcb.active_pid_ns()))
        .expect("published fork child must be visible in the caller's PID namespace")
        .data();

    if flags.contains(CloneFlags::CLONE_PARENT_SETTID) {
        // 对齐 Linux：fork 已成功，不因 parent_tid 写回失败而撤销子任务。
        let child_tid = child_vpid as i32;
        let _ = unsafe { write_one_to_user_protected(parent_tid, &child_tid) };
    }

    // 新的 ProcFS 是动态的，进程目录会在访问时按需创建
    // 不再需要显式注册进程

    if flags.contains(CloneFlags::CLONE_VFORK) {
        pcb.thread.write_irqsave().vfork_done = Some(vfork.clone());
    }

    ProcessManager::wake_up_new_task(&pcb).unwrap_or_else(|e| {
        panic!(
            "fork: Failed to wakeup new process, pid: [{:?}]. Error: {:?}",
            pcb.raw_pid(),
            e
        )
    });
    // Report the ptrace event only after wake_up_new_task.
    ProcessManager::ptrace_report_fork_event(&current_pcb, &pcb, ptrace_fork_session.as_ref());

    if flags.contains(CloneFlags::CLONE_VFORK) {
        // Wait for the child to exit or exec
        // Only a fatal signal can interrupt this wait
        if vfork.wait_for_completion_killable().is_err() {
            // Clear the child's vfork_done: the waiter has given up, so the child
            // must not complete() on a discarded completion during exec/exit.
            pcb.thread.write_irqsave().vfork_done = None;
            return Ok(child_vpid);
        }
        let done_vpid = crate::process::ptrace::ptracer_of(&current_pcb)
            .and_then(|tracer| pcb.task_pid_nr_ns(PidType::PID, Some(tracer.active_pid_ns())))
            .map(|p| p.data())
            .unwrap_or(child_vpid);
        current_pcb.ptrace_event(crate::process::ptrace::PtraceEvent::VForkDone, done_vpid);
    }

    return Ok(child_vpid);
}

impl KernelCloneArgs {
    pub fn copy_clone_args_from_user(
        &mut self,
        uargs_ptr: usize,
        size: usize,
    ) -> Result<(), SystemError> {
        // 编译时检查
        use kdepends::memoffset::offset_of;
        const {
            assert!(
                offset_of!(PosixCloneArgs, tls) + core::mem::size_of::<u64>()
                    == PosixCloneArgs::CLONE_ARGS_SIZE_VER0
            )
        };
        const {
            assert!(
                offset_of!(PosixCloneArgs, set_tid_size) + core::mem::size_of::<u64>()
                    == PosixCloneArgs::CLONE_ARGS_SIZE_VER1
            )
        };
        const {
            assert!(
                offset_of!(PosixCloneArgs, cgroup) + core::mem::size_of::<u64>()
                    == PosixCloneArgs::CLONE_ARGS_SIZE_VER2
            )
        };
        const { assert!(core::mem::size_of::<PosixCloneArgs>() == PosixCloneArgs::CLONE_ARGS_SIZE_VER2) };

        if unlikely(size as u64 > MMArch::PAGE_SIZE as u64) {
            return Err(SystemError::E2BIG);
        }
        if unlikely(size < PosixCloneArgs::CLONE_ARGS_SIZE_VER0) {
            return Err(SystemError::EINVAL);
        }

        // 仅根据用户提供的size从用户态读取，避免越界读取
        let bufreader = UserBufferReader::new(uargs_ptr as *const u8, size, true)?;

        // 默认零初始化整个结构体，然后仅覆盖前size字节，保证未提供部分为0
        let mut args: PosixCloneArgs = unsafe { core::mem::MaybeUninit::zeroed().assume_init() };
        let copy_size = core::cmp::min(size, core::mem::size_of::<PosixCloneArgs>());
        let args_prefix = unsafe {
            core::slice::from_raw_parts_mut(
                (&mut args as *mut PosixCloneArgs) as *mut u8,
                copy_size,
            )
        };
        // 从用户空间拷贝size字节到结构体前缀
        bufreader.copy_from_user::<u8>(args_prefix, 0)?;

        args.check_valid(size)?;

        self.flags = CloneFlags::from_bits(args.flags).ok_or(SystemError::EINVAL)?;
        self.pidfd = VirtAddr::new(args.pidfd as usize);
        self.child_tid = VirtAddr::new(args.child_tid as usize);
        self.parent_tid = VirtAddr::new(args.parent_tid as usize);
        self.exit_signal = args.exit_signal as i32;
        self.stack = args.stack as usize;
        self.stack_size = args.stack_size as usize;
        self.tls = args.tls as usize;
        self.set_tid_size = args.set_tid_size as usize;
        self.cgroup = args.cgroup as i32;

        if self.set_tid_size > 0 {
            let bufreader = UserBufferReader::new(
                args.set_tid as *const core::ffi::c_int,
                core::mem::size_of::<core::ffi::c_int>() * self.set_tid_size,
                true,
            )?;
            for i in 0..self.set_tid_size {
                let byte_offset = i * core::mem::size_of::<core::ffi::c_int>();
                let tid = bufreader.read_one_from_user::<core::ffi::c_int>(byte_offset)?;
                self.set_tid.push(tid as usize);
            }
        }

        Ok(())
    }
}
