#pragma once
#include <cstddef>
#include <cstdint>
#include <string>
#include <optional>

namespace fetchml::common {

// RAII wrapper for memory-mapped files
class MemoryMap {
    void* addr_ = nullptr;
    size_t size_ = 0;
    int fd_ = -1;
    bool writable_ = false;

public:
    MemoryMap() = default;
    ~MemoryMap();
    
    // Non-copyable but movable
    MemoryMap(const MemoryMap&) = delete;
    MemoryMap& operator=(const MemoryMap&) = delete;
    MemoryMap(MemoryMap&& other) noexcept;
    MemoryMap& operator=(MemoryMap&& other) noexcept;
    
    // Map file for reading
    static std::optional<MemoryMap> map_read(const char* path);
    
    // Map file for read-write (creates if needed)
    static std::optional<MemoryMap> map_write(const char* path, size_t size);
    
    void* data() const { return addr_; }
    size_t size() const { return size_; }
    bool valid() const { return addr_ != nullptr && addr_ != reinterpret_cast<void*>(-1); }
    
    void unmap();
    void sync();
};

// Efficient file descriptor wrapper with batch read operations
class FileHandle {
    int fd_ = -1;
    std::string path_;

public:
    FileHandle() = default;
    explicit FileHandle(const char* path, int flags, int mode = 0644);
    ~FileHandle();
    
    FileHandle(const FileHandle&) = delete;
    FileHandle& operator=(const FileHandle&) = delete;
    FileHandle(FileHandle&& other) noexcept;
    FileHandle& operator=(FileHandle&& other) noexcept;
    
    bool open(const char* path, int flags, int mode = 0644);
    void close();
    
    ssize_t read(void* buf, size_t count, off_t offset = -1);
    ssize_t write(const void* buf, size_t count, off_t offset = -1);
    
    bool valid() const { return fd_ >= 0; }
    int fd() const { return fd_; }
};

// Get file size or -1 on error
int64_t file_size(const char* path);

// Ensure directory exists (creates parents if needed)
bool ensure_dir(const char* path);

} // namespace fetchml::common
