/* Platform layer: Linux — fork/execvp, path helpers, error strings */

#ifndef _DEFAULT_SOURCE
#define _DEFAULT_SOURCE
#endif

#include "platform.h"
#include <unistd.h>
#include <sys/wait.h>
#include <errno.h>
#include <string.h>
#include <stdarg.h>
#include <stdint.h>
#include <stdio.h>

#define STATIC static

STATIC char last_error_msg[256] = { 0 };
STATIC PlatformSpawnHandle current_handle = { 0 };

/* ── Helpers ─────────────────────────────────────────────────────────── */

STATIC void set_last_error(const char *fmt, ...) {
    // Simple snprintf to a local buffer — fine for error paths
    char buf[256] = { 0 };
    va_list args;
    va_start(args, fmt);
    vsnprintf(buf, sizeof(buf), fmt, args);
    va_end(args);
    strncpy(last_error_msg, buf, sizeof(last_error_msg) - 1);
}

/* ── Platform API ────────────────────────────────────────────────────── */

PlatformError Platform_SpawnChild(const char *program, const char **argv,
                                  PlatformSpawnHandle *out_handle) {
    last_error_msg[0] = '\0';

    memset(out_handle, 0, sizeof(*out_handle));
    pid_t pid = fork();

    if (pid < 0) {
        snprintf(last_error_msg, sizeof(last_error_msg),
                 "fork() failed: %s", strerror(errno));
        out_handle->last_error = errno;
        return PLATFORM_GENERAL;
    }

    if (pid == 0) {
        // Child process — replace with target
        execvp(program, (char **)argv);
        _exit(127);  // execvp only returns on error
    }

    // Parent
    out_handle->handle = (void *)(intptr_t)pid;
    out_handle->status = SPAWN_WAITING;
    return PLATFORM_OK;
}

PlatformError Platform_WaitForChild(PlatformSpawnHandle *handle) {
    if (!handle || !handle->handle) return PLATFORM_GENERAL;

    pid_t pid = (pid_t)(intptr_t)handle->handle;
    int status = 0;
    waitpid(pid, &status, 0);

    if (WIFEXITED(status)) {
        handle->status = SPAWN_EXITED;
        handle->exit_code = WEXITSTATUS(status);
    } else if (WIFSIGNALED(status)) {
        handle->status = SPAWN_EXITED;
        handle->exit_code = WTERMSIG(status);
    } else {
        handle->status = SPAWN_EXIT_CODE_UNKNOWN;
    }

    handle->handle = NULL;  // Consumed
    return PLATFORM_OK;
}

SpawnStatus Platform_GetExitStatus(const PlatformSpawnHandle *handle, int *code) {
    if (!handle) return SPAWN_WAITING;
    if (code) *code = handle->exit_code;
    return handle->status;
}

void Platform_CloseSpawnHandle(PlatformSpawnHandle *handle) {
    if (!handle) return;
    handle->handle = NULL;
    handle->status = SPAWN_WAITING;
    handle->exit_code = 0;
    handle->last_error = 0;
}

const char *Platform_GetLastErrorMessage(void) {
    return last_error_msg;
}

const char *Platform_GetTempDir(void) {
    return "/tmp";
}

void Platform_OfferFileToUser(const char *path) {
    /* Desktop: the file is already on disk where the user wanted it. */
    (void)path;
}

bool Platform_NeedsFileUpload(void) { return false; }

void Platform_RequestFileUpload(void) {
    /* Desktop has a real filesystem and a working file browser; nothing to do. */
}

bool Platform_TakeUploadedFile(char *outPath, int cap) {
    (void)outPath; (void)cap;
    return false;
}
