const std = @import("std");
const testing = std.testing;

const src = @import("src");

const ws = src.net.ws_client;

test "status prewarm formatting - single entry" {
    var gpa = std.heap.GeneralPurposeAllocator(.{}){};
    defer _ = gpa.deinit();
    const allocator = gpa.allocator();

    const json_msg =
        \\{
        \\  "user": {"name": "u", "admin": false, "roles": []},
        \\  "tasks": {"total": 0, "queued": 0, "running": 0, "failed": 0, "completed": 0},
        \\  "queue": [],
        \\  "prewarm": [
        \\    {
        \\      "worker_id": "worker-01",
        \\      "task_id": "task-abc",
        \\      "started_at": "2025-12-15T23:00:00Z",
        \\      "updated_at": "2025-12-15T23:00:02Z",
        \\      "phase": "datasets",
        \\      "dataset_count": 2
        \\    }
        \\  ]
        \\}
    ;

    const parsed = try std.json.parseFromSlice(std.json.Value, allocator, json_msg, .{});
    defer parsed.deinit();

    const root: std.json.ObjectMap = parsed.value.object;
    const section_opt = try ws.Client.formatPrewarmFromStatusRoot(allocator, root);
    try testing.expect(section_opt != null);

    const section = section_opt.?;
    defer allocator.free(section);

    try testing.expect(std.mem.indexOf(u8, section, "Prewarm:") != null);
    try testing.expect(std.mem.indexOf(u8, section, "worker=worker-01") != null);
    try testing.expect(std.mem.indexOf(u8, section, "task=task-abc") != null);
    try testing.expect(std.mem.indexOf(u8, section, "phase=datasets") != null);
    try testing.expect(std.mem.indexOf(u8, section, "datasets=2") != null);
}

test "status prewarm formatting - missing field" {
    var gpa = std.heap.GeneralPurposeAllocator(.{}){};
    defer _ = gpa.deinit();
    const allocator = gpa.allocator();

    const json_msg = "{\"user\":{},\"tasks\":{},\"queue\":[]}";

    const parsed = try std.json.parseFromSlice(std.json.Value, allocator, json_msg, .{});
    defer parsed.deinit();

    const root: std.json.ObjectMap = parsed.value.object;
    const section_opt = try ws.Client.formatPrewarmFromStatusRoot(allocator, root);
    try testing.expect(section_opt == null);
}

test "status prewarm formatting - prewarm not array" {
    var gpa = std.heap.GeneralPurposeAllocator(.{}){};
    defer _ = gpa.deinit();
    const allocator = gpa.allocator();

    const json_msg = "{\"prewarm\":{}}";

    const parsed = try std.json.parseFromSlice(std.json.Value, allocator, json_msg, .{});
    defer parsed.deinit();

    const root: std.json.ObjectMap = parsed.value.object;
    const section_opt = try ws.Client.formatPrewarmFromStatusRoot(allocator, root);
    try testing.expect(section_opt == null);
}

test "status prewarm formatting - empty prewarm array" {
    var gpa = std.heap.GeneralPurposeAllocator(.{}){};
    defer _ = gpa.deinit();
    const allocator = gpa.allocator();

    const json_msg = "{\"prewarm\":[]}";

    const parsed = try std.json.parseFromSlice(std.json.Value, allocator, json_msg, .{});
    defer parsed.deinit();

    const root: std.json.ObjectMap = parsed.value.object;
    const section_opt = try ws.Client.formatPrewarmFromStatusRoot(allocator, root);
    try testing.expect(section_opt == null);
}

test "status prewarm formatting - mixed entries" {
    var gpa = std.heap.GeneralPurposeAllocator(.{}){};
    defer _ = gpa.deinit();
    const allocator = gpa.allocator();

    const json_msg =
        "{\"prewarm\":[123,\"x\",{\"worker_id\":\"w\",\"task_id\":\"t\",\"phase\":\"p\",\"dataset_count\":1,\"started_at\":\"s\"}]}";

    const parsed = try std.json.parseFromSlice(std.json.Value, allocator, json_msg, .{});
    defer parsed.deinit();

    const root: std.json.ObjectMap = parsed.value.object;
    const section_opt = try ws.Client.formatPrewarmFromStatusRoot(allocator, root);
    try testing.expect(section_opt != null);

    const section = section_opt.?;
    defer allocator.free(section);

    try testing.expect(std.mem.indexOf(u8, section, "Prewarm:") != null);
    try testing.expect(std.mem.indexOf(u8, section, "worker=w") != null);
    try testing.expect(std.mem.indexOf(u8, section, "task=t") != null);
    try testing.expect(std.mem.indexOf(u8, section, "phase=p") != null);
    try testing.expect(std.mem.indexOf(u8, section, "datasets=1") != null);
}
