// ==========================================================
// Domain 1: Protocol & IPC Unit Tests
// ==========================================================

#include "test_harness.hpp"

#include "common/protocol.hpp"
#include "ipc/shared_memory.hpp"
#include "input/human_curve.hpp"
#include "input/non_blocking_actuator.hpp"
#include "sensor/log_sensor.hpp"
#include "memory/imemory_reader.hpp"
#include "memory/rpm_reader.hpp"
#include "memory/aob_scanner.hpp"
#include "memory/offsets_store.hpp"
#include "memory/pe_fingerprint.hpp"
#include "memory/offset_registry.hpp"
#include "memory/simulated_reader.hpp"
#include "memory/entity_manager.hpp"
#include "memory/game_layout.hpp"
#include "memory/player_finder.hpp"
#include "memory/pointer_chain_resolver.hpp"
#include "memory/registry_live_label.hpp"
#include "memory/vitals_fingerprint.hpp"
#include "combat/reflex_manager.hpp"
#include "looting/loot_controller.hpp"
#include "combat/combo_manager.hpp"
#include "combat/kiting_engine.hpp"
#include "navigation/quest_navigator.hpp"
#include "navigation/terrain_grid.hpp"
#include "navigation/pathfinder.hpp"
#include "memory/terrain_reader.hpp"
#include "game_session.hpp"
#include "autologin/auto_login.hpp"
#include "navigation/town_quest_engine.hpp"
#include "common/coordinate_transform.hpp"
#include "brain/bot_brain.hpp"
#include "brain/area_events.hpp"
#include "brain/inventory_handler.hpp"
#include "combat/skills_table.hpp"
#include "combat/skill_definition.hpp"
#include "combat/skill_engine.hpp"
#include "brain/unstuck_handler.hpp"
#include "brain/map_device_handler.hpp"
#include "brain/character_fsm.hpp"
#include "brain/npc_interaction_handler.hpp"
#include "common/window_utils.hpp"
#include "common/math2d.hpp"
#include "common/string_utils.hpp"
#include "common/time_utils.hpp"
#include "common/toml_parser.hpp"
#include "common/logger.hpp"

#include <filesystem>
#include <atomic>
#include <algorithm>
#include <chrono>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <fstream>
#include <iostream>
#include <thread>
#include <vector>

// ==========================================================
// 1. Kiểm chứng bố cục giao thức
// ==========================================================
void TestProtocolLayout() {
    std::cout << "[Test 1] Layout giao thức nhị phân..." << std::endl;

    CHECK(sizeof(SharedMemoryHeader) == 64 && sizeof(PlayerTelemetryData) == 84 &&
          sizeof(EntityTelemetryData) == 88 && sizeof(AreaTelemetryData) == 96 &&
          sizeof(CommandPacket) == 36 && sizeof(TelemetryPacket) == 39112,
          "Struct sizeof invariants mismatch");

    CHECK(offsetof(SharedMemoryHeader, magic) == 0 &&
          offsetof(SharedMemoryHeader, protocolVersion) == 8 &&
          offsetof(SharedMemoryHeader, isRunning) == 12 &&
          offsetof(SharedMemoryHeader, telemetrySequence) == 16 &&
          offsetof(SharedMemoryHeader, commandSequence) == 24 &&
          offsetof(SharedMemoryHeader, commandReadIndex) == 32 &&
          offsetof(SharedMemoryHeader, lastCoreHeartbeat) == 40 &&
          offsetof(SharedMemoryHeader, lastAgentHeartbeat) == 48 &&
          offsetof(SharedMemoryHeader, reserved) == 56,
          "SharedMemoryHeader offset invariants mismatch");

    CHECK(offsetof(CommandPacket, commandId) == 0 &&
          offsetof(CommandPacket, opCode) == 8 &&
          offsetof(CommandPacket, targetX) == 12 &&
          offsetof(CommandPacket, targetY) == 16 &&
          offsetof(CommandPacket, targetZ) == 20 &&
          offsetof(CommandPacket, targetEntityId) == 24 &&
          offsetof(CommandPacket, priority) == 28 &&
          offsetof(CommandPacket, timeoutMs) == 32,
          "CommandPacket offset invariants mismatch");

    CHECK(offsetof(TelemetryPacket, snapshotId) == 0 &&
          offsetof(TelemetryPacket, timestamp) == 8 &&
          offsetof(TelemetryPacket, player) == 16 &&
          offsetof(TelemetryPacket, entityCount) == 100 &&
          offsetof(TelemetryPacket, entities) == 104 &&
          offsetof(TelemetryPacket, terrainWalkability) == 22632 &&
          offsetof(TelemetryPacket, area) == 39016,
          "TelemetryPacket offset invariants mismatch");

    std::cout << "  -> Header=64B, Player=84B, Entity=88B, Area=96B, Cmd=36B, Telemetry=39112B (100% Verified)" << std::endl;
}

// ==========================================================
// 3. IPC: Publish/đọc telemetry qua Seqlock double-buffer
// ==========================================================
void TestTelemetrySeqlock() {
    std::cout << "[Test 3] Telemetry Seqlock double-buffer..." << std::endl;

    const std::string kName = TestName("Local\POE2_Auto_TestMem_Seqlock");

    SharedMemoryManager server;
    SharedMemoryManager client;
    CHECK(server.Initialize(true, kName.c_str()) && client.Initialize(false, kName.c_str()), "Server/Client khởi tạo thất bại");

    TelemetryPacket out{};
    CHECK(!client.ReadTelemetry(out), "Đọc được dữ liệu khi sequence = 0 (lỗi!)");

    bool allWritten = true;
    for (uint64_t id = 1; id <= 5; ++id) {
        TelemetryPacket pkt{};
        pkt.snapshotId = id;
        pkt.timestamp = SharedMemoryManager::NowMs();
        pkt.player.currentHP = static_cast<uint32_t>(1000 + id);
        pkt.player.maxHP = 2000;
        if (!server.WriteTelemetry(pkt)) allWritten = false;
    }
    CHECK(allWritten, "Publish snapshot thất bại");

    CHECK(client.ReadTelemetry(out) && out.snapshotId == 5 && out.player.currentHP == 1005,
          "Client đọc snapshot #5 HP=1005 thất bại");

    std::cout << "  -> Publish 5 snapshot, client đọc đúng snapshot #5 (HP=1005)" << std::endl;
}

// ==========================================================
// 4. IPC: Stress test seqlock (writer + reader song song)
// ==========================================================
void TestTelemetryStress() {
    std::cout << "[Test 4] Stress seqlock (writer 2kHz + reader song song)..." << std::endl;

    const std::string kName = TestName("Local\\POE2_Auto_TestMem_Stress");
    constexpr uint64_t kTotalSnapshots = 300;

    SharedMemoryManager server;
    CHECK(server.Initialize(true, kName.c_str()), "Server khởi tạo thất bại");

    SharedMemoryManager client;
    CHECK(client.Initialize(false, kName.c_str()), "Client khởi tạo thất bại");

    std::atomic<bool> writerDone{ false };
    std::atomic<uint64_t> readFailures{ 0 };
    std::atomic<uint64_t> readCount{ 0 };
    std::atomic<uint64_t> lastSeenId{ 0 };

    // Reader: liên tục đọc, bảo đảm không bao giờ thấy snapshot rách (id giảm)
    std::thread reader([&]() {
        TelemetryPacket pkt{};
        uint64_t prevId = 0;
        while (!writerDone.load(std::memory_order_acquire)) {
            if (client.ReadTelemetry(pkt)) {
                if (pkt.snapshotId < prevId) {
                    readFailures.fetch_add(1, std::memory_order_relaxed); // Torn/regression!
                }
                prevId = pkt.snapshotId;
                readCount.fetch_add(1, std::memory_order_relaxed);
            }
        }
        lastSeenId.store(prevId, std::memory_order_release);
    });

    // Writer: publish 3000 snapshot với nhịp ~2kHz
    for (uint64_t id = 1; id <= kTotalSnapshots; ++id) {
        TelemetryPacket pkt{};
        pkt.snapshotId = id;
        pkt.timestamp = SharedMemoryManager::NowMs();
        pkt.player.currentHP = static_cast<uint32_t>(id % 5000);
        server.WriteTelemetry(pkt);
        std::this_thread::sleep_for(std::chrono::microseconds(500));
    }
    writerDone.store(true, std::memory_order_release);
    reader.join();

    CHECK(readFailures.load() == 0, "Phát hiện torn-read/regression trong stress test!");
    CHECK(readCount.load() > 0, "Reader không đọc được snapshot nào");
    CHECK(lastSeenId.load() >= kTotalSnapshots - 5, "Reader tụt lại quá xa");

    std::cout << "  -> " << readCount.load() << " lần đọc / " << kTotalSnapshots
              << " snapshot, 0 torn-read" << std::endl;
}

// ==========================================================
// 5. IPC: Hàng đợi lệnh SPSC ring (FIFO)
// ==========================================================
void TestCommandRing() {
    std::cout << "[Test 5] Command Ring SPSC (FIFO)..." << std::endl;

    const std::string kName = TestName("Local\POE2_Auto_TestMem_CmdRing");

    SharedMemoryManager server;
    SharedMemoryManager client;
    CHECK(server.Initialize(true, kName.c_str()) && client.Initialize(false, kName.c_str()), "Server/Client khởi tạo thất bại");

    bool allPublished = true;
    for (uint64_t i = 1; i <= 5; ++i) {
        CommandPacket cmd{};
        cmd.commandId = i;
        cmd.opCode = MacroOpCode::NAVIGATE_TO_COORD;
        cmd.targetX = static_cast<float>(i * 10);
        if (!client.PublishCommand(cmd)) allPublished = false;
    }
    CHECK(allPublished && server.PendingCommandCount() == 5, "Publish 5 lệnh hoặc pending count != 5");

    bool fifoOk = true;
    for (uint64_t i = 1; i <= 5; ++i) {
        CommandPacket cmd{};
        if (!server.FetchNextCommand(cmd) || cmd.commandId != i || std::fabs(cmd.targetX - static_cast<float>(i * 10)) >= 0.001f) {
            fifoOk = false;
        }
    }
    CommandPacket none{};
    CHECK(fifoOk && !server.FetchNextCommand(none) && server.PendingCommandCount() == 0,
          "FIFO 5 lệnh đúng thứ tự và hàng đợi trống");

    std::cout << "  -> FIFO 5 lệnh đúng thứ tự, hết hàng đợi trả về false" << std::endl;
}

// ==========================================================
// 6. IPC: Hàng đợi đầy & producer/consumer đa luồng
// ==========================================================
void TestCommandRingConcurrency() {
    std::cout << "[Test 6] Command Ring đa luồng (producer/consumer)..." << std::endl;

    const std::string kName = TestName("Local\\POE2_Auto_TestMem_CmdConc");
    constexpr uint64_t kTotalCommands = 200;

    SharedMemoryManager server;
    CHECK(server.Initialize(true, kName.c_str()), "Server khởi tạo thất bại");

    SharedMemoryManager client;
    CHECK(client.Initialize(false, kName.c_str()), "Client khởi tạo thất bại");

    // 6a. Làm đầy hàng đợi 16 slot -> lệnh thứ 17 phải bị từ chối
    uint64_t accepted = 0;
    for (uint64_t i = 1; i <= COMMAND_QUEUE_CAPACITY + 4; ++i) {
        CommandPacket cmd{};
        cmd.commandId = i;
        if (client.PublishCommand(cmd)) ++accepted;
    }
    CHECK(accepted == COMMAND_QUEUE_CAPACITY, "Cơ chế chống tràn hàng đợi sai");

    // 6b. Sau khi consumer rút bớt, producer tiếp tục đẩy được
    CommandPacket drain{};
    uint64_t drained = 0;
    while (server.FetchNextCommand(drain)) ++drained;
    CHECK(drained == COMMAND_QUEUE_CAPACITY, "Rút sai số lệnh");

    CommandPacket after{};
    after.commandId = 999;
    CHECK(client.PublishCommand(after), "Publish sau khi rút thất bại");
    CommandPacket out{};
    CHECK(server.FetchNextCommand(out) && out.commandId == 999, "Lệnh #999 thất lạc");

    // 6c. Producer/consumer chạy song song 200 lệnh, kiểm tra FIFO toàn cục
    std::atomic<bool> producerDone{ false };

    std::thread producer([&]() {
        for (uint64_t i = 1; i <= kTotalCommands; ++i) {
            CommandPacket cmd{};
            cmd.commandId = i;
            cmd.opCode = MacroOpCode::PICKUP_ITEM;
            // Retry khi hàng đợi đầy (hành vi chuẩn của producer thật)
            while (!client.PublishCommand(cmd)) {
                std::this_thread::sleep_for(std::chrono::microseconds(200));
            }
        }
        producerDone.store(true, std::memory_order_release);
    });

    uint64_t consumed = 0;
    uint64_t lastId = 0;
    bool orderOk = true;
    while (consumed < kTotalCommands) {
        CommandPacket cmd{};
        if (server.FetchNextCommand(cmd)) {
            if (cmd.commandId <= lastId) orderOk = false; // FIFO toàn cục bị phá
            lastId = cmd.commandId;
            ++consumed;
        } else {
            std::this_thread::sleep_for(std::chrono::microseconds(100));
        }
    }
    producer.join();

    CHECK(orderOk, "Thứ tự FIFO toàn cục bị phá khi chạy đa luồng");
    CHECK(consumed == kTotalCommands, "Thiếu lệnh trong luồng đa luồng");

    std::cout << "  -> 200 lệnh đa luồng, FIFO toàn cục đúng, chống tràn OK" << std::endl;
}

// ==========================================================
// 7. Watchdog nhịp tim Agent
// ==========================================================
void TestWatchdog() {
    std::cout << "[Test 7] Watchdog nhịp tim Agent..." << std::endl;

    // 7a. Chưa có agent nào kết nối
    {
        const std::string kName = TestName("Local\\POE2_Auto_TestMem_WdFresh");
        SharedMemoryManager server;
        CHECK(server.Initialize(true, kName.c_str()), "Server khởi tạo thất bại");
        CHECK(server.CheckAgentWatchdog(100)
                  == SharedMemoryManager::AgentWatchdogStatus::NoAgentEverConnected,
              "Trạng thái ban đầu phải là NoAgentEverConnected");
    }

    // 7b. Agent online rồi im lặng -> phải chuyển sang TimedOut
    {
        const std::string kName = TestName("Local\\POE2_Auto_TestMem_WdTimeout");
        SharedMemoryManager server;
        CHECK(server.Initialize(true, kName.c_str()), "Server khởi tạo thất bại");

        SharedMemoryManager client;
        CHECK(client.Initialize(false, kName.c_str()), "Client khởi tạo thất bại");

        CHECK(server.CheckAgentWatchdog(50)
                  == SharedMemoryManager::AgentWatchdogStatus::Healthy,
              "Agent vừa kết nối phải Healthy");

        std::this_thread::sleep_for(std::chrono::milliseconds(120));
        CHECK(server.CheckAgentWatchdog(50)
                  == SharedMemoryManager::AgentWatchdogStatus::TimedOut,
              "Agent im lặng 120ms (ngưỡng 50ms) phải TimedOut");

        // Agent gửi nhịp tim trở lại -> Healthy
        client.UpdateHeartbeat();
        CHECK(server.CheckAgentWatchdog(50)
                  == SharedMemoryManager::AgentWatchdogStatus::Healthy,
              "Agent gửi nhịp tim lại phải Healthy");
    }

    std::cout << "  -> NoAgent/Healthy/TimedOut hoạt động đúng" << std::endl;
}

// ==========================================================
// 11. LogSensor (tail file log giả lập đúng format POE2)
// ==========================================================
void TestLogSensor() {
    std::cout << "[Test 11] LogSensor tail + regex parsing..." << std::endl;

    const std::string path = TestName("test_latestclient.log");
    DeleteFileA(path.c_str());

    LogSensor sensor(path);
    CHECK(sensor.Start(), "Start tháº¥t báº¡i");

    // Táº¡o file rá»—ng vÃ  chá» worker má»Ÿ file (semantic tail: chá»‰ Ä‘á»c dá»¯ liá»‡u má»›i)
    {
        std::ofstream f(path, std::ios::binary);
        CHECK(f.good(), "KhÃ´ng táº¡o Ä‘Æ°á»£c file log test");
    }
    auto waitDeadline = std::chrono::steady_clock::now() + std::chrono::seconds(3);
    while (!sensor.IsFileOpen() && std::chrono::steady_clock::now() < waitDeadline) {
        std::this_thread::sleep_for(std::chrono::milliseconds(25));
    }
    CHECK(sensor.IsFileOpen(), "Sensor khÃ´ng má»Ÿ Ä‘Æ°á»£c file log");

    // Ghi 5 dÃ²ng log giáº£ láº­p Ä‘Ãºng cÃº phÃ¡p POE2 (theo docs/research/03)
    {
        std::ofstream f(path, std::ios::binary | std::ios::app);
        f << "2026/09/05 18:18:39 114637765 2caa229f [DEBUG Client 25032] Generating level 1 area \"G1_1\" with seed 13361591\n";
        f << "2026/09/05 18:18:40 114638265 7fbd1225 [INFO Client 25032] [SCENE] Set Source [The Riverbank]\n";
        f << "2026/09/05 18:18:52 114650343 4cba6a94 [INFO Client 25032] [LOADING SCREEN] (The Riverbank) Duration = 12.6816 seconds\n";
        f << "2026/09/05 18:19:01 114659000 9a1b2c3d [INFO Client 25032] @From SmoothPlayer: hi, trade?\n";
        f << "2026/09/05 18:20:00 114700000 8f8e8d8c [INFO Client 25032] Abnormal disconnect: SocketException\n";
        f.flush();
    }

    // Thu tháº­p 5 sá»± kiá»‡n vá»›i timeout 3s
    std::vector<GameEvent> events;
    auto deadline = std::chrono::steady_clock::now() + std::chrono::seconds(3);
    while (events.size() < 5 && std::chrono::steady_clock::now() < deadline) {
        GameEvent ev{};
        if (sensor.PollEvent(ev)) {
            events.push_back(ev);
        } else {
            std::this_thread::sleep_for(std::chrono::milliseconds(25));
        }
    }

    CHECK(events.size() == 5, "Sá»‘ sá»± kiá»‡n sai: " << events.size());
    if (events.size() == 5) {
        CHECK(events[0].type == GameEventType::AreaGenerated, "EV0 sai loáº¡i");
        CHECK(events[0].areaLevel == 1, "EV0 level sai");
        CHECK(events[0].text == "G1_1", "EV0 area code sai");
        CHECK(events[0].areaSeed == 13361591, "EV0 seed sai");
        CHECK(events[1].type == GameEventType::SceneChanged, "EV1 sai loáº¡i");
        CHECK(events[1].text == "The Riverbank", "EV1 tÃªn khu vá»±c sai");
        CHECK(events[2].type == GameEventType::LoadingFinished, "EV2 sai loáº¡i");
        CHECK(std::fabs(events[2].loadDurationSec - 12.6816f) < 0.001f, "EV2 duration sai");
        CHECK(events[3].type == GameEventType::WhisperReceived, "EV3 sai loáº¡i");
        CHECK(events[3].text == "SmoothPlayer", "EV3 sender sai");
        CHECK(events[3].text2 == "hi, trade?", "EV3 message sai");
        CHECK(events[4].type == GameEventType::AbnormalDisconnect, "EV4 sai loáº¡i");
        CHECK(events[4].text == "SocketException", "EV4 reason sai");
    }

    // Tail tiáº¿p: dá»¯ liá»‡u ghi thÃªm sau Ä‘Ã³ cÅ©ng pháº£i Ä‘Æ°á»£c nháº­n
    {
        std::ofstream f(path, std::ios::binary | std::ios::app);
        f << "2026/09/05 18:21:00 114710000 1a2b3c4d [INFO Client 25032] [SCENE] Set Source [Hideout]\n";
        f << "2026/09/05 18:22:00 114720000 2b3c4d5e [INFO Client 25032] : BEONGUSI has been slain.\n";
        f << "2026/09/05 18:22:05 114725000 3c4d5e6f [INFO Client 25032] : BestFriend has joined the area.\n";
        f << "2026/09/05 18:22:10 114730000 4d5e6f7a [INFO Client 25032] %LadyFingerz: ty!\n";
        f << "2026/09/05 18:22:15 114735000 5e6f7a8b [INFO Client 25032] : Trade accepted.\n";
        f << "2026/09/05 18:22:20 114740000 6f7a8b9c [INFO Client 25032] Connect time to instance server was 42ms\n";
        f.flush();
    }

    // Kiá»ƒm tra tÃ­nh nÄƒng Friend Whitelist
    sensor.AddFriend("BestFriend");
    CHECK(sensor.IsFriend("bestfriend"), "IsFriend case-insensitive test that bai");
    CHECK(!sensor.IsFriend("StrangerPlayer"), "StrangerPlayer khong duoc co trong friend list");

    bool gotHideout = false;
    bool gotSlain = false;
    bool gotJoined = false;
    bool gotParty = false;
    bool gotTrade = false;
    bool gotPing = false;

    GameEvent ev{};
    deadline = std::chrono::steady_clock::now() + std::chrono::seconds(3);
    while (std::chrono::steady_clock::now() < deadline) {
        if (sensor.PollEvent(ev)) {
            if (ev.type == GameEventType::SceneChanged && ev.text == "Hideout") gotHideout = true;
            if (ev.type == GameEventType::PlayerSlain && ev.text == "BEONGUSI") gotSlain = true;
            if (ev.type == GameEventType::PlayerJoinedArea && ev.text == "BestFriend") {
                gotJoined = true;
                CHECK(sensor.IsFriend(ev.text), "Doi tac BestFriend phai nam trong Whitelist");
            }
            if (ev.type == GameEventType::PartyChat && ev.text == "LadyFingerz" && ev.text2 == "ty!") gotParty = true;
            if (ev.type == GameEventType::TradeAccepted) gotTrade = true;
            if (ev.type == GameEventType::InstanceConnected && std::fabs(ev.loadDurationSec - 42.0f) < 0.1f) gotPing = true;
        } else {
            std::this_thread::sleep_for(std::chrono::milliseconds(25));
        }
        if (gotHideout && gotSlain && gotJoined && gotParty && gotTrade && gotPing) break;
    }
    CHECK(gotHideout, "Khong nhan duoc SceneChanged Hideout");
    CHECK(gotSlain, "Khong nhan duoc PlayerSlain BEONGUSI");
    CHECK(gotJoined, "Khong nhan duoc PlayerJoinedArea BestFriend");
    CHECK(gotParty, "Khong nhan duoc PartyChat");
    CHECK(gotTrade, "Khong nhan duoc TradeAccepted");
    CHECK(gotPing, "Khong nhan duoc InstanceConnected ping");

    sensor.Stop();
    CHECK(!sensor.IsRunning(), "Stop khÃ´ng hiá»‡u lá»±c");
    // TASK-OPT-06: XÃ¡c nháº­n DeleteFileA thÃ nh cÃ´ng 100%, khÃ´ng bá»‹ ERROR_SHARING_VIOLATION (32)
    CHECK(DeleteFileA(path.c_str()) != 0, "DeleteFileA tháº¥t báº¡i (ERROR_SHARING_VIOLATION 32) do rÃ² rá»‰ file handle");
    std::cout << "  -> Tail realtime + full regex sá»± kiá»‡n má»›i & Friend Whitelist OK" << std::endl;
}

// ==========================================================
// 11b. LogSensor seed SCENE chơi thật từ đuôi file (mở Core giữa map)
// Dòng log: Client.txt thật 10/09/2026 18:29 Hive Fortress (PID 36104)
// ==========================================================
void TestLogSensorReplayLatestZone() {
    std::cout << "[Test 11b] LogSensor seed zone tu duoi file (Hive Fortress)..." << std::endl;

    const std::string path = TestName("test_replay_hive_fortress.log");
    DeleteFileA(path.c_str());

    {
        std::ofstream f(path, std::ios::binary);
        CHECK(f.good(), "Khong tao duoc file log replay");
        f << "2026/09/10 18:21:04 337200000 7fbd1225 [INFO Client 36104] [SCENE] Set Source [Shoreline Hideout]\n";
        f << "2026/09/10 18:29:57 547320703 2caa229f [DEBUG Client 36104] Generating level 77 area \"ChayulaLeague_Tower\" with seed 3565528473\n";
        f << "2026/09/10 18:29:57 547321000 7fbd1225 [INFO Client 36104] [SCENE] Set Source [Hive Fortress]\n";
        f << "2026/09/10 18:29:59 547323234 4cba6a94 [INFO Client 36104] [LOADING SCREEN] (Hive Fortress) Duration = 2.65302 seconds\n";
        f << "2026/09/10 18:45:00 338000000 7fbd1225 [INFO Client 36104] [SCENE] Set Source [Act 2]\n";
        f << "2026/09/10 18:45:01 338000100 7fbd1225 [INFO Client 36104] [SCENE] Set Source [Atlas]\n";
        f << "2026/09/10 18:45:02 338000200 7fbd1225 [INFO Client 36104] [SCENE] Set Source [(null)]\n";
        f.flush();
    }

    LogSensor sensor(path);
    CHECK(sensor.Start(), "Start that bai");

    auto waitDeadline = std::chrono::steady_clock::now() + std::chrono::seconds(3);
    while (!sensor.IsFileOpen() && std::chrono::steady_clock::now() < waitDeadline) {
        std::this_thread::sleep_for(std::chrono::milliseconds(25));
    }
    CHECK(sensor.IsFileOpen(), "Sensor khong mo duoc file replay");

    bool gotGen = false;
    bool gotHive = false;
    bool gotLoad = false;
    bool gotUiLeak = false;
    GameEvent ev{};
    auto deadline = std::chrono::steady_clock::now() + std::chrono::seconds(3);
    while (std::chrono::steady_clock::now() < deadline) {
        if (sensor.PollEvent(ev)) {
            if (ev.type == GameEventType::AreaGenerated && ev.text == "ChayulaLeague_Tower"
                && ev.areaLevel == 77 && ev.areaSeed == 3565528473ull) {
                gotGen = true;
            }
            if (ev.type == GameEventType::SceneChanged && ev.text == "Hive Fortress") gotHive = true;
            if (ev.type == GameEventType::SceneChanged &&
                (ev.text == "Act 2" || ev.text == "Atlas" || ev.text == "(null)")) {
                gotUiLeak = true;
            }
            if (ev.type == GameEventType::LoadingFinished && ev.text == "Hive Fortress") gotLoad = true;
        } else {
            std::this_thread::sleep_for(std::chrono::milliseconds(25));
        }
        if (gotGen && gotHive && gotLoad) break;
    }
    CHECK(gotGen, "Seed phai phat AreaGenerated ChayulaLeague_Tower");
    CHECK(gotHive, "Seed phai phat SceneChanged Hive Fortress (khong phai Act 2/Atlas)");
    CHECK(gotLoad, "Seed phai phat LoadingFinished Hive Fortress");
    CHECK(!gotUiLeak, "Seed khong duoc phat SceneChanged UI overlay");

    {
        std::ofstream f(path, std::ios::binary | std::ios::app);
        f << "2026/09/10 18:50:00 338100000 7fbd1225 [INFO Client 36104] [SCENE] Set Source [The Riverbank]\n";
        f.flush();
    }
    bool gotRiver = false;
    deadline = std::chrono::steady_clock::now() + std::chrono::seconds(3);
    while (std::chrono::steady_clock::now() < deadline) {
        if (sensor.PollEvent(ev)) {
            if (ev.type == GameEventType::SceneChanged && ev.text == "The Riverbank") {
                gotRiver = true;
                break;
            }
        } else {
            std::this_thread::sleep_for(std::chrono::milliseconds(25));
        }
    }
    CHECK(gotRiver, "Sau seed van phai tail SCENE moi");

    sensor.Stop();
    CHECK(DeleteFileA(path.c_str()) != 0, "DeleteFileA replay log that bai");
    std::cout << "  -> Seed Hive Fortress + bo qua overlay + tail moi OK" << std::endl;
}

void TestLogSensorPreferClientTxt() {
    std::cout << "[Test 11c] LogSensor uu tien Client.txt hon LatestClient.txt..." << std::endl;

    const std::string def = LogSensor::kDefaultLogPath;
    CHECK(def.find("Client.txt") != std::string::npos, "kDefaultLogPath phai la Client.txt");
    CHECK(def.find("LatestClient.txt") == std::string::npos,
          "kDefaultLogPath khong duoc la LatestClient.txt");

    const std::string dir = TestName("logpref_dir");
    CreateDirectoryA(dir.c_str(), nullptr);
    const std::string client = dir + "\\Client.txt";
    const std::string latest = dir + "\\LatestClient.txt";
    const std::string fixture = dir + "\\fixture_replay.log";

    {
        std::ofstream f(client, std::ios::binary);
        f << "client\n";
    }
    {
        std::ofstream f(latest, std::ios::binary);
        f << "latest\n";
    }
    {
        std::ofstream f(fixture, std::ios::binary);
        f << "fixture\n";
    }

    CHECK(LogSensor::ResolveLogPath(latest) == client,
          "Khi ca hai file ton tai phai chon Client.txt");
    CHECK(LogSensor::ResolveLogPath(client) == client, "Client.txt giu nguyen");
    CHECK(LogSensor::ResolveLogPath(fixture) == fixture,
          "Fixture test khong bi doi sang Client.txt");

    CHECK(DeleteFileA(client.c_str()) != 0, "Xoa Client.txt tam");
    CHECK(LogSensor::ResolveLogPath(latest) == latest,
          "Khong co Client.txt thi fallback LatestClient.txt");

    DeleteFileA(latest.c_str());
    DeleteFileA(fixture.c_str());
    RemoveDirectoryA(dir.c_str());
    std::cout << "  -> SSoT Client.txt / fallback LatestClient / giu fixture OK" << std::endl;
}

// ==========================================================
// 28. KMBox Smooth Engine & Humanized Mouse
// ==========================================================
void TestKMBoxSmoothEngine() {
    std::cout << "[Test 28] KMBox Smooth Engine & Humanized Mouse..." << std::endl;

    KMBoxNet kmbox;
    kmbox.SetIgnoreWindowFocus(true);
    HumanCurveGenerator curveGen;

    // 1. Kiểm tra chế độ mô phỏng phần mềm
    kmbox.EnableEmulationMode(true);
    CHECK(kmbox.IsEmulationMode(), "EmulationMode phải là true");
    CHECK(kmbox.IsConnected(), "IsConnected phải là true khi bật EmulationMode");

    // Lấy tọa độ hiện tại
    POINT curPt{};
    GetCursorPos(&curPt);

    // Di chuyển tới chính tọa độ hiện tại -> Delta < 2 phải trả về true ngay lập tức
    bool resNear = kmbox.MoveMouseSmooth(curPt.x, curPt.y, curveGen, 10, 0);
    CHECK(resNear, "MoveMouseSmooth khi cự ly < 2 phải trả về true");

    // Di chuyển mượt với steps = 5, stepDelayMs = 0 (tối ưu tốc độ kiểm thử)
    bool resSmooth = kmbox.MoveMouseSmooth(curPt.x + 50, curPt.y + 50, curveGen, 5, 0);
    CHECK(resSmooth, "MoveMouseSmooth trong EmulationMode phải trả về true");

    // Click chuột mô phỏng sinh học (mean = 40ms, stdDev = 5ms)
    bool clickRes = kmbox.ClickMouseHumanized(1, curveGen, 40.0f, 5.0f);
    CHECK(clickRes, "ClickMouseHumanized trong EmulationMode phải trả về true");

    // 2. Kiểm tra chế độ phần cứng khi chưa cắm thiết bị
    kmbox.EnableEmulationMode(false);
    CHECK(!kmbox.IsEmulationMode(), "EmulationMode phải là false");
    CHECK(!kmbox.IsConnected(), "IsConnected phải là false khi chưa cắm thiết bị");

    // Click phần cứng khi chưa kết nối socket phải trả về false an toàn
    bool hwClick = kmbox.ClickMouseHumanized(1, curveGen, 40.0f, 5.0f);
    CHECK(!hwClick, "ClickMouseHumanized khi chưa cắm thiết bị phần cứng phải trả về false an toàn");

    std::cout << "  -> MoveMouseSmooth (Bézier + Fitts), Delta < 2 early exit, ClickMouseHumanized OK" << std::endl;
}

// ==========================================================
// 31. Test Watchdog Passive Co-Pilot Degrade & Recover (Rule 8 & 11)
// ==========================================================
void TestWatchdogPassiveCoPilotDegrade() {
    std::cout << "[Test 31] Watchdog Passive Co-Pilot Degrade & Recover (Rule 8 & 11)..." << std::endl;

    const std::string kName = TestName("Local\\POE2_Auto_TestMem_WdDegrade");
    SharedMemoryManager server;
    CHECK(server.Initialize(true, kName.c_str()), "Server khởi tạo thất bại");

    // 1. Trạng thái ban đầu: Chưa agent nào kết nối
    bool isPassiveCoPilotMode = false;
    auto status0 = server.CheckAgentWatchdog(50);
    CHECK(status0 == SharedMemoryManager::AgentWatchdogStatus::NoAgentEverConnected,
          "Ban đầu phải là NoAgentEverConnected");
    CHECK(!isPassiveCoPilotMode, "Chưa từng kết nối không kích hoạt Co-Pilot Passive");

    // 2. Agent kết nối và gửi heartbeat đầu tiên -> Healthy
    SharedMemoryManager client;
    CHECK(client.Initialize(false, kName.c_str()), "Client kết nối thất bại");
    client.UpdateHeartbeat();

    auto status1 = server.CheckAgentWatchdog(50);
    CHECK(status1 == SharedMemoryManager::AgentWatchdogStatus::Healthy, "Agent vừa gửi heartbeat phải Healthy");

    // 3. Agent mất kết nối (ngừng gửi heartbeat > 50ms) -> TimedOut -> TỰ ĐỘNG HẠ CẤP VỀ CO-PILOT PASSIVE
    std::this_thread::sleep_for(std::chrono::milliseconds(110));
    auto status2 = server.CheckAgentWatchdog(50);
    CHECK(status2 == SharedMemoryManager::AgentWatchdogStatus::TimedOut, "Sau 110ms im lặng phải TimedOut");

    // Mô phỏng logic state machine trong main loop (main.cpp:780-790)
    if (status2 == SharedMemoryManager::AgentWatchdogStatus::TimedOut) {
        if (!isPassiveCoPilotMode) {
            isPassiveCoPilotMode = true;
        }
    }
    CHECK(isPassiveCoPilotMode, "Khi TimedOut, Core PHẢI tự động chuyển sang Co-Pilot Passive mode");

    // 4. Khi ở Co-Pilot Passive, Agent gửi lệnh vĩ mô qua Command Ring nhưng Core KHÔNG die / crash
    CommandPacket cmd{};
    cmd.commandId = 1001;
    cmd.opCode = MacroOpCode::ENGAGE_TARGET;
    CHECK(client.PublishCommand(cmd), "Agent vẫn có thể publish lệnh vào ring buffer");

    CommandPacket fetchedCmd{};
    CHECK(server.FetchNextCommand(fetchedCmd), "Server vẫn rút được lệnh từ ring buffer an toàn");
    CHECK(fetchedCmd.commandId == 1001, "Lệnh #1001 không bị thất lạc");

    // 5. Agent kết nối lại (phục hồi nhịp tim) -> TỰ ĐỘNG PHỤC HỒI CHẾ ĐỘ TỰ HÀNH ĐẦY ĐỦ
    client.UpdateHeartbeat();
    auto status3 = server.CheckAgentWatchdog(50);
    CHECK(status3 == SharedMemoryManager::AgentWatchdogStatus::Healthy, "Heartbeat mới phải đưa status về Healthy");

    if (isPassiveCoPilotMode && status3 == SharedMemoryManager::AgentWatchdogStatus::Healthy) {
        isPassiveCoPilotMode = false;
    }
    CHECK(!isPassiveCoPilotMode, "Khi Healthy trở lại, Core PHẢI tự động phục hồi về Full Autonomous mode");

    std::cout << "  -> Watchdog TimedOut -> Co-Pilot Passive -> Heartbeat Recover OK" << std::endl;
}

// ==========================================================
// 34. Test Watcher Invariant Contract & Real Data Verification (Rule 12, 13 & 14)
//  - Kiểm chứng toàn bộ các Bất Biến Kiến Trúc (Architectural Invariants):
//    1. Vitals Invariant: Anti-778 bogus struct, ES cap <= 20000.
//    2. XYZ Planar Invariant: 2D planar motion (Z=const) nhận diện chính xác.
//    3. Isometric Projection: Dấu trừ canonical trên trục Y.
//    4. Watchdog Invariant: Timeout hạ cấp Co-Pilot Passive, cấm tự sát.
//    5. Real Data Invariant: Sử dụng dữ liệu hiện trường thực tế từ captures/.
// ==========================================================
void TestWatcherInvariantContract() {
    std::cout << "[Test 34] Watcher Invariant Contract & Real Data Verification (Rule 12, 13 & 14)..." << std::endl;

    GameSession session;
    std::string status;
    CHECK(session.Initialize("sim", status), "Khởi tạo GameSession sim thất bại");
    auto* sim = static_cast<SimulatedMemoryReader*>(session.Reader());

    const uintptr_t fakeBase = sim->BaseAddress() + 0x4D0000;
    const uint32_t fakePrefix[2] = { 2, 4 };
    std::memcpy(sim->Raw() + 0x4D0000, fakePrefix, sizeof(fakePrefix));
    const uint32_t bogusDump[] = { 778, 778, 1, 32763, 54, 779, 779 };
    std::memcpy(sim->Raw() + 0x4D0008, bogusDump, sizeof(bogusDump));
    const uintptr_t bogusAddr = fakeBase + 8;

    const uintptr_t realBase = sim->BaseAddress() + 0x4E0000;
    std::memcpy(sim->Raw() + 0x4E0000, fakePrefix, sizeof(fakePrefix));
    const uint32_t realDump[] = { 737, 737, 737, 756, 756, 741, 741 };
    std::memcpy(sim->Raw() + 0x4E0008, realDump, sizeof(realDump));
    const uintptr_t realPlayerAddr = realBase + 8;

    bool vitalsIntegrityOk = !session.IsValidLifeComponent(bogusAddr, false) &&
                             !session.IsValidShieldAddress(bogusAddr + 12) &&
                             session.IsValidLifeComponent(realPlayerAddr, false) &&
                             session.IsValidShieldAddress(realPlayerAddr + 12);
    CHECK(vitalsIntegrityOk, "Vitals integrity and anti-778 real data verification failed");

    const size_t kChunkSize = 1024;
    std::vector<uint8_t> memOverlap(kChunkSize * 2, 0x00);
    const size_t kTarget12 = 1020;
    const uint8_t pat12[12] = { 0xAA, 0xBB, 0xCC, 0xDD, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88 };
    std::memcpy(&memOverlap[kTarget12], pat12, 12);

    bool missed = true;
    for (size_t off = 0; off < memOverlap.size(); off += kChunkSize) {
        size_t scanLen = (std::min)(kChunkSize, memOverlap.size() - off);
        if (scanLen < 12) continue;
        for (size_t i = 0; i <= scanLen - 12; ++i) {
            if (std::memcmp(&memOverlap[off + i], pat12, 12) == 0) { missed = false; break; }
        }
    }
    std::vector<size_t> found12;
    for (size_t off = 0; off < memOverlap.size(); ) {
        size_t scanLen = (std::min)(kChunkSize, memOverlap.size() - off);
        if (scanLen >= 12) {
            for (size_t i = 0; i <= scanLen - 12; ++i) {
                if (std::memcmp(&memOverlap[off + i], pat12, 12) == 0) found12.push_back(off + i);
            }
        }
        if (off + kChunkSize >= memOverlap.size()) break;
        off += kChunkSize - 12;
    }
    CHECK(missed && !found12.empty() && found12[0] == kTarget12, "Chunk boundary overlap 12B failed");

    const float screenW = 1920.0f, screenH = 1080.0f, cx = screenW * 0.5f, cy = screenH * 0.5f;
    auto ptZero = common::WorldToScreenIsometric(0.0f, 0.0f, 0.0f, screenW, screenH, 50.0f);
    auto ptNE = common::WorldToScreenIsometric(100.0f, 100.0f, 50.0f, screenW, screenH, 50.0f);
    auto ptSW = common::WorldToScreenIsometric(-100.0f, -100.0f, 50.0f, screenW, screenH, 50.0f);
    auto ptSE = common::WorldToScreenIsometric(100.0f, -100.0f, 50.0f, screenW, screenH, 50.0f);
    bool isoOk = (std::abs(ptZero.x - cx) < 0.01f && std::abs(ptZero.y - cy) < 0.01f) &&
                 (std::abs(ptNE.x - cx) < 0.01f && ptNE.y < cy) &&
                 (ptSW.y > cy) && (ptSE.x > cx && std::abs(ptSE.y - cy) < 0.01f);
    CHECK(isoOk, "Isometric projection canonical minus sign failed");

    const std::string kWdName = TestName("Local\\POE2_Auto_TestMem_WdContract34");
    SharedMemoryManager wdServer;
    SharedMemoryManager wdClient;
    CHECK(wdServer.Initialize(true, kWdName.c_str()) && wdClient.Initialize(false, kWdName.c_str()), "Watchdog init failed");

    wdClient.UpdateHeartbeat();
    bool healthyOk = (wdServer.CheckAgentWatchdog(50) == SharedMemoryManager::AgentWatchdogStatus::Healthy);
    std::this_thread::sleep_for(std::chrono::milliseconds(110));
    bool timedOutOk = (wdServer.CheckAgentWatchdog(50) == SharedMemoryManager::AgentWatchdogStatus::TimedOut);

    CommandPacket testCmd{};
    testCmd.commandId = 3401;
    CommandPacket recCmd{};
    bool cmdPassOk = wdClient.PublishCommand(testCmd) && wdServer.FetchNextCommand(recCmd) && (recCmd.commandId == 3401);

    wdClient.UpdateHeartbeat();
    bool recoverOk = (wdServer.CheckAgentWatchdog(100) == SharedMemoryManager::AgentWatchdogStatus::Healthy);
    CHECK(healthyOk && timedOutOk && cmdPassOk && recoverOk, "Watchdog Passive Degrade & Isolation failed");

    std::cout << "  -> Watcher Invariant Contract & Real Data Verification OK" << std::endl;
}

// ==========================================================
// 37. AUDIT-3AM-CLI-CONFIG: Kiểm chứng bộ phân tích cờ dòng lệnh CLI & Hotkeys Invariants
// ==========================================================
void TestCliFlagsAndConfigInvariants() {
    std::cout << "[Test 37] CLI Flags & Configuration Invariants..." << std::endl;

    auto parseThreshold = [](float val) -> float {
        return (val > 1.0f) ? (val / 100.0f) : val;
    };
    bool threshOk = (std::abs(parseThreshold(60.0f) - 0.60f) < 1e-4f) &&
                    (std::abs(parseThreshold(0.60f) - 0.60f) < 1e-4f) &&
                    (std::abs(parseThreshold(25.0f) - 0.25f) < 1e-4f) &&
                    (std::abs(parseThreshold(22.0f) - 0.22f) < 1e-4f);
    CHECK(threshOk, "parseThreshold mismatch");

    QuestNavConfig qCfg;
    qCfg.targetZone = "Sandswept Marsh";
    QuestNavigator qNav(qCfg);
    QuestNavConfig qCfg2;
    qCfg2.targetZone = "G2_town";
    qNav.State().targetName = "";
    qNav.SetConfig(qCfg2);
    CHECK(qNav.State().targetName == "G2_town", "QuestNavigator targetZone config mismatch");

    AutoLoginConfig alCfg;
    alCfg.charSlot = 3;
    alCfg.characterName = "BEONGUSI";
    CHECK(alCfg.charSlot == 3 && alCfg.characterName == "BEONGUSI", "AutoLoginConfig slot/name mismatch");

    auto parseMoveMode = [](std::string mm) -> MovementMode {
        for (char& c : mm) c = static_cast<char>(::tolower(static_cast<unsigned char>(c)));
        if (mm == "wasd") return MovementMode::WASD;
        return MovementMode::MOUSE;
    };
    bool mmOk = (parseMoveMode("wasd") == MovementMode::WASD) &&
                (parseMoveMode("WASD") == MovementMode::WASD) &&
                (parseMoveMode("mouse") == MovementMode::MOUSE) &&
                (parseMoveMode("MOUSE") == MovementMode::MOUSE);
    CHECK(mmOk, "parseMoveMode case-insensitivity failed");

    auto isPanicStopSim = [](bool keyPause, bool keyCtrl, bool keyShift, bool keyF12) -> bool {
        return keyPause || (keyCtrl && keyShift && keyF12);
    };
    bool panicOk = !isPanicStopSim(false, false, false, true) &&
                   isPanicStopSim(true, false, false, false) &&
                   isPanicStopSim(false, true, true, true) &&
                   !isPanicStopSim(false, false, true, true) &&
                   !isPanicStopSim(false, true, false, true);
    CHECK(panicOk, "Panic stop key logic mismatch");

    ComboConfig testComboCfg;
    QuestNavConfig testQuestCfg;
    CHECK(testComboCfg.primarySkillVk == VK_RBUTTON && testComboCfg.isRangedMode &&
          testQuestCfg.combatStopDistance == 380.0f && testQuestCfg.isRanged,
          "Ranged combat defaults mismatch");

    auto applySkillCli = [](const std::vector<std::string>& args, ComboConfig& cCfg, QuestNavConfig& qCfg) {
        for (size_t i = 0; i < args.size(); ++i) {
            if (args[i] == "--skill-rmb" || args[i] == "--ranged") {
                cCfg.primarySkillVk = VK_RBUTTON;
                cCfg.isRangedMode = true;
                qCfg.combatStopDistance = 380.0f;
                qCfg.isRanged = true;
            } else if (args[i] == "--skill-lmb" || args[i] == "--melee") {
                cCfg.primarySkillVk = VK_LBUTTON;
                cCfg.isRangedMode = false;
                qCfg.combatStopDistance = 220.0f;
                qCfg.isRanged = false;
            } else if (args[i] == "--primary-skill" && i + 1 < args.size()) {
                std::string ps = args[++i];
                for (char& c : ps) c = static_cast<char>(::tolower(static_cast<unsigned char>(c)));
                if (ps == "rmb" || ps == "right" || ps == "rbutton") {
                    cCfg.primarySkillVk = VK_RBUTTON;
                    cCfg.isRangedMode = true;
                    qCfg.combatStopDistance = 380.0f;
                    qCfg.isRanged = true;
                } else if (ps == "lmb" || ps == "left" || ps == "lbutton") {
                    cCfg.primarySkillVk = VK_LBUTTON;
                    cCfg.isRangedMode = false;
                    qCfg.combatStopDistance = 220.0f;
                    qCfg.isRanged = false;
                }
            }
        }
    };

    ComboConfig c1; QuestNavConfig q1;
    applySkillCli({"--skill-lmb"}, c1, q1);
    ComboConfig c2; QuestNavConfig q2;
    applySkillCli({"--skill-rmb"}, c2, q2);
    CHECK(c1.primarySkillVk == VK_LBUTTON && !c1.isRangedMode && q1.combatStopDistance == 220.0f &&
          c2.primarySkillVk == VK_RBUTTON && c2.isRangedMode && q2.combatStopDistance == 380.0f,
          "CLI skill flag parser failed");

    auto parseMaxHpCli = [](const std::vector<std::string>& args) -> uint32_t {
        uint32_t hp = 0;
        for (size_t i = 0; i < args.size(); ++i) {
            if (args[i] == "--max-hp" && i + 1 < args.size()) {
                hp = static_cast<uint32_t>(std::strtoul(args[++i].c_str(), nullptr, 10));
            } else if (args[i] == "--ci" || args[i] == "--chaos-inoculation") {
                hp = 1;
            }
        }
        return hp;
    };
    ReflexConfig reflexCfg;
    QuestNavConfig questCfg;
    UnstuckConfig unstuckCfg;
    CHECK(parseMaxHpCli({"--max-hp", "1200"}) == 1200 && parseMaxHpCli({"--ci"}) == 1 &&
          reflexCfg.portalVk == 0xBE && questCfg.portalVk == 0xBE && unstuckCfg.portalVk == 0xBE &&
          questCfg.pulseEWithForward == false,
          "CLI CI max HP & portal key invariants mismatch");

    std::cout << "  -> CLI Flags, Target Zone, Character Slot & Hotkeys Invariants OK" << std::endl;
}

// ==========================================================
// Test 85: Core Engine Common Kernel Libraries (DOC-49 & Rule 16)
// ==========================================================
void TestCommonKernelLibraries() {
    std::cout << "[Test 85] Core Engine Common Kernel Libraries (math2d, string_utils, time_utils, toml_parser, window_utils)..." << std::endl;

    // 1. Math2D (Vec2, operators, Length, Distance, Normalized, Dot, Lerp, Isometric, WASD)
    common::Vec2 v1(3.0f, 4.0f);
    common::Vec2 v2(6.0f, 8.0f);
    common::Vec2 vNorm = v1.Normalized();
    common::Vec2 vAdd = v1 + v2;
    common::Vec2 vSub = v2 - v1;
    common::Vec2 vMul = v1 * 2.0f;
    common::Vec2 vDiv = v2 / 2.0f;
    common::Vec2 vLerp = common::Vec2::Lerp(common::Vec2(0.0f, 0.0f), common::Vec2(10.0f, 20.0f), 0.5f);

    bool vec2MathOk = (std::abs(v1.LengthSq() - 25.0f) < 0.001f) &&
                      (std::abs(v1.Length() - 5.0f) < 0.001f) &&
                      (std::abs(v1.Distance(v2) - 5.0f) < 0.001f) &&
                      (std::abs(vNorm.Length() - 1.0f) < 0.001f) &&
                      (std::abs(vNorm.x - 0.6f) < 0.001f) && (std::abs(vNorm.y - 0.8f) < 0.001f) &&
                      (vAdd.x == 9.0f && vAdd.y == 12.0f) &&
                      (vSub.x == 3.0f && vSub.y == 4.0f) &&
                      (vMul.x == 6.0f && vMul.y == 8.0f) &&
                      (vDiv.x == 3.0f && vDiv.y == 4.0f) &&
                      (std::abs(v1.Dot(v2) - 50.0f) < 0.001f) &&
                      (vLerp.x == 5.0f && vLerp.y == 10.0f);
    CHECK(vec2MathOk, "Vec2 toan hoc (operators, Length, Distance, Normalized, Dot, Lerp) phai dung");

    auto sp = common::WorldToScreenIsometric(100.0f, 0.0f, 1920.0f, 1080.0f);
    auto wasd = common::WorldToWasd(100.0f, 0.0f);
    CHECK(sp.x > 960 && !wasd.empty(), "WorldToScreenIsometric va WorldToWasd phai hop le");

    // 2. StringUtils
    auto tokens = common::Split("path,of,exile,2", ',');
    bool strUtilsOk = (common::ToLower("AutoPOE2_Core_Engine") == "autopoe2_core_engine") &&
                      (common::Trim("  \t\r\n  hello world  \r\n\t ") == std::string_view("hello world")) &&
                      (common::Trim("") == std::string_view("")) &&
                      (tokens.size() == 4 && tokens[0] == "path" && tokens[3] == "2") &&
                      common::StartsWith("Path of Exile 2", "Path") &&
                      !common::StartsWith("Path of Exile 2", "Exile") &&
                      common::EndsWith("Client.txt", ".txt") &&
                      !common::EndsWith("Client.txt", ".exe");
    CHECK(strUtilsOk, "StringUtils (ToLower, Trim, Split, StartsWith, EndsWith) phai dung");

    const uint8_t rawBytes[] = { 0xDE, 0xAD, 0xBE, 0xEF };
    CHECK(common::HexStr(rawBytes, sizeof(rawBytes), false) == "DEADBEEF" &&
          common::HexStr(rawBytes, sizeof(rawBytes), true) == "DE AD BE EF" &&
          common::HexStr(static_cast<uint64_t>(0x1234), true, 4) == "0x1234",
          "HexStr dinh dang byte va uint64_t phai dung");

    // 3. TimeUtils
    common::RateLimiter limiter(100);
    common::CooldownTimer cd(500);
    cd.Trigger(1000);
    common::Stopwatch sw;
    sw.Start();

    bool timeUtilsOk = (common::NowMs() > 0) &&
                       limiter.CanProceed(1000) && !limiter.CanProceed(1050) && limiter.CanProceed(1105) &&
                       !cd.IsReady(1200) && cd.RemainingMs(1200) == 300 && cd.IsReady(1501) &&
                       (sw.ElapsedMs() >= 0);
    CHECK(timeUtilsOk, "TimeUtils (NowMs, RateLimiter, CooldownTimer, Stopwatch) phai dung");

    // 4. TomlParser
    float zoomCap = 0.0f, dummy = 99.0f;
    int stepDelay = 0;
    uint32_t timeoutMs = 0;
    bool bTrue = false, bFalse = true;
    std::string zoneName;

    bool tomlOk = common::ParseTomlFloat("zoom_cap = 2.75", "zoom_cap", zoomCap) && std::abs(zoomCap - 2.75f) < 0.001f &&
                  !common::ParseTomlFloat("other_key = 5.0", "zoom_cap", dummy) &&
                  common::ParseTomlInt("step_delay = -42", "step_delay", stepDelay) && stepDelay == -42 &&
                  common::ParseTomlUint("timeout_ms = 5000", "timeout_ms", timeoutMs) && timeoutMs == 5000 &&
                  common::ParseTomlBool("auto_patrol = true", "auto_patrol", bTrue) && bTrue &&
                  common::ParseTomlBool("auto_patrol = false", "auto_patrol", bFalse) && !bFalse &&
                  common::ParseTomlString("name = \"Hideout\"", "name", zoneName) && zoneName == "Hideout";
    CHECK(tomlOk, "TomlParser (float, int, uint, bool, string) phai parse chinh xac");

    // 5. WindowUtils
    std::wstring exeDir = common::GetExecutableDirectory();
    CHECK(!exeDir.empty() && common::GetDpiScale(nullptr) == 1.0f,
          "WindowUtils GetExecutableDirectory va GetDpiScale(nullptr) phai dung");

    std::cout << "  -> Core Engine Common Kernel Libraries OK" << std::endl;
}

// ==========================================================
// Test 86: KMBox Bidirectional Key Translation & Reflex Kiting Lock
// ==========================================================
void TestKmboxBidirectionalAndKitingLock() {
    std::cout << "[Test 86] KMBox Bidirectional Key Translation & Reflex Kiting Lock..." << std::endl;

    // 1. Ánh xạ hai chiều Windows VK <-> USB HID (Table-driven verification)
    struct KeyPair { uint8_t vk; uint8_t hid; };
    const KeyPair kPairs[] = {
        {'W', 0x1A}, {'A', 0x04}, {'S', 0x16}, {'D', 0x07},
        {'E', 0x08}, {'F', 0x09},
        {VK_SPACE, 0x2C}, {VK_ESCAPE, 0x29}, {VK_OEM_PERIOD, 0x37},
        {'1', 0x1E}, {'5', 0x22}
    };
    bool allKeysOk = true;
    for (const auto& kp : kPairs) {
        if (KMBoxNet::VkToUsbHid(kp.vk) != kp.hid || KMBoxNet::UsbHidToVk(kp.hid) != kp.vk) {
            allKeysOk = false;
            break;
        }
    }
    CHECK(allKeysOk, "Anh xa hai chieu giua Windows VK va USB HID phai chinh xac");

    // 2. ReflexManager Kiting Lock (m_consumedExclusiveInput)
    ReflexConfig rcfg;
    ReflexManager rm(rcfg);
    CHECK(!rm.ConsumedExclusiveInput(), "ConsumedExclusiveInput ban dau phai la false");

    KMBoxNet kmbox;
    kmbox.SetIgnoreWindowFocus(true);
    kmbox.EnableEmulationMode(true);

    rm.TriggerKiting(0.0f, 50.0f, kmbox, 1000);
    CHECK(rm.ConsumedExclusiveInput(), "ConsumedExclusiveInput phai la true sau khi TriggerKiting kich hoat");

    rm.SetConsumedExclusiveInput(false);
    CHECK(!rm.ConsumedExclusiveInput(), "ConsumedExclusiveInput phai reset thanh false sau khi SetConsumedExclusiveInput(false)");

    std::cout << "  -> KMBox Bidirectional Key Translation & Reflex Kiting Lock OK" << std::endl;
}

// ==========================================================
// Test 87: IPC Command Directives & Profile Switching
// ==========================================================
void TestIpcCommandDirectivesAndProfileSwitching() {
    std::cout << "[Test 87] IPC Command Directives & Profile Switching (FORCE_PORTAL_RETURN & SET_COMBAT_PROFILE)..." << std::endl;

    const std::string kName = TestName("Local\\POE2_Auto_TestCmdDirectives");

    SharedMemoryManager server;
    CHECK(server.Initialize(true, kName.c_str()), "Server khởi tạo thất bại");

    SharedMemoryManager client;
    CHECK(client.Initialize(false, kName.c_str()), "Client khởi tạo thất bại");

    // 1. Kiểm thử OPCODE_FORCE_PORTAL_RETURN (11) qua SPSC Ring Buffer
    CommandPacket cmdPortal{};
    cmdPortal.commandId = 1001;
    cmdPortal.opCode = MacroOpCode::FORCE_PORTAL_RETURN;
    cmdPortal.timeoutMs = 1000;
    CHECK(client.PublishCommand(cmdPortal), "Publish FORCE_PORTAL_RETURN phải thành công");

    CommandPacket fetched{};
    CHECK(server.FetchNextCommand(fetched), "Fetch FORCE_PORTAL_RETURN phải thành công");
    CHECK(fetched.commandId == 1001, "Command ID phải khớp 1001");
    CHECK(fetched.opCode == MacroOpCode::FORCE_PORTAL_RETURN, "OpCode phải là FORCE_PORTAL_RETURN (11)");
    CHECK(static_cast<uint32_t>(fetched.opCode) == 11, "Giá trị số OpCode phải là 11");

    // 2. Kiểm thử NonBlockingActuator thực thi phím '.' (VK_OEM_PERIOD = 0xBE) dwell 100ms
    KMBoxNet kmbox;
    kmbox.EnableEmulationMode(true);
    kmbox.SetIgnoreWindowFocus(true);
    input::NonBlockingActuator actuator(kmbox);

    CHECK(!actuator.IsKeyHeld(0xBE), "Phím '.' ban đầu không được ở trạng thái held");
    const uint64_t tStart = 100000;
    CHECK(actuator.KeyPressVk(0xBE, 100, tStart), "Actuator KeyPressVk '.' phải thành công");
    CHECK(actuator.IsKeyHeld(0xBE), "Phím '.' phải được giữ sau khi KeyPressVk");
    CHECK(actuator.ActiveSlotCount() == 1, "ActiveSlotCount phải là 1");

    // Tick tại tStart + 50ms (chưa hết dwell 100ms)
    actuator.ProcessPendingReleases(tStart + 50);
    CHECK(actuator.IsKeyHeld(0xBE), "Phím '.' vẫn phải được giữ tại tStart + 50ms");

    // Tick tại tStart + 101ms (đã hết dwell 100ms)
    actuator.ProcessPendingReleases(tStart + 101);
    CHECK(!actuator.IsKeyHeld(0xBE), "Phím '.' phải được nhả sau 101ms");
    CHECK(actuator.ActiveSlotCount() == 0, "ActiveSlotCount phải trở về 0 sau khi nhả");

    // 3. Kiểm thử OPCODE_SET_COMBAT_PROFILE (12) & ComboManager state transitions
    ComboConfig comboCfg;
    comboCfg.enabled = true;
    ComboManager comboMgr(comboCfg);

    CHECK(comboMgr.GetCombatProfile() == CombatProfile::MOB_CLEARING, "Mặc định CombatProfile phải là MOB_CLEARING");
    CHECK(!comboMgr.IsBossBurstWindow(), "Mặc định BossBurstWindow phải là false");

    // Switch sang BOSS_BURST (targetX = 1.0f, targetEntityId = 8888)
    CommandPacket cmdBoss{};
    cmdBoss.commandId = 1002;
    cmdBoss.opCode = MacroOpCode::SET_COMBAT_PROFILE;
    cmdBoss.targetX = static_cast<float>(CombatProfile::BOSS_BURST);
    cmdBoss.targetEntityId = 8888;
    CHECK(client.PublishCommand(cmdBoss), "Publish SET_COMBAT_PROFILE BOSS_BURST phải thành công");

    CHECK(server.FetchNextCommand(fetched), "Fetch SET_COMBAT_PROFILE BOSS_BURST phải thành công");
    CHECK(fetched.opCode == MacroOpCode::SET_COMBAT_PROFILE, "OpCode phải là SET_COMBAT_PROFILE (12)");
    CHECK(static_cast<uint32_t>(fetched.opCode) == 12, "Giá trị số OpCode phải là 12");
    CHECK(fetched.targetEntityId == 8888, "targetEntityId phải là 8888");

    auto targetProf = static_cast<CombatProfile>(static_cast<uint32_t>(fetched.targetX));
    comboMgr.SetCombatProfile(targetProf, fetched.targetEntityId);
    CHECK(comboMgr.GetCombatProfile() == CombatProfile::BOSS_BURST, "Profile phải chuyển sang BOSS_BURST");
    CHECK(comboMgr.IsBossBurstWindow(), "isBossBurstWindow phải kích hoạt khi ở BOSS_BURST");

    // Switch sang MOB_CLEARING (targetX = 0.0f)
    CommandPacket cmdMob{};
    cmdMob.commandId = 1003;
    cmdMob.opCode = MacroOpCode::SET_COMBAT_PROFILE;
    cmdMob.targetX = static_cast<float>(CombatProfile::MOB_CLEARING);
    cmdMob.targetEntityId = 0;
    CHECK(client.PublishCommand(cmdMob), "Publish SET_COMBAT_PROFILE MOB_CLEARING phải thành công");

    CHECK(server.FetchNextCommand(fetched), "Fetch SET_COMBAT_PROFILE MOB_CLEARING phải thành công");
    targetProf = static_cast<CombatProfile>(static_cast<uint32_t>(fetched.targetX));
    comboMgr.SetCombatProfile(targetProf, fetched.targetEntityId);
    CHECK(comboMgr.GetCombatProfile() == CombatProfile::MOB_CLEARING, "Profile phải chuyển về MOB_CLEARING");
    CHECK(!comboMgr.IsBossBurstWindow(), "isBossBurstWindow phải tắt khi về MOB_CLEARING");

    // Switch sang SURVIVAL_KITING (targetX = 2.0f)
    CommandPacket cmdKite{};
    cmdKite.commandId = 1004;
    cmdKite.opCode = MacroOpCode::SET_COMBAT_PROFILE;
    cmdKite.targetX = static_cast<float>(CombatProfile::SURVIVAL_KITING);
    cmdKite.targetEntityId = 0;
    CHECK(client.PublishCommand(cmdKite), "Publish SET_COMBAT_PROFILE SURVIVAL_KITING phải thành công");

    CHECK(server.FetchNextCommand(fetched), "Fetch SET_COMBAT_PROFILE SURVIVAL_KITING phải thành công");
    targetProf = static_cast<CombatProfile>(static_cast<uint32_t>(fetched.targetX));
    comboMgr.SetCombatProfile(targetProf, fetched.targetEntityId);
    CHECK(comboMgr.GetCombatProfile() == CombatProfile::SURVIVAL_KITING, "Profile phải chuyển sang SURVIVAL_KITING");
    CHECK(!comboMgr.IsBossBurstWindow(), "isBossBurstWindow phải tắt khi ở SURVIVAL_KITING");

    // 4. Stress SPSC Ring & 0 Torn-Read verification
    constexpr int kStressCount = 2000;
    std::atomic<bool> producerDone{false};
    std::atomic<int> tornReadCount{0};
    std::atomic<int> consumedCount{0};

    std::thread consumerThread([&]() {
        CommandPacket c{};
        while (!producerDone.load(std::memory_order_acquire)) {
            while (server.FetchNextCommand(c)) {
                consumedCount.fetch_add(1, std::memory_order_relaxed);
                if (c.commandId != static_cast<uint64_t>(c.targetEntityId)) {
                    tornReadCount.fetch_add(1, std::memory_order_relaxed);
                }
                if (c.opCode != MacroOpCode::SET_COMBAT_PROFILE && c.opCode != MacroOpCode::FORCE_PORTAL_RETURN) {
                    tornReadCount.fetch_add(1, std::memory_order_relaxed);
                }
            }
            std::this_thread::yield();
        }
        while (server.FetchNextCommand(c)) {
            consumedCount.fetch_add(1, std::memory_order_relaxed);
            if (c.commandId != static_cast<uint64_t>(c.targetEntityId)) {
                tornReadCount.fetch_add(1, std::memory_order_relaxed);
            }
            if (c.opCode != MacroOpCode::SET_COMBAT_PROFILE && c.opCode != MacroOpCode::FORCE_PORTAL_RETURN) {
                tornReadCount.fetch_add(1, std::memory_order_relaxed);
            }
        }
    });

    for (int i = 0; i < kStressCount; ++i) {
        CommandPacket c{};
        c.commandId = 20000 + i;
        c.opCode = (i % 2 == 0) ? MacroOpCode::FORCE_PORTAL_RETURN : MacroOpCode::SET_COMBAT_PROFILE;
        c.targetEntityId = static_cast<uint32_t>(c.commandId);
        c.targetX = (i % 2 == 0) ? 0.0f : 1.0f;
        while (!client.PublishCommand(c)) {
            std::this_thread::yield();
        }
    }
    producerDone.store(true, std::memory_order_release);
    consumerThread.join();

    CHECK(tornReadCount.load() == 0, "Không được có bất kỳ torn-read nào trong SPSC Ring");
    CHECK(consumedCount.load() == kStressCount, "Toàn bộ lệnh stress phải được consume trọn vẹn");

    // 5. Benchmark 50,000 iterations: Publish + Fetch + Profile Switching latency (< 1.0 µs)
    constexpr int kBenchIters = 50000;
    CommandPacket benchCmd{};
    benchCmd.commandId = 99999;
    benchCmd.opCode = MacroOpCode::SET_COMBAT_PROFILE;
    benchCmd.targetX = static_cast<float>(CombatProfile::BOSS_BURST);
    benchCmd.targetEntityId = 777;

    CommandPacket benchFetched{};
    // Tắt cout buffer trong benchmark để loại bỏ độ trễ hiển thị console Windows
    auto* prevBuf = std::cout.rdbuf(nullptr);
    auto t0 = std::chrono::high_resolution_clock::now();
    for (int i = 0; i < kBenchIters; ++i) {
        client.PublishCommand(benchCmd);
        server.FetchNextCommand(benchFetched);
        auto prof = static_cast<CombatProfile>(static_cast<uint32_t>(benchFetched.targetX));
        comboMgr.SetCombatProfile(prof, benchFetched.targetEntityId);
    }
    auto t1 = std::chrono::high_resolution_clock::now();
    std::cout.rdbuf(prevBuf);

    const double totalUs = std::chrono::duration<double, std::micro>(t1 - t0).count();
    const double avgUs = totalUs / static_cast<double>(kBenchIters);

    CHECK(avgUs < 1.0, "Độ trễ trung bình Publish + Fetch + Profile Switch phải < 1.0 us");

    std::cout << "  -> IPC Command Directives & Profile Switching OK: "
              << kBenchIters << " iters, avg latency = " << avgUs << " us/iter (< 1.0 us threshold)"
              << std::endl;
}


