#pragma once

#include "PeerLink.hpp"
#include "PeerWorldController.hpp"
#include "world/World.hpp"

#include <chrono>
#include <fstream>
#include <memory>
#include <string>

namespace tw::p2p {

// Thin shell around World + PeerWorldController.
//
// Owns the World (ECS) and the controller that drives networking and
// simulation.  The only logic here is CSV output.
class TestPeerNode {
public:
    TestPeerNode(uint32_t self_id, uint16_t port,
                 std::unique_ptr<PeerLink> link,
                 const std::string& registry_path,
                 const std::string& csv_path);

    TestPeerNode(const TestPeerNode&) = delete;
    TestPeerNode& operator=(const TestPeerNode&) = delete;

    ~TestPeerNode() { m_csv.close(); }

    void register_self();

    bool wait_until_peers_registered(
        uint32_t expected_count,
        std::chrono::milliseconds timeout = std::chrono::milliseconds(30000));

    void discover_and_connect();

    void wait_for_connections(
        uint32_t expected_count,
        std::chrono::milliseconds timeout = std::chrono::milliseconds(2000));

    // Advance one tick; writes a CSV row if the world stepped.
    void tick();

    uint32_t  self_id()        const { return m_controller.self_id(); }
    uint32_t  current_frame()  const { return m_controller.current_frame(); }
    uint64_t  rollbacks()      const { return m_controller.rollbacks(); }
    uint64_t  stepped_frames() const { return m_controller.stepped_frames(); }
    glm::vec3 peer_position(uint32_t peer_id) const {
        return m_controller.peer_position(peer_id);
    }

private:
    tw::World           m_world;
    PeerWorldController m_controller;
    std::ofstream       m_csv;

    void write_csv_row();
};

} // namespace tw::p2p
