/* Complete external C11 host for ABI v1 command confirmation. */
#include "sqs_map.h"
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
static void ok(int status) { if (status != SQSM_MAP_OK) { fprintf(stderr, "%s\n", sqsm_map_last_error()); exit(1); } }
static int contains(sqsm_map_bytes_t out, const char *text) {
    char *copy = (char *)malloc((size_t)out.len + 1); assert(copy);
    memcpy(copy, out.data, (size_t)out.len); copy[out.len] = 0;
    int found = strstr(copy, text) != NULL; free(copy); return found;
}
int main(void) {
    sqsm_map_t map = 0; sqsm_map_bytes_t applied = {NULL, 0, 0}, rendered = {NULL, 0, 0}, out = {NULL, 0, 0};
    assert(sqsm_map_runtime_flags() & SQSM_MAP_COMMAND_BARRIERS);
    ok(sqsm_map_create(64, 64, &map));
    ok(sqsm_map_set_native_bearing(map, 10));
    ok(sqsm_map_flush_json(map, 0, 0, &applied));
    assert(contains(applied, "\"stage\":\"applied\"") && contains(applied, "\"submittedSequence\":1") && !contains(applied, "frameSequence"));
    ok(sqsm_map_flush_json(map, 0, 1, &rendered));
    assert(contains(rendered, "\"stage\":\"rendered\"") && contains(rendered, "\"frameSequence\":1"));
    /* A rejected mutation remains visible to subsequent barriers. */
    assert(sqsm_map_remove_layer(map, 999999) == SQSM_MAP_NOT_FOUND);
    ok(sqsm_map_set_native_bearing(map, 20));
    assert(sqsm_map_flush_json(map, 0, 0, &out) == SQSM_MAP_NOT_FOUND);
    assert(!out.data && !out.len && !out.allocation && strstr(sqsm_map_last_error(), "\"commandSequence\":2") && strstr(sqsm_map_last_error(), "\"code\":\"NOT_FOUND\""));
    /* Explicitly acknowledge that observed failure; this is not rollback. */
    ok(sqsm_map_flush_json(map, 2, 0, &out));
    assert(contains(out, "\"appliedSequence\":3")); ok(sqsm_map_bytes_free(out.allocation));
    assert(sqsm_map_flush_json(map, 4, 0, &out) == SQSM_MAP_INVALID_ARGUMENT && !out.allocation);
    assert(sqsm_map_flush_json(map, 0, 2, &out) == SQSM_MAP_INVALID_ARGUMENT && !out.allocation);
    ok(sqsm_map_destroy(map));
    /* Receipt allocations have their own lifetime after destruction. */
    assert(contains(rendered, "\"frameSequence\":1"));
    assert(sqsm_map_flush_json(map, 0, 0, &out) == SQSM_MAP_STALE_HANDLE && !out.allocation);
    ok(sqsm_map_bytes_free(applied.allocation)); ok(sqsm_map_bytes_free(rendered.allocation));
    puts("map command C ABI: applied/rendered, failure/recovery, flags, stale map and output ownership: PASS");
    return 0;
}
