const std = @import("std");
const c = @cImport({
    @cInclude("dataset_hash.h");
});

pub const HashError = error{
    ContextInitFailed,
    HashFailed,
    InvalidPath,
    OutOfMemory,
};

// Global context for reuse across multiple hash operations
var global_ctx: ?*c.fh_context_t = null;
var ctx_initialized = std.atomic.Value(bool).init(false);
var init_mutex = std.Thread.Mutex{};

/// Initialize global hash context once (thread-safe)
pub fn init() !void {
    if (ctx_initialized.load(.seq_cst)) return;

    init_mutex.lock();
    defer init_mutex.unlock();

    if (ctx_initialized.load(.seq_cst)) return; // Double-check

    const start = std.time.milliTimestamp();
    global_ctx = c.fh_init(0); // 0 = auto-detect threads
    const elapsed = std.time.milliTimestamp() - start;

    if (global_ctx == null) {
        return HashError.ContextInitFailed;
    }

    ctx_initialized.store(true, .seq_cst);
    std.log.info("[native] hash context initialized: {}ms", .{elapsed});
}

/// Hash a directory using the native library (reuses global context)
/// Returns the hex-encoded SHA256 hash string
pub fn hashDirectory(allocator: std.mem.Allocator, path: []const u8) ![]const u8 {
    try init(); // Idempotent initialization

    const ctx = global_ctx.?; // Safe: init() guarantees non-null

    // Convert path to null-terminated C string
    const c_path = try allocator.dupeZ(u8, path);
    defer allocator.free(c_path);

    // Call native function
    const result = c.fh_hash_directory_combined(ctx, c_path);
    if (result == null) {
        return HashError.HashFailed;
    }
    defer c.fh_free_string(result);

    // Convert result to Zig string
    const result_slice = std.mem.span(result);
    return try allocator.dupe(u8, result_slice);
}

/// Check if SIMD SHA256 is available
pub fn hasSimdSha256() bool {
    return c.fh_has_simd_sha256() == 1;
}

/// Get the name of the SIMD implementation being used
pub fn getSimdImplName() []const u8 {
    const name = c.fh_get_simd_impl_name();
    return std.mem.span(name);
}
