#ifndef UTILS_H
#define UTILS_H

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <stdbool.h>
#include <time.h>

#ifdef PLATFORM_WINDOWS
    #include <windows.h>
    #define PATH_SEP '\\'
#else
    #include <sys/stat.h>
    #include <unistd.h>
    #define PATH_SEP '/'
#endif

// ── Constants ──────────────────────────────────────────────────────
#define VKZ_BLOCK_SIZE      (64 * 1024)   // 64 KB per block
#define VKZ_MAX_MATCH_LEN   258
#define VKZ_MIN_MATCH_LEN   3
#define VKZ_WINDOW_SIZE     (32 * 1024)   // 32 KB sliding window
#define VKZ_HASH_BITS       15
#define VKZ_HASH_SIZE       (1 << VKZ_HASH_BITS)
#define VKZ_MAX_FILENAME    1024
#define VKZ_MAX_BLOCKS      (1024 * 1024) // Support files up to 64 GB

// ── Color output ───────────────────────────────────────────────────
#ifdef PLATFORM_WINDOWS
    #define COL_RESET   ""
    #define COL_RED     ""
    #define COL_GREEN   ""
    #define COL_YELLOW  ""
    #define COL_BLUE    ""
    #define COL_CYAN    ""
    #define COL_MAGENTA ""
    #define COL_BOLD    ""
#else
    #define COL_RESET   "\033[0m"
    #define COL_RED     "\033[31m"
    #define COL_GREEN   "\033[32m"
    #define COL_YELLOW  "\033[33m"
    #define COL_BLUE    "\033[34m"
    #define COL_CYAN    "\033[36m"
    #define COL_MAGENTA "\033[35m"
    #define COL_BOLD    "\033[1m"
#endif

// ── Logging macros ─────────────────────────────────────────────────
#define LOG_INFO(fmt, ...)  fprintf(stdout, COL_CYAN   "[INFO]  " COL_RESET fmt "\n", ##__VA_ARGS__)
#define LOG_OK(fmt, ...)    fprintf(stdout, COL_GREEN  "[OK]    " COL_RESET fmt "\n", ##__VA_ARGS__)
#define LOG_WARN(fmt, ...)  fprintf(stderr, COL_YELLOW "[WARN]  " COL_RESET fmt "\n", ##__VA_ARGS__)
#define LOG_ERR(fmt, ...)   fprintf(stderr, COL_RED    "[ERROR] " COL_RESET fmt "\n", ##__VA_ARGS__)

// ── Timer utilities ────────────────────────────────────────────────
typedef struct {
    struct timespec start;
    struct timespec end;
} Timer;

static inline void timer_start(Timer *t) {
#ifdef PLATFORM_WINDOWS
    timespec_get(&t->start, TIME_UTC);
#else
    clock_gettime(CLOCK_MONOTONIC, &t->start);
#endif
}

static inline double timer_stop(Timer *t) {
#ifdef PLATFORM_WINDOWS
    timespec_get(&t->end, TIME_UTC);
#else
    clock_gettime(CLOCK_MONOTONIC, &t->end);
#endif
    double elapsed = (double)(t->end.tv_sec - t->start.tv_sec);
    elapsed += (double)(t->end.tv_nsec - t->start.tv_nsec) / 1e9;
    return elapsed;
}

// ── File utilities ─────────────────────────────────────────────────
static inline uint64_t get_file_size(const char *path) {
    FILE *f = fopen(path, "rb");
    if (!f) return 0;
    fseek(f, 0, SEEK_END);
    uint64_t size = (uint64_t)ftell(f);
    fclose(f);
    return size;
}

static inline const char* get_filename(const char *path) {
    const char *name = strrchr(path, PATH_SEP);
    if (!name) name = strrchr(path, '/'); // fallback
    return name ? name + 1 : path;
}

static inline void format_size(uint64_t bytes, char *buf, size_t buf_size) {
    const char *units[] = {"B", "KB", "MB", "GB", "TB"};
    int unit = 0;
    double size = (double)bytes;
    while (size >= 1024.0 && unit < 4) {
        size /= 1024.0;
        unit++;
    }
    snprintf(buf, buf_size, "%.2f %s", size, units[unit]);
}

// ── Progress bar ───────────────────────────────────────────────────
static inline void print_progress(const char *label, uint64_t current, uint64_t total) {
    if (total == 0) return;
    int percent = (int)((current * 100) / total);
    int bar_width = 40;
    int filled = (percent * bar_width) / 100;

    fprintf(stdout, "\r%s [", label);
    for (int i = 0; i < bar_width; i++) {
        if (i < filled) fprintf(stdout, "█");
        else fprintf(stdout, "░");
    }
    fprintf(stdout, "] %3d%%", percent);
    if (current >= total) fprintf(stdout, "\n");
    fflush(stdout);
}

#endif // UTILS_H
