#include "settings/flags.h"
#include "db/database.h"
#include <stdio.h>
#include <string.h>

// Define all available WebKit2GTK flags
static const FlagInfo available_flags[] = {
    // Debugging & Logging
    {"WEBKIT_DEBUG",
     "Comma-separated list of logging channels (e.g., 'all', 'Network', "
     "'Loading=warning'). Prefix with '-' to disable.",
     FLAG_TYPE_STRING, FLAG_CATEGORY_DEBUG, "", TRUE},
    {"WEBKIT_INSPECTOR_SERVER",
     "Remote inspector server address:port (e.g., '127.0.0.1:10000')",
     FLAG_TYPE_STRING, FLAG_CATEGORY_DEBUG, "", TRUE},
    {"WEBKIT_INSPECTOR_HTTP_SERVER",
     "Remote inspector HTTP server address:port", FLAG_TYPE_STRING,
     FLAG_CATEGORY_DEBUG, "", TRUE},
    {"WEBKIT2_PAUSE_WEB_PROCESS_ON_LAUNCH",
     "Pause web process for 30 seconds on launch for debugger attachment (0 or "
     "1)",
     FLAG_TYPE_BOOLEAN, FLAG_CATEGORY_DEBUG, "0", TRUE},
    {"WEBKIT_DISABLE_SANDBOX_THIS_IS_DANGEROUS",
     "Disable sandbox for debugging (DANGEROUS - 0 or 1)", FLAG_TYPE_BOOLEAN,
     FLAG_CATEGORY_DEBUG, "0", TRUE},
    {"OS_ACTIVITY_MODE", "macOS logging verbosity (disable/off/info/debug)",
     FLAG_TYPE_STRING, FLAG_CATEGORY_DEBUG, "", TRUE},

    // JavaScriptCore
    {"JavaScriptCoreUseJIT",
     "Enable JavaScript JIT compiler (0 or 1). Disable for debugging.",
     FLAG_TYPE_BOOLEAN, FLAG_CATEGORY_JAVASCRIPT, "1", TRUE},
    {"JSC_useFTLJIT", "Enable JavaScript FTL JIT compiler (0 or 1)",
     FLAG_TYPE_BOOLEAN, FLAG_CATEGORY_JAVASCRIPT, "1", TRUE},
    {"JSC_logGC", "Enable JavaScriptCore garbage collection logging (0 or 1)",
     FLAG_TYPE_BOOLEAN, FLAG_CATEGORY_JAVASCRIPT, "0", TRUE},
    {"JSC_SIGNAL_FOR_GC",
     "Signal number for garbage collection on Linux/FreeBSD", FLAG_TYPE_INTEGER,
     FLAG_CATEGORY_JAVASCRIPT, "", TRUE},

    // Graphics & Rendering
    {"WEBKIT_FORCE_COMPOSITING_MODE",
     "Force accelerated compositing mode always on (0 or 1)", FLAG_TYPE_BOOLEAN,
     FLAG_CATEGORY_GRAPHICS, "0", TRUE},
    {"WEBKIT_DISABLE_COMPOSITING_MODE",
     "Force accelerated compositing mode always off (0 or 1)",
     FLAG_TYPE_BOOLEAN, FLAG_CATEGORY_GRAPHICS, "0", TRUE},
    {"WEBKIT_DISABLE_DMABUF_RENDERER", "Disable DMA buffer renderer (0 or 1)",
     FLAG_TYPE_BOOLEAN, FLAG_CATEGORY_GRAPHICS, "0", TRUE},
    {"WPE_DRM_DEVICE",
     "Primary DRM device path for GPU buffer allocation (e.g., "
     "'/dev/dri/card0')",
     FLAG_TYPE_STRING, FLAG_CATEGORY_GRAPHICS, "", TRUE},
    {"WPE_DRM_RENDER_NODE", "Render device path for buffer allocation",
     FLAG_TYPE_STRING, FLAG_CATEGORY_GRAPHICS, "", TRUE},
    {"WPE_DMABUF_BUFFER_FORMAT",
     "DMA buffer format (pixel_format:memory_layout:usage)", FLAG_TYPE_STRING,
     FLAG_CATEGORY_GRAPHICS, "", TRUE},

    // Memory & Performance
    {"Malloc",
     "Disable bmalloc and use system allocator instead (0 or 1). Useful for "
     "memory debugging.",
     FLAG_TYPE_BOOLEAN, FLAG_CATEGORY_MEMORY, "0", TRUE},
    {"GIGACAGE_ENABLED",
     "Enable gigacage memory protection (0 or 1). Disable for Valgrind.",
     FLAG_TYPE_BOOLEAN, FLAG_CATEGORY_MEMORY, "1", TRUE},
    {"WEBKIT_MALLOC_HEAP_BREAKDOWN_LOG_INTERVAL",
     "Heap breakdown report interval in seconds", FLAG_TYPE_INTEGER,
     FLAG_CATEGORY_MEMORY, "", TRUE},

    // Media
    {"MSE_MAX_BUFFER_SIZE",
     "Media Source Extension max buffer sizes (e.g., 'V:50M', 'audio:12k', "
     "'*:100M')",
     FLAG_TYPE_STRING, FLAG_CATEGORY_MEDIA, "", TRUE},

    // Process Configuration
    {"WEB_PROCESS_CMD_PREFIX",
     "Prefix command for web process (developer builds only)", FLAG_TYPE_STRING,
     FLAG_CATEGORY_OTHER, "", TRUE},
    {"NETWORK_PROCESS_CMD_PREFIX",
     "Prefix command for network process (developer builds only)",
     FLAG_TYPE_STRING, FLAG_CATEGORY_OTHER, "", TRUE},

    {NULL, NULL, 0, 0, NULL, FALSE} // Sentinel
};

struct _FlagsManager {
  Profile *profile;
  int flag_count;
};

FlagsManager *flags_manager_new(Profile *profile) {
  FlagsManager *manager = g_new0(FlagsManager, 1);
  manager->profile = profile;

  // Count flags
  manager->flag_count = 0;
  for (int i = 0; available_flags[i].name != NULL; i++) {
    manager->flag_count++;
  }

  return manager;
}

void flags_manager_free(FlagsManager *manager) {
  if (manager) {
    g_free(manager);
  }
}

const FlagInfo **flags_manager_get_all(FlagsManager *manager) {
  // Return pointer to static array
  return (const FlagInfo **)&available_flags;
}

char *flags_manager_get_value(FlagsManager *manager, const char *flag_name) {
  if (!manager || !flag_name || !manager->profile || !manager->profile->db) {
    return NULL;
  }

  // Try to get from database
  char *key = g_strdup_printf("flag_%s", flag_name);
  char *value = settings_get(manager->profile->db, key);
  g_free(key);

  // If not in database, check if it's set in environment
  if (!value) {
    const char *env_value = g_getenv(flag_name);
    if (env_value) {
      value = g_strdup(env_value);
    }
  }

  return value;
}

gboolean flags_manager_set_value(FlagsManager *manager, const char *flag_name,
                                 const char *value) {
  if (!manager || !flag_name || !manager->profile || !manager->profile->db) {
    return FALSE;
  }

  char *key = g_strdup_printf("flag_%s", flag_name);
  int result;

  if (value && strlen(value) > 0) {
    result = settings_set(manager->profile->db, key, value);
  } else {
    // Empty value means reset to default (delete from DB)
    result = settings_set(manager->profile->db, key, "");
  }

  g_free(key);

  // settings_set returns 0 on success, -1 on failure
  return (result == 0) ? TRUE : FALSE;
}

void flags_manager_apply_all(FlagsManager *manager) {
  if (!manager) {
    return;
  }

  g_print("Applying WebKit flags...\n");

  for (int i = 0; available_flags[i].name != NULL; i++) {
    const FlagInfo *flag = &available_flags[i];
    char *value = flags_manager_get_value(manager, flag->name);

    if (value && strlen(value) > 0) {
      g_setenv(flag->name, value, TRUE);
      g_print("  ✓ %s = %s\n", flag->name, value);
      g_free(value);
    }
  }
}

static const char *get_category_name(FlagCategory category) {
  switch (category) {
  case FLAG_CATEGORY_DEBUG:
    return "Debugging &amp; Logging";
  case FLAG_CATEGORY_JAVASCRIPT:
    return "JavaScriptCore";
  case FLAG_CATEGORY_GRAPHICS:
    return "Graphics &amp; Rendering";
  case FLAG_CATEGORY_MEMORY:
    return "Memory &amp; Performance";
  case FLAG_CATEGORY_MEDIA:
    return "Media";
  case FLAG_CATEGORY_OTHER:
    return "Other";
  default:
    return "Unknown";
  }
}

char *flags_manager_get_flags_html(FlagsManager *manager) {
  GString *html = g_string_new("");

  // HTML structure with modern styling
  g_string_append(html, "<!DOCTYPE html>\n");
  g_string_append(html, "<html>\n<head>\n");
  g_string_append(html, "<meta charset='UTF-8'>\n");
  g_string_append(html, "<meta name='viewport' content='width=device-width, "
                        "initial-scale=1.0'>\n");
  g_string_append(html, "<title>Leaf Flags</title>\n");
  g_string_append(html, "<style>\n");
  g_string_append(html,
                  "* { margin: 0; padding: 0; box-sizing: border-box; }\n");
  g_string_append(
      html,
      "body { font-family: -apple-system, BlinkMacSystemFont, "
      "'Segoe UI', Roboto, sans-serif; background: linear-gradient(135deg, "
      "#667eea 0%, #764ba2 100%); color: #333; padding: 20px; }\n");
  g_string_append(html, ".container { max-width: 1200px; margin: 0 auto; "
                        "background: white; border-radius: 16px; overflow: "
                        "hidden; box-shadow: 0 20px 60px rgba(0,0,0,0.3); }\n");
  g_string_append(html,
                  ".header { background: linear-gradient(135deg, #667eea 0%, "
                  "#764ba2 100%); color: white; padding: 40px; text-align: "
                  "center; }\n");
  g_string_append(html, ".header h1 { font-size: 2.5em; font-weight: 700; "
                        "margin-bottom: 10px; }\n");
  g_string_append(html, ".header p { font-size: 1.1em; opacity: 0.9; }\n");
  g_string_append(html, ".search-box { padding: 30px; background: #f8f9fa; "
                        "border-bottom: 1px solid #e9ecef; }\n");
  g_string_append(html,
                  ".search-box input { width: 100%; padding: 15px 20px; "
                  "font-size: 16px; border: 2px solid #dee2e6; border-radius: "
                  "8px; transition: all 0.3s; }\n");
  g_string_append(
      html, ".search-box input:focus { outline: none; border-color: #667eea; "
            "box-shadow: 0 0 0 3px rgba(102, 126, 234, 0.1); }\n");
  g_string_append(html, ".content { padding: 30px; }\n");
  g_string_append(html, ".category { margin-bottom: 40px; }\n");
  g_string_append(html, ".category h2 { font-size: 1.5em; color: #667eea; "
                        "margin-bottom: 20px; padding-bottom: 10px; "
                        "border-bottom: 2px solid #e9ecef; }\n");
  g_string_append(html, ".flag-item { background: #fff; border: 1px solid "
                        "#e9ecef; border-radius: 8px; padding: 20px; "
                        "margin-bottom: 15px; transition: all 0.3s; }\n");
  g_string_append(html, ".flag-item:hover { border-color: #667eea; box-shadow: "
                        "0 4px 12px rgba(102, 126, 234, 0.15); transform: "
                        "translateY(-2px); }\n");
  g_string_append(html, ".flag-name { font-weight: 600; font-size: 1.1em; "
                        "color: #2d3748; margin-bottom: 8px; font-family: "
                        "'Courier New', monospace; }\n");
  g_string_append(html, ".flag-desc { color: #718096; font-size: 0.95em; "
                        "margin-bottom: 15px; line-height: 1.6; }\n");
  g_string_append(html, ".flag-controls { display: flex; align-items: center; "
                        "gap: 15px; }\n");
  g_string_append(html, ".flag-controls input { flex: 1; padding: 10px 15px; "
                        "border: 2px solid #dee2e6; border-radius: 6px; "
                        "font-size: 14px; font-family: 'Courier New', "
                        "monospace; }\n");
  g_string_append(html, ".flag-controls input:focus { outline: none; "
                        "border-color: #667eea; }\n");
  g_string_append(
      html, ".flag-controls button { padding: 10px 20px; background: "
            "#667eea; color: white; border: none; border-radius: 6px; "
            "cursor: pointer; font-weight: 600; transition: all 0.3s; }\n");
  g_string_append(html, ".flag-controls button:hover { background: #5568d3; "
                        "transform: scale(1.05); }\n");
  g_string_append(html, ".flag-controls .reset-btn { background: #e53e3e; }\n");
  g_string_append(html,
                  ".flag-controls .reset-btn:hover { background: #c53030; }\n");
  g_string_append(html, ".badge { display: inline-block; background: #fbbf24; "
                        "color: #78350f; padding: 4px 12px; border-radius: "
                        "12px; font-size: 0.75em; font-weight: 600; "
                        "margin-left: 10px; }\n");
  g_string_append(html, ".no-results { text-align: center; padding: 60px 20px; "
                        "color: #718096; font-size: 1.2em; }\n");
  g_string_append(html, ".footer { background: #f8f9fa; padding: 20px; "
                        "text-align: center; color: #718096; font-size: "
                        "0.9em; border-top: 1px solid #e9ecef; }\n");
  g_string_append(html, "</style>\n</head>\n<body>\n");

  g_string_append(html, "<div class='container'>\n");

  // Header
  g_string_append(html, "<div class='header'>\n");
  g_string_append(html, "<h1>🚩 Leaf Flags</h1>\n");
  g_string_append(html, "<p>Configure WebKit2GTK environment variables</p>\n");
  g_string_append(html, "</div>\n");

  // Search box
  g_string_append(html, "<div class='search-box'>\n");
  g_string_append(html, "<input type='text' id='searchInput' "
                        "placeholder='🔍 Search flags...' "
                        "onkeyup='filterFlags()'>\n");
  g_string_append(html, "</div>\n");

  g_string_append(html, "<div class='content' id='flagsContent'>\n");

  // Group flags by category
  for (int cat = FLAG_CATEGORY_DEBUG; cat <= FLAG_CATEGORY_OTHER; cat++) {
    gboolean has_flags_in_category = FALSE;

    // Check if we have flags in this category
    for (int i = 0; available_flags[i].name != NULL; i++) {
      if (available_flags[i].category == cat) {
        has_flags_in_category = TRUE;
        break;
      }
    }

    if (!has_flags_in_category)
      continue;

    g_string_append_printf(html, "<div class='category' data-category='%d'>\n",
                           cat);
    g_string_append_printf(html, "<h2>%s</h2>\n", get_category_name(cat));

    // List flags in this category
    for (int i = 0; available_flags[i].name != NULL; i++) {
      const FlagInfo *flag = &available_flags[i];
      if (flag->category != cat)
        continue;

      char *current_value = flags_manager_get_value(manager, flag->name);
      const char *display_value =
          current_value ? current_value : flag->default_value;

      g_string_append_printf(html, "<div class='flag-item' data-flag='%s'>\n",
                             flag->name);
      g_string_append_printf(html, "<div class='flag-name'>%s", flag->name);
      if (flag->requires_restart) {
        g_string_append(html, "<span class='badge'>Requires Restart</span>");
      }
      g_string_append(html, "</div>\n");
      g_string_append_printf(html, "<div class='flag-desc'>%s</div>\n",
                             flag->description);
      g_string_append(html, "<div class='flag-controls'>\n");
      g_string_append_printf(html,
                             "<input type='text' value='%s' "
                             "onchange='saveFlag(\"%s\", this.value)'>\n",
                             display_value, flag->name);
      g_string_append_printf(
          html,
          "<button onclick='saveFlag(\"%s\", "
          "this.previousElementSibling.value)'>Save</button>\n",
          flag->name);
      g_string_append_printf(
          html,
          "<button class='reset-btn' onclick='resetFlag(\"%s\", "
          "\"%s\")'>Reset</button>\n",
          flag->name, flag->default_value);
      g_string_append(html, "</div>\n</div>\n");

      if (current_value) {
        g_free(current_value);
      }
    }

    g_string_append(html, "</div>\n");
  }

  g_string_append(
      html, "<div class='no-results' id='noResults' style='display:none;'>\n");
  g_string_append(html, "No flags match your search.\n");
  g_string_append(html, "</div>\n");

  g_string_append(html, "</div>\n"); // content

  // Footer
  g_string_append(html, "<div class='footer'>\n");
  g_string_append_printf(
      html,
      "Total flags: %d | Changes are saved to your profile database | "
      "Restart browser for most changes to take effect\n",
      manager->flag_count);
  g_string_append(html, "</div>\n");

  g_string_append(html, "</div>\n"); // container

  // JavaScript for search and save functionality
  g_string_append(html, "<script>\n");
  g_string_append(html, "function filterFlags() {\n");
  g_string_append(
      html, "  var input = "
            "document.getElementById('searchInput').value.toLowerCase();\n");
  g_string_append(html, "  var flags = "
                        "document.querySelectorAll('.flag-item');\n");
  g_string_append(html, "  var categories = "
                        "document.querySelectorAll('.category');\n");
  g_string_append(html, "  var visibleCount = 0;\n");
  g_string_append(html, "  categories.forEach(function(cat) {\n");
  g_string_append(html, "    var catVisible = false;\n");
  g_string_append(
      html,
      "    cat.querySelectorAll('.flag-item').forEach(function(flag) {\n");
  g_string_append(
      html, "      var name = flag.getAttribute('data-flag').toLowerCase();\n");
  g_string_append(
      html, "      var desc = "
            "flag.querySelector('.flag-desc').textContent.toLowerCase();\n");
  g_string_append(
      html,
      "      if (name.indexOf(input) > -1 || desc.indexOf(input) > -1) {\n");
  g_string_append(html, "        flag.style.display = '';\n");
  g_string_append(html, "        catVisible = true;\n");
  g_string_append(html, "        visibleCount++;\n");
  g_string_append(html, "      } else {\n");
  g_string_append(html, "        flag.style.display = 'none';\n");
  g_string_append(html, "      }\n");
  g_string_append(html, "    });\n");
  g_string_append(html, "    cat.style.display = catVisible ? '' : 'none';\n");
  g_string_append(html, "  });\n");
  g_string_append(html, "  document.getElementById('noResults').style.display "
                        "= visibleCount === 0 ? 'block' : 'none';\n");
  g_string_append(html, "}\n");
  g_string_append(html, "function saveFlag(name, value) {\n");
  g_string_append(html,
                  "  window.webkit.messageHandlers.flagChanged.postMessage({ "
                  "name: name, value: value });\n");
  g_string_append(html,
                  "  alert('Saved ' + name + ' = ' + value + '\\n\\nRestart "
                  "browser for changes to take effect.');\n");
  g_string_append(html, "}\n");
  g_string_append(html, "function resetFlag(name, defaultValue) {\n");
  g_string_append(html, "  var input = document.querySelector('[data-flag=\"' "
                        "+ name + '\"] input');\n");
  g_string_append(html, "  input.value = defaultValue;\n");
  g_string_append(html, "  saveFlag(name, defaultValue);\n");
  g_string_append(html, "}\n");
  g_string_append(html, "</script>\n");

  g_string_append(html, "</body>\n</html>");

  return g_string_free(html, FALSE);
}

int flags_manager_get_count(FlagsManager *manager) {
  return manager ? manager->flag_count : 0;
}
