use super::vfs::PollableInode;
use crate::arch::MMArch;
use crate::filesystem::epoll::event_poll::EPollItemList;
use crate::filesystem::vfs::file::FileFlags;
use crate::filesystem::vfs::{InodeMode, OpenFileBehavior, PostWriteSyncPolicy};
use crate::filesystem::{
    epoll::{event_poll::EventPoll, EPollEventType, EPollItem},
    vfs::{FilePrivateData, FileSystem, FileType, FsInfo, IndexNode, Magic, Metadata, SuperBlock},
};
use crate::libs::mutex::{Mutex, MutexGuard};
use crate::libs::wait_queue::WaitQueue;
use crate::mm::MemoryManagementArch;
use crate::process::ProcessManager;
use alloc::string::String;
use alloc::sync::Arc;
use alloc::vec::Vec;
use core::any::Any;
use ida::IdAllocator;
use system_error::SystemError;

const EVENTFD_MAX: u64 = u64::MAX - 1;

lazy_static::lazy_static! {
    static ref EVENTFD_FS: Arc<EventFdFs> = Arc::new(EventFdFs);
}

pub static EVENTFD_ID_ALLOCATOR: Mutex<IdAllocator> =
    Mutex::new(IdAllocator::new(0, u32::MAX as usize).unwrap());

/// EventFd 文件系统
///
/// EventFd 是一个伪文件系统，类似于 PipeFS，用于支持 eventfd 文件描述符
#[derive(Debug)]
pub struct EventFdFs;

impl EventFdFs {
    /// 获取全局 EventFdFs 实例
    pub fn instance() -> Arc<EventFdFs> {
        EVENTFD_FS.clone()
    }
}

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

    fn root_inode(&self) -> Arc<dyn IndexNode> {
        // EventFdFs 没有真正的根 inode，但我们需要实现这个方法
        // 返回一个空的 eventfd inode 作为占位符
        // 注意：这通常不会被调用，因为 eventfd 不是挂载的文件系统
        Arc::new(EventFdInode::new(EventFd::new(0, EventFdFlags::empty(), 0)))
    }

    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 {
        "eventfd"
    }

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

bitflags! {
    pub struct EventFdFlags: u32{
        /// Provide semaphore-like semantics for reads from the new
        /// file descriptor.
        const EFD_SEMAPHORE = 0o1;
        /// Set the close-on-exec (FD_CLOEXEC) flag on the new file
        /// descriptor
        const EFD_CLOEXEC = 0o2000000;
        /// Set the O_NONBLOCK file status flag on the open file
        /// description (see open(2)) referred to by the new file
        /// descriptor
        const EFD_NONBLOCK = 0o0004000;
    }
}

#[derive(Debug)]
pub struct EventFd {
    count: u64,
    flags: EventFdFlags,
    #[allow(unused)]
    id: u32,
}

impl EventFd {
    pub fn new(count: u64, flags: EventFdFlags, id: u32) -> Self {
        EventFd { count, flags, id }
    }
}

#[derive(Debug)]
pub struct EventFdInode {
    eventfd: Mutex<EventFd>,
    wait_queue: WaitQueue,
    epitems: EPollItemList,
}

impl EventFdInode {
    pub fn new(eventfd: EventFd) -> Self {
        EventFdInode {
            eventfd: Mutex::new(eventfd),
            wait_queue: WaitQueue::default(),
            epitems: EPollItemList::default(),
        }
    }
    fn readable(&self) -> bool {
        let count = self.eventfd.lock().count;
        return count > 0;
    }

    fn do_poll(
        &self,
        _private_data: &FilePrivateData,
        self_guard: &MutexGuard<'_, EventFd>,
    ) -> Result<usize, SystemError> {
        let mut events = EPollEventType::empty();
        if self_guard.count != 0 {
            events |= EPollEventType::EPOLLIN | EPollEventType::EPOLLRDNORM;
        }
        // Linux eventfd counter max is U64_MAX - 1. When count reaches that max,
        // any further write(8) would block (or EAGAIN for nonblock), so EPOLLOUT
        // must be cleared.
        if self_guard.count != EVENTFD_MAX {
            events |= EPollEventType::EPOLLOUT | EPollEventType::EPOLLWRNORM;
        }
        return Ok(events.bits() as usize);
    }
}

impl PollableInode for EventFdInode {
    fn poll(&self, _private_data: &FilePrivateData) -> Result<usize, SystemError> {
        let self_guard = self.eventfd.lock();
        self.do_poll(_private_data, &self_guard)
    }

    fn add_epitem(
        &self,
        epitem: Arc<EPollItem>,
        _private_data: &FilePrivateData,
    ) -> Result<(), SystemError> {
        self.epitems.add(epitem);
        Ok(())
    }

    fn remove_epitem(
        &self,
        epitem: &Arc<EPollItem>,
        _private_data: &FilePrivateData,
    ) -> Result<(), SystemError> {
        self.epitems.remove(epitem)
    }
}

impl IndexNode for EventFdInode {
    fn configure_open_file(&self, _data: &FilePrivateData, behavior: &mut OpenFileBehavior) {
        behavior.post_write_sync = PostWriteSyncPolicy::NotApplicable;
    }

    fn is_stream(&self) -> bool {
        // eventfd 属于典型的不可 seek 的伪文件描述符：
        // - lseek/pread/pwrite 应返回 ESPIPE（Linux 语义）
        true
    }

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

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

    /// # 从 counter 里读取一个 8 字节的int值
    ///
    /// 1. counter !=0
    ///     - EFD_SEMAPHORE 如果没有被设置，从 eventfd read，会得到 counter，并将它归0
    ///     - EFD_SEMAPHORE 如果被设置，从 eventfd read，会得到值 1，并将 counter - 1
    /// 2. counter == 0
    ///     - EFD_NONBLOCK 如果被设置，那么会以 EAGAIN 的错失败
    ///     - 否则 read 会被阻塞，直到为非0。
    fn read_at(
        &self,
        _offset: usize,
        len: usize,
        buf: &mut [u8],
        data_guard: MutexGuard<FilePrivateData>,
    ) -> Result<usize, SystemError> {
        let data = data_guard.clone();
        drop(data_guard);
        if len < 8 {
            return Err(SystemError::EINVAL);
        }
        let mut lock_efd = self.eventfd.lock();
        while lock_efd.count == 0 {
            if lock_efd.flags.contains(EventFdFlags::EFD_NONBLOCK) {
                drop(lock_efd);
                return Err(SystemError::EAGAIN_OR_EWOULDBLOCK);
            }

            drop(lock_efd);

            if ProcessManager::current_pcb().has_pending_signal_fast() {
                return Err(SystemError::ERESTARTSYS);
            }

            wq_wait_event_interruptible!(self.wait_queue, self.readable(), {})?;

            lock_efd = self.eventfd.lock();
        }
        let mut val = lock_efd.count;

        let mut eventfd = lock_efd;
        if eventfd.flags.contains(EventFdFlags::EFD_SEMAPHORE) {
            eventfd.count -= 1;
            val = 1;
        } else {
            eventfd.count = 0;
        }
        let val_bytes = val.to_ne_bytes();
        buf[..8].copy_from_slice(&val_bytes);
        let pollflag = EPollEventType::from_bits_truncate(self.do_poll(&data, &eventfd)? as u32);
        drop(eventfd);

        // 唤醒epoll中等待的进程
        EventPoll::wakeup_epoll(&self.epitems, pollflag)?;

        return Ok(8);
    }

    /// # 把一个 8 字节的int值写入到 counter 里
    ///
    /// - counter 最大值是 2^64 - 1
    /// - 如果写入时会发生溢出，则write会被阻塞
    ///     - 如果 EFD_NONBLOCK 被设置，那么以 EAGAIN 失败
    /// - 以不合法的值写入时，会以 EINVAL 失败
    ///     - 比如 0xffffffffffffffff 不合法
    ///     -  比如 写入的值 size 小于8字节
    fn write_at(
        &self,
        _offset: usize,
        len: usize,
        buf: &[u8],
        data: MutexGuard<FilePrivateData>,
    ) -> Result<usize, SystemError> {
        if len < 8 {
            return Err(SystemError::EINVAL);
        }
        let val = u64::from_ne_bytes(buf[..8].try_into().unwrap());
        if val == u64::MAX {
            return Err(SystemError::EINVAL);
        }
        let pollflag;
        loop {
            let mut eventfd = self.eventfd.lock();
            // Allow write when count + val <= EVENTFD_MAX.
            if EVENTFD_MAX.saturating_sub(eventfd.count) >= val {
                eventfd.count += val;
                pollflag =
                    EPollEventType::from_bits_truncate(self.do_poll(&data, &eventfd)? as u32);
                break;
            }
            if eventfd.flags.contains(EventFdFlags::EFD_NONBLOCK) {
                return Err(SystemError::EAGAIN_OR_EWOULDBLOCK);
            }
            drop(eventfd);
            if ProcessManager::current_pcb().has_pending_signal() {
                return Err(SystemError::ERESTARTSYS);
            }
            // 等待计数下降（被 read 消费）
            self.wait_queue.wait_event_interruptible(
                || {
                    let ev = self.eventfd.lock();
                    EVENTFD_MAX.saturating_sub(ev.count) >= val
                },
                None::<fn()>,
            )?;
        }
        self.wait_queue.wakeup_all(None);

        // 唤醒epoll中等待的进程
        EventPoll::wakeup_epoll(&self.epitems, pollflag)?;
        return Ok(8);
    }

    fn metadata(&self) -> Result<Metadata, SystemError> {
        let meta = Metadata {
            mode: InodeMode::from_bits_truncate(0o755),
            file_type: FileType::File,
            ..Default::default()
        };
        Ok(meta)
    }

    fn resize(&self, _len: usize) -> Result<(), SystemError> {
        Ok(())
    }

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

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

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

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

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