/* buddy_debug.c — ASCII visualization for buddy allocator
   Included from runtime.c only when DUMP_BUDDY is defined. */

static void buddy_dump(BuddyPool *pool, const char *op,
                       uint8_t *block, uint8_t order) {
  if (!pool || !pool->base) return;

  int levels = pool->max_order - BUDDY_MIN_ORDER + 1;

  /* Bitmap: one byte per min-block slot */
  size_t num_slots = pool->total_size >> BUDDY_MIN_ORDER;
  /* Dynamic VLA — pool sizes vary now */
  uint8_t *bitmap = alloca(num_slots);
  memset(bitmap, 0, num_slots); /* 0 = allocated */

  /* Walk all free lists and mark free slots */
  for (int i = 0; i < levels; i++) {
    for (BuddyBlock *p = pool->free_lists[i]; p; p = p->next) {
      size_t off = (uint8_t *)p - pool->base;
      size_t slot = off >> BUDDY_MIN_ORDER;
      size_t count = 1ULL << i; /* number of min-block slots in this block */
      for (size_t s = 0; s < count && (slot + s) < num_slots; s++)
        bitmap[slot + s] = 1;
    }
  }

  /* Render 64-char ASCII bar */
  size_t slots_per_char = num_slots / 64;
  if (slots_per_char == 0) slots_per_char = 1;
  char bar[65];
  size_t total_free_slots = 0;
  for (int c = 0; c < 64; c++) {
    size_t base_slot = c * slots_per_char;
    size_t free_count = 0;
    for (size_t s = 0; s < slots_per_char && (base_slot + s) < num_slots; s++) {
      if (bitmap[base_slot + s]) free_count++;
    }
    total_free_slots += free_count;
    /* Majority vote: if more than half are free, show free */
    bar[c] = (free_count > slots_per_char / 2) ? '.' : '#';
  }
  bar[64] = '\0';

  size_t blk_offset = block - pool->base;
  size_t blk_size = 1ULL << order;
  size_t total_free = total_free_slots << BUDDY_MIN_ORDER;
  size_t total_alloc = pool->total_size - total_free;

  fprintf(stderr, "buddy %s: pool %zuKB order %u (%zuKB) @ +%zuKB allocs=%u\n",
          op, pool->total_size / 1024, order, blk_size / 1024,
          blk_offset / 1024, pool->alloc_count);
  fprintf(stderr, "  [%s]\n", bar);
  fprintf(stderr, "  alloc: %zuKB  free: %zuKB  total: %zuKB\n",
          total_alloc / 1024, total_free / 1024, pool->total_size / 1024);

  /* Print free list population */
  fprintf(stderr, "  free lists:");
  for (int i = 0; i < levels; i++) {
    int count = 0;
    for (BuddyBlock *p = pool->free_lists[i]; p; p = p->next)
      count++;
    if (count > 0)
      fprintf(stderr, " o%d:%d", i + BUDDY_MIN_ORDER, count);
  }
  fprintf(stderr, "\n");
}
