path = "c:/Projects/AutoPOE2/src/core/memory/visual_mods.cpp"
with open(path, "r", encoding="utf-8") as f:
    content = f.read()

target = '''    // 1. Quét tìm clamp trong .text nếu chưa có địa chỉ
    if (m_zoomCodePatch.address == 0) {
        ModuleInfo mainMod;
        const uint32_t pid = m_reader.AttachedPid();
        if (ResolveMainModule(pid, m_reader, mainMod) && mainMod.base != 0 && mainMod.size != 0) {
            // POE2 clamp pattern: cmp byte ptr [rax+2Fh], 0
            const AobPattern clampPat = AobPattern::Parse("80 78 2F 00");
            uintptr_t match = AobScanner::ScanModule(m_reader, mainMod, clampPat);
            if (match != 0) {
                m_zoomCodePatch.address = match;
                m_zoomCodePatch.name = "CameraClampBypass_cmp2F";
                std::cout << "[VisualMods] Tim thay Zoom Clamp tai .text @ 0x"
                          << std::hex << match << std::dec << std::endl;
            }
        }
    }'''

repl = '''    // 1. Quét tìm clamp trong .text nếu chưa có địa chỉ (Multi-AOB + Context Sanity Verification)
    if (m_zoomCodePatch.address == 0) {
        ModuleInfo mainMod;
        const uint32_t pid = m_reader.AttachedPid();
        if (ResolveMainModule(pid, m_reader, mainMod) && mainMod.base != 0 && mainMod.size != 0) {
            // Ma trận mẫu AOB dự phòng theo thứ tự ưu tiên
            const std::string candidatePatterns[] = {
                "80 78 2F 00",            // Mẫu chính: cmp byte ptr [rax+2Fh], 0
                "80 ? 2F 00",             // Biến thể thanh ghi: cmp byte ptr [reg+2Fh], 0 (rcx, rdx, rbx, rsi, rdi)
                "F3 0F 10 ? 34 0F 2F"      // Biến thể so sánh float: movss xmm, [reg+34h]; comiss
            };

            for (const auto& patStr : candidatePatterns) {
                const AobPattern clampPat = AobPattern::Parse(patStr);
                auto hits = AobScanner::ScanModuleHits(m_reader, mainMod, clampPat, 4 * 1024 * 1024, 8);
                for (uintptr_t cand : hits) {
                    // Pre-Patch Context Sanity Check:
                    // Đọc cửa sổ 32 byte để xác thực ngữ cảnh Camera (phải có +0x34 maxDistance, +0x2C, hoặc 0x0F 0x2F comiss)
                    uint8_t win[32] = {};
                    if (m_reader.Read(cand, win, sizeof(win))) {
                        bool hasCameraContext = false;
                        for (size_t k = 0; k < sizeof(win) - 1; ++k) {
                            if (win[k] == 0x34 || win[k] == 0x2C || (win[k] == 0x0F && win[k+1] == 0x2F)) {
                                hasCameraContext = true;
                                break;
                            }
                        }
                        if (hasCameraContext) {
                            m_zoomCodePatch.address = cand;
                            m_zoomCodePatch.name = "CameraClampBypass_" + patStr;
                            std::cout << "[VisualMods] Tim thay Zoom Clamp hop le tai .text @ 0x"
                                      << std::hex << cand << std::dec << " (Pattern: " << patStr << ")" << std::endl;
                            break;
                        }
                    }
                }
                if (m_zoomCodePatch.address != 0) break;
            }

            if (m_zoomCodePatch.address == 0) {
                std::cout << "[VisualMods] Canh bao: Khong tim thay AOB clamp hop le trong .text (Game patch hoac binary khac biet)."
                          << " Tu dong ha cap xuong che do Data-Only Heap Mode an toan!" << std::endl;
            }
        }
    }'''

if target in content:
    content = content.replace(target, repl, 1)
    with open(path, "w", encoding="utf-8") as f:
        f.write(content)
    print("Successfully enhanced ApplyZoomCodePatch with multi-AOB and context verification.")
else:
    print("Target not found in visual_mods.cpp")
