use crate::arch::interrupt::TrapFrame;
use crate::arch::syscall::nr::SYS_CLONE;
use crate::mm::{access_ok, VirtAddr};
use crate::process::fork::{CloneFlags, KernelCloneArgs};
use crate::process::syscall::clone_utils::do_clone;
use crate::syscall::table::{FormattedSyscallParam, Syscall};
use alloc::vec::Vec;
use system_error::SystemError;

pub struct SysClone;

impl SysClone {
    fn flags(args: &[usize]) -> CloneFlags {
        // Linux 语义：legacy clone() 仅使用低 32 位 flags。
        CloneFlags::from_bits_truncate((args[0] as u64) & 0xffff_ffff)
    }

    fn stack(args: &[usize]) -> usize {
        args[1]
    }
    fn parent_tid(args: &[usize]) -> VirtAddr {
        VirtAddr::new(args[2])
    }

    fn child_tid(args: &[usize]) -> VirtAddr {
        VirtAddr::new(args[3])
    }

    fn tls(args: &[usize]) -> usize {
        args[4]
    }
}

impl Syscall for SysClone {
    fn num_args(&self) -> usize {
        5
    }

    fn handle(&self, args: &[usize], frame: &mut TrapFrame) -> Result<usize, SystemError> {
        let flags = Self::flags(args);
        let parent_tid = Self::parent_tid(args);
        let child_tid = Self::child_tid(args);

        // legacy clone() 只有 pidfd 复用 parent_tid 作为“必须成功”的输出参数。
        // parent/child settid 按 Linux 语义属于 best-effort 写回，不应在入口提前失败。
        if flags.contains(CloneFlags::CLONE_PIDFD) {
            access_ok(parent_tid, core::mem::size_of::<i32>())?;
        }

        let stack = Self::stack(args);
        let tls = Self::tls(args);

        let mut clone_args = KernelCloneArgs::new();
        clone_args.flags = flags;
        clone_args.stack = stack;
        // legacy clone() 复用 parent_tid 作为 CLONE_PIDFD 的输出地址；
        // clone3() 则通过独立的 pidfd 字段传入。
        clone_args.pidfd = parent_tid;
        clone_args.parent_tid = parent_tid;
        clone_args.child_tid = child_tid;
        clone_args.tls = tls;

        // 旧版 clone() 系统调用中，flags 的低 8 位用于指定 exit_signal
        let exit_signal_num = (args[0] & 0xFF) as i32;
        clone_args.exit_signal = exit_signal_num;

        do_clone(clone_args, frame)
    }

    fn entry_format(&self, args: &[usize]) -> Vec<FormattedSyscallParam> {
        vec![
            FormattedSyscallParam::new(
                "parent_tid",
                format!("{:#x}", Self::parent_tid(args).data()),
            ),
            FormattedSyscallParam::new("child_tid", format!("{:#x}", Self::child_tid(args).data())),
            FormattedSyscallParam::new("flags", format!("{:#x}", Self::flags(args))),
            FormattedSyscallParam::new("stack", format!("{:#x}", Self::stack(args))),
            FormattedSyscallParam::new("tls", format!("{:#x}", Self::tls(args))),
        ]
    }
}

syscall_table_macros::declare_syscall!(SYS_CLONE, SysClone);
