#include <stddef.h>
#include <stdint.h>
#include <stdarg.h>

// Types needed for stubs
typedef int32_t pid_t;
typedef int32_t uid_t;
typedef int32_t gid_t;
typedef int64_t off_t;
typedef int32_t mode_t;

struct stat {
    int st_mode;
};

int errno = 0;

// Basic memory stubs
extern void* malloc(size_t size);
extern void free(void* ptr);

// Forward declare memset (defined below)
void* memset(void* s, int c, size_t n);

// LwIP Panic Handler (for Membrane stack)
extern void console_write(const void* p, size_t len);

size_t strlen(const char* s) {
    size_t i = 0;
    while(s[i]) i++;
    return i;
}

void nexus_lwip_panic(const char* msg) {
    const char* prefix = "\n\x1b[1;31m[LwIP Fatal] ASSERTION FAILED: \x1b[0m";
    console_write(prefix, strlen(prefix));
    console_write(msg, strlen(msg));
    console_write("\n", 1);
    while(1) {}
}

int strncmp(const char *s1, const char *s2, size_t n) {
    for (size_t i = 0; i < n; i++) {
        if (s1[i] != s2[i]) return (unsigned char)s1[i] - (unsigned char)s2[i];
        if (s1[i] == 0) return 0;
    }
    return 0;
}

int atoi(const char* nptr) { return 0; }

double strtod(const char* nptr, char** endptr) {
    if (endptr) *endptr = (char*)nptr;
    return 0.0; 
}

double pow(double x, double y) { return 0.0; }
double log10(double x) { return 0.0; }

// --- SYSCALL INTERFACE ---

long syscall(long nr, long a0, long a1, long a2) {
    long res;
#if defined(__riscv)
    register long a7 asm("a7") = nr;
    register long _a0 asm("a0") = a0;
    register long _a1 asm("a1") = a1;
    register long _a2 asm("a2") = a2;
    asm volatile("ecall" 
        : "+r"(_a0) 
        : "r"(a7), "r"(_a1), "r"(_a2) 
        : "memory");
    res = _a0;
#else
    res = -1;
#endif
    return res;
}

// IO stubs (Real Syscalls)

int write(int fd, const void *buf, size_t count) {
    // 0x204 = SYS_WRITE
    return (int)syscall(0x204, fd, (long)buf, count);
}

int read(int fd, void *buf, size_t count) {
    // 0x203 = SYS_READ
    return (int)syscall(0x203, fd, (long)buf, count);
}

int open(const char *pathname, int flags, ...) {
    // 0x200 = SYS_OPEN
    return (int)syscall(0x200, (long)pathname, flags, 0);
}

int close(int fd) {
    // 0x201 = SYS_CLOSE
    return (int)syscall(0x201, fd, 0, 0);
}

int execv(const char *path, char *const argv[]) {
    // 0x600 = KEXEC (Replace current fiber/process)
    // Note: argv is currently ignored by kernel kexec, it just runs the binary
    return (int)syscall(0x600, (long)path, 0, 0);
}

// Robust Formatter
typedef struct {
    char *buf;
    size_t size;
    size_t pos;
} OutCtx;

static void out_char(OutCtx *ctx, char c) {
    if (ctx->buf && ctx->size > 0 && ctx->pos < ctx->size - 1) {
        ctx->buf[ctx->pos] = c;
    }
    ctx->pos++;
}

static void out_num(OutCtx *ctx, unsigned long n, int base, int width, int zeropad, int upper) {
    char buf[64];
    const char *digits = upper ? "0123456789ABCDEF" : "0123456789abcdef";
    int i = 0;
    if (n == 0) buf[i++] = '0';
    else while (n > 0) { buf[i++] = digits[n % base]; n /= base; }
    while (i < width) buf[i++] = (zeropad ? '0' : ' ');
    while (i > 0) out_char(ctx, buf[--i]);
}

static int vformat(OutCtx *ctx, const char *fmt, va_list ap) {
    if (!fmt) return 0;
    const char *p = fmt;
    ctx->pos = 0;
    while (*p) {
        if (*p != '%') { out_char(ctx, *p++); continue; }
        p++; // skip %
        if (!*p) break;
        int zeropad = 0, width = 0, l_mod = 0, h_mod = 0;
        if (*p == '0') { zeropad = 1; p++; }
        while (*p >= '0' && *p <= '9') { width = width * 10 + (*p - '0'); p++; }
        while (*p == 'l') { l_mod++; p++; }
        if (*p == 'h') { h_mod = 1; p++; }
        if (!*p) break;
        
        switch (*p) {
            case 's': {
                const char *s = va_arg(ap, const char *);
                if (!s) s = "(null)";
                while (*s) out_char(ctx, *s++);
                break;
            }
            case 'c': out_char(ctx, (char)va_arg(ap, int)); break;
            case 'd':
            case 'i': {
                long n = (l_mod >= 1) ? va_arg(ap, long) : va_arg(ap, int);
                unsigned long un;
                if (n < 0) { out_char(ctx, '-'); un = 0UL - (unsigned long)n; }
                else un = (unsigned long)n;
                out_num(ctx, un, 10, width, zeropad, 0);
                break;
            }
            case 'u': {
                unsigned long n = (l_mod >= 1) ? va_arg(ap, unsigned long) : va_arg(ap, unsigned int);
                out_num(ctx, n, 10, width, zeropad, 0);
                break;
            }
            case 'p':
            case 'x':
            case 'X': {
                unsigned long n;
                if (*p == 'p') n = (unsigned long)va_arg(ap, void *);
                else n = (l_mod >= 1) ? va_arg(ap, unsigned long) : va_arg(ap, unsigned int);
                out_num(ctx, n, 16, width, zeropad, (*p == 'X'));
                break;
            }
            case '%': out_char(ctx, '%'); break;
            default: out_char(ctx, '%'); out_char(ctx, *p); break;
        }
        p++;
    }
    if (ctx->buf && ctx->size > 0) {
        size_t end = (ctx->pos < ctx->size) ? ctx->pos : ctx->size - 1;
        ctx->buf[end] = '\0';
    }
    return (int)ctx->pos;
}

int vsnprintf(char *str, size_t size, const char *format, va_list ap) {
    OutCtx ctx = { .buf = str, .size = size, .pos = 0 };
    return vformat(&ctx, format, ap);
}

int snprintf(char *str, size_t size, const char *format, ...) {
    va_list ap; va_start(ap, format);
    int res = vsnprintf(str, size, format, ap);
    va_end(ap);
    return res;
}

int sprintf(char *str, const char *format, ...) {
    va_list ap; va_start(ap, format);
    int res = vsnprintf(str, (size_t)-1, format, ap);
    va_end(ap);
    return res;
}

int vprintf(const char *format, va_list ap) {
    char tmp[1024];
    int n = vsnprintf(tmp, sizeof(tmp), format, ap);
    if (n > 0) console_write(tmp, (n < (int)sizeof(tmp)) ? (size_t)n : sizeof(tmp)-1);
    return n;
}

int printf(const char *format, ...) {
    va_list ap; va_start(ap, format);
    int res = vprintf(format, ap);
    va_end(ap);
    return res;
}

int fwrite(const void *ptr, size_t size, size_t nmemb, void *stream) {
    return write(1, ptr, size * nmemb);
}

int fflush(void *stream) { return 0; }

// System stubs
extern void nexus_yield(void);
// void exit(int status) { while(1) { nexus_yield(); } } // Moved to libc_shim.zig
void (*signal(int sig, void (*func)(int)))(int) { return NULL; }

// LwIP Time - moved to sys_arch.c
// uint32_t sys_now() { return 0; }

// RNG for LwIP (Project Prometheus)
int rand(void) {
    static unsigned long next = 1;
    next = next * 1103515245 + 12345;
    return (unsigned int)(next/65536) % 32768;
}

// Utils
uint16_t htons(uint16_t h) {
    return (h << 8) | (h >> 8);
}

void* memcpy(void* dest, const void* src, size_t n) {
    uint8_t* d = dest;
    const uint8_t* s = src;
    for (size_t i = 0; i < n; i++) d[i] = s[i];
    return dest;
}

void* memset(void* s, int c, size_t n) {
    uint8_t* p = s;
    for (size_t i = 0; i < n; i++) p[i] = (uint8_t)c;
    return s;
}

int memcmp(const void *s1, const void *s2, size_t n) {
    const unsigned char *p1 = (const unsigned char *)s1;
    const unsigned char *p2 = (const unsigned char *)s2;
    for (size_t i = 0; i < n; i++) {
        if (p1[i] != p2[i]) return p1[i] - p2[i];
    }
    return 0;
}

void *memmove(void *dest, const void *src, size_t n) {
    char *d = (char *)dest;
    const char *s = (const char *)src;
    if (d < s) {
        for (size_t i = 0; i < n; i++) d[i] = s[i];
    } else {
        for (size_t i = n; i > 0; i--) d[i - 1] = s[i - 1];
    }
    return dest;
}

char *strchr(const char *s, int c) {
    while (*s != (char)c) {
        if (!*s++) return NULL;
    }
    return (char *)s;
}

char *strcpy(char *dest, const char *src) {
    char *d = dest;
    while ((*d++ = *src++));
    return dest;
}

int strcmp(const char *s1, const char *s2) {
    while(*s1 && (*s1 == *s2)) {
        s1++; s2++;
    }
    return *(const unsigned char*)s1 - *(const unsigned char*)s2;
}

size_t strspn(const char *s, const char *accept) {
    const char *p = s;
    const char *a;
    while (*p) {
        for (a = accept; *a; a++) {
            if (*p == *a) break;
        }
        if (*a == '\0') return p - s;
        p++;
    }
    return p - s;
}

size_t strcspn(const char *s, const char *reject) {
    const char *p = s;
    const char *r;
    while (*p) {
        for (r = reject; *r; r++) {
            if (*p == *r) return p - s;
        }
        p++;
    }
    return p - s;
}

uint32_t lfs_crc(uint32_t crc, const void *buffer, size_t size) {
    static const uint32_t rtable[16] = {
        0x00000000, 0x1db71064, 0x3b6e20c8, 0x26d930ac,
        0x76dc4190, 0x6b6b51f4, 0x4db26158, 0x5005713c,
        0xedb88320, 0xf00f9344, 0xd6d6a3e8, 0xcb61b38c,
        0x9b64c2b0, 0x86d3d2d4, 0xa00ae278, 0xbdbdf21c,
    };
    const uint8_t *data = (const uint8_t *)buffer;
    for (size_t i = 0; i < size; i++) {
        crc = (crc >> 4) ^ rtable[(crc ^ (data[i] >> 0)) & 0xf];
        crc = (crc >> 4) ^ rtable[(crc ^ (data[i] >> 4)) & 0xf];
    }
    return crc;
}

void console_write(const void* p, size_t len) {
    // Phase 11: Real Syscalls only. No direct MMIO.
    write(1, p, len);
}

void ion_egress_to_port(uint16_t port, void* pkt);

int execve(const char *pathname, char *const argv[], char *const envp[]) { return -1; }
pid_t fork(void) { return -1; }
pid_t wait(int *status) { return -1; }
