/*
 * Copyright (C) 2025 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <chrono>
#include <iostream>
#include <cstring>
#include <vector>
#include <thread>
#include <chrono>
#include <cstring>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <poll.h>
#include <unistd.h>
#include <random>
#include <future>
#include <thread>

#include <android-base/file.h>
#include <android-base/logging.h>
#include <android-base/scopeguard.h>
#include <IOUringSocketHandler/IOUringSocketHandler.h>

#include <gtest/gtest.h>

// Test all combinations of queue_depth and messages
struct TestParam {
    int queue_depth;
    int numMessages;
    int messageSize;
};

class IOUringSocketHandlerTest : public ::testing::TestWithParam<TestParam> {
public:
    bool IsIouringSupported() {
        return IOUringSocketHandler::IsIouringSupported();
    }
    void SendMsg(int sock_send, const bool non_block);

protected:
    void SetUp() override {
    }
    void TearDown() override {
        close(sock_recv_);
        close(sock_send_);
    }
    void ReceiveThreaduring(int sock_recv);
    bool CreateServerSocket();
    std::unique_ptr<IOUringSocketHandler> handler_;
    void InitializeHandler(int socket_fd = 1);
    // Default queue depth
    int queue_depth_ = 1;
    int sock_recv_;
    int sock_send_;
    int socks[2];
    std::vector<std::string> sent_messages; // Store sent messages for comparison
};

bool IOUringSocketHandlerTest::CreateServerSocket() {
    if (socketpair(AF_UNIX, SOCK_DGRAM, 0, socks) < 0) {
        PLOG(ERROR) << "socketpair failed";
        return false;
    }

    int on = 1;
    if (setsockopt(socks[0], SOL_SOCKET, SO_PASSCRED, &on, sizeof(on)) != 0) {
        PLOG(ERROR) << "setsockopt SO_PASSCRED failed for socks[0]";
        close(socks[0]);
        close(socks[1]);
        return false;
    }

    if (setsockopt(socks[1], SOL_SOCKET, SO_PASSCRED, &on, sizeof(on)) != 0) {
        PLOG(ERROR) << "setsockopt SO_PASSCRED failed for socks[1]";
        close(socks[0]);
        close(socks[1]);
        return false;
    }

    sock_recv_ = socks[0];
    sock_send_ = socks[1];
    return true;
}

// Function to generate a random string
static std::string generateRandomString(size_t length) {
    static const char charset[] =
        "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
    std::random_device rd;
    std::mt19937 gen(rd());
    std::uniform_int_distribution<> dis(0, sizeof(charset) - 2);

    std::string str(length, 0);
    for (size_t i = 0; i < length; ++i) {
        str[i] = charset[dis(gen)];
    }
    return str;
}

void IOUringSocketHandlerTest::InitializeHandler(int socket_fd) {
    handler_ = std::make_unique<IOUringSocketHandler>(socket_fd);
}

TEST_F(IOUringSocketHandlerTest, SetupIoUring) {
    if (!IsIouringSupported()) {
        GTEST_SKIP() << "io_uring not supported. Skipping Test.";
    }
    InitializeHandler();
    EXPECT_TRUE(handler_->SetupIoUring(queue_depth_));
}

TEST_F(IOUringSocketHandlerTest, AllocateAndRegisterBuffers) {
    if (!IsIouringSupported()) {
        GTEST_SKIP() << "io_uring not supported. Skipping Test.";
    }
    InitializeHandler();
    EXPECT_TRUE(handler_->SetupIoUring(queue_depth_));
    EXPECT_TRUE(handler_->AllocateAndRegisterBuffers(8, 4096));
}

TEST_F(IOUringSocketHandlerTest, MultipleAllocateAndRegisterBuffers) {
    if (!IsIouringSupported()) {
        GTEST_SKIP() << "io_uring not supported. Skipping Test.";
    }
    InitializeHandler();

    EXPECT_TRUE(handler_->SetupIoUring(queue_depth_));

    EXPECT_TRUE(handler_->AllocateAndRegisterBuffers(4, 4096));
    handler_->DeRegisterBuffers();

    EXPECT_TRUE(handler_->AllocateAndRegisterBuffers(2, 1024*1024L));
    handler_->DeRegisterBuffers();

    EXPECT_TRUE(handler_->AllocateAndRegisterBuffers(32, 1024));
    handler_->DeRegisterBuffers();

    // num_buffers should be power of 2
    EXPECT_FALSE(handler_->AllocateAndRegisterBuffers(5, 4096));
}

TEST_F(IOUringSocketHandlerTest, TestStopAPI) {
    if (!IsIouringSupported()) {
        GTEST_SKIP() << "io_uring not supported. Skipping Test.";
    }
    ASSERT_TRUE(CreateServerSocket());
    InitializeHandler(sock_recv_);
    ASSERT_TRUE(handler_->SetupIoUring(16));
    handler_->AllocateAndRegisterBuffers(16, 4096);
    ASSERT_TRUE(handler_->EnqueueMultishotRecvmsg());

    std::atomic<bool> thread_started{false};
    std::atomic<bool> thread_exited{false};
    std::thread receive_thread([this, &thread_started, &thread_exited]() {
        thread_started = true;
        struct ucred* cred = nullptr;
        void* this_recv = nullptr;
        size_t len = 0;
        // This should block until Stop is called
        handler_->ReceiveData(&this_recv, len, &cred);

        // After Stop is called, these should be nullptr/0
        EXPECT_EQ(this_recv, nullptr);
        EXPECT_EQ(len, 0);
        EXPECT_EQ(cred, nullptr);

        thread_exited = true;
    });

    while (!thread_started) std::this_thread::yield();
    std::this_thread::sleep_for(std::chrono::milliseconds(50));

    handler_->Stop();
    receive_thread.join();
    EXPECT_TRUE(thread_exited);
}

void IOUringSocketHandlerTest::SendMsg(int sock_send, const bool non_block) {
   const TestParam params = GetParam();
   for (int i = 0; i < params.numMessages; ++i) {
     std::string message = generateRandomString(params.messageSize);

     sent_messages.push_back(message);
     struct ucred cred;
     memset(&cred, 0, sizeof(cred));
     cred.pid = getpid();
     cred.uid = getuid();
     cred.gid = getgid();

     struct iovec iov_send;
     iov_send.iov_base = const_cast<char*>(message.data());
     iov_send.iov_len = params.messageSize;

     struct msghdr msg_send;
     memset(&msg_send, 0, sizeof(msg_send));
     msg_send.msg_iov = &iov_send;
     msg_send.msg_iovlen = 1;

     char control_buffer_send[CMSG_SPACE(sizeof(cred))];
     memset(control_buffer_send, 0, sizeof(control_buffer_send));
     msg_send.msg_control = control_buffer_send;
     msg_send.msg_controllen = sizeof(control_buffer_send);

     struct cmsghdr* cmsg_send = CMSG_FIRSTHDR(&msg_send);
     cmsg_send->cmsg_level = SOL_SOCKET;
     cmsg_send->cmsg_type = SCM_CREDENTIALS;
     cmsg_send->cmsg_len = CMSG_LEN(sizeof(cred));
     memcpy(CMSG_DATA(cmsg_send), &cred, sizeof(cred));

     int flags = 0;
     if (non_block) {
        flags = MSG_DONTWAIT;
     }
     ssize_t sent_bytes;
        while (true) {
            sent_bytes = sendmsg(sock_send, &msg_send, flags);
            if (sent_bytes >= 0) {
                break; // Success
            }
            if (errno == EAGAIN || errno == EWOULDBLOCK) {
                // Try again
                continue;
            } else {
                perror("sendmsg failed");
                return;
            }
        }
    }
}

void IOUringSocketHandlerTest::ReceiveThreaduring(int sock_recv) {
    std::unique_ptr<IOUringSocketHandler> uring_listener;
    uring_listener = std::make_unique<IOUringSocketHandler>(sock_recv);
    const TestParam params = GetParam();
    ASSERT_TRUE(uring_listener->SetupIoUring(params.queue_depth));
    uring_listener->AllocateAndRegisterBuffers(
        params.queue_depth, params.messageSize);

    ASSERT_TRUE(uring_listener->EnqueueMultishotRecvmsg());

    long long received_messages = 0;
    int index = 0;
    while (received_messages < params.numMessages) {
        struct ucred* cred = nullptr;
        void* this_recv = nullptr;
        size_t len = 0;
        uring_listener->ReceiveData(&this_recv, len, &cred);
        // Release the buffer from here onwards
        {
            auto scope_guard =
                android::base::make_scope_guard([&uring_listener]() -> void {
                  uring_listener->ReleaseBuffer(); });

            if (len <= 0) {
                continue;
            }
            received_messages++;
            char* char_ptr = static_cast<char*>(this_recv);
            std::string payload_string(char_ptr, len);
            std::string orig_string = sent_messages[index];
            // Compare payload data
            EXPECT_EQ(payload_string, orig_string);
            // Verify credentials
            EXPECT_EQ(cred->uid, getuid());
            EXPECT_EQ(cred->gid, getgid());
            EXPECT_EQ(cred->pid, getpid());
            index += 1;
        }
    }
}

TEST_P(IOUringSocketHandlerTest, RecvmsgDataIntegrity) {
  if (!IsIouringSupported()) {
      GTEST_SKIP() << "io_uring not supported. Skipping Test.";
  }
  ASSERT_TRUE(CreateServerSocket());
  std::vector<std::thread> send_threads;
  send_threads.emplace_back([this](){ SendMsg(sock_send_, false); });
  ReceiveThreaduring(sock_recv_);
  for (auto& thread : send_threads) {
    thread.join();
  }
  close(sock_send_);
  close(sock_recv_);
}

TEST_P(IOUringSocketHandlerTest, RecvmsgDataIntegrityNonBlockingSend) {
  if (!IsIouringSupported()) {
      GTEST_SKIP() << "io_uring not supported. Skipping Test.";
  }
  ASSERT_TRUE(CreateServerSocket());
  int flags = fcntl(sock_send_, F_GETFL, 0);
  ASSERT_NE(fcntl(sock_send_, F_SETFL, flags | O_NONBLOCK), -1);

  std::vector<std::thread> send_threads;
  send_threads.emplace_back([this](){ SendMsg(sock_send_, true); });

  ReceiveThreaduring(sock_recv_);
  for (auto& thread : send_threads) {
    thread.join();
  }

  close(sock_send_);
  close(sock_recv_);
}

std::vector<TestParam> GetConfigs() {
  std::vector<TestParam> testParams;

  std::vector<int> queue_depth = {1, 8, 16, 32, 64, 128, 256, 512};
  std::vector<int> num_messages = {1, 100, 250, 500, 1000, 1500, 2000, 5000};
  std::vector<int> message_sizes = {1, 100, 520, 1024, 2042, 3168, 4068, 4096};

  // This will test 512 combinations
  for (auto message_size: message_sizes) {
    for (auto q_depth : queue_depth) {
      for (auto n_messages : num_messages) {
        TestParam param;
        param.queue_depth = q_depth;
        param.numMessages = n_messages;
        param.messageSize = message_size;
        testParams.push_back(std::move(param));
      }
    }
  }

  return testParams;
}

INSTANTIATE_TEST_SUITE_P(Io, IOUringSocketHandlerTest,
                         ::testing::ValuesIn(GetConfigs()));

int main(int argc, char** argv) {
    ::testing::InitGoogleTest(&argc, argv);
    return RUN_ALL_TESTS();
}
