#include "communicate.hpp"

#include <array>
#include <asio.hpp>
#include <iostream>
#include <string>
#include <thread>

constexpr size_t g_BuffSize = 1024 * 10;
class Client
{
public:
    Client(asio::io_context& io_context) : io_context_(io_context), socket_(io_context)
    {
        ip_ = "127.0.0.1";
        port_ = "9999";
    }

public:
    bool connect()
    {
        try {
            asio::ip::tcp::resolver resolver(io_context_);
            asio::ip::tcp::resolver::results_type endpoints = resolver.resolve(ip_, port_);
            asio::connect(socket_, endpoints);
            std::cout << "Connected to server " << ip_ << ":" << port_ << std::endl;
            return true;
        } catch (const std::exception& ex) {
            std::cerr << "Exception: " << ex.what() << "\n";
            return false;
        }
    }

    FrameData* post_deepseek(const std::string& text)
    {
        FrameData send;
        send.type = FrameType::TYPE_REQUEST;
        send.data = new char[text.size()];
        send.len = text.size();
        memcpy(send.data, text.c_str(), text.size());

        char* send_data{};
        int len{};

        std::shared_ptr<int> deleter(new int(1), [send_data](int* p) {
            delete p;
            delete[] send_data;
        });

        if (!com_pack(&send, &send_data, len)) {
            std::cerr << "com_pack error" << std::endl;
            return nullptr;
        }

        auto send_size = socket_.write_some(asio::buffer(send_data, len));
        if (send_size != len) {
            std::cerr << "send_size != text.size()" << std::endl;
            return nullptr;
        }
        size_t read_size = socket_.read_some(asio::buffer(tmp_buf_));
        FrameData* ret = nullptr;
        while (read_size > 0) {
            buffer_.push(tmp_buf_.data(), read_size);
            auto* frame = com_parse(buffer_);
            if (frame) {
                ret = frame;
                return ret;
            }
            read_size = socket_.read_some(asio::buffer(tmp_buf_));
        }
        return ret;
    }

private:
    std::string ip_{};
    std::string port_{};
    asio::ip::tcp::socket socket_;
    asio::io_context& io_context_;
    CMutBuffer buffer_{};
    std::array<char, g_BuffSize> tmp_buf_{};
};

int main()
{
#ifdef _WIN32
    system("chcp 65001");
#endif

    asio::io_context io_context;
    Client client(io_context);

    if (!client.connect()) {
        return -1;
    }

    std::thread t([&io_context]() { io_context.run(); });

    std::string text = "将【天文历】翻译为英文，直接给出结果。";
    // std::string text = "This is a test.";
    FrameData* frame = client.post_deepseek(text);
    if (frame) {
        std::cout << "type: " << frame->type << std::endl;
        std::cout << "data: " << frame->data << std::endl;
        std::cout << "len: " << frame->len << std::endl;
        std::cout << "protk: " << frame->protk << std::endl;
        std::cout << "coptk: " << frame->coptk << std::endl;
    }

    delete frame;
    t.join();

    return 0;
}