use alloc::boxed::Box;
use alloc::vec;

use system_error::SystemError;

use crate::exception::workqueue::{schedule_work, Work};
use crate::net::socket::inet::InetSocket;
use crate::net::socket::PMSG;
use crate::syscall::user_buffer::UserBuffer;
use crate::time::timer::{next_n_us_timer_jiffies, Timer, TimerFunction};

use alloc::sync::Weak;

use super::constants;
use super::inner;
use super::TcpSocket;

const USER_RECV_STAGING_SIZE: usize = 64 * 1024;

#[inline]
fn discard_recv_queue(socket: &mut smoltcp::socket::tcp::Socket) {
    while socket.can_recv() {
        match socket.recv(|data| (data.len(), data.len())) {
            Ok(0) => break,
            Ok(_) => {}
            Err(_) => break,
        }
    }
}

impl TcpSocket {
    fn maybe_schedule_cork_timeout(&self) {
        if !self
            .options
            .tcp_cork
            .load(core::sync::atomic::Ordering::Relaxed)
        {
            return;
        }

        if self.cork_buf.lock().is_empty() {
            return;
        }

        if self
            .cork_timer_active
            .compare_exchange(
                false,
                true,
                core::sync::atomic::Ordering::AcqRel,
                core::sync::atomic::Ordering::Relaxed,
            )
            .is_err()
        {
            return;
        }

        let timer = Timer::new(
            Box::new(CorkFlushTimer {
                socket: self.self_ref.clone(),
            }),
            next_n_us_timer_jiffies(constants::TCP_CORK_FLUSH_TIMEOUT_US),
        );
        timer.activate();
    }

    fn handle_cork_timeout(&self) {
        self.cork_timer_active
            .store(false, core::sync::atomic::Ordering::Release);

        if self.cork_buf.lock().is_empty() {
            return;
        }

        if let Err(e) = self.flush_cork_buffer() {
            if e == SystemError::EAGAIN_OR_EWOULDBLOCK {
                self.maybe_schedule_cork_timeout();
            }
        }
    }

    fn maybe_complete_shutdown_wr_fin(&self) {
        if !self.is_send_shutdown() {
            return;
        }
        if !self
            .send_fin_deferred
            .swap(false, core::sync::atomic::Ordering::Relaxed)
        {
            return;
        }

        let mut writer = self.inner.write();
        let inner = match writer.take() {
            Some(inner) => inner,
            None => return,
        };
        match inner {
            inner::Inner::Established(established) => {
                established.with_mut(|socket| socket.close());
                writer.replace(inner::Inner::Established(established));
            }
            other => {
                writer.replace(other);
            }
        }
    }

    fn recv_established(
        &self,
        socket: &mut smoltcp::socket::tcp::Socket,
        buf: &mut [u8],
        flags: PMSG,
    ) -> Result<usize, SystemError> {
        let mut current_buf = buf;
        let is_recv_shutdown = self.is_recv_shutdown();
        if is_recv_shutdown {
            let remaining = self.recv_shutdown.remaining_limit();
            if remaining == 0 {
                discard_recv_queue(socket);
                return Ok(0);
            }
            let cap = core::cmp::min(current_buf.len(), remaining);
            current_buf = &mut current_buf[..cap];
        }

        if !socket.can_recv() {
            if !socket.may_recv() {
                return match socket.recv(|_data| (0usize, ())) {
                    Ok(()) => Ok(0),
                    Err(smoltcp::socket::tcp::RecvError::Finished) => Ok(0),
                    Err(smoltcp::socket::tcp::RecvError::InvalidState) => {
                        Err(SystemError::ECONNRESET)
                    }
                };
            }
            return Err(SystemError::EAGAIN_OR_EWOULDBLOCK);
        }

        // gVisor tcp_socket.cc MsgTrunc* tests: for TCP stream, MSG_TRUNC means
        // "report the length but don't copy payload into userspace".
        // - Without MSG_PEEK: also consume (discard) the bytes.
        // - With MSG_PEEK: do not consume.
        if flags.contains(PMSG::TRUNC) {
            if flags.contains(PMSG::PEEK) {
                let queued = socket.recv_queue();
                return Ok(core::cmp::min(current_buf.len(), queued));
            }

            let mut total = 0usize;
            while total < current_buf.len() {
                if !socket.can_recv() {
                    break;
                }

                let want = current_buf.len() - total;
                let got = match socket.recv(|data| {
                    let take = core::cmp::min(want, data.len());
                    // Discard without copying.
                    (take, take)
                }) {
                    Ok(n) => n,
                    Err(smoltcp::socket::tcp::RecvError::InvalidState) => {
                        return Err(SystemError::ENOTCONN);
                    }
                    Err(smoltcp::socket::tcp::RecvError::Finished) => {
                        return Ok(total);
                    }
                };

                if got == 0 {
                    break;
                }
                total += got;
            }

            if total == 0 {
                return Err(SystemError::EAGAIN_OR_EWOULDBLOCK);
            }
            if is_recv_shutdown && self.recv_shutdown.record_read(total) {
                discard_recv_queue(socket);
            }
            return Ok(total);
        }

        if flags.contains(PMSG::PEEK) {
            return match socket.peek_slice(current_buf) {
                Ok(size) => Ok(size),
                Err(smoltcp::socket::tcp::RecvError::InvalidState) => Err(SystemError::ECONNRESET),
                Err(smoltcp::socket::tcp::RecvError::Finished) => Ok(0),
            };
        }

        // smoltcp::tcp::Socket::recv_slice() 只会出队一段“连续”的 rx buffer。
        // 对于环形缓冲区发生 wrap 的情况，即使队列里有更多数据也可能只读到一部分。
        // Linux 的 stream socket 行为：一次 recv 尽量返回当前已到达的所有数据(直到用户缓冲区满)。
        let mut total = 0usize;
        while total < current_buf.len() {
            if !socket.can_recv() {
                break;
            }

            let want = current_buf.len() - total;
            let got = match socket.recv(|data| {
                let take = core::cmp::min(want, data.len());
                if take > 0 {
                    current_buf[total..total + take].copy_from_slice(&data[..take]);
                }
                (take, take)
            }) {
                Ok(n) => n,
                Err(smoltcp::socket::tcp::RecvError::InvalidState) => {
                    return Err(SystemError::ENOTCONN);
                }
                Err(smoltcp::socket::tcp::RecvError::Finished) => {
                    // FIN 已到达。
                    // 如果这次已读到部分数据，先把数据返回；否则返回 0 表示 EOF。
                    return Ok(total);
                }
            };

            if got == 0 {
                break;
            }
            total += got;
        }

        if total == 0 {
            return Err(SystemError::EAGAIN_OR_EWOULDBLOCK);
        }
        if is_recv_shutdown && self.recv_shutdown.record_read(total) {
            discard_recv_queue(socket);
        }
        Ok(total)
    }

    fn recv_established_to_user(
        &self,
        established: &inner::Established,
        user_buffer: &mut UserBuffer<'_>,
        offset: usize,
    ) -> Result<usize, SystemError> {
        if offset > user_buffer.len() {
            return Err(SystemError::EINVAL);
        }

        let mut user_remaining = user_buffer.len() - offset;
        let is_recv_shutdown = self.is_recv_shutdown();
        if is_recv_shutdown {
            let remaining = self.recv_shutdown.remaining_limit();
            if remaining == 0 {
                established.with_mut(discard_recv_queue);
                return Ok(0);
            }
            user_remaining = core::cmp::min(user_remaining, remaining);
        }

        if user_remaining == 0 {
            return Ok(0);
        }

        // Avoid allocating the staging buffer for the common nonblocking EAGAIN path.
        let readable = established.with_mut(|socket| {
            if socket.can_recv() {
                return Ok(true);
            }
            if socket.may_recv() {
                return Err(SystemError::EAGAIN_OR_EWOULDBLOCK);
            }
            match socket.recv(|_data| (0usize, ())) {
                Ok(()) | Err(smoltcp::socket::tcp::RecvError::Finished) => Ok(false),
                Err(smoltcp::socket::tcp::RecvError::InvalidState) => Err(SystemError::ECONNRESET),
            }
        })?;
        if !readable {
            return Ok(0);
        }

        // User pages may fault and sleep. Copy through a bounded kernel buffer so the
        // interface-wide SocketSet lock is never held while touching userspace.
        let mut staging = vec![0u8; core::cmp::min(user_remaining, USER_RECV_STAGING_SIZE)];

        let mut total = 0usize;
        while total < user_remaining {
            let want = user_remaining - total;
            let staged = established.with_mut(|socket| {
                if !socket.can_recv() {
                    return 0;
                }
                match socket.peek(core::cmp::min(want, staging.len())) {
                    Ok(data) => {
                        let size = data.len();
                        staging[..size].copy_from_slice(data);
                        size
                    }
                    Err(_) => 0,
                }
            });
            if staged == 0 {
                break;
            }

            if let Err(error) = user_buffer.write_to_user(offset + total, &staging[..staged]) {
                if error == SystemError::EFAULT && total > 0 {
                    break;
                }
                return Err(error);
            }

            // Ingress can append bytes while the SocketSet lock is dropped; a terminal state
            // transition can instead clear the queue. recv_lock excludes local consumers, so the
            // head cannot otherwise move. Require the snapshotted contiguous length before
            // consuming; if the queue was cleared, the copied bytes linearize immediately before
            // that terminal transition.
            let committed = established.with_mut(|socket| {
                socket
                    .recv(|data| {
                        if data.len() >= staged {
                            (staged, true)
                        } else {
                            (0, false)
                        }
                    })
                    .unwrap_or_default()
            });

            total += staged;
            if !committed {
                break;
            }
        }

        if total == 0 {
            // The stack may have processed FIN/RST after the allocation-time readiness probe.
            // Re-evaluate the terminal state instead of turning EOF into a spurious EAGAIN.
            return established.with_mut(|socket| {
                if socket.can_recv() || socket.may_recv() {
                    return Err(SystemError::EAGAIN_OR_EWOULDBLOCK);
                }
                match socket.recv(|_data| (0usize, ())) {
                    Ok(()) | Err(smoltcp::socket::tcp::RecvError::Finished) => Ok(0),
                    Err(smoltcp::socket::tcp::RecvError::InvalidState) => {
                        Err(SystemError::ECONNRESET)
                    }
                }
            });
        }
        if is_recv_shutdown && self.recv_shutdown.record_read(total) {
            established.with_mut(discard_recv_queue);
        }
        Ok(total)
    }

    fn finish_recv_progress(&self, consumed: bool) {
        if consumed {
            self.notify();
        }

        if let Some(iface) = self.stack_poll_iface_snapshot() {
            // After a successful TCP recv() we may have just freed a significant portion of the
            // receive window. On loopback/blocking-large-send paths, sender progress depends on
            // promptly turning that freed window into ACK/window-update processing and sender-side
            // wakeups. A single poll is not always enough to complete the roundtrip, so mirror the
            // send path and drive the stack until quiescent.
            if let Some(netns) = iface.common().net_namespace() {
                netns.wakeup_poll_thread();
            }
            super::poll_util::poll_iface_until_quiescent(iface.as_ref());
        }
    }

    pub(super) fn try_recv_with_flags(
        &self,
        buf: &mut [u8],
        flags: PMSG,
    ) -> Result<usize, SystemError> {
        let recv_guard = self.recv_lock.lock();
        let mut total_read = 0;

        loop {
            // SelfConnected does not rely on protocol-stack progress; avoid calling iface.poll()
            // here to prevent hangs when running the whole syscall test suite.
            if let Some(iface) = self.stack_poll_iface_snapshot() {
                if let Some(netns) = iface.common().net_namespace() {
                    netns.wakeup_poll_thread();
                }
                super::poll_util::poll_iface_until_quiescent(iface.as_ref());
            }

            let iter_result = match self
                .inner
                .read()
                .as_ref()
                .expect("Tcp inner::Inner is None")
            {
                inner::Inner::Established(established) => established.with_mut(|socket| {
                    self.recv_established(socket, &mut buf[total_read..], flags)
                }),
                inner::Inner::SelfConnected(sc) => {
                    // Self-connect: data path is a local queue.
                    let mut current_buf = &mut buf[total_read..];
                    let mut recv_exhausted = false;
                    if self.is_recv_shutdown() {
                        let remaining = self.recv_shutdown.remaining_limit();
                        if remaining == 0 {
                            sc.discard_all();
                            recv_exhausted = true;
                        } else {
                            let cap = core::cmp::min(current_buf.len(), remaining);
                            current_buf = &mut current_buf[..cap];
                        }
                    }

                    if recv_exhausted {
                        Ok(0)
                    } else {
                        let peek = flags.contains(PMSG::PEEK);
                        let trunc = flags.contains(PMSG::TRUNC);
                        match sc.recv_into(current_buf, peek, trunc) {
                            Ok(n) => {
                                if self.is_recv_shutdown()
                                    && !peek
                                    && self.recv_shutdown.record_read(n)
                                {
                                    sc.discard_all();
                                }
                                Ok(n)
                            }
                            Err(error) => Err(error),
                        }
                    }
                }
                inner::Inner::Connecting(connecting) => {
                    if let Some(err) = connecting.failure_reason() {
                        connecting.consume_error();
                        return Err(err);
                    }
                    if connecting.is_refused_consumed() {
                        return Ok(0);
                    }
                    Err(SystemError::EAGAIN_OR_EWOULDBLOCK)
                }
                inner::Inner::Init(_) | inner::Inner::Closed(_) => Err(SystemError::ENOTCONN),
                _ => Err(SystemError::EINVAL),
            };

            match iter_result {
                Ok(n) => {
                    // For PEEK, we don't loop/accumulate because we are not consuming.
                    // Also for TRUNC+PEEK.
                    if flags.contains(PMSG::PEEK) {
                        return Ok(n);
                    }

                    total_read += n;

                    if n == 0 {
                        // EOF
                        break;
                    }

                    if total_read == buf.len() {
                        // Buffer full
                        break;
                    }

                    // We read some data, but buffer not full.
                    // Loop again to poll and see if more data arrived in NIC queue.
                }
                Err(SystemError::EAGAIN_OR_EWOULDBLOCK) => {
                    if total_read > 0 {
                        break;
                    }
                    return Err(SystemError::EAGAIN_OR_EWOULDBLOCK);
                }
                Err(e) => return Err(e),
            }
        }

        // For self-connect, consuming bytes frees space for senders waiting on EPOLLOUT.
        // Wake waiters and refresh pollee after we actually consumed data.
        drop(recv_guard);
        self.finish_recv_progress(total_read > 0 && !flags.contains(PMSG::PEEK));

        Ok(total_read)
    }

    fn try_recv_to_user_buffer(
        &self,
        user_buffer: &mut UserBuffer<'_>,
        offset: usize,
    ) -> Result<usize, SystemError> {
        let recv_guard = self.recv_lock.lock();
        let mut total_read = offset;

        loop {
            if let Some(iface) = self.stack_poll_iface_snapshot() {
                if let Some(netns) = iface.common().net_namespace() {
                    netns.wakeup_poll_thread();
                }
                super::poll_util::poll_iface_until_quiescent(iface.as_ref());
            }

            let iter_result = match self
                .inner
                .read()
                .as_ref()
                .expect("Tcp inner::Inner is None")
            {
                inner::Inner::Established(established) => {
                    self.recv_established_to_user(established, user_buffer, total_read)
                }
                inner::Inner::SelfConnected(sc) => {
                    let mut limit = user_buffer.len().saturating_sub(total_read);
                    let mut recv_exhausted = false;
                    if self.is_recv_shutdown() {
                        let remaining = self.recv_shutdown.remaining_limit();
                        if remaining == 0 {
                            sc.discard_all();
                            recv_exhausted = true;
                        } else {
                            limit = core::cmp::min(limit, remaining);
                        }
                    }

                    if recv_exhausted {
                        Ok(0)
                    } else {
                        match sc.recv_to_user(user_buffer, total_read, limit) {
                            Ok(n) => {
                                if self.is_recv_shutdown() && self.recv_shutdown.record_read(n) {
                                    sc.discard_all();
                                }
                                Ok(n)
                            }
                            Err(error) => Err(error),
                        }
                    }
                }
                inner::Inner::Connecting(connecting) => {
                    if let Some(err) = connecting.failure_reason() {
                        connecting.consume_error();
                        return Err(err);
                    }
                    if connecting.is_refused_consumed() {
                        return Ok(0);
                    }
                    Err(SystemError::EAGAIN_OR_EWOULDBLOCK)
                }
                inner::Inner::Init(_) | inner::Inner::Closed(_) => Err(SystemError::ENOTCONN),
                _ => Err(SystemError::EINVAL),
            };

            match iter_result {
                Ok(n) => {
                    total_read += n;

                    if n == 0 || total_read == user_buffer.len() {
                        break;
                    }
                }
                Err(e) => {
                    if total_read > offset {
                        break;
                    }
                    return Err(e);
                }
            }
        }

        drop(recv_guard);
        self.finish_recv_progress(total_read > offset);
        Ok(total_read - offset)
    }

    pub(super) fn try_read_to_user_buffer(
        &self,
        user_buffer: &mut UserBuffer<'_>,
    ) -> Result<usize, SystemError> {
        self.try_recv_to_user_buffer(user_buffer, 0)
    }

    pub(super) fn recv_to_user_buffer_impl(
        &self,
        user_buffer: &mut UserBuffer<'_>,
        nonblock: bool,
        waitall: bool,
    ) -> Result<usize, SystemError> {
        if self.is_recv_shutdown() {
            let limit = self.recv_shutdown.limit();
            if limit == 0 {
                return Ok(0);
            }
        }

        if nonblock {
            return self.try_read_to_user_buffer(user_buffer);
        }

        let mut total_read = 0usize;
        loop {
            match self.try_recv_to_user_buffer(user_buffer, total_read) {
                Ok(n) => {
                    total_read += n;
                    if n == 0 || total_read == user_buffer.len() || !waitall {
                        return Ok(total_read);
                    }
                }
                Err(SystemError::EAGAIN_OR_EWOULDBLOCK) => {
                    if let Some(iface) = self.stack_poll_iface_snapshot() {
                        super::poll_util::poll_iface_until_quiescent(iface.as_ref());
                    }
                    let events = self.check_io_event();
                    if events.intersects(
                        crate::filesystem::epoll::EPollEventType::EPOLLIN
                            | crate::filesystem::epoll::EPollEventType::EPOLLHUP
                            | crate::filesystem::epoll::EPollEventType::EPOLLRDHUP
                            | crate::filesystem::epoll::EPollEventType::EPOLLERR,
                    ) {
                        continue;
                    }

                    let wait_ret = self.wait_queue.wait_event_io_interruptible_timeout(
                        || {
                            self.check_io_event().intersects(
                                crate::filesystem::epoll::EPollEventType::EPOLLIN
                                    | crate::filesystem::epoll::EPollEventType::EPOLLHUP
                                    | crate::filesystem::epoll::EPollEventType::EPOLLRDHUP
                                    | crate::filesystem::epoll::EPollEventType::EPOLLERR,
                            )
                        },
                        self.recv_timeout(),
                    );
                    if let Err(error) = wait_ret {
                        if total_read > 0 {
                            return Ok(total_read);
                        }
                        return Err(error);
                    }
                }
                Err(error) => {
                    if total_read > 0 {
                        return Ok(total_read);
                    }
                    return Err(error);
                }
            }
        }
    }

    pub(super) fn read_to_user_buffer_impl(
        &self,
        user_buffer: &mut UserBuffer<'_>,
    ) -> Result<usize, SystemError> {
        self.recv_to_user_buffer_impl(user_buffer, self.is_nonblock(), false)
    }

    pub fn try_send(&self, buf: &[u8]) -> Result<usize, SystemError> {
        if buf.is_empty() {
            // Linux 语义：对 SOCK_STREAM，写入 0 字节应当立刻成功返回 0，且不阻塞。
            return Ok(0);
        }
        if self.is_send_shutdown() {
            return Err(SystemError::EPIPE);
        }

        // If there are pending cork-buffered bytes (e.g., uncork flush hit EAGAIN),
        // keep ordering by enqueueing new bytes behind them, and opportunistically flush.
        {
            let mut cork_buf = self.cork_buf.lock();
            if !cork_buf.is_empty() {
                let cap = self
                    .send_buf_size()
                    .load(core::sync::atomic::Ordering::Relaxed);
                let free = cap.saturating_sub(cork_buf.len());
                if free == 0 {
                    return Err(SystemError::EAGAIN_OR_EWOULDBLOCK);
                }
                let n = core::cmp::min(free, buf.len());
                cork_buf.extend_from_slice(&buf[..n]);
                drop(cork_buf);

                if !self
                    .options
                    .tcp_cork
                    .load(core::sync::atomic::Ordering::Relaxed)
                {
                    if let Err(e) = self.flush_cork_buffer() {
                        if e != SystemError::EAGAIN_OR_EWOULDBLOCK {
                            return Err(e);
                        }
                        self.maybe_schedule_cork_timeout();
                    }
                } else {
                    self.maybe_schedule_cork_timeout();
                }
                return Ok(n);
            }
        }

        if self
            .options
            .tcp_cork
            .load(core::sync::atomic::Ordering::Relaxed)
        {
            let mss = self
                .tcp_max_seg()
                .load(core::sync::atomic::Ordering::Relaxed);
            let cap = self
                .send_buf_size()
                .load(core::sync::atomic::Ordering::Relaxed);
            let mut cork_buf = self.cork_buf.lock();
            let free = cap.saturating_sub(cork_buf.len());
            if free == 0 {
                return Err(SystemError::EAGAIN_OR_EWOULDBLOCK);
            }
            let n = core::cmp::min(free, buf.len());
            cork_buf.extend_from_slice(&buf[..n]);
            if cork_buf.len() >= mss {
                drop(cork_buf);
                if let Err(e) = self.flush_cork_buffer() {
                    if e != SystemError::EAGAIN_OR_EWOULDBLOCK {
                        return Err(e);
                    }
                    self.maybe_schedule_cork_timeout();
                }
            } else {
                drop(cork_buf);
                self.maybe_schedule_cork_timeout();
            }
            return Ok(n);
        }
        self.try_send_direct(buf)
    }

    pub(crate) fn flush_cork_buffer(&self) -> Result<(), SystemError> {
        if self
            .cork_flush_in_progress
            .compare_exchange(
                false,
                true,
                core::sync::atomic::Ordering::Acquire,
                core::sync::atomic::Ordering::Relaxed,
            )
            .is_err()
        {
            return Ok(());
        }
        let _guard = CorkFlushGuard(self);

        loop {
            let cork_buf = self.cork_buf.lock();
            if cork_buf.is_empty() {
                self.maybe_complete_shutdown_wr_fin();
                return Ok(());
            }
            let data = cork_buf.clone();
            drop(cork_buf);

            let to_send = data.len();
            let sent = self.try_send_direct(data.as_slice())?;

            if sent == 0 {
                return Err(SystemError::EAGAIN_OR_EWOULDBLOCK);
            }

            let mut cork_buf = self.cork_buf.lock();
            cork_buf.drain(..core::cmp::min(sent, to_send));
        }
    }

    fn try_send_direct(&self, buf: &[u8]) -> Result<usize, SystemError> {
        // Self-connect fast path: avoid smoltcp and iface polling.
        let self_connected_result = {
            let inner_guard = self.inner.read();
            if let Some(inner::Inner::SelfConnected(sc)) = inner_guard.as_ref() {
                Some(sc.send_slice(buf, self.is_send_shutdown()))
            } else {
                None
            }
        };
        if let Some(result) = self_connected_result {
            let n = result?;
            // Wake reader (same fd in another thread) and refresh events. `inner_guard`
            // must be gone because notify() refreshes events by reading `inner` again.
            self.notify();
            return Ok(n);
        }
        // TODO: add nonblock check of connecting socket
        //
        // IMPORTANT: to avoid "all sleepers, no pollers" stalls on loopback (gVisor BlockingLargeSend),
        // we must ensure the protocol stack is progressed:
        // - poll BEFORE sending: to drain acks/advance state and make more send capacity available
        // - poll AFTER sending: to actually transmit queued segments and process immediate loopback delivery
        // Additionally, wake the netns poll thread so timers/retransmits can progress even if callers sleep.
        let maybe_iface = self.stack_poll_iface_snapshot();
        if let Some(iface) = maybe_iface.as_ref() {
            if let Some(netns) = iface.common().net_namespace() {
                netns.wakeup_poll_thread();
            }
            // Loopback / fast-path correctness:
            // Poll once may only enqueue TX (or only process RX) without completing the
            // loopback roundtrip (TX->RX->ACK). If we return EAGAIN too early here,
            // acks processed shortly afterwards can free send buffer and make POLLOUT
            // appear spuriously (gVisor PollWithFullBufferBlocks).
            super::poll_util::poll_iface_until_quiescent(iface.as_ref());
        }

        // Fast path: Established.
        // NOTE: do not early-return while holding any lock; we may need to poll after send.
        let mut result: Option<Result<usize, SystemError>> = None;
        {
            let inner_guard = self.inner.read();
            if let Some(inner::Inner::Established(est)) = inner_guard.as_ref() {
                result = Some(est.send_slice(buf));
            }
        }
        if let Some(ret) = result {
            if let Some(iface) = maybe_iface.as_ref() {
                if let Some(netns) = iface.common().net_namespace() {
                    netns.wakeup_poll_thread();
                }
                super::poll_util::poll_iface_until_quiescent(iface.as_ref());
            }
            return ret;
        }

        // Handle transition from Connecting to Established
        let mut writer = self.inner.write();
        if let Some(inner) = writer.take() {
            let ret = match inner {
                inner::Inner::Connecting(conn) => {
                    let (new_inner, res) = conn.into_result();
                    match new_inner {
                        inner::Inner::Established(est) => {
                            let r = est.send_slice(buf);
                            writer.replace(inner::Inner::Established(est));
                            r
                        }
                        other => {
                            writer.replace(other);
                            // If connection failed, return error (EPIPE or EAGAIN if still connecting)
                            match res {
                                Ok(_) => Err(SystemError::EAGAIN_OR_EWOULDBLOCK), // Should be Established if Ok
                                Err(e) => Err(e),
                            }
                        }
                    }
                }
                inner::Inner::Established(est) => {
                    let r = est.send_slice(buf);
                    writer.replace(inner::Inner::Established(est));
                    r
                }
                other => {
                    writer.replace(other);
                    Err(SystemError::EPIPE)
                }
            };

            // Drop lock before polling to avoid lock-order inversion with iface.poll()->notify().
            drop(writer);
            if let Some(iface) = maybe_iface.as_ref() {
                if let Some(netns) = iface.common().net_namespace() {
                    netns.wakeup_poll_thread();
                }
                super::poll_util::poll_iface_until_quiescent(iface.as_ref());
            }
            return ret;
        }

        Err(SystemError::ENOTCONN)
    }
}

struct CorkFlushGuard<'a>(&'a TcpSocket);
impl Drop for CorkFlushGuard<'_> {
    fn drop(&mut self) {
        self.0
            .cork_flush_in_progress
            .store(false, core::sync::atomic::Ordering::Release);
    }
}

#[derive(Debug)]
struct CorkFlushTimer {
    socket: Weak<TcpSocket>,
}

impl TimerFunction for CorkFlushTimer {
    fn run(&mut self) -> Result<(), SystemError> {
        if let Some(socket) = self.socket.upgrade() {
            let socket = socket.clone();
            schedule_work(Work::new(move || {
                socket.handle_cork_timeout();
            }));
        }
        Ok(())
    }
}
