view mrjunejune/main.c @ 269:de291f396881

install initial production config Copy the ignored repository config into /etc/mrjunejune on first deployment while preserving existing production configuration on later deploys. Co-authored-by: Copilot <[email protected]>
author MrJuneJune <me@mrjunejune.com>
date Fri, 07 Aug 2026 13:08:10 -0700
parents 056790c4fb0d
children e02e2036ef84
line wrap: on
line source

#include "seobeo/seobeo.h"
#include "markdown_converter/markdown_to_html.h"
#include "s3/s3_uploader.h"
#include "deita/deita.h"
#include "mrjunejune/latex_renderer.h"
#include "mrjunejune/conversation_api.h"
#include "mrjunejune/auth_api.h"
#include "mrjunejune/admin_api.h"
#include "mrjunejune/template_renderer.h"
#include "auth/auth_crypto.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include <time.h>
#include <sys/stat.h>
#include <stdarg.h>
#include <stdatomic.h>
#include <pthread.h>
#include <arpa/inet.h>
#include <openssl/crypto.h>

// UUID + /tmp/ + format (max 4)
#define TMP_FILE_LENGTH 47
#define UUID_LEN 37

volatile sig_atomic_t stop_server = 0;
static _Atomic uint32 counter = 0;
static _Atomic boolean g_latex_rendering = FALSE;
static Seobeo_Worker_Pool *g_media_worker_pool = NULL;

// Media processing context owned by a background worker.
typedef struct {
  int64    media_id;
  char     s3_key_original[512];
  char     s3_key_processed[512];
  char     content_type[128];
  char     access_token[256];
  char     db_path[256];
  S3_Config s3_config;
} Media_Processing_Context;

typedef struct {
  char *input_path;
  char *output_path;
  int result;
} File_Converter_Config;

// Server configuration (loaded from .config)
static char g_upload_auth_token[256] = {0};
static char g_s3_region[64] = "us-west-2";
static char g_s3_bucket[128] = "mrjunejune";
static char g_s3_cloudfront_url[256] = {0};
static char g_db_path[256] = "mrjunejune/data/mrjunejune.db";
static int  g_s3_url_expires = 3600;
static S3_Config g_s3_config = {0};
static Deita_Connection *g_db_connection = NULL;
/* S3 credentials — never logged; zero after use in init. */
static char g_s3_access_key[128] = {0};
static char g_s3_secret_key[128] = {0};

/* Auth configuration */
static char    g_auth_cookie_secret[AUTH_CRYPTO_COOKIE_SECRET_MAX_BYTES * 2 + 1] = {0};
static char    g_auth_bootstrap_username[64] = {0};
static char    g_auth_bootstrap_password_hash[AUTH_CRYPTO_PASSWORD_HASH_ENCODED_SIZE] = {0};
static char    g_auth_trusted_proxy[AUTH_CRYPTO_IP_MAX_BYTES] = {0};
static int64   g_auth_session_idle_ttl = AUTH_API_SESSION_IDLE_TTL_DEFAULT;
static int64   g_auth_session_abs_ttl  = AUTH_API_SESSION_ABS_TTL_DEFAULT;
static int64   g_auth_guest_ttl        = AUTH_API_GUEST_TTL_DEFAULT;
static boolean g_auth_dev_insecure     = FALSE;
static char    g_server_host[128]      = {0};   /* SERVER_HOST; empty → 0.0.0.0 */

/* Guest inference / quota configuration */
#define G_GUEST_DAILY_TURNS_DEFAULT         10
#define G_GUEST_DAILY_OUTPUT_TOKENS_DEFAULT 20000
#define G_GUEST_REQUEST_OUTPUT_TOKENS_MIN   1
#define G_GUEST_DAILY_TURNS_MIN             1
#define G_GUEST_DAILY_TURNS_MAX             10000
#define G_GUEST_DAILY_OUTPUT_TOKENS_MIN     1
#define G_GUEST_DAILY_OUTPUT_TOKENS_MAX     1000000
#define G_GUEST_REQUEST_OUTPUT_TOKENS_DEFAULT 2048
static boolean g_guest_inference_enabled     = FALSE;
static int64   g_guest_daily_turns           = G_GUEST_DAILY_TURNS_DEFAULT;
static int64   g_guest_daily_output_tokens   = G_GUEST_DAILY_OUTPUT_TOKENS_DEFAULT;
static int64   g_guest_request_output_tokens = G_GUEST_REQUEST_OUTPUT_TOKENS_DEFAULT;

/*
 * Strict full-string integer parse: returns FALSE if value is empty,
 * has trailing non-digit characters, or overflows a long.
 */
static boolean config__parse_int64_strict(const char *value, int64 *out)
{
  if (!value || value[0] == '\0')
    return FALSE;
  char *end = NULL;
  long v = strtol(value, &end, 10);
  if (end == value || *end != '\0')
    return FALSE;
  *out = (int64)v;
  return TRUE;
}

/*
 * Decode a lowercase or uppercase hex string into raw bytes.
 * Returns the number of decoded bytes, or 0 on any error.
 * hex_len must be even; each pair of hex chars produces one byte.
 */
static size_t config__hex_decode(const char *hex, uint8 *out, size_t out_capacity)
{
  if (!hex || !out) return 0;
  size_t hex_len = strlen(hex);
  if (hex_len == 0 || hex_len % 2 != 0) return 0;
  size_t byte_count = hex_len / 2;
  if (byte_count > out_capacity) return 0;
  for (size_t i = 0; i < byte_count; i++)
  {
    int h, l;
    char hi = hex[i * 2];
    char lo = hex[i * 2 + 1];
    if      (hi >= '0' && hi <= '9') h = hi - '0';
    else if (hi >= 'a' && hi <= 'f') h = hi - 'a' + 10;
    else if (hi >= 'A' && hi <= 'F') h = hi - 'A' + 10;
    else return 0;
    if      (lo >= '0' && lo <= '9') l = lo - '0';
    else if (lo >= 'a' && lo <= 'f') l = lo - 'a' + 10;
    else if (lo >= 'A' && lo <= 'F') l = lo - 'A' + 10;
    else return 0;
    out[i] = (uint8)((h << 4) | l);
  }
  return byte_count;
}

static void load_config(const char *config_path)
{
  boolean config_loaded = FALSE;
  FILE *f = fopen(config_path, "r");
  char workspace_config_path[1024] = {0};
  if (!f)
  {
    const char *workspace = getenv("BUILD_WORKSPACE_DIRECTORY");
    if (workspace && workspace[0] != '\0')
    {
      int written = snprintf(
          workspace_config_path,
          sizeof(workspace_config_path),
          "%s/%s",
          workspace,
          config_path);
      if (written > 0 && (size_t)written < sizeof(workspace_config_path))
        f = fopen(workspace_config_path, "r");
    }
  }
  if (!f)
  {
    printf("[CONFIG] Warning: Could not open %s, using defaults\n", config_path);
  }
  else
  {
    config_loaded = TRUE;
    char line[512];
    while (fgets(line, sizeof(line), f))
    {
      // Skip comments and empty lines
      if (line[0] == '#' || line[0] == '\n' || line[0] == '\r') continue;

      char *eq = strchr(line, '=');
      if (!eq) continue;

      *eq = '\0';
      char *key = line;
      char *value = eq + 1;

      // Trim newline from value
      size_t vlen = strlen(value);
      while (vlen > 0 && (value[vlen-1] == '\n' || value[vlen-1] == '\r'))
        value[--vlen] = '\0';

      if (strcmp(key, "UPLOAD_AUTH_TOKEN") == 0)
      {
        strncpy(g_upload_auth_token, value, sizeof(g_upload_auth_token) - 1);
      }
    else if (strcmp(key, "S3_REGION") == 0)
    {
      strncpy(g_s3_region, value, sizeof(g_s3_region) - 1);
    }
    else if (strcmp(key, "S3_BUCKET") == 0)
    {
      strncpy(g_s3_bucket, value, sizeof(g_s3_bucket) - 1);
    }
    else if (strcmp(key, "S3_URL_EXPIRES") == 0)
    {
      int64 v;
      if (!config__parse_int64_strict(value, &v) || v <= 0)
      {
        fprintf(stderr, "[CONFIG] ERROR: S3_URL_EXPIRES must be a positive integer\n");
        exit(1);
      }
      g_s3_url_expires = (int)v;
    }
    else if (strcmp(key, "S3_CLOUDFRONT_URL") == 0)
    {
      strncpy(g_s3_cloudfront_url, value, sizeof(g_s3_cloudfront_url) - 1);
    }
    else if (strcmp(key, "DB_PATH") == 0)
    {
      strncpy(g_db_path, value, sizeof(g_db_path) - 1);
    }
    else if (strcmp(key, "AWS_MRJUNEJUNE_ACCESS_KEY") == 0)
    {
      strncpy(g_s3_access_key, value, sizeof(g_s3_access_key) - 1);
    }
    else if (strcmp(key, "AWS_MRJUNEJUNE_SECRET_ACCESS_KEY") == 0)
    {
      strncpy(g_s3_secret_key, value, sizeof(g_s3_secret_key) - 1);
    }
    else if (strcmp(key, "AUTH_COOKIE_SECRET") == 0)
    {
      /* Never log this value */
      strncpy(g_auth_cookie_secret, value, sizeof(g_auth_cookie_secret) - 1);
    }
    else if (strcmp(key, "AUTH_BOOTSTRAP_USERNAME") == 0)
    {
      strncpy(g_auth_bootstrap_username, value,
              sizeof(g_auth_bootstrap_username) - 1);
    }
    else if (strcmp(key, "AUTH_BOOTSTRAP_PASSWORD_HASH") == 0)
    {
      strncpy(g_auth_bootstrap_password_hash, value,
              sizeof(g_auth_bootstrap_password_hash) - 1);
    }
    else if (strcmp(key, "AUTH_TRUSTED_PROXY") == 0)
    {
      strncpy(g_auth_trusted_proxy, value, sizeof(g_auth_trusted_proxy) - 1);
    }
    else if (strcmp(key, "AUTH_SESSION_IDLE_TTL") == 0)
    {
      int64 v;
      if (!config__parse_int64_strict(value, &v) || v <= 0)
      {
        fprintf(stderr, "[CONFIG] ERROR: AUTH_SESSION_IDLE_TTL must be a positive integer\n");
        exit(1);
      }
      g_auth_session_idle_ttl = v;
    }
    else if (strcmp(key, "AUTH_SESSION_ABS_TTL") == 0)
    {
      int64 v;
      if (!config__parse_int64_strict(value, &v) || v <= 0)
      {
        fprintf(stderr, "[CONFIG] ERROR: AUTH_SESSION_ABS_TTL must be a positive integer\n");
        exit(1);
      }
      g_auth_session_abs_ttl = v;
    }
    else if (strcmp(key, "AUTH_GUEST_TTL") == 0)
    {
      int64 v;
      if (!config__parse_int64_strict(value, &v) || v <= 0)
      {
        fprintf(stderr, "[CONFIG] ERROR: AUTH_GUEST_TTL must be a positive integer\n");
        exit(1);
      }
      g_auth_guest_ttl = v;
    }
      else if (strcmp(key, "AUTH_DEV_INSECURE_COOKIE") == 0)
      {
        g_auth_dev_insecure =
            (strcmp(value, "1") == 0 || strcmp(value, "true") == 0);
      }
      else if (strcmp(key, "SERVER_HOST") == 0)
      {
        strncpy(g_server_host, value, sizeof(g_server_host) - 1);
      }
      else if (strcmp(key, "MRJUNEJUNE_ALLOW_GUEST_INFERENCE") == 0)
      {
        if (strcmp(value, "1") == 0 || strcasecmp(value, "true") == 0)
          g_guest_inference_enabled = TRUE;
        else if (strcmp(value, "0") == 0 || strcasecmp(value, "false") == 0)
          g_guest_inference_enabled = FALSE;
        else
        {
          fprintf(
              stderr,
              "[CONFIG] ERROR: MRJUNEJUNE_ALLOW_GUEST_INFERENCE must be true or false\n");
          exit(1);
        }
      }
      else if (strcmp(key, "AUTH_GUEST_DAILY_TURNS") == 0)
      {
        int64 v;
        if (!config__parse_int64_strict(value, &v) ||
            v < G_GUEST_DAILY_TURNS_MIN || v > G_GUEST_DAILY_TURNS_MAX)
        {
          printf("[CONFIG] ERROR: AUTH_GUEST_DAILY_TURNS must be %d..%d\n",
                 G_GUEST_DAILY_TURNS_MIN, G_GUEST_DAILY_TURNS_MAX);
          exit(1);
        }
        g_guest_daily_turns = v;
      }
      else if (strcmp(key, "AUTH_GUEST_DAILY_OUTPUT_TOKENS") == 0)
      {
        int64 v;
        if (!config__parse_int64_strict(value, &v) ||
            v < G_GUEST_DAILY_OUTPUT_TOKENS_MIN ||
            v > G_GUEST_DAILY_OUTPUT_TOKENS_MAX)
        {
          printf("[CONFIG] ERROR: AUTH_GUEST_DAILY_OUTPUT_TOKENS must be %d..%d\n",
                 G_GUEST_DAILY_OUTPUT_TOKENS_MIN, G_GUEST_DAILY_OUTPUT_TOKENS_MAX);
          exit(1);
        }
        g_guest_daily_output_tokens = v;
      }
      else if (strcmp(key, "AUTH_GUEST_REQUEST_OUTPUT_TOKENS") == 0)
      {
        int64 v;
        if (!config__parse_int64_strict(value, &v) ||
            v < G_GUEST_REQUEST_OUTPUT_TOKENS_MIN)
        {
          printf("[CONFIG] ERROR: AUTH_GUEST_REQUEST_OUTPUT_TOKENS must be >= %d\n",
                 G_GUEST_REQUEST_OUTPUT_TOKENS_MIN);
          exit(1);
        }
        g_guest_request_output_tokens = v;
      }
    }
    fclose(f);
  }

  printf("[CONFIG] Loaded: token=%s..., region=%s, bucket=%s, expires=%d, cloudfront=%s, db=%s\n",
         g_upload_auth_token[0] ? "***" : "(empty)",
         g_s3_region, g_s3_bucket, g_s3_url_expires,
         g_s3_cloudfront_url[0] ? g_s3_cloudfront_url : "(none)",
         g_db_path);
  printf("[CONFIG] Auth: secret=%s, bootstrap_user=%s, trusted_proxy=%s\n",
         g_auth_cookie_secret[0] ? "(set)" : "(not set)",
         g_auth_bootstrap_username[0] ? g_auth_bootstrap_username : "(none)",
         g_auth_trusted_proxy[0] ? "(set)" : "(not set)");

  const char *database_path_override = getenv("MRJUNEJUNE_DB_PATH");
  const char *test_tmpdir = getenv("TEST_TMPDIR");
  if (database_path_override && database_path_override[0] != '\0')
  {
    strncpy(g_db_path, database_path_override, sizeof(g_db_path) - 1);
  }
  else if (test_tmpdir && test_tmpdir[0] != '\0')
  {
    snprintf(g_db_path, sizeof(g_db_path), "%s/mrjunejune.db", test_tmpdir);
  }

  /* Environment configuration is a compatibility/testing fallback only when
   * no config file is present. Dynamic supervisor wiring is read separately. */
  if (!config_loaded)
  {
    const char *env;

    /* S3 / server config env overrides */
    if ((env = getenv("UPLOAD_AUTH_TOKEN")) && env[0] != '\0')
      strncpy(g_upload_auth_token, env, sizeof(g_upload_auth_token) - 1);
    if ((env = getenv("S3_REGION")) && env[0] != '\0')
      strncpy(g_s3_region, env, sizeof(g_s3_region) - 1);
    if ((env = getenv("S3_BUCKET")) && env[0] != '\0')
      strncpy(g_s3_bucket, env, sizeof(g_s3_bucket) - 1);
    if ((env = getenv("S3_CLOUDFRONT_URL")) && env[0] != '\0')
      strncpy(g_s3_cloudfront_url, env, sizeof(g_s3_cloudfront_url) - 1);
    if ((env = getenv("S3_URL_EXPIRES")) && env[0] != '\0')
    {
      int64 v;
      if (!config__parse_int64_strict(env, &v) || v <= 0)
      {
        fprintf(stderr, "[CONFIG] ERROR: S3_URL_EXPIRES must be a positive integer\n");
        exit(1);
      }
      g_s3_url_expires = (int)v;
    }
    if ((env = getenv("AWS_MRJUNEJUNE_ACCESS_KEY")) && env[0] != '\0')
      strncpy(g_s3_access_key, env, sizeof(g_s3_access_key) - 1);
    if ((env = getenv("AWS_MRJUNEJUNE_SECRET_ACCESS_KEY")) && env[0] != '\0')
      strncpy(g_s3_secret_key, env, sizeof(g_s3_secret_key) - 1);

    /* Auth env overrides */
    if ((env = getenv("AUTH_COOKIE_SECRET")) && env[0] != '\0')
      strncpy(g_auth_cookie_secret, env, sizeof(g_auth_cookie_secret) - 1);
    if ((env = getenv("AUTH_BOOTSTRAP_USERNAME")) && env[0] != '\0')
      strncpy(g_auth_bootstrap_username, env,
              sizeof(g_auth_bootstrap_username) - 1);
    if ((env = getenv("AUTH_BOOTSTRAP_PASSWORD_HASH")) && env[0] != '\0')
      strncpy(g_auth_bootstrap_password_hash, env,
              sizeof(g_auth_bootstrap_password_hash) - 1);
    if ((env = getenv("AUTH_TRUSTED_PROXY")) && env[0] != '\0')
      strncpy(g_auth_trusted_proxy, env, sizeof(g_auth_trusted_proxy) - 1);
    if ((env = getenv("AUTH_SESSION_IDLE_TTL")) && env[0] != '\0')
    {
      int64 v;
      if (!config__parse_int64_strict(env, &v) || v <= 0)
      {
        fprintf(stderr, "[CONFIG] ERROR: AUTH_SESSION_IDLE_TTL must be a positive integer\n");
        exit(1);
      }
      g_auth_session_idle_ttl = v;
    }
    if ((env = getenv("AUTH_SESSION_ABS_TTL")) && env[0] != '\0')
    {
      int64 v;
      if (!config__parse_int64_strict(env, &v) || v <= 0)
      {
        fprintf(stderr, "[CONFIG] ERROR: AUTH_SESSION_ABS_TTL must be a positive integer\n");
        exit(1);
      }
      g_auth_session_abs_ttl = v;
    }
    if ((env = getenv("AUTH_GUEST_TTL")) && env[0] != '\0')
    {
      int64 v;
      if (!config__parse_int64_strict(env, &v) || v <= 0)
      {
        fprintf(stderr, "[CONFIG] ERROR: AUTH_GUEST_TTL must be a positive integer\n");
        exit(1);
      }
      g_auth_guest_ttl = v;
    }
    if ((env = getenv("AUTH_DEV_INSECURE_COOKIE")) && env[0] != '\0')
      g_auth_dev_insecure =
          (strcmp(env, "1") == 0 || strcmp(env, "true") == 0);
    if ((env = getenv("SERVER_HOST")) && env[0] != '\0')
      strncpy(g_server_host, env, sizeof(g_server_host) - 1);

    /* Guest inference enable: runtime-only, boolean parsed strictly. */
    if ((env = getenv("MRJUNEJUNE_ALLOW_GUEST_INFERENCE")) && env[0] != '\0')
      g_guest_inference_enabled =
          (strcmp(env, "1") == 0 || strcasecmp(env, "true") == 0);
    else if ((env = getenv("MRJUNEJUNE_ALLOW_ANONYMOUS_INFERENCE")) && env[0] != '\0')
      g_guest_inference_enabled =
          (strcmp(env, "1") == 0 || strcasecmp(env, "true") == 0);

    /* Guest quota env overrides: strict full-string integer, fail on malformed. */
    if ((env = getenv("AUTH_GUEST_DAILY_TURNS")) && env[0] != '\0')
    {
      int64 v;
      if (!config__parse_int64_strict(env, &v) ||
          v < G_GUEST_DAILY_TURNS_MIN || v > G_GUEST_DAILY_TURNS_MAX)
      {
        fprintf(stderr,
                "[CONFIG] ERROR: AUTH_GUEST_DAILY_TURNS must be %d..%d\n",
                G_GUEST_DAILY_TURNS_MIN, G_GUEST_DAILY_TURNS_MAX);
        exit(1);
      }
      g_guest_daily_turns = v;
    }
    if ((env = getenv("AUTH_GUEST_DAILY_OUTPUT_TOKENS")) && env[0] != '\0')
    {
      int64 v;
      if (!config__parse_int64_strict(env, &v) ||
          v < G_GUEST_DAILY_OUTPUT_TOKENS_MIN ||
          v > G_GUEST_DAILY_OUTPUT_TOKENS_MAX)
      {
        fprintf(stderr,
                "[CONFIG] ERROR: AUTH_GUEST_DAILY_OUTPUT_TOKENS must be %d..%d\n",
                G_GUEST_DAILY_OUTPUT_TOKENS_MIN, G_GUEST_DAILY_OUTPUT_TOKENS_MAX);
        exit(1);
      }
      g_guest_daily_output_tokens = v;
    }
    if ((env = getenv("AUTH_GUEST_REQUEST_OUTPUT_TOKENS")) && env[0] != '\0')
    {
      int64 v;
      if (!config__parse_int64_strict(env, &v) ||
          v < G_GUEST_REQUEST_OUTPUT_TOKENS_MIN)
      {
        fprintf(stderr,
                "[CONFIG] ERROR: AUTH_GUEST_REQUEST_OUTPUT_TOKENS must be >= %d\n",
                G_GUEST_REQUEST_OUTPUT_TOKENS_MIN);
        exit(1);
      }
      g_guest_request_output_tokens = v;
    }
  }
}

static void init_database(void)
{
  // Create data directory if needed
  char *last_slash = strrchr(g_db_path, '/');
  if (last_slash)
  {
    char dir_path[256];
    size_t dir_len = last_slash - g_db_path;
    strncpy(dir_path, g_db_path, dir_len);
    dir_path[dir_len] = '\0';
    mkdir(dir_path, 0755);
  }

  g_db_connection = Deita_Connection_Create(DEITA_DATABASE_TYPE_SQLITE3, g_db_path);
  if (!g_db_connection || !Deita_Connection_Is_Open(g_db_connection))
  {
    printf("[DB] ERROR: Failed to open database at %s\n", g_db_path);
    return;
  }

  // Create editor_content table
  const char *create_table =
    "CREATE TABLE IF NOT EXISTS editor_content ("
    "  id INTEGER PRIMARY KEY AUTOINCREMENT,"
    "  access_token TEXT NOT NULL,"
    "  doc_id TEXT NOT NULL,"
    "  content TEXT,"
    "  created_at INTEGER DEFAULT (strftime('%s', 'now')),"
    "  updated_at INTEGER DEFAULT (strftime('%s', 'now')),"
    "  UNIQUE(access_token, doc_id)"
    ")";

  int32 result = Deita_Query_Execute_Update(g_db_connection, create_table);
  if (result < 0)
  {
    printf("[DB] ERROR: Failed to create editor_content table\n");
  }

  // Create media_uploads table
  const char *create_media_uploads =
    "CREATE TABLE IF NOT EXISTS media_uploads ("
    "  id INTEGER PRIMARY KEY AUTOINCREMENT,"
    "  access_token TEXT NOT NULL,"
    "  original_filename TEXT NOT NULL,"
    "  content_type TEXT NOT NULL,"
    "  s3_key_original TEXT NOT NULL,"
    "  s3_key_processed TEXT,"
    "  file_size INTEGER,"
    "  status TEXT NOT NULL DEFAULT 'pending',"
    "  error_message TEXT,"
    "  created_at INTEGER DEFAULT (strftime('%s', 'now')),"
    "  updated_at INTEGER DEFAULT (strftime('%s', 'now'))"
    ")";

  result = Deita_Query_Execute_Update(g_db_connection, create_media_uploads);
  if (result < 0)
  {
    printf("[DB] ERROR: Failed to create media_uploads table\n");
  }

  // Create indices for media_uploads
  const char *create_status_idx =
    "CREATE INDEX IF NOT EXISTS idx_media_uploads_status ON media_uploads(status)";
  result = Deita_Query_Execute_Update(g_db_connection, create_status_idx);
  if (result < 0)
  {
    printf("[DB] ERROR: Failed to create status index\n");
  }

  const char *create_token_status_idx =
    "CREATE INDEX IF NOT EXISTS idx_media_uploads_token_status "
    "ON media_uploads(access_token, status)";
  result = Deita_Query_Execute_Update(g_db_connection, create_token_status_idx);
  if (result < 0)
  {
    printf("[DB] ERROR: Failed to create token_status index\n");
  }
  else
  {
    printf("[DB] Initialized: %s\n", g_db_path);
  }
}

void handle_sigint(int sig)
{
  (void)sig;
  stop_server = 1;
  Seobeo_Web_Server_Stop();
}

static Seobeo_Request_Entry *html_render_error(Dowa_Arena *arena, const char *msg)
{
  Seobeo_Request_Entry *resp = NULL;
  Dowa_HashMap_Push_Arena(resp, "status", "500", arena);
  Dowa_HashMap_Push_Arena(resp, "content-type", "text/plain; charset=utf-8", arena);
  Dowa_HashMap_Push_Arena(resp, "body", (char *)msg, arena);
  return resp;
}

#define HTML_PAGE_CAP (128 * 1024)

Seobeo_Request_Entry* GetHomePage(Seobeo_Request_Entry *req, Dowa_Arena *arena)
{
  Seobeo_Request_Entry *resp = NULL;
  char *final_body = Dowa_Arena_Allocate(arena, HTML_PAGE_CAP);
  if (!final_body || !Mjj_Template_Render_File(final_body, HTML_PAGE_CAP, "/index.html", arena))
    return html_render_error(arena, "Internal Server Error");
  Dowa_HashMap_Push_Arena(resp, "body", final_body, arena);
  return resp;
}

Seobeo_Request_Entry* GetResume(Seobeo_Request_Entry *req, Dowa_Arena *arena)
{
  Seobeo_Request_Entry *resp = NULL;
  char *final_body = Dowa_Arena_Allocate(arena, HTML_PAGE_CAP);
  if (!final_body || !Mjj_Template_Render_File(final_body, HTML_PAGE_CAP, "/resume/index.html", arena))
    return html_render_error(arena, "Internal Server Error");
  Dowa_HashMap_Push_Arena(resp, "body", final_body, arena);
  return resp;
}

Seobeo_Request_Entry* GetTools(Seobeo_Request_Entry *req, Dowa_Arena *arena)
{
  Seobeo_Request_Entry *resp = NULL;
  char *final_body = Dowa_Arena_Allocate(arena, HTML_PAGE_CAP);
  if (!final_body || !Mjj_Template_Render_File(final_body, HTML_PAGE_CAP, "/tools/index.html", arena))
    return html_render_error(arena, "Internal Server Error");
  Dowa_HashMap_Push_Arena(resp, "body", final_body, arena);
  return resp;
}


Seobeo_Request_Entry* GetMDToHTML(Seobeo_Request_Entry *req, Dowa_Arena *arena)
{
  Seobeo_Request_Entry *resp = NULL;
  char *final_body = Dowa_Arena_Allocate(arena, HTML_PAGE_CAP);
  if (!final_body || !Mjj_Template_Render_File(final_body, HTML_PAGE_CAP, "/tools/markdown_to_html/index.html", arena))
    return html_render_error(arena, "Internal Server Error");
  Dowa_HashMap_Push_Arena(resp, "body", final_body, arena);
  return resp;
}

Seobeo_Request_Entry* GetFileConverter(Seobeo_Request_Entry *req, Dowa_Arena *arena)
{
  Seobeo_Request_Entry *resp = NULL;
  char *final_body = Dowa_Arena_Allocate(arena, HTML_PAGE_CAP);
  if (!final_body || !Mjj_Template_Render_File(final_body, HTML_PAGE_CAP, "/tools/file_converter/index.html", arena))
    return html_render_error(arena, "Internal Server Error");
  Dowa_HashMap_Push_Arena(resp, "body", final_body, arena);
  return resp;
}

Seobeo_Request_Entry* GetHlsPlayer(Seobeo_Request_Entry *req, Dowa_Arena *arena)
{
  Seobeo_Request_Entry *resp = NULL;
  char *final_body = Dowa_Arena_Allocate(arena, HTML_PAGE_CAP);
  if (!final_body || !Mjj_Template_Render_File(final_body, HTML_PAGE_CAP, "/tools/hls_player/index.html", arena))
    return html_render_error(arena, "Internal Server Error");
  Dowa_HashMap_Push_Arena(resp, "body", final_body, arena);
  return resp;
}

Seobeo_Request_Entry* GetLatexEditor(Seobeo_Request_Entry *req, Dowa_Arena *arena)
{
  Seobeo_Request_Entry *resp = NULL;
  char *final_body = Dowa_Arena_Allocate(arena, HTML_PAGE_CAP);
  if (!final_body || !Mjj_Template_Render_File(final_body, HTML_PAGE_CAP, "/tools/latex_editor/index.html", arena))
    return html_render_error(arena, "Internal Server Error");
  Dowa_HashMap_Push_Arena(resp, "body", final_body, arena);
  return resp;
}


static Seobeo_Request_Entry *LatexErrorResponse(
    Dowa_Arena *arena,
    int status,
    const char *message)
{
  Seobeo_Request_Entry *resp = NULL;
  char *status_value = Dowa_Arena_Allocate(arena, 16);
  snprintf(status_value, 16, "%d", status);
  char *body = Dowa_Arena_Allocate(arena, strlen(message) + 1);
  strcpy(body, message);
  Dowa_HashMap_Push_Arena(resp, "status", status_value, arena);
  Dowa_HashMap_Push_Arena(resp, "content-type", "text/plain; charset=utf-8", arena);
  Dowa_HashMap_Push_Arena(resp, "cache-control", "no-store", arena);
  Dowa_HashMap_Push_Arena(resp, "body", body, arena);
  return resp;
}

Seobeo_Request_Entry *RenderLatexPdf(Seobeo_Request_Entry *req, Dowa_Arena *arena)
{
  void *body_kv = Dowa_HashMap_Get_Ptr(req, "Body");
  void *length_kv = Dowa_HashMap_Get_Ptr(req, "Content-Length");
  if (!body_kv || !length_kv)
    return LatexErrorResponse(arena, 400, "LaTeX source and Content-Length are required.");

  const char *length_value = ((Seobeo_Request_Entry *)length_kv)->value;
  char *length_end = NULL;
  errno = 0;
  unsigned long long parsed_length = strtoull(length_value, &length_end, 10);
  if (errno != 0 ||
      length_end == length_value ||
      *length_end != '\0' ||
      parsed_length == 0)
    return LatexErrorResponse(arena, 400, "Content-Length is invalid.");
  if (parsed_length > LATEX_SOURCE_MAX_BYTES)
    return LatexErrorResponse(arena, 413, "LaTeX source exceeds the 64 KiB limit.");

  boolean expected = FALSE;
  if (!atomic_compare_exchange_strong(
          &g_latex_rendering,
          &expected,
          TRUE))
    return LatexErrorResponse(arena, 429, "The LaTeX compiler is busy. Try again shortly.");

  Latex_Render_Result render = Latex_Render(
      (const uint8 *)((Seobeo_Request_Entry *)body_kv)->value,
      (size_t)parsed_length);
  atomic_store(&g_latex_rendering, FALSE);
  if (render.status != LATEX_RENDER_OK)
  {
    int status = 500;
    if (render.status == LATEX_RENDER_INVALID_INPUT)
      status = 400;
    else if (render.status == LATEX_RENDER_COMPILE_ERROR)
      status = 422;
    else if (render.status == LATEX_RENDER_TIMEOUT)
      status = 504;
    else if (render.status == LATEX_RENDER_COMPILER_UNAVAILABLE)
      status = 503;

    const char *diagnostics = render.diagnostics
        ? render.diagnostics
        : "LaTeX rendering failed.";
    char *body = Dowa_Arena_Allocate(arena, strlen(diagnostics) + 1);
    strcpy(body, diagnostics);
    Latex_Render_Result_Destroy(&render);
    return LatexErrorResponse(arena, status, body);
  }

  char *pdf = Dowa_Arena_Allocate(arena, render.pdf_size + 1);
  if (!pdf)
  {
    Latex_Render_Result_Destroy(&render);
    return LatexErrorResponse(arena, 500, "The generated PDF is too large to return.");
  }
  memcpy(pdf, render.pdf_data, render.pdf_size);
  pdf[render.pdf_size] = '\0';
  char *content_length = Dowa_Arena_Allocate(arena, 32);
  snprintf(content_length, 32, "%zu", render.pdf_size);
  Latex_Render_Result_Destroy(&render);

  Seobeo_Request_Entry *resp = NULL;
  Dowa_HashMap_Push_Arena(resp, "status", "200", arena);
  Dowa_HashMap_Push_Arena(resp, "content-type", "application/pdf", arena);
  Dowa_HashMap_Push_Arena(resp, "content-length", content_length, arena);
  Dowa_HashMap_Push_Arena(resp, "content-disposition", "inline; filename=\"document.pdf\"", arena);
  Dowa_HashMap_Push_Arena(resp, "cache-control", "no-store", arena);
  Dowa_HashMap_Push_Arena(resp, "x-content-type-options", "nosniff", arena);
  Dowa_HashMap_Push_Arena(resp, "body", pdf, arena);
  return resp;
}

// Joinable worker function for local image conversion.
void Simple_WebpConverter_Background(void *arg)
{
  File_Converter_Config *configuration = (File_Converter_Config *)arg;

  char cmd[1024];
  snprintf(cmd, sizeof(cmd), "ffmpeg -y -i %s -quality 80 %s 2>/tmp/error_log",
           configuration->input_path, configuration->output_path);
  Seobeo_Log(SEOBEO_INFO, "[MEDIA] Running FFmpeg: %s\n", cmd);
  configuration->result = system(cmd);

  Seobeo_Log(
      SEOBEO_INFO,
      "[MEDIA] FFmpeg result: %d\n",
      configuration->result);
  if (configuration->result != 0)
  {
    Seobeo_Log(SEOBEO_ERROR, "[MEDIA] ERROR: FFmpeg conversion failed\n");
    return;
  }
  Seobeo_Log(
      SEOBEO_INFO,
      "[MEDIA] Successfully converted to webp: %s\n",
      configuration->output_path);
}

Seobeo_Request_Entry *ConvertImageToWebP(Seobeo_Request_Entry *req, Dowa_Arena *arena)
{
  Seobeo_Request_Entry *resp = NULL;

  if (!req)
  {
    Seobeo_Log(SEOBEO_ERROR, "Request is NULL\n");
    char *error_msg = "Internal error: no request data";
    Dowa_HashMap_Push_Arena(resp, "status", "500", arena);
    Dowa_HashMap_Push_Arena(resp, "content-type", "text/plain", arena);
    Dowa_HashMap_Push_Arena(resp, "body", error_msg, arena);
    return resp;
  }

  size_t req_length = Dowa_Array_Length(req);
  printf("Request has %zu entries\n", req_length);

  for (size_t i = 0; i < req_length; i++)
  {
    Seobeo_Log(SEOBEO_INFO, "  Key[%zu]: '%s'\n", i, req[i].key);
  }

  void *body_kv = Dowa_HashMap_Get_Ptr(req, "Body");
  if (!body_kv)
  {
    printf("ERROR: No 'Body' key found in request\n");

    char *error_msg = "No file data provided";
    Dowa_HashMap_Push_Arena(resp, "status", "400", arena);
    Dowa_HashMap_Push_Arena(resp, "content-type", "text/plain", arena);
    Dowa_HashMap_Push_Arena(resp, "body", error_msg, arena);
    return resp;
  }

  void *cl_kv = Dowa_HashMap_Get_Ptr(req, "Content-Length");
  if (!cl_kv)
  {
    char *error_msg = "No Content-Length header";
    Dowa_HashMap_Push_Arena(resp, "status", "400", arena);
    Dowa_HashMap_Push_Arena(resp, "content-type", "text/plain", arena);
    Dowa_HashMap_Push_Arena(resp, "body", error_msg, arena);
    return resp;
  }

  const char *file_data = ((Seobeo_Request_Entry*)body_kv)->value;
  const char *content_length_str = ((Seobeo_Request_Entry*)cl_kv)->value;
  size_t file_size = atoi(content_length_str);

  Seobeo_Log(SEOBEO_DEBUG, "Converting image, file_size=%zu bytes\n", file_size);

  int open_flags = O_RDWR | O_CREAT | O_EXCL;

  char *uuid4 = (char *)Dowa_Arena_Allocate(arena, UUID_LEN);
  uint32 seed =
      (uint32)time(NULL) ^
      (uint32)Seobeo_Thread_Current_Id() ^
      counter++;
  Dowa_String_UUID(seed, uuid4);
  char *input_path = Dowa_Arena_Allocate(arena, TMP_FILE_LENGTH);;
  snprintf(input_path, TMP_FILE_LENGTH, "/tmp/%s", uuid4);
  int input_fd = open(input_path, open_flags, 0600);
  if (input_fd == -1)
  {
    char *error_msg = "Failed to create temporary file";
    Dowa_HashMap_Push_Arena(resp, "status", "500", arena);
    Dowa_HashMap_Push_Arena(resp, "content-type", "text/plain", arena);
    Dowa_HashMap_Push_Arena(resp, "body", error_msg, arena);
    return resp;
  }
  write(input_fd, file_data, file_size);
  close(input_fd);


  uuid4 = (char *)Dowa_Arena_Allocate(arena, UUID_LEN);
  seed =
      (uint32)time(NULL) ^
      (uint32)Seobeo_Thread_Current_Id() ^
      counter++;
  Dowa_String_UUID(seed, uuid4);
  char *output_path = (char *)Dowa_Arena_Allocate(arena, TMP_FILE_LENGTH);;
  snprintf(output_path, TMP_FILE_LENGTH, "/tmp/%s.webp", uuid4);
  Seobeo_Log(SEOBEO_DEBUG, "output_path %s\n", output_path);
  Seobeo_Log(SEOBEO_DEBUG, "open_flags: 0x%x\n", open_flags);
  Seobeo_Log(SEOBEO_DEBUG, "input_path: %s\n", input_path);
  int output_fd = open(output_path, open_flags, 0600);
  Seobeo_Log(SEOBEO_DEBUG, "output_fd: %d\n", output_fd);
  if (output_fd == -1)
  {
    unlink(input_path);
    Seobeo_Log(SEOBEO_DEBUG, "errno: %d (%s)\n", errno, strerror(errno));
    char *error_msg = "Failed to create output file";
    Dowa_HashMap_Push_Arena(resp, "status", "500", arena);
    Dowa_HashMap_Push_Arena(resp, "content-type", "text/plain", arena);
    Dowa_HashMap_Push_Arena(resp, "body", error_msg, arena);
    return resp;
  }
  close(output_fd);

  File_Converter_Config *configuration = Dowa_Arena_Allocate(arena, sizeof(File_Converter_Config));
  configuration->input_path = input_path;
  configuration->output_path = output_path;
  configuration->result = -1;

  Seobeo_Thread *p_worker = Seobeo_Thread_Start(
      Simple_WebpConverter_Background,
      configuration,
      NULL);
  if (!p_worker ||
      Seobeo_Thread_Join(p_worker) != SEOBEO_WORKER_OK ||
      configuration->result != 0)
  {
    unlink(input_path);
    unlink(output_path);
    char *error_msg = "FFmpeg conversion failed";
    Dowa_HashMap_Push_Arena(resp, "status", "500", arena);
    Dowa_HashMap_Push_Arena(resp, "content-type", "text/plain", arena);
    Dowa_HashMap_Push_Arena(resp, "body", error_msg, arena);
    return resp;
  }

  FILE *out_file = fopen(output_path, "rb");
  if (!out_file)
  {
    unlink(input_path);
    unlink(output_path);
    char *error_msg = "Failed to read converted file";
    Dowa_HashMap_Push_Arena(resp, "status", "500", arena);
    Dowa_HashMap_Push_Arena(resp, "content-type", "text/plain", arena);
    Dowa_HashMap_Push_Arena(resp, "body", error_msg, arena);
    return resp;
  }
  fclose(out_file);

  unlink(input_path);
  char *filename = strrchr(output_path, '/') + 1;
  char *response_body = Dowa_Arena_Allocate(arena, 512);
  snprintf(response_body, 512,
           "{\"success\":true,\"download_url\":\"/api/download/%s\",\"expires\":\"10 minutes\"}",
           filename);
  Dowa_HashMap_Push_Arena(resp, "status", "200", arena);
  Dowa_HashMap_Push_Arena(resp, "content-type", "application/json", arena);
  Dowa_HashMap_Push_Arena(resp, "body", response_body, arena);

  Seobeo_Log(SEOBEO_DEBUG, "Image converted, available at /api/download/%s\n", filename);

  return resp;
}

Seobeo_Request_Entry *ConvertVideoToMP4(Seobeo_Request_Entry *req, Dowa_Arena *arena)
{
  Seobeo_Request_Entry *resp = NULL;

  void *body_kv = Dowa_HashMap_Get_Ptr(req, "Body");
  if (!body_kv)
  {
    char *error_msg = "No file data provided";
    Dowa_HashMap_Push_Arena(resp, "status", "400", arena);
    Dowa_HashMap_Push_Arena(resp, "content-type", "text/plain", arena);
    Dowa_HashMap_Push_Arena(resp, "body", error_msg, arena);
    return resp;
  }

  // Get Content-Length to know the actual binary size
  void *cl_kv = Dowa_HashMap_Get_Ptr(req, "Content-Length");
  if (!cl_kv)
  {
    char *error_msg = "No Content-Length header";
    Dowa_HashMap_Push_Arena(resp, "status", "400", arena);
    Dowa_HashMap_Push_Arena(resp, "content-type", "text/plain", arena);
    Dowa_HashMap_Push_Arena(resp, "body", error_msg, arena);
    return resp;
  }

  const char *file_data = ((Seobeo_Request_Entry*)body_kv)->value;
  const char *content_length_str = ((Seobeo_Request_Entry*)cl_kv)->value;
  size_t file_size = atoi(content_length_str);

  printf("DEBUG: Converting video, file_size=%zu bytes\n", file_size);

  int open_flags = O_RDWR | O_CREAT | O_EXCL;

  char *uuid4 = (char *)Dowa_Arena_Allocate(arena, UUID_LEN);
  uint32 seed =
      (uint32)time(NULL) ^
      (uint32)Seobeo_Thread_Current_Id() ^
      counter++;
  Dowa_String_UUID(seed, uuid4);
  char *input_path = Dowa_Arena_Allocate(arena, TMP_FILE_LENGTH);
  snprintf(input_path, TMP_FILE_LENGTH, "/tmp/%s", uuid4);
  Seobeo_Log(SEOBEO_DEBUG, "Input path: %s\n", input_path);

  int input_fd = open(input_path, open_flags, 0600);
  if (input_fd == -1)
  {
    Seobeo_Log(SEOBEO_DEBUG, "errno: %d (%s)\n", errno, strerror(errno));
    char *error_msg = "Failed to create temporary file";
    Dowa_HashMap_Push_Arena(resp, "status", "500", arena);
    Dowa_HashMap_Push_Arena(resp, "content-type", "text/plain", arena);
    Dowa_HashMap_Push_Arena(resp, "body", error_msg, arena);
    return resp;
  }

  write(input_fd, file_data, file_size);
  close(input_fd);

  seed =
      (uint32)time(NULL) ^
      (uint32)Seobeo_Thread_Current_Id() ^
      counter++;
  Dowa_String_UUID(seed, uuid4);
  char *output_path = (char *)Dowa_Arena_Allocate(arena, TMP_FILE_LENGTH);;
  snprintf(output_path, TMP_FILE_LENGTH, "/tmp/%s.mp4", uuid4);
  int output_fd = open(output_path, open_flags, 0600);
  if (output_fd == -1)
  {
    unlink(input_path);
    char *error_msg = "Failed to create output file";
    Dowa_HashMap_Push_Arena(resp, "status", "500", arena);
    Dowa_HashMap_Push_Arena(resp, "content-type", "text/plain", arena);
    Dowa_HashMap_Push_Arena(resp, "body", error_msg, arena);
    return resp;
  }
  close(output_fd);

  char cmd[512];
  snprintf(cmd, sizeof(cmd),
           "ffmpeg -y -i %s -c:v libx264 -preset fast -crf 23 -c:a aac %s 2>/tmp/error_log",
           input_path, output_path);
  int result = system(cmd);
  if (result != 0)
  {
    unlink(input_path);
    unlink(output_path);
    char *error_msg = "FFmpeg conversion failed";
    Dowa_HashMap_Push_Arena(resp, "status", "500", arena);
    Dowa_HashMap_Push_Arena(resp, "content-type", "text/plain", arena);
    Dowa_HashMap_Push_Arena(resp, "body", error_msg, arena);
    return resp;
  }

  unlink(input_path);
  char *filename = strrchr(output_path, '/') + 1;
  char *response_body = Dowa_Arena_Allocate(arena, 512);
  snprintf(response_body, 512,
           "{\"success\":true,\"download_url\":\"/api/download/%s\",\"expires\":\"10 minutes\"}",
           filename);
  Dowa_HashMap_Push_Arena(resp, "status", "200", arena);
  Dowa_HashMap_Push_Arena(resp, "content-type", "application/json", arena);
  Dowa_HashMap_Push_Arena(resp, "body", response_body, arena);

  printf("DEBUG: Video converted, available at /api/download/%s\n", filename);
  return resp;
}

static boolean Converted_Filename_Is_Valid(const char *filename)
{
  if (!filename)
    return FALSE;
  const char *extension = strrchr(filename, '.');
  if (!extension || (strcmp(extension, ".webp") != 0 &&
                     strcmp(extension, ".mp4") != 0))
    return FALSE;
  if ((size_t)(extension - filename) != 36)
    return FALSE;
  for (size_t i = 0; i < 36; i++)
  {
    char value = filename[i];
    if (i == 8 || i == 13 || i == 18 || i == 23)
    {
      if (value != '-')
        return FALSE;
      continue;
    }
    if (!((value >= '0' && value <= '9') ||
          (value >= 'a' && value <= 'f') ||
          (value >= 'A' && value <= 'F')))
      return FALSE;
  }
  return TRUE;
}

static Seobeo_Request_Entry *Converted_File_Error(
    Dowa_Arena *arena,
    char *status,
    char *message)
{
  Seobeo_Request_Entry *resp = NULL;
  Dowa_HashMap_Push_Arena(resp, "status", status, arena);
  Dowa_HashMap_Push_Arena(resp, "content-type", "text/plain", arena);
  Dowa_HashMap_Push_Arena(resp, "body", message, arena);
  return resp;
}

Seobeo_Request_Entry *DeleteConvertedFile(
    Seobeo_Request_Entry *req,
    Dowa_Arena *arena)
{
  void *filename_kv = Dowa_HashMap_Get_Ptr(req, ":filename");
  const char *filename = filename_kv
      ? ((Seobeo_Request_Entry *)filename_kv)->value
      : NULL;
  if (!Converted_Filename_Is_Valid(filename))
    return Converted_File_Error(arena, "400", "Invalid converted filename");

  char filepath[512];
  snprintf(filepath, sizeof(filepath), "/tmp/%s", filename);
  if (unlink(filepath) != 0 && errno != ENOENT)
    return Converted_File_Error(arena, "500", "Unable to delete converted file");

  Seobeo_Request_Entry *resp = NULL;
  Dowa_HashMap_Push_Arena(resp, "status", "204", arena);
  Dowa_HashMap_Push_Arena(resp, "body", "", arena);
  return resp;
}

Seobeo_Request_Entry *DownloadConvertedFile(Seobeo_Request_Entry *req, Dowa_Arena *arena)
{
  Seobeo_Request_Entry *resp = NULL;

  void *filename_kv = Dowa_HashMap_Get_Ptr(req, ":filename");
  if (!filename_kv)
  {
    char *error_msg = "No filename specified";
    Dowa_HashMap_Push_Arena(resp, "status", "404", arena);
    Dowa_HashMap_Push_Arena(resp, "content-type", "text/plain", arena);
    Dowa_HashMap_Push_Arena(resp, "body", error_msg, arena);
    return resp;
  }

  const char *filename = ((Seobeo_Request_Entry*)filename_kv)->value;
  if (!Converted_Filename_Is_Valid(filename))
    return Converted_File_Error(arena, "400", "Invalid converted filename");

  char filepath[512];
  snprintf(filepath, sizeof(filepath), "/tmp/%s", filename);

  FILE *file = fopen(filepath, "rb");
  if (!file)
  {
    char *error_msg = "File not found or expired";
    Dowa_HashMap_Push_Arena(resp, "status", "404", arena);
    Dowa_HashMap_Push_Arena(resp, "content-type", "text/plain", arena);
    Dowa_HashMap_Push_Arena(resp, "body", error_msg, arena);
    return resp;
  }

  fseek(file, 0, SEEK_END);
  size_t file_size = ftell(file);
  fseek(file, 0, SEEK_SET);

  char *file_data = malloc(file_size + 1);
  if (!file_data)
  {
    fclose(file);
    char *error_msg = "Memory allocation failed";
    Dowa_HashMap_Push_Arena(resp, "status", "500", arena);
    Dowa_HashMap_Push_Arena(resp, "content-type", "text/plain", arena);
    Dowa_HashMap_Push_Arena(resp, "body", error_msg, arena);
    return resp;
  }

  fread(file_data, 1, file_size, file);
  file_data[file_size] = '\0';
  fclose(file);

  char *content_type = "application/octet-stream";
  if (strcmp(strrchr(filename, '.'), ".webp") == 0)
    content_type = "image/webp";
  else if (strstr(filename, ".mp4"))
    content_type = "video/mp4";

  char *body = Dowa_Arena_Allocate(arena, file_size + 1);
  memcpy(body, file_data, file_size);
  body[file_size] = '\0';
  free(file_data);

  unlink(filepath);

  printf("DEBUG: Served and deleted file: %s (%zu bytes)\n", filename, file_size);

  char *content_length = Dowa_Arena_Allocate(arena, 32);
  snprintf(content_length, 32, "%zu", file_size);

  Dowa_HashMap_Push_Arena(resp, "status", "200", arena);
  Dowa_HashMap_Push_Arena(resp, "content-type", content_type, arena);
  Dowa_HashMap_Push_Arena(resp, "content-length", content_length, arena);
  Dowa_HashMap_Push_Arena(resp, "body", body, arena);

  return resp;
}

Seobeo_Request_Entry *RenderBlogList(Seobeo_Request_Entry *req, Dowa_Arena *arena)
{
  Seobeo_Request_Entry *resp = NULL;
  char *final_body = Dowa_Arena_Allocate(arena, HTML_PAGE_CAP);
  if (!final_body || !Mjj_Template_Render_File(final_body, HTML_PAGE_CAP, "/blog/index.html", arena))
    return html_render_error(arena, "Internal Server Error");
  Dowa_HashMap_Push_Arena(resp, "body", final_body, arena);
  return resp;
}


Seobeo_Request_Entry *RenderBlog(Seobeo_Request_Entry *req, Dowa_Arena *arena)
{
  Seobeo_Request_Entry *resp = NULL;

  char *file_path = Dowa_Arena_Allocate(arena, 1024);
  void *blog_id_kv = Dowa_HashMap_Get_Ptr(req, ":blog_id");
  char *blog_id = ((Seobeo_Request_Entry*)blog_id_kv)->value;
  snprintf(file_path, 1024, "/blog/%s/index.html", blog_id);

  char *final_body = Dowa_Arena_Allocate(arena, HTML_PAGE_CAP);
  if (!final_body || !Mjj_Template_Render_File(final_body, HTML_PAGE_CAP, file_path, arena))
  {
    Seobeo_Request_Entry *err = NULL;
    Dowa_HashMap_Push_Arena(err, "status", "404", arena);
    Dowa_HashMap_Push_Arena(err, "content-type", "text/plain; charset=utf-8", arena);
    Dowa_HashMap_Push_Arena(err, "body", "Not found", arena);
    return err;
  }
  Dowa_HashMap_Push_Arena(resp, "body", final_body, arena);
  return resp;
}

void Chat_Handler(Seobeo_WebSocket_Server_Connection *p_conn, Seobeo_WebSocket_Message *p_msg, void *p_user_data)
{
  (void)p_user_data;

  if (p_msg->opcode == SEOBEO_WS_OPCODE_TEXT)
  {
    char message[2048];
    snprintf(message, sizeof(message), "[%s]: %.*s", p_conn->client_id, (int)p_msg->length, (char*)p_msg->data);

    Seobeo_Log(SEOBEO_INFO, "[Chat] Broadcasting: %s\n", message);
    Seobeo_WebSocket_Server_Broadcast_Text(message, p_conn);
  }
}

Seobeo_Request_Entry *GetTalk(Seobeo_Request_Entry *req, Dowa_Arena *arena)
{
  Seobeo_Request_Entry *resp = NULL;
  char *final_body = Dowa_Arena_Allocate(arena, HTML_PAGE_CAP);
  if (!final_body || !Mjj_Template_Render_File(final_body, HTML_PAGE_CAP, "/talk/index.html", arena))
    return html_render_error(arena, "Internal Server Error");
  Dowa_HashMap_Push_Arena(resp, "body", final_body, arena);
  return resp;
}

Seobeo_Request_Entry *GetJrpg(Seobeo_Request_Entry *req, Dowa_Arena *arena)
{
  Seobeo_Request_Entry *resp = NULL;
  char *final_body = Dowa_Arena_Allocate(arena, HTML_PAGE_CAP);
  if (!final_body || !Mjj_Template_Render_File(final_body, HTML_PAGE_CAP, "/jrpg/index.html", arena))
    return html_render_error(arena, "Internal Server Error");
  Dowa_HashMap_Push_Arena(resp, "body", final_body, arena);
  Dowa_HashMap_Push_Arena(resp, "referrer-policy", "no-referrer", arena);
  return resp;
}

Seobeo_Request_Entry *GetLogin(Seobeo_Request_Entry *req, Dowa_Arena *arena)
{
  (void)req;
  Seobeo_Request_Entry *resp = NULL;
  char *final_body = Dowa_Arena_Allocate(arena, HTML_PAGE_CAP);
  if (!final_body || !Mjj_Template_Render_File(final_body, HTML_PAGE_CAP, "/login/index.html", arena))
  {
    Seobeo_Request_Entry *err = NULL;
    Dowa_HashMap_Push_Arena(err, "status", "500", arena);
    Dowa_HashMap_Push_Arena(err, "content-type", "text/plain; charset=utf-8", arena);
    Dowa_HashMap_Push_Arena(err, "cache-control", "no-store", arena);
    Dowa_HashMap_Push_Arena(err, "body", "Internal Server Error", arena);
    return err;
  }
  Dowa_HashMap_Push_Arena(resp, "body", final_body, arena);
  Dowa_HashMap_Push_Arena(
      resp, "content-type", "text/html; charset=utf-8", arena);
  Dowa_HashMap_Push_Arena(resp, "cache-control", "no-store", arena);
  Dowa_HashMap_Push_Arena(resp, "pragma", "no-cache", arena);
  Dowa_HashMap_Push_Arena(resp, "x-content-type-options", "nosniff", arena);
  Dowa_HashMap_Push_Arena(resp, "referrer-policy", "no-referrer", arena);
  Dowa_HashMap_Push_Arena(
      resp, "content-security-policy", "frame-ancestors 'none'", arena);
  return resp;
}

Seobeo_Request_Entry *GetNotesLogin(Seobeo_Request_Entry *req, Dowa_Arena *arena)
{
  Seobeo_Request_Entry *resp = NULL;
  char *final_body = Dowa_Arena_Allocate(arena, HTML_PAGE_CAP);
  if (!final_body || !Mjj_Template_Render_File(final_body, HTML_PAGE_CAP, "/notes/login.html", arena))
    return html_render_error(arena, "Internal Server Error");
  Dowa_HashMap_Push_Arena(resp, "body", final_body, arena);
  return resp;
}

Seobeo_Request_Entry *GetNotes(Seobeo_Request_Entry *req, Dowa_Arena *arena)
{
  Seobeo_Request_Entry *resp = NULL;
  char *final_body = Dowa_Arena_Allocate(arena, HTML_PAGE_CAP);
  if (!final_body || !Mjj_Template_Render_File(final_body, HTML_PAGE_CAP, "/notes/index.html", arena))
    return html_render_error(arena, "Internal Server Error");
  Dowa_HashMap_Push_Arena(resp, "body", final_body, arena);
  return resp;
}

Seobeo_Request_Entry *GetNoteById(Seobeo_Request_Entry *req, Dowa_Arena *arena)
{
  Seobeo_Request_Entry *resp = NULL;
  char *final_body = Dowa_Arena_Allocate(arena, HTML_PAGE_CAP);
  if (!final_body || !Mjj_Template_Render_File(final_body, HTML_PAGE_CAP, "/notes/index.html", arena))
    return html_render_error(arena, "Internal Server Error");
  Dowa_HashMap_Push_Arena(resp, "body", final_body, arena);
  return resp;
}

CREATE_REDIRECT_HANDLER(HomePage, "/")
CREATE_REDIRECT_HANDLER(Resume, "/resume")
CREATE_REDIRECT_HANDLER(Tools, "/tools")
CREATE_REDIRECT_HANDLER(MarkDownToHtml, "/tools/markdown_to_html")
CREATE_REDIRECT_HANDLER(FileConverter, "/tools/file_converter")
CREATE_REDIRECT_HANDLER(HlsPlayer, "/tools/hls_player")
CREATE_REDIRECT_HANDLER(LatexEditor, "/tools/latex_editor")
CREATE_REDIRECT_HANDLER(Talk, "/talk")
CREATE_REDIRECT_HANDLER(Jrpg, "/jrpg")
CREATE_REDIRECT_HANDLER(Editor, "/editor")

// S3 Upload URL API
// POST /api/s3/upload-url
// Headers: Authorization: Bearer <token>, Content-Type: application/json
// Body: {"filename": "photo.png", "content_type": "image/png"}
// Returns: {"upload_url": "https://...", "key": "uploads/..."}
Seobeo_Request_Entry *GetS3UploadUrl(Seobeo_Request_Entry *req, Dowa_Arena *arena)
{
  Seobeo_Request_Entry *resp = NULL;

  // Check auth token
  void *auth_kv = Dowa_HashMap_Get_Ptr(req, "Authorization");
  if (!auth_kv)
  {
    Dowa_HashMap_Push_Arena(resp, "status", "401", arena);
    Dowa_HashMap_Push_Arena(resp, "content-type", "application/json", arena);
    Dowa_HashMap_Push_Arena(resp, "body", "{\"error\":\"Missing Authorization header\"}", arena);
    return resp;
  }

  const char *auth_header = ((Seobeo_Request_Entry*)auth_kv)->value;

  // Expect "Bearer <token>"
  if (strncmp(auth_header, "Bearer ", 7) != 0)
  {
    Dowa_HashMap_Push_Arena(resp, "status", "401", arena);
    Dowa_HashMap_Push_Arena(resp, "content-type", "application/json", arena);
    Dowa_HashMap_Push_Arena(resp, "body", "{\"error\":\"Invalid Authorization format, use Bearer token\"}", arena);
    return resp;
  }

  const char *token = auth_header + 7;
  if (strlen(g_upload_auth_token) == 0 || strcmp(token, g_upload_auth_token) != 0)
  {
    Dowa_HashMap_Push_Arena(resp, "status", "403", arena);
    Dowa_HashMap_Push_Arena(resp, "content-type", "application/json", arena);
    Dowa_HashMap_Push_Arena(resp, "body", "{\"error\":\"Invalid token\"}", arena);
    return resp;
  }

  // Parse request body for filename and content_type
  void *body_kv = Dowa_HashMap_Get_Ptr(req, "Body");
  if (!body_kv)
  {
    Dowa_HashMap_Push_Arena(resp, "status", "400", arena);
    Dowa_HashMap_Push_Arena(resp, "content-type", "application/json", arena);
    Dowa_HashMap_Push_Arena(resp, "body", "{\"error\":\"Missing request body\"}", arena);
    return resp;
  }

  const char *body = ((Seobeo_Request_Entry*)body_kv)->value;

  // Simple JSON parsing for filename and content_type
  char filename[256] = {0};
  char content_type[128] = "application/octet-stream";

  // Find "filename":"value"
  const char *fn_key = strstr(body, "\"filename\"");
  if (fn_key)
  {
    const char *fn_start = strchr(fn_key + 10, '"');
    if (fn_start)
    {
      fn_start++;
      const char *fn_end = strchr(fn_start, '"');
      if (fn_end && (size_t)(fn_end - fn_start) < sizeof(filename))
      {
        memcpy(filename, fn_start, fn_end - fn_start);
        filename[fn_end - fn_start] = '\0';
      }
    }
  }

  // Find "content_type":"value"
  const char *ct_key = strstr(body, "\"content_type\"");
  if (ct_key)
  {
    const char *ct_start = strchr(ct_key + 14, '"');
    if (ct_start)
    {
      ct_start++;
      const char *ct_end = strchr(ct_start, '"');
      if (ct_end && (size_t)(ct_end - ct_start) < sizeof(content_type))
      {
        memcpy(content_type, ct_start, ct_end - ct_start);
        content_type[ct_end - ct_start] = '\0';
      }
    }
  }

  if (strlen(filename) == 0)
  {
    Dowa_HashMap_Push_Arena(resp, "status", "400", arena);
    Dowa_HashMap_Push_Arena(resp, "content-type", "application/json", arena);
    Dowa_HashMap_Push_Arena(resp, "body", "{\"error\":\"Missing filename in request body\"}", arena);
    return resp;
  }

  // Generate unique S3 key with timestamp
  char s3_key[512];
  char *uuid = Dowa_Arena_Allocate(arena, UUID_LEN);
  uint32 seed =
      (uint32)time(NULL) ^
      (uint32)Seobeo_Thread_Current_Id() ^
      counter++;
  Dowa_String_UUID(seed, uuid);
  snprintf(s3_key, sizeof(s3_key), "uploads/%s/%s", uuid, filename);

  // Generate presigned URL
  S3_Presigned_URL presigned = S3_Presign_Put(&g_s3_config, s3_key, content_type, g_s3_url_expires);

  if (!presigned.success)
  {
    Dowa_HashMap_Push_Arena(resp, "status", "500", arena);
    Dowa_HashMap_Push_Arena(resp, "content-type", "application/json", arena);
    char *error_body = Dowa_Arena_Allocate(arena, 256);
    snprintf(error_body, 256, "{\"error\":\"Failed to generate upload URL: %s\"}",
             presigned.error_message ? presigned.error_message : "unknown");
    Dowa_HashMap_Push_Arena(resp, "body", error_body, arena);
    S3_Presigned_URL_Destroy(&presigned);
    return resp;
  }

  // Build public URL using CloudFront
  char public_url[512];
  if (g_s3_cloudfront_url[0])
  {
    snprintf(public_url, sizeof(public_url), "%s/%s", g_s3_cloudfront_url, s3_key);
  }
  else
  {
    snprintf(public_url, sizeof(public_url), "https://%s.s3.%s.amazonaws.com/%s",
             g_s3_bucket, g_s3_region, s3_key);
  }

  // Build response
  char *response_body = Dowa_Arena_Allocate(arena, 4096 + strlen(presigned.url));
  snprintf(response_body, 4096 + strlen(presigned.url),
           "{\"upload_url\":\"%s\",\"public_url\":\"%s\",\"key\":\"%s\",\"expires\":%d}",
           presigned.url, public_url, s3_key, g_s3_url_expires);

  S3_Presigned_URL_Destroy(&presigned);

  Dowa_HashMap_Push_Arena(resp, "status", "200", arena);
  Dowa_HashMap_Push_Arena(resp, "content-type", "application/json", arena);
  Dowa_HashMap_Push_Arena(resp, "body", response_body, arena);

  printf("[S3] Generated upload URL for: %s\n", s3_key);

  return resp;
}

// Editor Content Save API
// POST /api/editor/save
// Headers: Authorization: Bearer <token>
// Body: {"doc_id": "my-doc", "content": "<html content>"}
Seobeo_Request_Entry *EditorSave(Seobeo_Request_Entry *req, Dowa_Arena *arena)
{
  Seobeo_Request_Entry *resp = NULL;

  // Check auth token
  void *auth_kv = Dowa_HashMap_Get_Ptr(req, "Authorization");
  if (!auth_kv)
  {
    Dowa_HashMap_Push_Arena(resp, "status", "401", arena);
    Dowa_HashMap_Push_Arena(resp, "content-type", "application/json", arena);
    Dowa_HashMap_Push_Arena(resp, "body", "{\"error\":\"Missing Authorization header\"}", arena);
    return resp;
  }

  const char *auth_header = ((Seobeo_Request_Entry*)auth_kv)->value;
  if (strncmp(auth_header, "Bearer ", 7) != 0)
  {
    Dowa_HashMap_Push_Arena(resp, "status", "401", arena);
    Dowa_HashMap_Push_Arena(resp, "content-type", "application/json", arena);
    Dowa_HashMap_Push_Arena(resp, "body", "{\"error\":\"Invalid Authorization format\"}", arena);
    return resp;
  }

  const char *token = auth_header + 7;
  if (strlen(g_upload_auth_token) == 0 || strcmp(token, g_upload_auth_token) != 0)
  {
    Dowa_HashMap_Push_Arena(resp, "status", "403", arena);
    Dowa_HashMap_Push_Arena(resp, "content-type", "application/json", arena);
    Dowa_HashMap_Push_Arena(resp, "body", "{\"error\":\"Invalid token\"}", arena);
    return resp;
  }

  if (!g_db_connection)
  {
    Dowa_HashMap_Push_Arena(resp, "status", "500", arena);
    Dowa_HashMap_Push_Arena(resp, "content-type", "application/json", arena);
    Dowa_HashMap_Push_Arena(resp, "body", "{\"error\":\"Database not available\"}", arena);
    return resp;
  }

  // Parse request body
  void *body_kv = Dowa_HashMap_Get_Ptr(req, "Body");
  if (!body_kv)
  {
    Dowa_HashMap_Push_Arena(resp, "status", "400", arena);
    Dowa_HashMap_Push_Arena(resp, "content-type", "application/json", arena);
    Dowa_HashMap_Push_Arena(resp, "body", "{\"error\":\"Missing request body\"}", arena);
    return resp;
  }

  const char *body = ((Seobeo_Request_Entry*)body_kv)->value;

  // Parse doc_id and content from JSON
  char doc_id[256] = "default";
  char *content = NULL;
  size_t content_len = 0;

  // Find "doc_id":"value"
  const char *doc_key = strstr(body, "\"doc_id\"");
  if (doc_key)
  {
    const char *doc_start = strchr(doc_key + 8, '"');
    if (doc_start)
    {
      doc_start++;
      const char *doc_end = strchr(doc_start, '"');
      if (doc_end && (size_t)(doc_end - doc_start) < sizeof(doc_id))
      {
        memcpy(doc_id, doc_start, doc_end - doc_start);
        doc_id[doc_end - doc_start] = '\0';
      }
    }
  }

  // Find "content":"value" - content can be large and contain escaped characters
  const char *content_key = strstr(body, "\"content\"");
  if (content_key)
  {
    const char *content_start = strchr(content_key + 9, '"');
    if (content_start)
    {
      content_start++;
      // Find closing quote (accounting for escaped quotes)
      const char *p = content_start;
      while (*p)
      {
        if (*p == '\\' && *(p+1))
        {
          p += 2;
          continue;
        }
        if (*p == '"') break;
        p++;
      }
      content_len = p - content_start;
      content = Dowa_Arena_Allocate(arena, content_len + 1);
      memcpy(content, content_start, content_len);
      content[content_len] = '\0';
    }
  }

  if (!content)
  {
    Dowa_HashMap_Push_Arena(resp, "status", "400", arena);
    Dowa_HashMap_Push_Arena(resp, "content-type", "application/json", arena);
    Dowa_HashMap_Push_Arena(resp, "body", "{\"error\":\"Missing content\"}", arena);
    return resp;
  }

  // Upsert content
  const char *upsert_query =
    "INSERT INTO editor_content (access_token, doc_id, content, updated_at) "
    "VALUES (?, ?, ?, strftime('%s', 'now')) "
    "ON CONFLICT(access_token, doc_id) DO UPDATE SET "
    "content = excluded.content, updated_at = strftime('%s', 'now')";

  const char *params[] = { token, doc_id, content };
  int32 result = Deita_Query_Execute_Update_Prepared(g_db_connection, upsert_query, 3, params);

  if (result < 0)
  {
    Dowa_HashMap_Push_Arena(resp, "status", "500", arena);
    Dowa_HashMap_Push_Arena(resp, "content-type", "application/json", arena);
    Dowa_HashMap_Push_Arena(resp, "body", "{\"error\":\"Failed to save\"}", arena);
    return resp;
  }

  printf("[EDITOR] Saved doc_id=%s, content_len=%zu\n", doc_id, content_len);

  Dowa_HashMap_Push_Arena(resp, "status", "200", arena);
  Dowa_HashMap_Push_Arena(resp, "content-type", "application/json", arena);
  Dowa_HashMap_Push_Arena(resp, "body", "{\"success\":true}", arena);
  return resp;
}

// Editor Content Load API
// GET /api/editor/load/:doc_id
// Headers: Authorization: Bearer <token>
Seobeo_Request_Entry *EditorLoad(Seobeo_Request_Entry *req, Dowa_Arena *arena)
{
  Seobeo_Request_Entry *resp = NULL;

  // Check auth token
  void *auth_kv = Dowa_HashMap_Get_Ptr(req, "Authorization");
  if (!auth_kv)
  {
    Dowa_HashMap_Push_Arena(resp, "status", "401", arena);
    Dowa_HashMap_Push_Arena(resp, "content-type", "application/json", arena);
    Dowa_HashMap_Push_Arena(resp, "body", "{\"error\":\"Missing Authorization header\"}", arena);
    return resp;
  }

  const char *auth_header = ((Seobeo_Request_Entry*)auth_kv)->value;
  if (strncmp(auth_header, "Bearer ", 7) != 0)
  {
    Dowa_HashMap_Push_Arena(resp, "status", "401", arena);
    Dowa_HashMap_Push_Arena(resp, "content-type", "application/json", arena);
    Dowa_HashMap_Push_Arena(resp, "body", "{\"error\":\"Invalid Authorization format\"}", arena);
    return resp;
  }

  const char *token = auth_header + 7;
  if (strlen(g_upload_auth_token) == 0 || strcmp(token, g_upload_auth_token) != 0)
  {
    Dowa_HashMap_Push_Arena(resp, "status", "403", arena);
    Dowa_HashMap_Push_Arena(resp, "content-type", "application/json", arena);
    Dowa_HashMap_Push_Arena(resp, "body", "{\"error\":\"Invalid token\"}", arena);
    return resp;
  }

  if (!g_db_connection)
  {
    Dowa_HashMap_Push_Arena(resp, "status", "500", arena);
    Dowa_HashMap_Push_Arena(resp, "content-type", "application/json", arena);
    Dowa_HashMap_Push_Arena(resp, "body", "{\"error\":\"Database not available\"}", arena);
    return resp;
  }

  // Get doc_id from URL parameter
  void *doc_id_kv = Dowa_HashMap_Get_Ptr(req, ":doc_id");
  const char *doc_id = "default";
  if (doc_id_kv)
  {
    doc_id = ((Seobeo_Request_Entry*)doc_id_kv)->value;
  }

  // Query content
  const char *select_query =
    "SELECT content, updated_at FROM editor_content WHERE access_token = ? AND doc_id = ?";
  const char *params[] = { token, doc_id };

  Deita_Result_Set *p_result = Deita_Query_Execute_Prepared(g_db_connection, select_query, 2, params, arena);

  if (p_result && Deita_Result_Set_Next(p_result))
  {
    const char *content = Deita_Result_Set_Get_Text(p_result, 0);
    int64 updated_at = Deita_Result_Set_Get_Integer(p_result, 1);

    // Build JSON response - escape content
    size_t content_len = content ? strlen(content) : 0;
    char *response_body = Dowa_Arena_Allocate(arena, content_len + 256);
    snprintf(response_body, content_len + 256,
             "{\"doc_id\":\"%s\",\"content\":\"%s\",\"updated_at\":%lld}",
             doc_id, content ? content : "", (long long)updated_at);

    Dowa_HashMap_Push_Arena(resp, "status", "200", arena);
    Dowa_HashMap_Push_Arena(resp, "content-type", "application/json", arena);
    Dowa_HashMap_Push_Arena(resp, "body", response_body, arena);

    printf("[EDITOR] Loaded doc_id=%s\n", doc_id);
  }
  else
  {
    // No content found, return empty
    char *response_body = Dowa_Arena_Allocate(arena, 128);
    snprintf(response_body, 128, "{\"doc_id\":\"%s\",\"content\":\"\",\"updated_at\":0}", doc_id);

    Dowa_HashMap_Push_Arena(resp, "status", "200", arena);
    Dowa_HashMap_Push_Arena(resp, "content-type", "application/json", arena);
    Dowa_HashMap_Push_Arena(resp, "body", response_body, arena);
  }

  if (p_result) Deita_Result_Set_Free(p_result);
  return resp;
}

// Media Upload API - Create media record
// POST /api/media/create
// Headers: Authorization: Bearer <token>, Content-Type: application/json
// Body: {"filename": "photo.jpg", "content_type": "image/jpeg"}
// Returns: {"media_id": 123, "upload_url": "https://...", "expires": 3600}
Seobeo_Request_Entry *MediaCreate(Seobeo_Request_Entry *req, Dowa_Arena *arena)
{
  Seobeo_Request_Entry *resp = NULL;

  // Check auth token
  void *auth_kv = Dowa_HashMap_Get_Ptr(req, "Authorization");
  if (!auth_kv)
  {
    Dowa_HashMap_Push_Arena(resp, "status", "401", arena);
    Dowa_HashMap_Push_Arena(resp, "content-type", "application/json", arena);
    Dowa_HashMap_Push_Arena(resp, "body", "{\"error\":\"Missing Authorization header\"}", arena);
    return resp;
  }

  const char *auth_header = ((Seobeo_Request_Entry*)auth_kv)->value;
  if (strncmp(auth_header, "Bearer ", 7) != 0)
  {
    Dowa_HashMap_Push_Arena(resp, "status", "401", arena);
    Dowa_HashMap_Push_Arena(resp, "content-type", "application/json", arena);
    Dowa_HashMap_Push_Arena(resp, "body", "{\"error\":\"Invalid Authorization format\"}", arena);
    return resp;
  }

  const char *token = auth_header + 7;
  if (strlen(g_upload_auth_token) == 0 || strcmp(token, g_upload_auth_token) != 0)
  {
    Dowa_HashMap_Push_Arena(resp, "status", "403", arena);
    Dowa_HashMap_Push_Arena(resp, "content-type", "application/json", arena);
    Dowa_HashMap_Push_Arena(resp, "body", "{\"error\":\"Invalid token\"}", arena);
    return resp;
  }

  if (!g_db_connection)
  {
    Dowa_HashMap_Push_Arena(resp, "status", "500", arena);
    Dowa_HashMap_Push_Arena(resp, "content-type", "application/json", arena);
    Dowa_HashMap_Push_Arena(resp, "body", "{\"error\":\"Database not available\"}", arena);
    return resp;
  }

  // Parse request body
  void *body_kv = Dowa_HashMap_Get_Ptr(req, "Body");
  if (!body_kv)
  {
    Dowa_HashMap_Push_Arena(resp, "status", "400", arena);
    Dowa_HashMap_Push_Arena(resp, "content-type", "application/json", arena);
    Dowa_HashMap_Push_Arena(resp, "body", "{\"error\":\"Missing request body\"}", arena);
    return resp;
  }

  const char *body = ((Seobeo_Request_Entry*)body_kv)->value;

  // Parse filename and content_type
  char filename[256] = {0};
  char content_type[128] = "application/octet-stream";

  // Find "filename":"value"
  const char *fn_key = strstr(body, "\"filename\"");
  if (fn_key)
  {
    const char *fn_start = strchr(fn_key + 10, '"');
    if (fn_start)
    {
      fn_start++;
      const char *fn_end = strchr(fn_start, '"');
      if (fn_end && (size_t)(fn_end - fn_start) < sizeof(filename))
      {
        memcpy(filename, fn_start, fn_end - fn_start);
        filename[fn_end - fn_start] = '\0';
      }
    }
  }

  // Find "content_type":"value"
  const char *ct_key = strstr(body, "\"content_type\"");
  if (ct_key)
  {
    const char *ct_start = strchr(ct_key + 14, '"');
    if (ct_start)
    {
      ct_start++;
      const char *ct_end = strchr(ct_start, '"');
      if (ct_end && (size_t)(ct_end - ct_start) < sizeof(content_type))
      {
        memcpy(content_type, ct_start, ct_end - ct_start);
        content_type[ct_end - ct_start] = '\0';
      }
    }
  }

  if (strlen(filename) == 0)
  {
    Dowa_HashMap_Push_Arena(resp, "status", "400", arena);
    Dowa_HashMap_Push_Arena(resp, "content-type", "application/json", arena);
    Dowa_HashMap_Push_Arena(resp, "body", "{\"error\":\"Missing filename\"}", arena);
    return resp;
  }

  // Generate UUID for this upload
  char *uuid = Dowa_Arena_Allocate(arena, UUID_LEN);
  uint32 seed =
      (uint32)time(NULL) ^
      (uint32)Seobeo_Thread_Current_Id() ^
      counter++;
  Dowa_String_UUID(seed, uuid);

  // Generate S3 keys
  char s3_key_original[512];
  char s3_key_processed[512];
  snprintf(s3_key_original, sizeof(s3_key_original), "uploads/%s/%s", uuid, filename);

  // Only use .webp for images
  int is_image = (strncmp(content_type, "image/", 6) == 0);
  if (is_image)
  {
    snprintf(s3_key_processed, sizeof(s3_key_processed), "uploads/%s/processed.webp", uuid);
  }
  else
  {
    s3_key_processed[0] = '\0'; // No processed version for non-images
  }

  // Insert into database
  const char *insert_query =
    "INSERT INTO media_uploads (access_token, original_filename, content_type, s3_key_original, s3_key_processed, status) "
    "VALUES (?, ?, ?, ?, ?, 'pending') RETURNING id";

  const char *params[] = { token, filename, content_type, s3_key_original, s3_key_processed };
  Deita_Result_Set *id_result = Deita_Query_Execute_Prepared(
      g_db_connection,
      insert_query,
      5,
      params,
      arena);
  if (!id_result || !Deita_Result_Set_Next(id_result))
  {
    if (id_result) Deita_Result_Set_Free(id_result);
    Dowa_HashMap_Push_Arena(resp, "status", "500", arena);
    Dowa_HashMap_Push_Arena(resp, "content-type", "application/json", arena);
    Dowa_HashMap_Push_Arena(resp, "body", "{\"error\":\"Failed to create media record\"}", arena);
    return resp;
  }

  int64 media_id = Deita_Result_Set_Get_Integer(id_result, 0);
  Deita_Result_Set_Free(id_result);

  // Generate presigned PUT URL
  S3_Presigned_URL presigned = S3_Presign_Put(&g_s3_config, s3_key_original, content_type, g_s3_url_expires);

  if (!presigned.success)
  {
    Dowa_HashMap_Push_Arena(resp, "status", "500", arena);
    Dowa_HashMap_Push_Arena(resp, "content-type", "application/json", arena);
    char *error_body = Dowa_Arena_Allocate(arena, 256);
    snprintf(error_body, 256, "{\"error\":\"Failed to generate upload URL: %s\"}",
             presigned.error_message ? presigned.error_message : "unknown");
    Dowa_HashMap_Push_Arena(resp, "body", error_body, arena);
    S3_Presigned_URL_Destroy(&presigned);
    return resp;
  }

  // Build public URL using CloudFront or S3
  char public_url[512];
  if (g_s3_cloudfront_url[0])
  {
    snprintf(public_url, sizeof(public_url), "%s/%s", g_s3_cloudfront_url, s3_key_original);
  }
  else
  {
    snprintf(public_url, sizeof(public_url), "https://%s.s3.%s.amazonaws.com/%s",
             g_s3_bucket, g_s3_region, s3_key_original);
  }

  // Build response
  char *response_body = Dowa_Arena_Allocate(arena, 4096 + strlen(presigned.url) + strlen(public_url));
  snprintf(response_body, 4096 + strlen(presigned.url) + strlen(public_url),
           "{\"media_id\":%lld,\"upload_url\":\"%s\",\"public_url\":\"%s\",\"expires\":%d}",
           (long long)media_id, presigned.url, public_url, g_s3_url_expires);

  S3_Presigned_URL_Destroy(&presigned);

  Dowa_HashMap_Push_Arena(resp, "status", "200", arena);
  Dowa_HashMap_Push_Arena(resp, "content-type", "application/json", arena);
  Dowa_HashMap_Push_Arena(resp, "body", response_body, arena);

  printf("[MEDIA] Created media_id=%lld, file=%s\n", (long long)media_id, filename);

  return resp;
}

// Worker-pool task for S3 media processing.
void Media_Process_Background(void *arg)
{
  Media_Processing_Context *ctx = (Media_Processing_Context *)arg;

  Seobeo_Log(SEOBEO_INFO, "[MEDIA] Background worker started for media_id=%lld\n", (long long)ctx->media_id);
  Seobeo_Log(SEOBEO_INFO, "[MEDIA] S3 key original: %s\n", ctx->s3_key_original);
  Seobeo_Log(SEOBEO_INFO, "[MEDIA] S3 key processed: %s\n", ctx->s3_key_processed);
  Seobeo_Log(SEOBEO_INFO, "[MEDIA] DB path: %s\n", ctx->db_path);

  // Open a worker-local DB connection.
  Deita_Connection *db_conn = Deita_Connection_Create(DEITA_DATABASE_TYPE_SQLITE3, ctx->db_path);
  if (!db_conn || !Deita_Connection_Is_Open(db_conn))
  {
    Seobeo_Log(SEOBEO_ERROR, "[MEDIA] Worker ERROR: Failed to open database for media_id=%lld\n", (long long)ctx->media_id);
    return;
  }

  // Update status to 'processing'
  const char *update_processing =
    "UPDATE media_uploads SET status='processing', updated_at=strftime('%s','now') WHERE id=?";
  char media_id_str[32];
  snprintf(media_id_str, sizeof(media_id_str), "%lld", (long long)ctx->media_id);
  const char *params[] = { media_id_str };
  int32 update_result = Deita_Query_Execute_Update_Prepared(db_conn, update_processing, 1, params);
  Seobeo_Log(SEOBEO_INFO, "[MEDIA] Updated status to 'processing' for media_id=%lld (result=%d)\n", (long long)ctx->media_id, update_result);

  // Generate presigned GET URL for download (10 min expiry)
  Seobeo_Log(SEOBEO_INFO, "[MEDIA] Generating presigned GET URL for media_id=%lld\n", (long long)ctx->media_id);
  S3_Presigned_URL download_url = S3_Presign_Get(&ctx->s3_config, ctx->s3_key_original, 600);
  if (!download_url.success)
  {
    const char *error_msg = download_url.error_message ? download_url.error_message : "Failed to generate download URL";
    Seobeo_Log(SEOBEO_ERROR, "[MEDIA] ERROR: Failed to generate download URL for media_id=%lld: %s\n",
               (long long)ctx->media_id, error_msg);
    const char *update_error =
      "UPDATE media_uploads SET status='error', error_message=?, updated_at=strftime('%s','now') WHERE id=?";
    const char *error_params[] = { error_msg, media_id_str };
    Deita_Query_Execute_Update_Prepared(db_conn, update_error, 2, error_params);
    S3_Presigned_URL_Destroy(&download_url);
    Deita_Connection_Close(db_conn);
    return;
  }
  Seobeo_Log(SEOBEO_INFO, "[MEDIA] Generated presigned URL: %.100s...\n", download_url.url);

  // Generate temp file paths
  char tmp_input[256];
  char tmp_output[256];
  char *uuid_input = malloc(UUID_LEN);
  char *uuid_output = malloc(UUID_LEN);
  uint32 seed1 =
      (uint32)time(NULL) ^
      (uint32)Seobeo_Thread_Current_Id() ^
      counter++;
  uint32 seed2 =
      (uint32)time(NULL) ^
      (uint32)Seobeo_Thread_Current_Id() ^
      counter++;
  Dowa_String_UUID(seed1, uuid_input);
  Dowa_String_UUID(seed2, uuid_output);
  snprintf(tmp_input, sizeof(tmp_input), "/tmp/%s", uuid_input);
  snprintf(tmp_output, sizeof(tmp_output), "/tmp/%s.webp", uuid_output);
  free(uuid_input);
  free(uuid_output);

  // Download from S3
  Seobeo_Log(SEOBEO_INFO, "[MEDIA] Downloading from S3 to %s for media_id=%lld\n", tmp_input, (long long)ctx->media_id);
  Seobeo_Client_Request *download_req = Seobeo_Client_Request_Create(download_url.url);
  Seobeo_Client_Request_Set_Download_Path(download_req, tmp_input);
  Seobeo_Client_Response *download_resp = Seobeo_Client_Request_Execute(download_req);

  S3_Presigned_URL_Destroy(&download_url);

  if (!download_resp || download_resp->status_code != 200)
  {
    int status = download_resp ? download_resp->status_code : 0;
    Seobeo_Log(SEOBEO_ERROR, "[MEDIA] ERROR: Failed to download from S3 for media_id=%lld (status=%d)\n",
               (long long)ctx->media_id, status);
    const char *update_error =
      "UPDATE media_uploads SET status='error', error_message=?, updated_at=strftime('%s','now') WHERE id=?";
    const char *error_params[] = { "Failed to download from S3", media_id_str };
    Deita_Query_Execute_Update_Prepared(db_conn, update_error, 2, error_params);
    if (download_req) Seobeo_Client_Request_Destroy(download_req);
    if (download_resp) Seobeo_Client_Response_Destroy(download_resp);
    unlink(tmp_input);
    Deita_Connection_Close(db_conn);
    return;
  }

  Seobeo_Log(SEOBEO_INFO, "[MEDIA] Successfully downloaded file to %s\n", tmp_input);
  Seobeo_Client_Request_Destroy(download_req);
  Seobeo_Client_Response_Destroy(download_resp);

  // Convert to webp using FFmpeg
  char cmd[1024];
  char log_file[256];
  snprintf(log_file, sizeof(log_file), "/tmp/ffmpeg_%lld.log", (long long)ctx->media_id);
  snprintf(cmd, sizeof(cmd), "ffmpeg -y -i %s -quality 80 %s 2>%s",
           tmp_input, tmp_output, log_file);

  Seobeo_Log(SEOBEO_INFO, "[MEDIA] Running FFmpeg: %s\n", cmd);
  int ffmpeg_result = system(cmd);
  Seobeo_Log(SEOBEO_INFO, "[MEDIA] FFmpeg result: %d for media_id=%lld\n", ffmpeg_result, (long long)ctx->media_id);

  if (ffmpeg_result != 0)
  {
    Seobeo_Log(SEOBEO_ERROR, "[MEDIA] ERROR: FFmpeg conversion failed for media_id=%lld (exit code %d). Check log: %s\n",
               (long long)ctx->media_id, ffmpeg_result, log_file);
    const char *update_error =
      "UPDATE media_uploads SET status='error', error_message=?, updated_at=strftime('%s','now') WHERE id=?";
    const char *error_params[] = { "Image conversion failed", media_id_str };
    Deita_Query_Execute_Update_Prepared(db_conn, update_error, 2, error_params);
    unlink(tmp_input);
    unlink(tmp_output);
    Deita_Connection_Close(db_conn);
    return;
  }
  Seobeo_Log(SEOBEO_INFO, "[MEDIA] Successfully converted to webp: %s\n", tmp_output);

  // Upload processed file to S3
  Seobeo_Log(SEOBEO_INFO, "[MEDIA] Uploading processed file to S3: %s -> %s\n", tmp_output, ctx->s3_key_processed);
  S3_Result upload_result = S3_Upload_File_With_Content_Type(
    &ctx->s3_config, tmp_output, ctx->s3_key_processed, "image/webp");

  if (!upload_result.success)
  {
    const char *error_msg = upload_result.error_message ? upload_result.error_message : "Failed to upload processed file";
    Seobeo_Log(SEOBEO_ERROR, "[MEDIA] ERROR: Failed to upload processed file for media_id=%lld: %s (HTTP status: %d)\n",
               (long long)ctx->media_id, error_msg, upload_result.status_code);
    const char *update_error =
      "UPDATE media_uploads SET status='error', error_message=?, updated_at=strftime('%s','now') WHERE id=?";
    const char *error_params[] = { error_msg, media_id_str };
    Deita_Query_Execute_Update_Prepared(db_conn, update_error, 2, error_params);
    unlink(tmp_input);
    unlink(tmp_output);
    Deita_Connection_Close(db_conn);
    return;
  }

  Seobeo_Log(SEOBEO_INFO, "[MEDIA] Successfully uploaded processed file to S3\n");

  // Update status to 'finished'
  const char *update_finished =
    "UPDATE media_uploads SET status='finished', updated_at=strftime('%s','now') WHERE id=?";
  Deita_Query_Execute_Update_Prepared(db_conn, update_finished, 1, params);

  Seobeo_Log(SEOBEO_INFO, "[MEDIA] Successfully processed media_id=%lld - COMPLETE\n", (long long)ctx->media_id);

  // Cleanup
  unlink(tmp_input);
  unlink(tmp_output);
  Deita_Connection_Close(db_conn);
}

// Media Upload API - Mark uploaded
// POST /api/media/:id/uploaded
// Headers: Authorization: Bearer <token>
Seobeo_Request_Entry *MediaUploaded(Seobeo_Request_Entry *req, Dowa_Arena *arena)
{
  Seobeo_Request_Entry *resp = NULL;

  // Check auth token
  void *auth_kv = Dowa_HashMap_Get_Ptr(req, "Authorization");
  if (!auth_kv)
  {
    Dowa_HashMap_Push_Arena(resp, "status", "401", arena);
    Dowa_HashMap_Push_Arena(resp, "content-type", "application/json", arena);
    Dowa_HashMap_Push_Arena(resp, "body", "{\"error\":\"Missing Authorization header\"}", arena);
    return resp;
  }

  const char *auth_header = ((Seobeo_Request_Entry*)auth_kv)->value;
  if (strncmp(auth_header, "Bearer ", 7) != 0)
  {
    Dowa_HashMap_Push_Arena(resp, "status", "401", arena);
    Dowa_HashMap_Push_Arena(resp, "content-type", "application/json", arena);
    Dowa_HashMap_Push_Arena(resp, "body", "{\"error\":\"Invalid Authorization format\"}", arena);
    return resp;
  }

  const char *token = auth_header + 7;
  if (strlen(g_upload_auth_token) == 0 || strcmp(token, g_upload_auth_token) != 0)
  {
    Dowa_HashMap_Push_Arena(resp, "status", "403", arena);
    Dowa_HashMap_Push_Arena(resp, "content-type", "application/json", arena);
    Dowa_HashMap_Push_Arena(resp, "body", "{\"error\":\"Invalid token\"}", arena);
    return resp;
  }

  if (!g_db_connection)
  {
    Dowa_HashMap_Push_Arena(resp, "status", "500", arena);
    Dowa_HashMap_Push_Arena(resp, "content-type", "application/json", arena);
    Dowa_HashMap_Push_Arena(resp, "body", "{\"error\":\"Database not available\"}", arena);
    return resp;
  }

  // Extract media_id from URL params
  void *id_kv = Dowa_HashMap_Get_Ptr(req, ":id");
  if (!id_kv)
  {
    Dowa_HashMap_Push_Arena(resp, "status", "400", arena);
    Dowa_HashMap_Push_Arena(resp, "content-type", "application/json", arena);
    Dowa_HashMap_Push_Arena(resp, "body", "{\"error\":\"Missing media ID\"}", arena);
    return resp;
  }

  const char *media_id_str = ((Seobeo_Request_Entry*)id_kv)->value;
  int64 media_id = atoll(media_id_str);

  // Verify access_token matches and get content_type
  const char *select_query =
    "SELECT content_type, s3_key_original, s3_key_processed FROM media_uploads WHERE id = ? AND access_token = ?";
  const char *select_params[] = { media_id_str, token };

  Deita_Result_Set *p_result = Deita_Query_Execute_Prepared(g_db_connection, select_query, 2, select_params, arena);

  if (!p_result || !Deita_Result_Set_Next(p_result))
  {
    if (p_result) Deita_Result_Set_Free(p_result);
    Dowa_HashMap_Push_Arena(resp, "status", "404", arena);
    Dowa_HashMap_Push_Arena(resp, "content-type", "application/json", arena);
    Dowa_HashMap_Push_Arena(resp, "body", "{\"error\":\"Media not found or access denied\"}", arena);
    return resp;
  }

  const char *content_type = Deita_Result_Set_Get_Text(p_result, 0);
  const char *s3_key_original = Deita_Result_Set_Get_Text(p_result, 1);
  const char *s3_key_processed = Deita_Result_Set_Get_Text(p_result, 2);

  // Copy values before freeing result set
  char content_type_copy[128];
  char s3_key_original_copy[512];
  char s3_key_processed_copy[512];
  strncpy(content_type_copy, content_type, sizeof(content_type_copy) - 1);
  strncpy(s3_key_original_copy, s3_key_original, sizeof(s3_key_original_copy) - 1);
  strncpy(s3_key_processed_copy, s3_key_processed, sizeof(s3_key_processed_copy) - 1);
  content_type_copy[sizeof(content_type_copy) - 1] = '\0';
  s3_key_original_copy[sizeof(s3_key_original_copy) - 1] = '\0';
  s3_key_processed_copy[sizeof(s3_key_processed_copy) - 1] = '\0';

  Deita_Result_Set_Free(p_result);

  // Update status to 'uploaded'
  const char *update_query =
    "UPDATE media_uploads SET status='uploaded', updated_at=strftime('%s','now') WHERE id=?";
  const char *update_params[] = { media_id_str };
  int32 result = Deita_Query_Execute_Update_Prepared(g_db_connection, update_query, 1, update_params);

  if (result < 0)
  {
    Dowa_HashMap_Push_Arena(resp, "status", "500", arena);
    Dowa_HashMap_Push_Arena(resp, "content-type", "application/json", arena);
    Dowa_HashMap_Push_Arena(resp, "body", "{\"error\":\"Failed to update status\"}", arena);
    return resp;
  }

  Seobeo_Log(SEOBEO_INFO, "[MEDIA] Content type for media_id=%lld: '%s'\n", (long long)media_id, content_type_copy);

  // Images are processed asynchronously by the bounded media pool.
  if (strncmp(content_type_copy, "image/", 6) == 0)
  {
    Seobeo_Log(SEOBEO_INFO, "[MEDIA] Queueing image processing for media_id=%lld\n", (long long)media_id);

    // The pool owns this context after a successful submission.
    Media_Processing_Context *ctx = malloc(sizeof(Media_Processing_Context));
    if (!ctx)
    {
      Dowa_HashMap_Push_Arena(resp, "status", "500", arena);
      Dowa_HashMap_Push_Arena(resp, "content-type", "application/json", arena);
      Dowa_HashMap_Push_Arena(resp, "body", "{\"error\":\"Unable to allocate media work\"}", arena);
      return resp;
    }
    ctx->media_id = media_id;
    strncpy(ctx->s3_key_original, s3_key_original_copy, sizeof(ctx->s3_key_original) - 1);
    strncpy(ctx->s3_key_processed, s3_key_processed_copy, sizeof(ctx->s3_key_processed) - 1);
    strncpy(ctx->content_type, content_type_copy, sizeof(ctx->content_type) - 1);
    strncpy(ctx->access_token, token, sizeof(ctx->access_token) - 1);
    strncpy(ctx->db_path, g_db_path, sizeof(ctx->db_path) - 1);
    ctx->s3_key_original[sizeof(ctx->s3_key_original) - 1] = '\0';
    ctx->s3_key_processed[sizeof(ctx->s3_key_processed) - 1] = '\0';
    ctx->content_type[sizeof(ctx->content_type) - 1] = '\0';
    ctx->access_token[sizeof(ctx->access_token) - 1] = '\0';
    ctx->db_path[sizeof(ctx->db_path) - 1] = '\0';
    ctx->s3_config = g_s3_config;

    Seobeo_Worker_Result worker_result =
        g_media_worker_pool
            ? Seobeo_Worker_Pool_Submit(
                g_media_worker_pool,
                Media_Process_Background,
                ctx,
                free)
            : SEOBEO_WORKER_STOPPED;
    if (worker_result != SEOBEO_WORKER_OK)
    {
      Seobeo_Log(
          SEOBEO_ERROR,
          "[MEDIA] Worker submission failed with result=%d for media_id=%lld\n",
          worker_result,
          (long long)media_id);
      free(ctx);
      const char *update_error =
        "UPDATE media_uploads SET status='error', error_message=?, updated_at=strftime('%s','now') WHERE id=?";
      const char *error_params[] = {
        "Media worker queue is unavailable",
        media_id_str,
      };
      Deita_Query_Execute_Update_Prepared(
          g_db_connection,
          update_error,
          2,
          error_params);
      Dowa_HashMap_Push_Arena(resp, "status", "503", arena);
      Dowa_HashMap_Push_Arena(resp, "content-type", "application/json", arena);
      Dowa_HashMap_Push_Arena(resp, "body", "{\"error\":\"Media worker queue is unavailable\"}", arena);
      return resp;
    }
    Seobeo_Log(
        SEOBEO_INFO,
        "[MEDIA] Submitted media_id=%lld to the worker pool\n",
        (long long)media_id);
  }
  else
  {
    Seobeo_Log(SEOBEO_INFO, "[MEDIA] Non-image file, skipping background processing for media_id=%lld\n", (long long)media_id);
  }

  Dowa_HashMap_Push_Arena(resp, "status", "200", arena);
  Dowa_HashMap_Push_Arena(resp, "content-type", "application/json", arena);
  Dowa_HashMap_Push_Arena(resp, "body", "{\"success\":true,\"status\":\"uploaded\"}", arena);

  Seobeo_Log(SEOBEO_INFO, "[MEDIA] Marked uploaded media_id=%lld\n", (long long)media_id);

  return resp;
}

// Media Upload API - Get status
// GET /api/media/:id/status
// Headers: Authorization: Bearer <token>
// Returns: {"id": 123, "status": "finished", "processed_url": "https://...", "error_message": null}
Seobeo_Request_Entry *MediaStatus(Seobeo_Request_Entry *req, Dowa_Arena *arena)
{
  Seobeo_Request_Entry *resp = NULL;

  // Check auth token
  void *auth_kv = Dowa_HashMap_Get_Ptr(req, "Authorization");
  if (!auth_kv)
  {
    Dowa_HashMap_Push_Arena(resp, "status", "401", arena);
    Dowa_HashMap_Push_Arena(resp, "content-type", "application/json", arena);
    Dowa_HashMap_Push_Arena(resp, "body", "{\"error\":\"Missing Authorization header\"}", arena);
    return resp;
  }

  const char *auth_header = ((Seobeo_Request_Entry*)auth_kv)->value;
  if (strncmp(auth_header, "Bearer ", 7) != 0)
  {
    Dowa_HashMap_Push_Arena(resp, "status", "401", arena);
    Dowa_HashMap_Push_Arena(resp, "content-type", "application/json", arena);
    Dowa_HashMap_Push_Arena(resp, "body", "{\"error\":\"Invalid Authorization format\"}", arena);
    return resp;
  }

  const char *token = auth_header + 7;
  if (strlen(g_upload_auth_token) == 0 || strcmp(token, g_upload_auth_token) != 0)
  {
    Dowa_HashMap_Push_Arena(resp, "status", "403", arena);
    Dowa_HashMap_Push_Arena(resp, "content-type", "application/json", arena);
    Dowa_HashMap_Push_Arena(resp, "body", "{\"error\":\"Invalid token\"}", arena);
    return resp;
  }

  if (!g_db_connection)
  {
    Dowa_HashMap_Push_Arena(resp, "status", "500", arena);
    Dowa_HashMap_Push_Arena(resp, "content-type", "application/json", arena);
    Dowa_HashMap_Push_Arena(resp, "body", "{\"error\":\"Database not available\"}", arena);
    return resp;
  }

  // Extract media_id from URL params
  void *id_kv = Dowa_HashMap_Get_Ptr(req, ":id");
  if (!id_kv)
  {
    Dowa_HashMap_Push_Arena(resp, "status", "400", arena);
    Dowa_HashMap_Push_Arena(resp, "content-type", "application/json", arena);
    Dowa_HashMap_Push_Arena(resp, "body", "{\"error\":\"Missing media ID\"}", arena);
    return resp;
  }

  const char *media_id_str = ((Seobeo_Request_Entry*)id_kv)->value;

  // Query media status
  const char *select_query =
    "SELECT id, status, s3_key_original, s3_key_processed, error_message FROM media_uploads WHERE id = ? AND access_token = ?";
  const char *select_params[] = { media_id_str, token };

  Deita_Result_Set *p_result = Deita_Query_Execute_Prepared(g_db_connection, select_query, 2, select_params, arena);

  if (!p_result || !Deita_Result_Set_Next(p_result))
  {
    if (p_result) Deita_Result_Set_Free(p_result);
    Dowa_HashMap_Push_Arena(resp, "status", "404", arena);
    Dowa_HashMap_Push_Arena(resp, "content-type", "application/json", arena);
    Dowa_HashMap_Push_Arena(resp, "body", "{\"error\":\"Media not found\"}", arena);
    return resp;
  }

  int64 id = Deita_Result_Set_Get_Integer(p_result, 0);
  const char *status = Deita_Result_Set_Get_Text(p_result, 1);
  const char *s3_key_original = Deita_Result_Set_Get_Text(p_result, 2);
  const char *s3_key_processed = Deita_Result_Set_Get_Text(p_result, 3);
  const char *error_message = Deita_Result_Set_Get_Text(p_result, 4);

  // Build CloudFront URL for processed file if status is 'finished'
  char processed_url[1024] = {0};
  if (strcmp(status, "finished") == 0 && s3_key_processed && strlen(s3_key_processed) > 0)
  {
    if (g_s3_cloudfront_url[0])
    {
      snprintf(processed_url, sizeof(processed_url), "%s/%s", g_s3_cloudfront_url, s3_key_processed);
    }
    else
    {
      snprintf(processed_url, sizeof(processed_url), "https://%s.s3.%s.amazonaws.com/%s",
               g_s3_bucket, g_s3_region, s3_key_processed);
    }
  }

  // Build CloudFront URL for original file (for non-images or before processing completes)
  char original_url[1024] = {0};
  if (s3_key_original && strlen(s3_key_original) > 0)
  {
    if (g_s3_cloudfront_url[0])
    {
      snprintf(original_url, sizeof(original_url), "%s/%s", g_s3_cloudfront_url, s3_key_original);
    }
    else
    {
      snprintf(original_url, sizeof(original_url), "https://%s.s3.%s.amazonaws.com/%s",
               g_s3_bucket, g_s3_region, s3_key_original);
    }
  }

  // Build JSON response with both processed_url and original_url
  char *response_body = Dowa_Arena_Allocate(arena, 3072);

  // Build the base response
  int offset = snprintf(response_body, 3072,
                        "{\"id\":%lld,\"status\":\"%s\",",
                        (long long)id, status);

  // Add processed_url
  if (strlen(processed_url) > 0)
  {
    offset += snprintf(response_body + offset, 3072 - offset,
                       "\"processed_url\":\"%s\",", processed_url);
  }
  else
  {
    offset += snprintf(response_body + offset, 3072 - offset,
                       "\"processed_url\":null,");
  }

  // Add original_url
  if (strlen(original_url) > 0)
  {
    offset += snprintf(response_body + offset, 3072 - offset,
                       "\"original_url\":\"%s\",", original_url);
  }
  else
  {
    offset += snprintf(response_body + offset, 3072 - offset,
                       "\"original_url\":null,");
  }

  // Add error_message
  if (error_message && strlen(error_message) > 0)
  {
    snprintf(response_body + offset, 3072 - offset,
             "\"error_message\":\"%s\"}", error_message);
  }
  else
  {
    snprintf(response_body + offset, 3072 - offset,
             "\"error_message\":null}");
  }

  Deita_Result_Set_Free(p_result);

  Dowa_HashMap_Push_Arena(resp, "status", "200", arena);
  Dowa_HashMap_Push_Arena(resp, "content-type", "application/json", arena);
  Dowa_HashMap_Push_Arena(resp, "body", response_body, arena);

  return resp;
}

int main(void)
{
  signal(SIGINT, handle_sigint);
  signal(SIGTERM, handle_sigint);

  // Load the ignored runtime config when present; environment overrides follow.
  const char *config_path = getenv("MRJUNEJUNE_CONFIG_PATH");
  load_config(
      config_path && config_path[0] != '\0'
          ? config_path
          : "mrjunejune/.config");

  // Initialize S3 config using global credentials populated by load_config
  g_s3_config.access_key_id = g_s3_access_key;
  g_s3_config.secret_access_key = g_s3_secret_key;
  g_s3_config.region = g_s3_region;
  g_s3_config.bucket = g_s3_bucket;
  g_s3_config.endpoint = NULL;
  g_s3_config.use_path_style = FALSE;

  printf("[S3] Configured: region=%s, bucket=%s, key=%s...\n",
         g_s3_region, g_s3_bucket, g_s3_access_key[0] ? "***" : "(missing)");

  // Show current working directory
  char cwd[1024];
  if (getcwd(cwd, sizeof(cwd)) != NULL)
  {
    printf("[STARTUP] Current working directory: %s\n", cwd);
    printf("[STARTUP] Database path (relative): %s\n", g_db_path);
  }

  // Initialize database
  init_database();
  {
    /* Validate per-request token cap against daily limit now that both
     * are finalised (env overrides run inside load_config). */
    if (g_guest_request_output_tokens > g_guest_daily_output_tokens)
      g_guest_request_output_tokens = g_guest_daily_output_tokens;

    Conversation_API_Guest_Policy policy = {
      .guest_inference_enabled = g_guest_inference_enabled,
      .daily_turns             = g_guest_daily_turns,
      .daily_output_tokens     = g_guest_daily_output_tokens,
      .request_output_tokens   = g_guest_request_output_tokens,
    };
    if (!Conversation_API_Init(g_db_path, &policy))
      Seobeo_Log(SEOBEO_ERROR, "[CONVERSATION] Store unavailable\n");
  }

  /* Validate and decode AUTH_COOKIE_SECRET: hex string → raw bytes. */
  uint8  cookie_secret_bytes[AUTH_CRYPTO_COOKIE_SECRET_MAX_BYTES];
  size_t cookie_secret_byte_len = 0;
  {
    size_t hex_len = strlen(g_auth_cookie_secret);
    boolean bad_len = (
        hex_len < (size_t)(AUTH_CRYPTO_COOKIE_SECRET_MIN_BYTES * 2) ||
        hex_len > (size_t)(AUTH_CRYPTO_COOKIE_SECRET_MAX_BYTES * 2) ||
        hex_len % 2 != 0);
    if (bad_len)
    {
      OPENSSL_cleanse(g_auth_cookie_secret, sizeof(g_auth_cookie_secret));
      fprintf(stderr,
              "[AUTH] AUTH_COOKIE_SECRET must be %d–%d hex chars "
              "(%d–%d random bytes). "
              "Generate with: openssl rand -hex 32\n",
              AUTH_CRYPTO_COOKIE_SECRET_MIN_BYTES * 2,
              AUTH_CRYPTO_COOKIE_SECRET_MAX_BYTES * 2,
              AUTH_CRYPTO_COOKIE_SECRET_MIN_BYTES,
              AUTH_CRYPTO_COOKIE_SECRET_MAX_BYTES);
      exit(1);
    }
    cookie_secret_byte_len = config__hex_decode(
        g_auth_cookie_secret, cookie_secret_bytes, sizeof(cookie_secret_bytes));
    OPENSSL_cleanse(g_auth_cookie_secret, sizeof(g_auth_cookie_secret));
    if (cookie_secret_byte_len < (size_t)AUTH_CRYPTO_COOKIE_SECRET_MIN_BYTES)
    {
      OPENSSL_cleanse(cookie_secret_bytes, sizeof(cookie_secret_bytes));
      fprintf(stderr,
              "[AUTH] AUTH_COOKIE_SECRET contains non-hex characters or "
              "is too short.\n");
      exit(1);
    }
  }

  /* Bootstrap pairing: both username+hash must be set, or both absent. */
  {
    boolean has_user = g_auth_bootstrap_username[0] != '\0';
    boolean has_hash = g_auth_bootstrap_password_hash[0] != '\0';
    if (has_user != has_hash)
    {
      OPENSSL_cleanse(cookie_secret_bytes, sizeof(cookie_secret_bytes));
      fprintf(stderr,
              "[AUTH] AUTH_BOOTSTRAP_USERNAME and AUTH_BOOTSTRAP_PASSWORD_HASH "
              "must both be set or both absent.\n");
      exit(1);
    }
    if (has_hash &&
        Auth_Crypto_Password_Hash_Validate(g_auth_bootstrap_password_hash) != AUTH_CRYPTO_OK)
    {
      OPENSSL_cleanse(cookie_secret_bytes, sizeof(cookie_secret_bytes));
      fprintf(stderr,
              "[AUTH] AUTH_BOOTSTRAP_PASSWORD_HASH has unrecognized format "
              "(expected zenbu-scrypt$v=1$...).\n");
      exit(1);
    }
  }

  /* TTL validation: all positive, idle <= abs, all within 1 min – 1 year. */
#define CONFIG_TTL_MIN_SECS 60
#define CONFIG_TTL_MAX_SECS 31536000
  {
    int64 idle  = g_auth_session_idle_ttl;
    int64 abst  = g_auth_session_abs_ttl;
    int64 guest = g_auth_guest_ttl;
    if (idle <= 0 || abst <= 0 || guest <= 0 ||
        idle < CONFIG_TTL_MIN_SECS || idle > CONFIG_TTL_MAX_SECS ||
        abst < CONFIG_TTL_MIN_SECS || abst > CONFIG_TTL_MAX_SECS ||
        guest < CONFIG_TTL_MIN_SECS || guest > CONFIG_TTL_MAX_SECS)
    {
      OPENSSL_cleanse(cookie_secret_bytes, sizeof(cookie_secret_bytes));
      fprintf(stderr,
              "[AUTH] TTL values must be %d–%d seconds.\n",
              CONFIG_TTL_MIN_SECS, CONFIG_TTL_MAX_SECS);
      exit(1);
    }
    if (idle > abst)
    {
      OPENSSL_cleanse(cookie_secret_bytes, sizeof(cookie_secret_bytes));
      fprintf(stderr,
              "[AUTH] AUTH_SESSION_IDLE_TTL must not exceed "
              "AUTH_SESSION_ABS_TTL.\n");
      exit(1);
    }
  }

  /* Trusted proxy: validate and canonicalize via inet_pton/inet_ntop. */
  if (g_auth_trusted_proxy[0] != '\0')
  {
    struct in_addr  addr4;
    struct in6_addr addr6;
    char canonical[AUTH_CRYPTO_IP_MAX_BYTES];
    canonical[0] = '\0';
    if (inet_pton(AF_INET, g_auth_trusted_proxy, &addr4) == 1)
    {
      if (!inet_ntop(AF_INET, &addr4, canonical, sizeof(canonical)))
      {
        OPENSSL_cleanse(cookie_secret_bytes, sizeof(cookie_secret_bytes));
        fprintf(stderr,
                "[AUTH] AUTH_TRUSTED_PROXY: IPv4 canonicalization failed.\n");
        exit(1);
      }
    }
    else if (inet_pton(AF_INET6, g_auth_trusted_proxy, &addr6) == 1)
    {
      if (!inet_ntop(AF_INET6, &addr6, canonical, sizeof(canonical)))
      {
        OPENSSL_cleanse(cookie_secret_bytes, sizeof(cookie_secret_bytes));
        fprintf(stderr,
                "[AUTH] AUTH_TRUSTED_PROXY: IPv6 canonicalization failed.\n");
        exit(1);
      }
    }
    else
    {
      OPENSSL_cleanse(cookie_secret_bytes, sizeof(cookie_secret_bytes));
      fprintf(stderr,
              "[AUTH] AUTH_TRUSTED_PROXY must be a valid IPv4 or IPv6 "
              "address (e.g. 192.168.1.1 or ::1).\n");
      exit(1);
    }
    strncpy(g_auth_trusted_proxy, canonical, sizeof(g_auth_trusted_proxy) - 1);
    g_auth_trusted_proxy[sizeof(g_auth_trusted_proxy) - 1] = '\0';
  }

  /*
   * Loopback enforcement: AUTH_DEV_INSECURE_COOKIE=true is only permitted
   * when SERVER_HOST is explicitly a loopback address.  Production/edge
   * deployments must use Secure cookies.
   */
  {
    boolean is_loopback = (
        strcmp(g_server_host, "127.0.0.1") == 0 ||
        strcmp(g_server_host, "::1")        == 0 ||
        strcmp(g_server_host, "localhost")   == 0);
    if (g_auth_dev_insecure && !is_loopback)
    {
      OPENSSL_cleanse(cookie_secret_bytes, sizeof(cookie_secret_bytes));
      fprintf(stderr,
              "[AUTH] AUTH_DEV_INSECURE_COOKIE=true requires SERVER_HOST "
              "to be a loopback address (127.0.0.1, ::1, or localhost). "
              "Set SERVER_HOST=127.0.0.1 for local development.\n");
      exit(1);
    }
  }

  /* Initialize auth module — fail closed: no auth means no server. */
  {
    if (!Auth_API_Init(
            g_db_path,
            cookie_secret_bytes, cookie_secret_byte_len,
            g_auth_bootstrap_username[0] ? g_auth_bootstrap_username : NULL,
            g_auth_bootstrap_password_hash[0] ? g_auth_bootstrap_password_hash : NULL,
            g_auth_trusted_proxy[0] ? g_auth_trusted_proxy : NULL,
            g_auth_session_idle_ttl,
            g_auth_session_abs_ttl,
            g_auth_guest_ttl,
            g_auth_dev_insecure))
    {
      OPENSSL_cleanse(cookie_secret_bytes, sizeof(cookie_secret_bytes));
      fprintf(stderr,
              "[AUTH] Auth init failed — refusing to start server.\n");
      exit(1);
    }
    OPENSSL_cleanse(cookie_secret_bytes, sizeof(cookie_secret_bytes));
  }
  const char *sidecar_path = getenv("MRJUNEJUNE_INFERENCE_SIDECAR_PATH");
  const char *copilot_cli_path = getenv("MRJUNEJUNE_COPILOT_CLI_PATH");
  if (sidecar_path && copilot_cli_path)
  {
    if (!Conversation_API_Enable_Inference(sidecar_path, copilot_cli_path))
      Seobeo_Log(SEOBEO_ERROR, "[INFERENCE] Sidecar unavailable\n");
  }
  else
  {
    Seobeo_Log(
        SEOBEO_WARNING,
        "[INFERENCE] Runtime paths not configured; turns return 503\n");
  }

  g_media_worker_pool = Seobeo_Worker_Pool_Create(2, 16);
  if (!g_media_worker_pool)
  {
    Seobeo_Log(
        SEOBEO_ERROR,
        "[MEDIA] Unable to initialize the media worker pool\n");
  }

  Seobeo_Router_Init();
  Auth_API_Register_Routes();
  Admin_API_Register_Routes();
  Conversation_API_Register_Routes();

  Seobeo_Router_Register("GET", "/", GetHomePage);
  Seobeo_Router_Register("GET", "/index.html", GetRedirectHomePage);

  Seobeo_Router_Register("GET", "/resume", GetResume);
  Seobeo_Router_Register("GET", "/resume/index.html", GetRedirectResume);

  Seobeo_Router_Register("GET", "/tools", GetTools);
  Seobeo_Router_Register("GET", "/tools/index.html", GetRedirectTools);

  Seobeo_Router_Register("GET", "/tools/markdown_to_html", GetMDToHTML);
  Seobeo_Router_Register("GET", "/tools/markdown_to_html/index.html", GetRedirectMarkDownToHtml);

  Seobeo_Router_Register("GET", "/tools/file_converter", GetFileConverter);
  Seobeo_Router_Register("GET", "/tools/file_converter/index.html", GetRedirectFileConverter);
  Seobeo_Router_Register("GET", "/tools/hls_player", GetHlsPlayer);
  Seobeo_Router_Register("GET", "/tools/hls_player/index.html", GetRedirectHlsPlayer);
  Seobeo_Router_Register("GET", "/tools/latex_editor", GetLatexEditor);
  Seobeo_Router_Register("GET", "/tools/latex_editor/index.html", GetRedirectLatexEditor);

  // -- File converter --/
  Seobeo_Router_Register("POST", "/api/convert/image-to-webp", ConvertImageToWebP);
  Seobeo_Router_Register("POST", "/api/convert/video-to-mp4", ConvertVideoToMP4);
  Seobeo_Router_Register("GET", "/api/download/:filename", DownloadConvertedFile);
  Seobeo_Router_Register("DELETE", "/api/download/:filename", DeleteConvertedFile);
  Seobeo_Router_Register("POST", "/api/latex/render", RenderLatexPdf);

  // -- S3 Upload --/
  Seobeo_Router_Register("POST", "/api/s3/upload-url", GetS3UploadUrl);

  // -- Media Upload --/
  Seobeo_Router_Register("POST", "/api/media/create", MediaCreate);
  Seobeo_Router_Register("POST", "/api/media/:id/uploaded", MediaUploaded);
  Seobeo_Router_Register("GET", "/api/media/:id/status", MediaStatus);

  // -- Editor --/
  Seobeo_Router_Register("POST", "/api/editor/save", EditorSave);
  Seobeo_Router_Register("GET", "/api/editor/load/:doc_id", EditorLoad);

  // -- Blog --/
  Seobeo_Router_Register("GET", "/blog", RenderBlogList);
  Seobeo_Router_Register("GET", "/blog/:blog_id", RenderBlog);

  // -- Talk --/
  Seobeo_Router_Register("GET", "/talk", GetTalk);
  Seobeo_Router_Register("GET", "/talk/index.html", GetRedirectTalk);

  // -- JRPG agent chat --/
  Seobeo_Router_Register("GET", "/jrpg", GetJrpg);
  Seobeo_Router_Register("GET", "/jrpg/index.html", GetRedirectJrpg);

  // -- Login --/
  Seobeo_Router_Register("GET", "/login", GetLogin);

  // -- Notes --/
  Seobeo_Router_Register("GET", "/notes", GetNotes);
  Seobeo_Router_Register("GET", "/notes/", GetNotes);
  Seobeo_Router_Register("GET", "/notes/index.html", GetNotes);
  Seobeo_Router_Register("GET", "/notes/login", GetNotesLogin);
  Seobeo_Router_Register("GET", "/notes/login/", GetNotesLogin);
  Seobeo_Router_Register("GET", "/notes/:note_id", GetNoteById);

  Seobeo_WebSocket_Server_Init();
  Seobeo_WebSocket_Server_Register("/chat", Chat_Handler, NULL);

  Seobeo_Log(SEOBEO_INFO, "WTF is going on\n");
  const char *server_port = getenv("MRJUNEJUNE_PORT");
  if (!server_port || server_port[0] == '\0')
    server_port = "6969";
  const char *server_bind = g_server_host[0] ? g_server_host : "0.0.0.0";
  Mjj_Template_Renderer_Init("mrjunejune/src");
  int server_result = Seobeo_Web_Server_Start_On(
      server_bind, "mrjunejune/src", server_port, SEOBEO_MODE_EDGE, 4);
  Seobeo_Worker_Pool_Destroy(g_media_worker_pool);
  g_media_worker_pool = NULL;
  Conversation_API_Destroy();
  Auth_API_Destroy();
  if (server_result != 0)
  {
    fprintf(stderr, "[STARTUP] Server bind/listen failed (host=%s port=%s)\n",
            server_bind, server_port);
    return 1;
  }
  return 0;
}