/**
 * MVGAL WoW64 Thunk Layer - Enhanced Implementation
 *
 * Bridges 32-bit Windows applications running under Wine/Proton to the 64-bit MVGAL runtime.
 * Handles:
 *   - Structure repacking (32-bit pointers to 64-bit)
 *   - Calling convention translation (stdcall to System V)
 *   - Handle mapping (32-bit to 64-bit)
 *   - Registry/INI emulation for GPU configuration
 *   - Gaming workload optimization for Steam/Proton integration
 *   - Frame pacing for multi-GPU gaming
 *
 * SPDX-License-Identifier: MIT
 */

#include "mvgal/mvgal_wow64.h"

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
#include <unistd.h>
#include <sys/mman.h>
#include <errno.h>
#include <time.h>
#include <stdatomic.h>

/* ============================================================================
 * WoW64 State
 * ============================================================================ */

static bool g_wow64_initialized = false;
static pthread_mutex_t g_wow64_mutex = PTHREAD_MUTEX_INITIALIZER;
static mvgal_wow64_config_t g_wow64_config = {0};

/* Handle mapping tables */
#define MVGAL_WOW64_MAX_HANDLES 4096

typedef struct {
    uint32_t handle32;
    void* ptr64;
    bool used;
    uint32_t type; /* 0=buffer, 1=fence, 2=semaphore, 3=queue */
} wow64_handle_entry_t;

static wow64_handle_entry_t g_wow64_handles[MVGAL_WOW64_MAX_HANDLES];
static uint32_t g_wow64_next_handle = 0x10000000; /* Start at 256MB to avoid low addresses */

/* Gaming state tracking */
static struct {
    uint64_t last_frame_time_ns;
    uint64_t frame_count;
    uint32_t current_gpu_idx; /* For AFR: 0 or 1 */
} g_wow64_gaming_state = {0};

/* ============================================================================
 * WoW64 Handle Management
 * ============================================================================ */

static wow64_handle_entry_t* allocate_wow64_handle(void* ptr64)
{
    pthread_mutex_lock(&g_wow64_mutex);
    
    for (int i = 0; i < MVGAL_WOW64_MAX_HANDLES; i++) {
        if (!g_wow64_handles[i].used) {
            g_wow64_handles[i].handle32 = g_wow64_next_handle++;
            g_wow64_handles[i].ptr64 = ptr64;
            g_wow64_handles[i].used = true;
            pthread_mutex_unlock(&g_wow64_mutex);
            return &g_wow64_handles[i];
        }
    }
    
    pthread_mutex_unlock(&g_wow64_mutex);
    return NULL;
}

static void* lookup_wow64_handle(uint32_t handle32)
{
    pthread_mutex_lock(&g_wow64_mutex);
    
    for (int i = 0; i < MVGAL_WOW64_MAX_HANDLES; i++) {
        if (g_wow64_handles[i].used && g_wow64_handles[i].handle32 == handle32) {
            void* ptr = g_wow64_handles[i].ptr64;
            pthread_mutex_unlock(&g_wow64_mutex);
            return ptr;
        }
    }
    
    pthread_mutex_unlock(&g_wow64_mutex);
    return NULL;
}

static void free_wow64_handle(uint32_t handle32)
{
    pthread_mutex_lock(&g_wow64_mutex);
    
    for (int i = 0; i < MVGAL_WOW64_MAX_HANDLES; i++) {
        if (g_wow64_handles[i].used && g_wow64_handles[i].handle32 == handle32) {
            g_wow64_handles[i].used = false;
            break;
        }
    }
    
    pthread_mutex_unlock(&g_wow64_mutex);
}

/* ============================================================================
 * WoW64 Initialization
 * ============================================================================ */

bool mvgal_wow64_is_active(void)
{
    /* Check if we're running as 32-bit on 64-bit system */
    /* This is typically detected via Wine's WoW64 detection */
    const char* wine_arch = getenv("WINEARCH");
    const char* wine_loader = getenv("WINELOADER");
    
    return (wine_arch && strcmp(wine_arch, "win64") != 0) ||
           (wine_loader && strstr(wine_loader, "wine") != NULL);
}

bool mvgal_wow64_init(void)
{
    pthread_mutex_lock(&g_wow64_mutex);
    
    if (g_wow64_initialized) {
        pthread_mutex_unlock(&g_wow64_mutex);
        return true;
    }
    
    /* Initialize handle table */
    memset(g_wow64_handles, 0, sizeof(g_wow64_handles));
    g_wow64_next_handle = 0x10000000;
    
    /* Set default configuration */
    memset(&g_wow64_config, 0, sizeof(g_wow64_config));
    g_wow64_config.context_type = MVGAL_WOW64_CONTEXT_UNKNOWN;
    g_wow64_config.enable_frame_pacing = false;
    g_wow64_config.enable_afr = false;
    g_wow64_config.gpu_mask = 0x3; /* Default: first 2 GPUs */
    g_wow64_config.strategy = 0; /* Auto */
    g_wow64_config.power_limit_scale = 1.0f;
    
    /* Initialize gaming state */
    memset(&g_wow64_gaming_state, 0, sizeof(g_wow64_gaming_state));
    
    g_wow64_initialized = true;
    pthread_mutex_unlock(&g_wow64_mutex);
    
    fprintf(stderr, "[MVGAL-WoW64] WoW64 thunk layer initialized\n");
    return true;
}

bool mvgal_wow64_init_with_config(const mvgal_wow64_config_t *config)
{
    if (!mvgal_wow64_init()) {
        return false;
    }
    
    if (config) {
        pthread_mutex_lock(&g_wow64_mutex);
        g_wow64_config = *config;
        pthread_mutex_unlock(&g_wow64_mutex);
        
        fprintf(stderr, "[MVGAL-WoW64] Config applied: context=%d, afr=%d, frame_pacing=%d\n",
                config->context_type, config->enable_afr, config->enable_frame_pacing);
    }
    
    return true;
}

void mvgal_wow64_shutdown(void)
{
    pthread_mutex_lock(&g_wow64_mutex);
    g_wow64_initialized = false;
    pthread_mutex_unlock(&g_wow64_mutex);
}

/* ============================================================================
 * WoW64 Instance Management
 * ============================================================================ */

struct mvgal_wow64_instance {
    void* instance64;     /* 64-bit VkInstance */
    uint32_t gpu_mask;    /* Which GPUs are available */
};

mvgal_wow64_instance_t* mvgal_wow64_create_instance(void)
{
    if (!mvgal_wow64_init()) {
        return NULL;
    }
    
    mvgal_wow64_instance_t* inst = calloc(1, sizeof(*inst));
    if (!inst) {
        return NULL;
    }
    
    /* Forward to MVGAL core */
    /* In production, this would call into the actual Vulkan loader */
    inst->instance64 = (void*)1; /* Placeholder */
    
    /* Get available GPUs */
    inst->gpu_mask = 0x3; /* Assume 2 GPUs for now */
    
    return inst;
}

void mvgal_wow64_destroy_instance(mvgal_wow64_instance_t* instance)
{
    if (!instance) {
        return;
    }
    
    /* Forward to MVGAL core for cleanup */
    free(instance);
}

/* ============================================================================
 * WoW64 Device Management
 * ============================================================================ */

struct mvgal_wow64_device {
    mvgal_wow64_instance_t* parent_instance;
    void* device64;
    uint32_t gpu_index;
};

mvgal_wow64_device_t* mvgal_wow64_create_device(mvgal_wow64_instance_t* instance,
                                                   uint32_t device_idx)
{
    if (!instance || !g_wow64_initialized) {
        return NULL;
    }
    
    mvgal_wow64_device_t* dev = calloc(1, sizeof(*dev));
    if (!dev) {
        return NULL;
    }
    
    dev->parent_instance = instance;
    dev->device64 = (void*)(uintptr_t)(device_idx + 2); /* Placeholder */
    dev->gpu_index = device_idx;
    
    return dev;
}

void mvgal_wow64_destroy_device(mvgal_wow64_device_t* device)
{
    if (!device) {
        return;
    }
    
    free(device);
}

/* ============================================================================
 * WoW64 Buffer Management
 * ============================================================================ */

struct mvgal_wow64_buffer {
    mvgal_wow64_device_t* parent_device;
    void* buffer64;
    uint64_t size;
    void* mapped_ptr;
    uint64_t mapped_size;
};

mvgal_wow64_buffer_t* mvgal_wow64_create_buffer(mvgal_wow64_device_t* device,
                                                   uint64_t size,
                                                   uint32_t flags)
{
    if (!device || !g_wow64_initialized) {
        return NULL;
    }
    
    mvgal_wow64_buffer_t* buf = calloc(1, sizeof(*buf));
    if (!buf) {
        return NULL;
    }
    
    buf->parent_device = device;
    buf->size = size;
    buf->buffer64 = (void*)0xDEADBEEF; /* Placeholder */
    
    /* In production, allocate via MVGAL memory manager */
    
    return buf;
}

void mvgal_wow64_destroy_buffer(mvgal_wow64_buffer_t* buffer)
{
    if (!buffer) {
        return;
    }
    
    if (buffer->mapped_ptr) {
        munmap(buffer->mapped_ptr, buffer->mapped_size);
    }
    
    free(buffer);
}

int mvgal_wow64_map_buffer(mvgal_wow64_buffer_t* buffer,
                           uint64_t offset,
                           uint64_t size,
                           uint32_t* ptr)
{
    if (!buffer || !ptr || !g_wow64_initialized) {
        return -1;
    }
    
    if (offset + size > buffer->size) {
        return -1;
    }
    
    /* Map buffer into 32-bit addressable space */
    void* mapped = mmap(NULL, size, PROT_READ | PROT_WRITE,
                        MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
    if (mapped == MAP_FAILED) {
        return -1;
    }
    
    buffer->mapped_ptr = mapped;
    buffer->mapped_size = size;
    *ptr = mvgal_wow64_ptr64_to_ptr32(mapped);
    
    return 0;
}

/* ============================================================================
 * WoW64 Vulkan Thunk Functions
 * ============================================================================ */

/* Forward declarations to actual Vulkan implementation */
extern int mvgal_create_instance_64(const void* pCreateInfo, void** pInstance);
extern void mvgal_destroy_instance_64(void* instance);
extern int mvgal_create_device_64(void* physicalDevice, const void* pCreateInfo, void** pDevice);
extern void mvgal_destroy_device_64(void* device);

/* Helper to repack 32-bit Vulkan structures to 64-bit */
static void* repack_application_info_32_to_64(const VkApplicationInfo32* info32)
{
    if (!info32) {
        return NULL;
    }
    
    /* Allocate 64-bit structure */
    void* info64 = malloc(sizeof(VkApplicationInfo32) + 1024); /* Add space for strings */
    if (!info64) {
        return NULL;
    }
    
    /* Repack fields (strings would need copying in production) */
    /* This is simplified for illustration */
    memcpy(info64, info32, sizeof(VkApplicationInfo32));
    
    return info64;
}

int MVGAL_WOW64_STDCALL mvgal_wow64_vkCreateInstance(
    const VkInstanceCreateInfo32* pCreateInfo32,
    const VkInstanceCreateInfo32* pAllocator32,
    uint32_t* pInstance)
{
    (void)pAllocator32; /* Unused */
    
    if (!pCreateInfo32 || !pInstance) {
        return -1; /* VK_ERROR_INITIALIZATION_FAILED */
    }
    
    /* Lazy init */
    if (!mvgal_wow64_init()) {
        return -1;
    }
    
    /* Repack to 64-bit structure */
    void* pCreateInfo64 = malloc(sizeof(VkInstanceCreateInfo32) + 1024);
    if (!pCreateInfo64) {
        return -1;
    }
    
    memcpy(pCreateInfo64, pCreateInfo32, sizeof(VkInstanceCreateInfo32));
    
    /* Forward to 64-bit implementation */
    int result = mvgal_create_instance_64(pCreateInfo64, NULL);
    
    free(pCreateInfo64);
    
    if (result == 0) {
        /* Return a 32-bit handle */
        mvgal_wow64_instance_t* inst = mvgal_wow64_create_instance();
        if (inst) {
            *pInstance = mvgal_wow64_ptr64_to_ptr32(inst);
            return 0;
        }
    }
    
    return -1; /* VK_ERROR_INITIALIZATION_FAILED */
}

void MVGAL_WOW64_STDCALL mvgal_wow64_vkDestroyInstance(
    uint32_t instance,
    const VkInstanceCreateInfo32* pAllocator32)
{
    (void)pAllocator32; /* Unused */
    
    mvgal_wow64_instance_t* inst = (mvgal_wow64_instance_t*)mvgal_wow64_ptr32_to_ptr64(instance);
    if (inst) {
        mvgal_wow64_destroy_instance(inst);
    }
    
    /* Forward to 64-bit implementation */
    mvgal_destroy_instance_64(NULL);
}

int MVGAL_WOW64_STDCALL mvgal_wow64_vkCreateDevice(
    uint32_t physicalDevice,
    const VkInstanceCreateInfo32* pCreateInfo32,
    const VkInstanceCreateInfo32* pAllocator32,
    uint32_t* pDevice)
{
    (void)pAllocator32; /* Unused */
    
    if (!pCreateInfo32 || !pDevice) {
        return -1;
    }
    
    /* Create a dummy instance for the device - in production this comes from context */
    mvgal_wow64_instance_t* inst = mvgal_wow64_create_instance();
    if (!inst) {
        return -1;
    }
    
    mvgal_wow64_device_t* dev = mvgal_wow64_create_device(inst, physicalDevice);
    if (!dev) {
        mvgal_wow64_destroy_instance(inst);
        return -1;
    }
    
    *pDevice = mvgal_wow64_ptr64_to_ptr32(dev);
    return 0;
}

void MVGAL_WOW64_STDCALL mvgal_wow64_vkDestroyDevice(
    uint32_t device,
    const VkInstanceCreateInfo32* pAllocator32)
{
    (void)pAllocator32; /* Unused */
    
    mvgal_wow64_device_t* dev = (mvgal_wow64_device_t*)mvgal_wow64_ptr32_to_ptr64(device);
    if (dev) {
        mvgal_wow64_destroy_device(dev);
    }
    
    /* Forward to 64-bit implementation */
    mvgal_destroy_device_64(NULL);
}

int MVGAL_WOW64_STDCALL mvgal_wow64_vkAllocateMemory(
    uint32_t device,
    const VkInstanceCreateInfo32* pAllocateInfo32,
    const VkInstanceCreateInfo32* pAllocator32,
    uint32_t* pMemory)
{
    (void)pAllocator32; /* Unused */
    
    mvgal_wow64_device_t* dev = (mvgal_wow64_device_t*)mvgal_wow64_ptr32_to_ptr64(device);
    if (!dev || !pAllocateInfo32 || !pMemory) {
        /* Create a temporary device for testing if none provided */
        mvgal_wow64_instance_t* inst = mvgal_wow64_create_instance();
        if (!inst) {
            return -1;
        }
        dev = mvgal_wow64_create_device(inst, 0);
        if (!dev) {
            mvgal_wow64_destroy_instance(inst);
            return -1;
        }
        /* Note: we leak inst for simplicity in this stub */
    }
    
    /* Allocate buffer */
    mvgal_wow64_buffer_t* buf = mvgal_wow64_create_buffer(dev, 1024 * 1024, 0);
    if (!buf) {
        return -1;
    }
    
    *pMemory = mvgal_wow64_ptr64_to_ptr32(buf);
    return 0;
}

int MVGAL_WOW64_STDCALL mvgal_wow64_vkFreeMemory(
    uint32_t device,
    uint32_t memory,
    const VkInstanceCreateInfo32* pAllocator32)
{
    (void)device; /* Unused - memory handle contains all needed info */
    (void)pAllocator32; /* Unused */
    
    mvgal_wow64_buffer_t* buf = (mvgal_wow64_buffer_t*)mvgal_wow64_ptr32_to_ptr64(memory);
    if (buf) {
        mvgal_wow64_destroy_buffer(buf);
    }
    return 0;
}

/* ------------------------------------------------------------------ */
/*  Stub implementations for 64-bit Vulkan forwarding                 */
/*  These are normally provided by the Vulkan ICD integration           */
/* ------------------------------------------------------------------ */

int mvgal_create_instance_64(const void* pCreateInfo, void** pInstance)
{
    (void)pCreateInfo;
    (void)pInstance;
    /* Stub: In production, this forwards to the real Vulkan loader */
    return 0;
}

void mvgal_destroy_instance_64(void* instance)
{
    (void)instance;
    /* Stub */
}

int mvgal_create_device_64(void* physicalDevice, const void* pCreateInfo, void** pDevice)
{
    (void)physicalDevice;
    (void)pCreateInfo;
    (void)pDevice;
    /* Stub */
    return 0;
}

void mvgal_destroy_device_64(void* device)
{
    (void)device;
    /* Stub */
}

/* ------------------------------------------------------------------ */
/*  WoW64 Vulkan Queue Management                                     */
/* ------------------------------------------------------------------ */

/* Queue handles are managed via the generic wow64_handle_entry_t mechanism */
/* Queue-specific structure is internal to the implementation */

/* Queue handle registry - uses the same mechanism as other handles */
static wow64_handle_entry_t* allocate_wow64_queue_handle(void* ptr64)
{
    return allocate_wow64_handle(ptr64);
}

static void* lookup_wow64_queue(uint32_t handle32)
{
    return lookup_wow64_handle(handle32);
}

void MVGAL_WOW64_STDCALL mvgal_wow64_vkGetDeviceQueue(
    uint32_t device,
    uint32_t queueFamilyIndex,
    uint32_t queueIndex,
    uint32_t* pQueue
) {
    if (!pQueue) {
        return;
    }

    mvgal_wow64_device_t* dev = (mvgal_wow64_device_t*)mvgal_wow64_ptr32_to_ptr64(device);
    if (!dev) {
        *pQueue = 0;
        return;
    }

    /* Create a simple queue handle - store as 64-bit pointer to device */
    /* In production, this would query the Vulkan loader for the actual queue */
    void* queue_ptr = (void*)(uintptr_t)device; /* Use device as queue placeholder */

    wow64_handle_entry_t* entry = allocate_wow64_queue_handle(queue_ptr);
    if (entry) {
        *pQueue = entry->handle32;
    } else {
        *pQueue = 0;
    }
    (void)queueFamilyIndex;
    (void)queueIndex;
}

/* Simplified VkSubmitInfo32 for thunking */
typedef struct {
    uint32_t sType;
    uint32_t pNext;
    uint32_t flags;
    uint32_t waitSemaphoreCount;
    uint32_t pWaitSemaphores;
    uint32_t pWaitDstStageMask;
    uint32_t commandBufferCount;
    uint32_t pCommandBuffers;
    uint32_t signalSemaphoreCount;
    uint32_t pSignalSemaphores;
} VkSubmitInfo32;

/**
 * @brief Log WoW64 queue submit (weak symbol to avoid direct Vulkan dependency)
 */
__attribute__((weak)) void mvgal_wow64_log_submit(const char *func, uint32_t count)
{
    (void)func;
    (void)count;
}

int MVGAL_WOW64_STDCALL mvgal_wow64_vkQueueSubmit(
    uint32_t queue,
    uint32_t submitCount,
    uint32_t pSubmits,
    uint32_t fence
) {
    void* q = lookup_wow64_queue(queue);
    if (!q) {
        return -1; /* VK_ERROR_INITIALIZATION_FAILED */
    }

    /* Gaming AFR support: alternate frames between GPUs */
    uint32_t device_mask = g_wow64_config.gpu_mask;
    if (g_wow64_config.enable_afr && (g_wow64_config.gpu_mask & 0x3) == 0x3) {
        /* Two GPUs available for AFR */
        uint32_t frame_idx = atomic_load_explicit((atomic_uint *)&g_wow64_gaming_state.frame_count, memory_order_relaxed);
        g_wow64_gaming_state.frame_count = frame_idx + 1;
        
        /* Alternate: even frames to GPU 0, odd frames to GPU 1 */
        uint32_t gpu_bit = (frame_idx % 2) ? 0x2 : 0x1; /* GPU 1 or GPU 0 */
        device_mask = gpu_bit;
        
        /* Frame pacing: track time and optionally sleep for vsync */
        if (g_wow64_config.enable_frame_pacing) {
            struct timespec now;
            clock_gettime(CLOCK_MONOTONIC, &now);
            uint64_t now_ns = now.tv_sec * 1000000000ULL + now.tv_nsec;
            
            /* Sleep to maintain ~60 FPS frame pacing (16.67ms per frame) */
            uint64_t target_interval_ns = 16666667ULL; /* ~60 FPS */
            if (g_wow64_gaming_state.last_frame_time_ns > 0) {
                uint64_t elapsed = now_ns - g_wow64_gaming_state.last_frame_time_ns;
                if (elapsed < target_interval_ns) {
                    struct timespec sleep_time = {
                        0,
                        (target_interval_ns - elapsed) % 1000000000ULL
                    };
                    nanosleep(&sleep_time, NULL);
                }
            }
            g_wow64_gaming_state.last_frame_time_ns = now_ns;
        }
    }

    /* For now, just validate and log */
    (void)submitCount;
    (void)pSubmits;
    (void)fence;
    (void)device_mask; /* Would be passed to MVGAL layer for routing */

    mvgal_wow64_log_submit("mvgal_wow64_vkQueueSubmit", submitCount);

    return 0; /* VK_SUCCESS */
}

/* ============================================================================
 * Enhanced WoW64 API Functions
 * ============================================================================ */

mvgal_error_t mvgal_wow64_set_config(const mvgal_wow64_config_t *config)
{
    if (!config) {
        return MVGAL_ERROR_INVALID_ARGUMENT;
    }
    
    pthread_mutex_lock(&g_wow64_mutex);
    g_wow64_config = *config;
    pthread_mutex_unlock(&g_wow64_mutex);
    
    return MVGAL_SUCCESS;
}

mvgal_error_t mvgal_wow64_get_config(mvgal_wow64_config_t *config)
{
    if (!config) {
        return MVGAL_ERROR_INVALID_ARGUMENT;
    }
    
    pthread_mutex_lock(&g_wow64_mutex);
    *config = g_wow64_config;
    pthread_mutex_unlock(&g_wow64_mutex);
    
    return MVGAL_SUCCESS;
}

void mvgal_wow64_enable_frame_pacing(bool enable)
{
    pthread_mutex_lock(&g_wow64_mutex);
    g_wow64_config.enable_frame_pacing = enable;
    if (enable) {
        g_wow64_gaming_state.last_frame_time_ns = 0;
        g_wow64_gaming_state.frame_count = 0;
    }
    pthread_mutex_unlock(&g_wow64_mutex);
}

void MVGAL_WOW64_STDCALL mvgal_wow64_set_gpu_mask(uint32_t mask)
{
    pthread_mutex_lock(&g_wow64_mutex);
    g_wow64_config.gpu_mask = mask;
    pthread_mutex_unlock(&g_wow64_mutex);
}

uint32_t MVGAL_WOW64_STDCALL mvgal_wow64_get_gpu_count(void)
{
    uint32_t count = 0;
    uint32_t mask = 0;
    
    pthread_mutex_lock(&g_wow64_mutex);
    mask = g_wow64_config.gpu_mask;
    pthread_mutex_unlock(&g_wow64_mutex);
    
    while (mask) {
        count += mask & 1;
        mask >>= 1;
    }
    
    return count > 0 ? count : 1; /* At least 1 GPU */
}

/* ============================================================================
 * WoW64 Fence Support
 * ============================================================================ */

int MVGAL_WOW64_STDCALL mvgal_wow64_vkCreateFence(
    uint32_t device,
    uint32_t pCreateInfo32,
    uint32_t pAllocator32,
    uint32_t pFence
) {
    (void)pAllocator32;
    
    mvgal_wow64_fence_t *fence = calloc(1, sizeof(*fence));
    if (!fence) {
        return -1; /* VK_ERROR_OUT_OF_HOST_MEMORY */
    }
    
    fence->signaled = false;
    
    wow64_handle_entry_t *entry = allocate_wow64_handle(fence);
    if (!entry) {
        free(fence);
        return -1; /* VK_ERROR_OUT_OF_HOST_MEMORY */
    }
    entry->type = 1; /* Fence type */
    
    *(uint32_t*)mvgal_wow64_ptr32_to_ptr64(pFence) = entry->handle32;
    return 0; /* VK_SUCCESS */
}

int MVGAL_WOW64_STDCALL mvgal_wow64_vkWaitForFences(
    uint32_t device,
    uint32_t fenceCount,
    uint32_t pFences,
    uint32_t waitAll,
    uint32_t timeout_ns
) {
    (void)device;
    (void)waitAll;
    
    /* Simple implementation: just check if fence exists */
    for (uint32_t i = 0; i < fenceCount; i++) {
        uint32_t fence_handle = *(((uint32_t*)mvgal_wow64_ptr32_to_ptr64(pFences)) + i);
        mvgal_wow64_fence_t *fence = (mvgal_wow64_fence_t*)lookup_wow64_handle(fence_handle);
        if (!fence) {
            return -1; /* VK_ERROR_INITIALIZATION_FAILED */
        }
        /* In production: wait on fence with timeout */
    }
    
    return 0; /* VK_SUCCESS */
}

void MVGAL_WOW64_STDCALL mvgal_wow64_vkDestroyFence(
    uint32_t device,
    uint32_t fence,
    uint32_t pAllocator32
) {
    (void)device;
    (void)pAllocator32;
    
    mvgal_wow64_fence_t *f = (mvgal_wow64_fence_t*)lookup_wow64_handle(fence);
    if (f) {
        free(f);
        free_wow64_handle(fence);
    }
}

/* ============================================================================
 * Steam/Proton Integration
 * ============================================================================ */

uint32_t mvgal_wow64_get_steam_app_id(void)
{
    /* Try to read Steam App ID from Wine registry or environment */
    const char *app_id_str = getenv("SteamAppId");
    if (app_id_str) {
        return (uint32_t)strtoul(app_id_str, NULL, 10);
    }
    
    /* Could also check Wine registry: HKCU/Software/Wine/Steam/AppId */
    return 0;
}

void mvgal_wow64_apply_steam_profile(uint32_t app_id)
{
    switch (app_id) {
    case 0: /* Not a Steam game or unknown */
        break;
    case 239350: /* Apex Legends */
    case 1172470: /* Apex Legends (Steam) */
        g_wow64_config.enable_afr = true;
        g_wow64_config.enable_frame_pacing = true;
        g_wow64_config.gpu_mask = 0x3; /* GPU 0 + 1 */
        break;
    case 1782210: /* Baldur's Gate 3 */
        g_wow64_config.enable_afr = true;
        g_wow64_config.enable_frame_pacing = true;
        g_wow64_config.gpu_mask = 0x3;
        break;
    case 2715910: /* Cyberpunk 2077 */
        g_wow64_config.enable_afr = true;
        g_wow64_config.enable_frame_pacing = true;
        g_wow64_config.power_limit_scale = 0.95f; /* Reduce power slightly */
        break;
    case 389630: /* Blender (for rendering) */
        g_wow64_config.context_type = MVGAL_WOW64_CONTEXT_RENDERING;
        g_wow64_config.enable_afr = false;
        g_wow64_config.gpu_mask = 0xF; /* All GPUs */
        break;
    case 4000: /* AutoCAD */
    case 75340: /* 3ds Max */
        g_wow64_config.context_type = MVGAL_WOW64_CONTEXT_RENDERING;
        g_wow64_config.enable_afr = false;
        g_wow64_config.gpu_mask = 0x3; /* Limited GPU use */
        break;
    default:
        /* Generic gaming profile */
        g_wow64_config.enable_afr = true;
        g_wow64_config.enable_frame_pacing = true;
        break;
    }
}

/* ============================================================================
 * Enhanced Gaming Functions
 * ============================================================================ */

uint32_t mvgal_wow64_detect_steam_app_id(void)
{
    /* Check SteamAppId environment variable */
    const char *app_id_str = getenv("SteamAppId");
    if (app_id_str) {
        return (uint32_t)strtoul(app_id_str, NULL, 10);
    }
    
    /* Check STEAM_APP_ID */
    app_id_str = getenv("STEAM_APP_ID");
    if (app_id_str) {
        return (uint32_t)strtoul(app_id_str, NULL, 10);
    }
    
    /* Try to read from Wine registry if available */
    /* This would be implemented via wine reg query in production */
    
    return 0;
}

mvgal_distribution_strategy_t mvgal_wow64_get_game_profile(
    uint32_t app_id,
    mvgal_workload_type_t *workload_type
) {
    if (workload_type) {
        *workload_type = MVGAL_WORKLOAD_GRAPHICS; /* Default */
    }
    
    if (app_id == 0) {
        /* Auto-detect failed, return default */
        return MVGAL_STRATEGY_AFR;
    }
    
    /* Apply profile and return strategy */
    mvgal_wow64_apply_steam_profile(app_id);
    
    switch (app_id) {
    case 1172470: /* Apex Legends */
    case 1782210: /* Baldur's Gate 3 */
    case 2715910: /* Cyberpunk 2077 */
        return MVGAL_STRATEGY_AFR;
        
    case 546560: /* Half-Life: Alyx (VR) */
        return MVGAL_STRATEGY_SFR;
        
    case 389630: /* Blender */
    case 4000: /* AutoCAD */
    case 75340: /* 3ds Max */
        if (workload_type) {
            *workload_type = MVGAL_WORKLOAD_COMPUTE; /* Rendering workload */
        }
        return MVGAL_STRATEGY_COMPUTE_OFFLOAD;
        
    default:
        return MVGAL_STRATEGY_AFR;
    }
}

bool mvgal_wow64_can_frame_pace(void)
{
    /* Frame pacing requires at least 2 GPUs for AFR */
    uint32_t gpu_count = mvgal_wow64_get_gpu_count();
    return gpu_count >= 2 && g_wow64_config.enable_frame_pacing;
}

bool mvgal_wow64_enable_frame_pacing_with_config(const mvgal_frame_pacing_config_t *config)
{
    if (!config) {
        return false;
    }
    
    pthread_mutex_lock(&g_wow64_mutex);
    g_wow64_config.enable_frame_pacing = config->enabled;
    
    if (config->enabled) {
        g_wow64_gaming_state.last_frame_time_ns = 0;
        g_wow64_gaming_state.frame_count = 0;
    }
    
    pthread_mutex_unlock(&g_wow64_mutex);
    
    return true;
}

bool mvgal_wow64_update_config(const mvgal_wow64_config_t *config)
{
    if (!config) {
        return false;
    }
    
    pthread_mutex_lock(&g_wow64_mutex);
    g_wow64_config = *config;
    
    if (config->context_type == MVGAL_WOW64_CONTEXT_GAMING) {
        g_wow64_gaming_state.last_frame_time_ns = 0;
        g_wow64_gaming_state.frame_count = 0;
    }
    
    pthread_mutex_unlock(&g_wow64_mutex);
    
    fprintf(stderr, "[MVGAL-WoW64] Config updated: context=%d, strategy=%u, mask=0x%x\n",
            config->context_type, config->strategy, config->gpu_mask);
    
    return true;
}

uint64_t mvgal_wow64_get_gpu_mask(void)
{
    uint64_t mask = 0;
    pthread_mutex_lock(&g_wow64_mutex);
    mask = g_wow64_config.gpu_mask;
    pthread_mutex_unlock(&g_wow64_mutex);
    return mask;
}

uint64_t mvgal_wow64_estimate_frame_time_ns(uint64_t gpu0_time_ns, uint64_t gpu1_time_ns)
{
    /* For AFR, the frame time is dominated by the slower GPU */
    /* Add frame pacing overhead (~2ms) if enabled */
    uint64_t max_time = (gpu0_time_ns > gpu1_time_ns) ? gpu0_time_ns : gpu1_time_ns;
    uint64_t pacing_overhead = g_wow64_config.enable_frame_pacing ? 2000000ULL : 0;
    
    return max_time + pacing_overhead;
}