/*
 * KateRTX · krtx-grok · ELF · SpaceXAI / xAI Grok API
 * No libcurl-dev · uses system curl(1)
 * Key: XAI_API_KEY · or ~/.config/biggrinrtx/xai.key (chmod 600)
 * Never hardcode secrets · never print full key
 *
 *   gcc -O2 -o bin/krtx-grok src/krtx_grok.c
 *   krtx-grok status
 *   krtx-grok "hello from desk"
 *   krtx-grok chat "summarize this"
 *   krtx-grok -m grok-4.5 chat "…"
 */
#define _GNU_SOURCE
#include <ctype.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <unistd.h>

#define API_BASE "https://api.x.ai/v1"
#define DEFAULT_MODEL "grok-4.5"
#define KEY_PATH_SUFFIX "/.config/biggrinrtx/xai.key"
#define MAX_OUT (512 * 1024)

static char keybuf[512];

static int read_key(void) {
  const char *env = getenv("XAI_API_KEY");
  if (env && env[0]) {
    snprintf(keybuf, sizeof keybuf, "%s", env);
    size_t n = strlen(keybuf);
    while (n && isspace((unsigned char)keybuf[n - 1])) keybuf[--n] = 0;
    if (keybuf[0] && keybuf[0] != '#') return 0;
  }
  const char *home = getenv("HOME");
  if (!home || !home[0]) return -1;
  char path[640];
  snprintf(path, sizeof path, "%s%s", home, KEY_PATH_SUFFIX);
  FILE *f = fopen(path, "r");
  if (!f) return -1;
  keybuf[0] = 0;
  char line[512];
  while (fgets(line, sizeof line, f)) {
    char *p = line;
    while (*p && isspace((unsigned char)*p)) p++;
    if (!*p || *p == '#') continue;
    snprintf(keybuf, sizeof keybuf, "%s", p);
    size_t n = strlen(keybuf);
    while (n && isspace((unsigned char)keybuf[n - 1])) keybuf[--n] = 0;
    break;
  }
  fclose(f);
  return keybuf[0] ? 0 : -1;
}

static void key_hint(void) {
  fprintf(stderr,
          "krtx-grok: no API key\n"
          "  export XAI_API_KEY=…\n"
          "  or: install -m 600 /dev/stdin ~/.config/biggrinrtx/xai.key <<<'xai-…'\n"
          "  console: https://console.x.ai\n");
}

static char *json_escape(const char *s) {
  size_t need = 3;
  for (const char *p = s; *p; p++) {
    unsigned char c = (unsigned char)*p;
    if (c == '"' || c == '\\' || c < 0x20) need += 6;
    else need += 1;
  }
  char *o = (char *)malloc(need + 8);
  if (!o) return NULL;
  char *w = o;
  *w++ = '"';
  for (const char *p = s; *p; p++) {
    unsigned char c = (unsigned char)*p;
    if (c == '"' || c == '\\') {
      *w++ = '\\';
      *w++ = (char)c;
    } else if (c == '\n') {
      *w++ = '\\';
      *w++ = 'n';
    } else if (c == '\r') {
      *w++ = '\\';
      *w++ = 'r';
    } else if (c == '\t') {
      *w++ = '\\';
      *w++ = 't';
    } else if (c < 0x20) {
      /* skip */
    } else {
      *w++ = (char)c;
    }
  }
  *w++ = '"';
  *w = 0;
  return o;
}

static void print_content_field(const char *json) {
  const char *p = strstr(json, "\"content\"");
  if (!p) p = strstr(json, "\"output_text\"");
  if (!p) {
    fputs(json, stdout);
    if (json[0] && json[strlen(json) - 1] != '\n') fputc('\n', stdout);
    return;
  }
  p = strchr(p, ':');
  if (!p) {
    fputs(json, stdout);
    return;
  }
  p++;
  while (*p && isspace((unsigned char)*p)) p++;
  if (*p != '"') {
    fputs(p, stdout);
    return;
  }
  p++;
  for (; *p; p++) {
    if (*p == '\\' && p[1]) {
      p++;
      if (*p == 'n')
        putchar('\n');
      else if (*p == 'r')
        putchar('\r');
      else if (*p == 't')
        putchar('\t');
      else if (*p == 'u') {
        for (int i = 0; i < 4 && p[1]; i++) p++;
      } else
        putchar(*p);
    } else if (*p == '"')
      break;
    else
      putchar(*p);
  }
  putchar('\n');
}

/* POST JSON with Bearer key via SPV curl containment unit */
static int curl_post_json(const char *url, const char *json_body) {
  if (access("/usr/bin/curl", X_OK) != 0 && access("/bin/curl", X_OK) != 0) {
    fprintf(stderr, "krtx-grok: curl(1) not found\n");
    return 2;
  }
  const char *ctmp = getenv("TMPDIR");
  char tmpl[700];
  if (ctmp && ctmp[0])
    snprintf(tmpl, sizeof tmpl, "%s/krtx-grok-XXXXXX", ctmp);
  else {
    const char *home = getenv("HOME");
    if (home && home[0])
      snprintf(tmpl, sizeof tmpl, "%s/Projects/x/out/spv_contain/tmp/krtx-grok-XXXXXX", home);
    else
      snprintf(tmpl, sizeof tmpl, "/tmp/krtx-grok-XXXXXX");
  }
  {
    char dir[700];
    snprintf(dir, sizeof dir, "%s", tmpl);
    char *sl = strrchr(dir, '/');
    if (sl) {
      *sl = 0;
      char mk[800];
      snprintf(mk, sizeof mk, "mkdir -p '%s' && chmod 700 '%s'", dir, dir);
      (void)system(mk);
    }
  }
  int fd = mkstemp(tmpl);
  if (fd < 0) {
    fprintf(stderr, "krtx-grok: mkstemp: %s\n", strerror(errno));
    return 1;
  }
  if (json_body) {
    size_t L = strlen(json_body);
    if (write(fd, json_body, L) != (ssize_t)L) {
      close(fd);
      unlink(tmpl);
      return 1;
    }
  }
  close(fd);
  chmod(tmpl, 0600);

  char wrap[640];
  const char *home = getenv("HOME");
  const char *wenv = getenv("SPV_CURL_WRAPPER");
  if (wenv && wenv[0])
    snprintf(wrap, sizeof wrap, "%s", wenv);
  else if (home && home[0])
    snprintf(wrap, sizeof wrap, "%s/Projects/x/Build/spv-curl-contain.sh", home);
  else
    snprintf(wrap, sizeof wrap, "/home/default/Projects/x/Build/spv-curl-contain.sh");

  char *cmd = NULL;
  if (access(wrap, X_OK) == 0) {
    if (asprintf(&cmd,
                 "SPV_CONTAIN=1 '%s' curl -sS --max-time 120 '%s' "
                 "-H 'Authorization: Bearer %s' "
                 "-H 'Content-Type: application/json' "
                 "-d @%s",
                 wrap, url, keybuf, tmpl) < 0) {
      unlink(tmpl);
      return 1;
    }
  } else {
    fprintf(stderr, "krtx-grok: WARN SPV contain missing · refusing free curl for Grok\n");
    unlink(tmpl);
    return 3;
  }
  FILE *p = popen(cmd, "r");
  free(cmd);
  if (!p) {
    unlink(tmpl);
    fprintf(stderr, "krtx-grok: popen contain curl failed\n");
    return 1;
  }
  char *out = (char *)malloc(MAX_OUT);
  if (!out) {
    pclose(p);
    unlink(tmpl);
    return 1;
  }
  size_t n = fread(out, 1, MAX_OUT - 1, p);
  out[n] = 0;
  int st = pclose(p);
  unlink(tmpl);
  if (n == 0) {
    fprintf(stderr, "krtx-grok: empty response (curl %d)\n", st);
    free(out);
    return 1;
  }
  if (strstr(out, "\"error\"") && !strstr(out, "\"content\"")) {
    fputs(out, stderr);
    if (out[n - 1] != '\n') fputc('\n', stderr);
    free(out);
    return 1;
  }
  print_content_field(out);
  free(out);
  return 0;
}

static int curl_get_auth(const char *url) {
  if (access("/usr/bin/curl", X_OK) != 0 && access("/bin/curl", X_OK) != 0) {
    fprintf(stderr, "krtx-grok: curl(1) not found\n");
    return 2;
  }
  char wrap[640];
  const char *home = getenv("HOME");
  const char *wenv = getenv("SPV_CURL_WRAPPER");
  if (wenv && wenv[0])
    snprintf(wrap, sizeof wrap, "%s", wenv);
  else if (home && home[0])
    snprintf(wrap, sizeof wrap, "%s/Projects/x/Build/spv-curl-contain.sh", home);
  else
    snprintf(wrap, sizeof wrap, "/home/default/Projects/x/Build/spv-curl-contain.sh");
  if (access(wrap, X_OK) != 0) {
    fprintf(stderr, "krtx-grok: SPV contain missing · refuse free Grok curl\n");
    return 3;
  }
  char *cmd = NULL;
  if (asprintf(&cmd,
               "SPV_CONTAIN=1 '%s' curl -sS --max-time 60 '%s' "
               "-H 'Authorization: Bearer %s' "
               "-H 'Accept: application/json'",
               wrap, url, keybuf) < 0)
    return 1;
  FILE *p = popen(cmd, "r");
  free(cmd);
  if (!p) return 1;
  char *out = (char *)malloc(MAX_OUT);
  if (!out) {
    pclose(p);
    return 1;
  }
  size_t n = fread(out, 1, MAX_OUT - 1, p);

  out[n] = 0;
  pclose(p);
  fputs(out, stdout);
  if (n && out[n - 1] != '\n') fputc('\n', stdout);
  free(out);
  return 0;
}


static int cmd_chat(const char *prompt, const char *model) {
  char *mod_js = json_escape(model);
  char *pr_js = json_escape(prompt);
  if (!mod_js || !pr_js) {
    free(mod_js);
    free(pr_js);
    return 1;
  }
  char *body = NULL;
  if (asprintf(&body,
               "{\"model\":%s,\"messages\":[{\"role\":\"user\",\"content\":%s}],"
               "\"temperature\":0.7}",
               mod_js, pr_js) < 0) {
    free(mod_js);
    free(pr_js);
    return 1;
  }
  free(mod_js);
  free(pr_js);
  int rc = curl_post_json(API_BASE "/chat/completions", body);
  free(body);
  return rc;
}

static int cmd_status(void) {
  printf("krtx-grok · ELF · SpaceXAI / xAI\n");
  printf("  base    %s\n", API_BASE);
  printf("  model   %s (default)\n", DEFAULT_MODEL);
  if (read_key() == 0) {
    size_t n = strlen(keybuf);
    const char *tail = n > 4 ? keybuf + (n - 4) : "****";
    printf("  key     set (…%s)\n", tail);
  } else {
    printf("  key     MISSING\n");
    key_hint();
  }
  printf("  curl    %s\n",
         (access("/usr/bin/curl", X_OK) == 0 || access("/bin/curl", X_OK) == 0) ? "ok" : "MISSING");
  printf("  law     key never in ELF · desk only · no public PHP\n");
  return 0;
}

static void usage(const char *a0) {
  fprintf(stderr,
          "usage: %s [chat] \"prompt…\"\n"
          "       %s status | models\n"
          "       %s -m MODEL chat \"prompt…\"\n"
          "env XAI_API_KEY · file ~/.config/biggrinrtx/xai.key\n"
          "API %s · default model %s\n",
          a0, a0, a0, API_BASE, DEFAULT_MODEL);
}

static char *join_args(int argc, char **argv, int from) {
  size_t need = 1;
  for (int j = from; j < argc; j++) need += strlen(argv[j]) + 1;
  char *buf = (char *)malloc(need);
  if (!buf) return NULL;
  buf[0] = 0;
  for (int j = from; j < argc; j++) {
    if (j > from) strcat(buf, " ");
    strcat(buf, argv[j]);
  }
  return buf;
}

int main(int argc, char **argv) {
  const char *model = DEFAULT_MODEL;
  int i = 1;
  if (argc < 2) {
    usage(argv[0]);
    return 2;
  }
  if (i < argc && (!strcmp(argv[i], "-m") || !strcmp(argv[i], "--model"))) {
    if (i + 1 >= argc) {
      usage(argv[0]);
      return 2;
    }
    model = argv[i + 1];
    i += 2;
  }
  if (i >= argc) {
    usage(argv[0]);
    return 2;
  }
  const char *cmd = argv[i];

  if (!strcmp(cmd, "help") || !strcmp(cmd, "-h") || !strcmp(cmd, "--help")) {
    usage(argv[0]);
    return 0;
  }
  if (!strcmp(cmd, "status") || !strcmp(cmd, "st")) return cmd_status();

  if (!strcmp(cmd, "models")) {
    if (read_key() != 0) {
      key_hint();
      return 2;
    }
    return curl_get_auth(API_BASE "/models");
  }

  int from = i;
  if (!strcmp(cmd, "chat") || !strcmp(cmd, "ask") || !strcmp(cmd, "grok")) {
    from = i + 1;
    if (from >= argc) {
      fprintf(stderr, "krtx-grok: need prompt\n");
      return 2;
    }
  }
  char *prompt = join_args(argc, argv, from);
  if (!prompt) return 1;
  if (read_key() != 0) {
    key_hint();
    free(prompt);
    return 2;
  }
  int rc = cmd_chat(prompt, model);
  free(prompt);
  return rc;
}
