// control_domain_server.cpp
// 运控域 TCP 服务，监听端口 9002（默认）。

#include "control_domain_server.hpp"

#include <cstdio>
#include <thread>
#include <stdexcept>

#include "frame_codec.hpp"
#include "data_types.hpp"

namespace vaw
{

ControlDomainServer::ControlDomainServer(uint16_t port, ControlHandler* handler)
    : port_(port), handler_(handler), running_(false), listen_sock_(SOCK_INVALID)
{}

ControlDomainServer::~ControlDomainServer()
{
    stop();
}

void ControlDomainServer::run()
{
#ifdef _WIN32
    WSADATA wsa;
    WSAStartup(MAKEWORD(2, 2), &wsa);
#endif

    listen_sock_ = ::socket(AF_INET, SOCK_STREAM, 0);
    if (listen_sock_ == SOCK_INVALID)
        throw std::runtime_error("运控：创建 socket 失败");

    int opt = 1;
    ::setsockopt(listen_sock_, SOL_SOCKET, SO_REUSEADDR,
                 reinterpret_cast<const char*>(&opt), sizeof(opt));

    sockaddr_in addr{};
    addr.sin_family      = AF_INET;
    addr.sin_port        = htons(port_);
    addr.sin_addr.s_addr = INADDR_ANY;

    if (::bind(listen_sock_, reinterpret_cast<sockaddr*>(&addr), sizeof(addr)) < 0)
        throw std::runtime_error("运控：bind 失败");

    ::listen(listen_sock_, 8);
    running_ = true;
    std::printf("[control] 监听端口 %d\n", port_);

    while (running_) {
        sockaddr_in client_addr{};
#ifdef _WIN32
        int addr_len = sizeof(client_addr);
#else
        socklen_t addr_len = sizeof(client_addr);
#endif
        sock_t conn = ::accept(listen_sock_,
                               reinterpret_cast<sockaddr*>(&client_addr), &addr_len);
        if (conn == SOCK_INVALID) break;

        std::thread([this, conn]() { handle_connection(conn); }).detach();
    }
}

void ControlDomainServer::stop()
{
    running_ = false;
    if (listen_sock_ != SOCK_INVALID) {
        ::shutdown(listen_sock_, SOCK_SHUTDOWN_BOTH);
        SOCK_CLOSE(listen_sock_);
        listen_sock_ = SOCK_INVALID;
    }
}

void ControlDomainServer::handle_connection(sock_t conn)
{
    std::printf("[control] 新连接\n");
    try {
        MsgType     msg_type;
        std::string payload;
        recv_frame(conn, msg_type, payload);
        std::printf("[control] 收到帧 type=%u\n",
                    static_cast<unsigned>(msg_type));

        nlohmann::json j_payload;
        if (!payload.empty())
            j_payload = nlohmann::json::parse(payload);

        switch (msg_type) {

            case MsgType::CONTROL_GET_READINESS_REQ: {
                auto rsp = handler_->get_readiness(j_payload);
                nlohmann::json j_rsp = rsp;
                send_frame(conn, MsgType::CONTROL_GET_READINESS_RSP, j_rsp.dump());
                break;
            }

            case MsgType::CONTROL_EVALUATION_REQ: {
                ControllerEvaluationRequest req;
                from_json(j_payload, req);
                auto rsp = handler_->execute_evaluation(req);
                nlohmann::json j_rsp = rsp;
                send_frame(conn, MsgType::CONTROL_EVALUATION_RSP, j_rsp.dump());
                break;
            }

            default:
                std::printf("[control] 未知帧类型 %u，忽略\n",
                            static_cast<unsigned>(msg_type));
                break;
        }
    } catch (const std::exception& e) {
        std::printf("[control] 处理帧异常: %s\n", e.what());
    }
    SOCK_CLOSE(conn);
}

}  // namespace vaw
