//! Shared JSON parsing helpers used by all API providers.
//! Centralises the common patterns: extracting floats, strings,
//! unsigned ints, and mapping HTTP errors.

const std = @import("std");

/// Extract a required float from a JSON value (string, float, or integer).
/// Returns 0 for null, missing, or unparseable values.
pub fn parseJsonFloat(val: ?std.json.Value) f64 {
    const v = val orelse return 0;
    return switch (v) {
        .float => |f| f,
        .integer => |i| @floatFromInt(i),
        .string => |s| std.fmt.parseFloat(f64, s) catch 0,
        else => 0,
    };
}

/// Extract an optional float. Returns null for missing/null JSON values.
pub fn optFloat(val: ?std.json.Value) ?f64 {
    const v = val orelse return null;
    return switch (v) {
        .float => |f| f,
        .integer => |i| @floatFromInt(i),
        .null => null,
        else => null,
    };
}

/// Extract an optional unsigned integer. Returns null for missing/null/negative values.
/// Float values are accepted only if they are whole numbers (e.g. 1234.0).
pub fn optUint(val: ?std.json.Value) ?u64 {
    const v = val orelse return null;
    return switch (v) {
        .integer => |i| if (i >= 0) @intCast(i) else null,
        .float => |f| if (f >= 0 and f == @floor(f)) @intFromFloat(f) else null,
        .null => null,
        else => null,
    };
}

/// Extract an optional string. Returns null for missing or non-string values.
pub fn jsonStr(val: ?std.json.Value) ?[]const u8 {
    const v = val orelse return null;
    return switch (v) {
        .string => |s| s,
        else => null,
    };
}
