#include <stdint.h>
#include <stdio.h>
#include <string.h>

#include "bio/bio.h"
#include "bio/bio_gguf.h"
#include "bio/bio_lattice.h"

static void write_u32(FILE *f, uint32_t v) {
    fputc((int)(v & 0xffu), f);
    fputc((int)((v >> 8) & 0xffu), f);
    fputc((int)((v >> 16) & 0xffu), f);
    fputc((int)((v >> 24) & 0xffu), f);
}

static void write_u64(FILE *f, uint64_t v) {
    for (unsigned i = 0; i < 8u; ++i) {
        fputc((int)((v >> (i * 8u)) & 0xffu), f);
    }
}

static void write_string(FILE *f, const char *s) {
    const uint64_t n = (uint64_t)strlen(s);
    write_u64(f, n);
    fwrite(s, 1u, (size_t)n, f);
}

static long align_file(FILE *f, uint32_t alignment) {
    long pos = ftell(f);
    const long aligned = (pos + (long)alignment - 1L) & ~((long)alignment - 1L);
    while (pos < aligned) {
        fputc(0, f);
        ++pos;
    }
    return aligned;
}

static int write_minimal_gguf(const char *path) {
    FILE *f = fopen(path, "wb");
    if (f == NULL) {
        return 1;
    }

    write_u32(f, 0x46554747u); /* GGUF */
    write_u32(f, 3u);
    write_u64(f, 1u); /* tensor_count */
    write_u64(f, 1u); /* metadata_count */

    write_string(f, "general.alignment");
    write_u32(f, 4u);  /* uint32 metadata value */
    write_u32(f, 32u);

    write_string(f, "blk.0.attn_q.weight");
    write_u32(f, 2u);  /* dims */
    write_u64(f, 32u);
    write_u64(f, 1u);
    write_u32(f, BIO_GGUF_TYPE_Q4_0);
    write_u64(f, 0u);  /* offset from aligned data base */

    align_file(f, 32u);
    for (uint8_t i = 0; i < 18u; ++i) {
        fputc((int)i, f);
    }

    fclose(f);
    return 0;
}

int main(int argc, char **argv) {
    const char *path = argc > 1 ? argv[1] : "tests/fixtures/minimal-q4.gguf";
    bio_gguf_model model;
    uint8_t packed[2] = {0};

    if (write_minimal_gguf(path) != 0) {
        fprintf(stderr, "failed to write fixture: %s\n", path);
        return 1;
    }

    if (bio_gguf_open(path, &model) != BIO_OK) {
        fprintf(stderr, "bio_gguf_open failed\n");
        return 1;
    }
    if (model.version != 3u || model.tensor_count != 1u || model.metadata_count != 1u ||
        model.alignment != 32u || model.registered_tensor_count != 1u) {
        fprintf(stderr, "unexpected GGUF header parse\n");
        bio_gguf_close(&model);
        return 1;
    }
    if (strcmp(model.tensors[0].name, "blk.0.attn_q.weight") != 0 ||
        model.tensors[0].ggml_type != BIO_GGUF_TYPE_Q4_0 ||
        model.tensors[0].byte_size != 18u || model.tensors[0].int4_compatible == 0u) {
        fprintf(stderr, "unexpected tensor span parse\n");
        bio_gguf_close(&model);
        return 1;
    }
    bio_gguf_close(&model);

    bio_int4_set_nibble(packed, 0u, 0x0au);
    bio_int4_set_nibble(packed, 1u, 0x05u);
    bio_int4_set_nibble(packed, 2u, 0x0fu);
    if (packed[0] != 0x5au || bio_int4_get_nibble(packed, 2u) != 0x0fu ||
        bio_int4_packed_bytes(3u) != 2u) {
        fprintf(stderr, "INT4 lattice helpers failed\n");
        return 1;
    }

    if (bio_v1_absorb_gguf(path) != BIO_OK) {
        fprintf(stderr, "bio_v1_absorb_gguf failed\n");
        return 1;
    }

    puts("bio-tests: native GGUF mmap and INT4 lattice ok");
    return 0;
}
