#pragma once
#include <stddef.h>
#include <stdint.h>

// Binary index file format constants
#define INDEX_MAGIC "FQI1"
#define CURRENT_VERSION 1

// On-disk entry layout (fixed-size for direct access)
#pragma pack(push, 1)
struct DiskEntry {
    char id[64];
    char job_name[128];
    char status[16];
    int64_t priority;
    int64_t created_at;
    int64_t next_retry;
    uint64_t reserved[3];  // Padding: 64+128+16+8+8+8+24 = 256 bytes
};
#pragma pack(pop)
static_assert(sizeof(DiskEntry) == 256, "DiskEntry must be 256 bytes");

// File header
#pragma pack(push, 1)
struct FileHeader {
    char magic[4];
    uint64_t version;
    uint64_t entry_count;
    uint64_t reserved[3];  // Padding: 4+8+8+24 = 44 bytes, align to 48
    char padding[4];       // Extra padding for alignment
};
#pragma pack(pop)
static_assert(sizeof(FileHeader) == 48, "FileHeader must be 48 bytes");

// Storage state - just data, no methods
struct IndexStorage {
    char index_path[4096];  // PATH_MAX on Linux
    int fd;
    void* mmap_ptr;
    size_t mmap_size;
};

// Initialize storage (replaces constructor, returns false on invalid path)
bool storage_init(IndexStorage* storage, const char* queue_dir);

// Cleanup (replaces destructor)
void storage_cleanup(IndexStorage* storage);

// Open/create storage
bool storage_open(IndexStorage* storage);
void storage_close(IndexStorage* storage);

// Read all entries from storage
bool storage_read_entries(IndexStorage* storage, DiskEntry* out_entries, size_t max_count, size_t* out_count);

// Write all entries to storage (atomic)
bool storage_write_entries(IndexStorage* storage, const DiskEntry* entries, size_t count);

// Memory-mapped access for reads
bool storage_mmap_for_read(IndexStorage* storage);
void storage_munmap(IndexStorage* storage);

const DiskEntry* storage_mmap_entries(IndexStorage* storage);
size_t storage_mmap_entry_count(IndexStorage* storage);

// Helper
static inline bool storage_valid(IndexStorage* storage) { return storage && storage->fd >= 0; }
