BareGit
#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include <mw/http_client_mock.hpp>

#include "llm_client.hpp"

using ::testing::_;
using ::testing::Return;

TEST(OpenAiClientTest, SuccessfulGeneration)
{
    auto mock_session = std::make_unique<mw::HTTPSessionMock>();

    std::string mock_json_response = R"({
        "choices": [
            {
                "message": {
                    "role": "assistant",
                    "content": "Hello! How can I help?"
                }
            }
        ]
    })";

    mw::HTTPResponse http_response(200, mock_json_response);

    EXPECT_CALL(*mock_session, post(_)).WillOnce(Return(&http_response));

    OpenAiClient client("fake_key", "gpt-4o", "https://fake.endpoint.com/v1", std::move(mock_session));

    std::vector<Message> history = {UserMessage{"Hi"}};
    nlohmann::json tools = nlohmann::json::array();

    auto result = client.generateResponse(history, tools).get();
    ASSERT_TRUE(result.has_value());

    auto& assistant_msg = std::get<AssistantMessage>(result.value());
    ASSERT_TRUE(assistant_msg.content.has_value());
    EXPECT_EQ(*assistant_msg.content, "Hello! How can I help?");
    EXPECT_TRUE(assistant_msg.tool_calls.empty());
}

TEST(OpenAiClientTest, ToolCallGeneration)
{
    auto mock_session = std::make_unique<mw::HTTPSessionMock>();

    std::string mock_json_response = R"({
        "choices": [
            {
                "message": {
                    "role": "assistant",
                    "content": null,
                    "tool_calls": [
                        {
                            "id": "call_123",
                            "type": "function",
                            "function": {
                                "name": "calculator",
                                "arguments": "{\"a\": 2, \"b\": 2, \"operation\": \"add\"}"
                            }
                        }
                    ]
                }
            }
        ]
    })";

    mw::HTTPResponse http_response(200, mock_json_response);

    EXPECT_CALL(*mock_session, post(_)).WillOnce(Return(&http_response));

    OpenAiClient client("fake_key", "gpt-4o", "https://fake.endpoint.com/v1", std::move(mock_session));

    std::vector<Message> history = {UserMessage{"Calculate 2+2"}};
    nlohmann::json tools = nlohmann::json::array();

    auto result = client.generateResponse(history, tools).get();
    ASSERT_TRUE(result.has_value());

    auto& assistant_msg = std::get<AssistantMessage>(result.value());
    EXPECT_FALSE(assistant_msg.content.has_value());
    ASSERT_EQ(assistant_msg.tool_calls.size(), 1);
    EXPECT_EQ(assistant_msg.tool_calls[0].name, "calculator");
    EXPECT_EQ(assistant_msg.tool_calls[0].arguments["a"], 2);
}

TEST(OpenAiClientTest, NetworkFailureReturnsError)
{
    auto mock_session = std::make_unique<mw::HTTPSessionMock>();

    EXPECT_CALL(*mock_session, post(_))
        .WillOnce(Return(std::unexpected(mw::runtimeError("Network Error"))));

    OpenAiClient client("fake_key", "gpt-4o", "https://fake.endpoint.com/v1", std::move(mock_session));

    std::vector<Message> history = {UserMessage{"Hi"}};
    nlohmann::json tools = nlohmann::json::array();

    auto result = client.generateResponse(history, tools).get();
    EXPECT_FALSE(result.has_value());
    EXPECT_EQ(mw::errorMsg(result.error()), "Network Error");
}