use alloc::collections::LinkedList;
use alloc::string::String;
use alloc::sync::{Arc, Weak};
use alloc::vec::Vec;
use core::any::Any;
use core::mem::size_of;

use bitflags::bitflags;

use crate::arch::ipc::signal::{SigSet, Signal};
use crate::arch::MMArch;
use crate::filesystem::epoll::event_poll::EventPoll;
use crate::filesystem::epoll::{EPollEventType, EPollItem};
use crate::filesystem::vfs::file::FileFlags;
use crate::filesystem::vfs::{
    vcore::generate_inode_id, FilePrivateData, FileSystem, FileType, FsInfo, IndexNode, InodeFlags,
    InodeMode, Magic, Metadata, PollableInode, SuperBlock,
};
use crate::ipc::sighand::SigHand;
use crate::libs::mutex::MutexGuard;
use crate::libs::spinlock::{SpinLock, SpinLockGuard};
use crate::mm::MemoryManagementArch;
use crate::process::ProcessManager;
use crate::syscall::user_access::UserBufferReader;
use system_error::SystemError;

lazy_static::lazy_static! {
    static ref SIGNALFD_FS: Arc<SignalFdFs> = Arc::new(SignalFdFs);
}

#[derive(Debug)]
pub struct SignalFdFs;

impl SignalFdFs {
    pub fn instance() -> Arc<Self> {
        SIGNALFD_FS.clone()
    }
}

impl FileSystem for SignalFdFs {
    fn page_cache_writeback_domain(
        &self,
    ) -> Option<&Arc<crate::filesystem::page_cache::PageCacheWritebackDomain>> {
        None
    }

    fn root_inode(&self) -> Arc<dyn IndexNode> {
        // signalfd 为伪文件系统（anon_inode 风格），root inode 不会被真正使用。
        Arc::new(SignalFdInode::new(SigSet::empty(), SignalFdFlags::empty()))
    }

    fn info(&self) -> FsInfo {
        FsInfo {
            blk_dev_id: 0,
            max_name_len: 255,
        }
    }

    fn as_any_ref(&self) -> &dyn Any {
        self
    }

    fn name(&self) -> &str {
        "signalfd"
    }

    fn super_block(&self) -> SuperBlock {
        SuperBlock::new(
            Magic::EVENTFD_MAGIC,
            <MMArch as MemoryManagementArch>::PAGE_SIZE as u64,
            255,
        )
    }
}

bitflags! {
    pub struct SignalFdFlags: u32 {
        const SFD_NONBLOCK = 0o0004000;
        const SFD_CLOEXEC  = 0o02000000;
    }
}

/// Linux signalfd_siginfo 为 128 字节。
/// gVisor 测试仅检查 read 返回值为 sizeof(signalfd_siginfo)。
#[repr(C)]
#[derive(Clone, Copy)]
struct SignalFdSigInfo {
    bytes: [u8; 128],
}

impl SignalFdSigInfo {
    fn from_signal(sig: Signal) -> Self {
        let mut bytes = [0u8; 128];
        // ssi_signo (u32)
        bytes[0..4].copy_from_slice(&(sig as u32).to_ne_bytes());
        Self { bytes }
    }
}

#[derive(Debug)]
struct SignalFdState {
    mask: SigSet,
    flags: SignalFdFlags,
    metadata: Metadata,
}

#[derive(Debug)]
pub struct SignalFdInode {
    state: SpinLock<SignalFdState>,
    epitems: SpinLock<LinkedList<SignalFdEPollRegistration>>,
}

#[derive(Debug)]
struct SignalFdEPollRegistration {
    epitem: Arc<EPollItem>,
    sighand: Weak<SigHand>,
}

impl SignalFdInode {
    pub fn new(mask: SigSet, flags: SignalFdFlags) -> Self {
        let metadata = Metadata {
            dev_id: 0,
            inode_id: generate_inode_id(),
            size: 0,
            blk_size: 0,
            blocks: 0,
            atime: crate::time::PosixTimeSpec::default(),
            mtime: crate::time::PosixTimeSpec::default(),
            ctime: crate::time::PosixTimeSpec::default(),
            btime: crate::time::PosixTimeSpec::default(),
            file_type: FileType::CharDevice,
            mode: InodeMode::from_bits_truncate(0o600),
            nlinks: 1,
            uid: 0,
            gid: 0,
            raw_dev: Default::default(),
            flags: InodeFlags::empty(),
        };
        Self {
            state: SpinLock::new(SignalFdState {
                mask,
                flags,
                metadata,
            }),
            epitems: SpinLock::new(LinkedList::new()),
        }
    }

    fn has_pending_for_mask(&self, mask: &SigSet) -> bool {
        let pcb = ProcessManager::current_pcb();
        let siginfo = pcb.sig_info_irqsave();
        let mut pending = siginfo.sig_pending().signal();
        drop(siginfo);
        pending |= pcb.sighand().shared_pending_signal();
        !(pending & *mask).is_empty()
    }

    fn readable(&self) -> bool {
        let mask = self.state.lock_irqsave().mask;
        self.has_pending_for_mask(&mask)
    }

    fn dequeue_one(&self) -> Option<Signal> {
        let pcb = ProcessManager::current_pcb();
        let mask = self.state.lock_irqsave().mask;
        let ignore_mask = mask.complement();
        let (sig, _info) = pcb.dequeue_pending_signal(&ignore_mask);
        if sig == Signal::INVALID {
            None
        } else {
            Some(sig)
        }
    }

    fn nonblock(&self, state_guard: &SpinLockGuard<'_, SignalFdState>) -> bool {
        state_guard.flags.contains(SignalFdFlags::SFD_NONBLOCK)
    }

    pub(super) fn set_mask_and_flags(&self, mask: SigSet, flags: SignalFdFlags) {
        let mut guard = self.state.lock_irqsave();
        guard.mask = mask;
        guard.flags = flags;
    }
}

impl PollableInode for SignalFdInode {
    fn poll(&self, _private_data: &FilePrivateData) -> Result<usize, SystemError> {
        let mask = self.state.lock_irqsave().mask;
        if self.has_pending_for_mask(&mask) {
            Ok((EPollEventType::EPOLLIN | EPollEventType::EPOLLRDNORM).bits() as usize)
        } else {
            Ok(0)
        }
    }

    fn add_epitem(
        &self,
        epitem: Arc<EPollItem>,
        _private_data: &FilePrivateData,
    ) -> Result<(), SystemError> {
        let sighand = ProcessManager::current_pcb().sighand();
        self.epitems
            .lock_irqsave()
            .push_back(SignalFdEPollRegistration {
                epitem: epitem.clone(),
                sighand: Arc::downgrade(&sighand),
            });
        sighand.signalfd_epitems().add(epitem);
        Ok(())
    }

    fn remove_epitem(
        &self,
        epitem: &Arc<EPollItem>,
        _private_data: &FilePrivateData,
    ) -> Result<(), SystemError> {
        let owner = {
            let mut registrations = self.epitems.lock_irqsave();
            let mut owner = None;
            registrations.retain(|registration| {
                if Arc::ptr_eq(&registration.epitem, epitem) {
                    owner = Some(registration.sighand.clone());
                    false
                } else {
                    true
                }
            });
            owner
        };
        let Some(owner) = owner else {
            return Err(SystemError::ENOENT);
        };
        if let Some(sighand) = owner.upgrade() {
            let _ = sighand.signalfd_epitems().remove(epitem);
        }
        Ok(())
    }
}

impl IndexNode for SignalFdInode {
    fn is_stream(&self) -> bool {
        true
    }

    fn open(
        &self,
        _data: MutexGuard<FilePrivateData>,
        _flags: &FileFlags,
    ) -> Result<(), SystemError> {
        Ok(())
    }

    fn close(&self, _data: MutexGuard<FilePrivateData>) -> Result<(), SystemError> {
        Ok(())
    }

    fn read_at(
        &self,
        _offset: usize,
        len: usize,
        buf: &mut [u8],
        data_guard: MutexGuard<FilePrivateData>,
    ) -> Result<usize, SystemError> {
        // 释放 FilePrivateData 锁，避免在阻塞时持有锁导致 panic
        drop(data_guard);

        if len < size_of::<SignalFdSigInfo>() {
            return Err(SystemError::EINVAL);
        }

        loop {
            if let Some(sig) = self.dequeue_one() {
                let info = SignalFdSigInfo::from_signal(sig);
                buf[0..size_of::<SignalFdSigInfo>()].copy_from_slice(&info.bytes);
                return Ok(size_of::<SignalFdSigInfo>());
            }

            let state_guard = self.state.lock_irqsave();
            if self.nonblock(&state_guard) {
                return Err(SystemError::EAGAIN_OR_EWOULDBLOCK);
            }
            drop(state_guard);

            // 阻塞等待：在 sighand 的共享 signalfd_wqh 上睡眠。
            // 信号投递路径（含 hardirq）通过 signalfd_wqh.wakeup_all() 唤醒。
            let pcb = ProcessManager::current_pcb();
            let sighand = pcb.sighand();
            let r = wq_wait_event_interruptible!(sighand.signalfd_wqh(), self.readable(), {});
            if r.is_err() {
                return Err(SystemError::ERESTARTSYS);
            }
        }
    }

    fn write_at(
        &self,
        _offset: usize,
        _len: usize,
        _buf: &[u8],
        _data: MutexGuard<FilePrivateData>,
    ) -> Result<usize, SystemError> {
        Err(SystemError::EINVAL)
    }

    fn fs(&self) -> Arc<dyn FileSystem> {
        SignalFdFs::instance()
    }

    fn as_any_ref(&self) -> &dyn Any {
        self
    }

    fn list(&self) -> Result<Vec<String>, SystemError> {
        Err(SystemError::EINVAL)
    }

    fn metadata(&self) -> Result<Metadata, SystemError> {
        Ok(self.state.lock_irqsave().metadata.clone())
    }

    fn as_pollable_inode(&self) -> Result<&dyn PollableInode, SystemError> {
        Ok(self)
    }

    fn absolute_path(&self) -> Result<String, SystemError> {
        Ok(String::from("signalfd"))
    }
}

pub(super) fn read_user_sigset(mask_ptr: usize, mask_size: usize) -> Result<SigSet, SystemError> {
    // Linux 内核 ABI 中，rt_sig* / signalfd* 的 sigsetsize 通常为 8（64-bit）。
    // 但用户态 libc 可能传入更大的 sigset_t（例如 1024-bit / 128 bytes）。
    // 我们当前只支持 64 个信号，因此只读取前 8 字节。
    if mask_size < size_of::<u64>() {
        return Err(SystemError::EINVAL);
    }
    let reader = UserBufferReader::new(mask_ptr as *const u64, size_of::<u64>(), true)?;
    let bits = reader.read_one_from_user::<u64>(0)?;
    Ok(SigSet::from_bits_truncate(bits))
}

/// 在向 pcb 投递信号后，唤醒该 pcb 中所有 signalfd 等待者。
///
/// 此函数可能在 hardirq 上下文中调用（例如 timer IRQ → ITIMER_PROF → SIGPROF），
/// 因此通知路径必须完全 hardirq-safe。
///
/// 1. **共享等待队列唤醒**：通过 `sighand.signalfd_wqh().wakeup_all()`
///    唤醒所有阻塞在 signalfd `read()` 的线程。`WaitQueue` 内部使用
///    `SpinLock` + `lock_irqsave`，hardirq 安全。
///
/// 2. **epoll 通知**：通过 `sighand.signalfd_epitems()` 直接调用 `wakeup_epoll`，
///    无需遍历 fd_table。`signalfd_epitems` 使用 irqsave SpinLock，hardirq 安全。
///    signalfd 的 `add_epitem` 在将 epitem 注册到自身 epitems 的同时，
///    也会注册到 sighand 的 signalfd_epitems 中。
pub fn notify_signalfd_for_pcb(pcb: &Arc<crate::process::ProcessControlBlock>, _sig: Signal) {
    let sighand = pcb.sighand();

    // 唤醒 signalfd read() 阻塞线程：hardirq-safe
    sighand.signalfd_wqh().wakeup_all(None);

    // epoll 通知：直接通过 sighand 的 signalfd_epitems 调用 wakeup_epoll，
    // 完全 hardirq-safe（仅获取 irqsave SpinLock），无需遍历 fd_table。
    let _ = EventPoll::wakeup_epoll(
        sighand.signalfd_epitems(),
        EPollEventType::EPOLLIN | EPollEventType::EPOLLRDNORM,
    );
}
