#include "web/navigation.h"
#include "db/database.h"
#include "settings/flags.h"
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define DEFAULT_HOME_PAGE "leaf://newtab"

// Forward declarations
static gboolean is_valid_url(const char *input);
static char *get_search_url(const char *query, const char *engine);
static char *url_encode(const char *str);

// Include newtab header
#include "ui/newtab.h"

// URL-encode a string for use in search queries
static char *url_encode(const char *str) {
  if (!str)
    return NULL;

  // Allocate worst-case size (each char could become %XX)
  size_t len = strlen(str);
  char *encoded = malloc(len * 3 + 1);
  if (!encoded)
    return NULL;

  char *p = encoded;
  for (size_t i = 0; i < len; i++) {
    unsigned char c = (unsigned char)str[i];
    if (isalnum(c) || c == '-' || c == '_' || c == '.' || c == '~') {
      *p++ = c;
    } else if (c == ' ') {
      *p++ = '+';
    } else {
      sprintf(p, "%%%02X", c);
      p += 3;
    }
  }
  *p = '\0';
  return encoded;
}

// Check if input is a valid URL or should be treated as a search query
static gboolean is_valid_url(const char *input) {
  if (!input || strlen(input) == 0)
    return FALSE;

  // Check for spaces - URLs don't have spaces, search queries often do
  if (strchr(input, ' ') != NULL)
    return FALSE;

  // Check for explicit protocol
  if (strstr(input, "://") != NULL)
    return TRUE;

  // Check for localhost or IP address patterns
  if (strncmp(input, "localhost", 9) == 0 ||
      strncmp(input, "127.0.0.1", 9) == 0)
    return TRUE;

  // Simple IP address check (starts with digit and contains dots)
  if (isdigit(input[0]) && strchr(input, '.') != NULL) {
    // Basic heuristic for IP addresses
    int dots = 0;
    for (const char *p = input; *p; p++) {
      if (*p == '.')
        dots++;
    }
    if (dots >= 3)
      return TRUE;
  }

  // Check for common TLDs
  const char *tlds[] = {".com", ".org", ".net", ".edu", ".gov", ".io",
                        ".co",  ".uk",  ".us",  ".de",  ".fr",  ".jp",
                        ".cn",  ".au",  ".ca",  ".in",  ".br",  ".ru",
                        ".dev", ".app", ".ai",  NULL};

  for (int i = 0; tlds[i] != NULL; i++) {
    if (strstr(input, tlds[i]) != NULL)
      return TRUE;
  }

  return FALSE;
}

// Get search URL for the given query and search engine
static char *get_search_url(const char *query, const char *engine) {
  if (!query)
    return NULL;

  char *encoded_query = url_encode(query);
  if (!encoded_query)
    return NULL;

  char *search_url = NULL;

  // Default to Google if engine is not specified
  const char *search_engine = engine ? engine : "Google";

  if (g_strcmp0(search_engine, "Google") == 0) {
    search_url =
        g_strdup_printf("https://www.google.com/search?q=%s", encoded_query);
  } else if (g_strcmp0(search_engine, "DuckDuckGo") == 0) {
    search_url = g_strdup_printf("https://duckduckgo.com/?q=%s", encoded_query);
  } else if (g_strcmp0(search_engine, "Bing") == 0) {
    search_url =
        g_strdup_printf("https://www.bing.com/search?q=%s", encoded_query);
  } else if (g_strcmp0(search_engine, "Brave Search") == 0) {
    search_url =
        g_strdup_printf("https://search.brave.com/search?q=%s", encoded_query);
  } else {
    // Default to Google for unknown engines
    search_url =
        g_strdup_printf("https://www.google.com/search?q=%s", encoded_query);
  }

  free(encoded_query);
  return search_url;
}

// Signal handler for URL changes
static void on_notify_uri(WebKitWebView *webview, GParamSpec *pspec,
                          NavigationContext *ctx) {
  const gchar *uri = webkit_web_view_get_uri(webview);
  if (uri && ctx->url_entry) {
    // Don't show leaf:// in address bar if possible, or show "New Tab"
    if (g_str_has_prefix(uri, "leaf://newtab"))
      gtk_entry_set_text(ctx->url_entry, "");
    else
      gtk_entry_set_text(ctx->url_entry, uri);
  }
}

// Signal handler for load progress
static void on_notify_estimated_load_progress(WebKitWebView *webview,
                                              GParamSpec *pspec,
                                              NavigationContext *ctx) {
  gdouble progress = webkit_web_view_get_estimated_load_progress(webview);
  // Could be used for progress bar in the future
  (void)progress; // Suppress unused warning
}

// Signal handler for title changes
static void on_notify_title(WebKitWebView *webview, GParamSpec *pspec,
                            NavigationContext *ctx) {
  const gchar *title = webkit_web_view_get_title(webview);
  if (title) {
    // Could update window title here
  }
}

void navigation_init(WebKitWebView *webview, GtkEntry *url_entry,
                     Profile *profile) {
  NavigationContext *ctx = g_new0(NavigationContext, 1);
  ctx->webview = webview;
  ctx->url_entry = url_entry;
  ctx->profile = profile;

  // Connect WebKit signals
  g_signal_connect(webview, "notify::uri", G_CALLBACK(on_notify_uri), ctx);
  g_signal_connect(webview, "notify::estimated-load-progress",
                   G_CALLBACK(on_notify_estimated_load_progress), ctx);
  g_signal_connect(webview, "notify::title", G_CALLBACK(on_notify_title), ctx);

  // Set initial URL
  const gchar *uri = webkit_web_view_get_uri(webview);
  if (uri) {
    if (g_str_has_prefix(uri, "leaf://newtab"))
      gtk_entry_set_text(url_entry, "");
    else
      gtk_entry_set_text(url_entry, uri);
  }
}

void navigation_load_url(WebKitWebView *webview, const char *url) {
  navigation_load_url_with_profile(webview, url, NULL);
}

// Forward declaration of global flags manager getter
extern FlagsManager *get_global_flags_manager(void);

void navigation_load_url_with_profile(WebKitWebView *webview, const char *url,
                                      Profile *profile) {
  if (!url || strlen(url) == 0) {
    return;
  }

  // Check for leaf:// custom scheme
  if (g_str_has_prefix(url, "leaf://flags") ||
      g_str_has_prefix(url, "leaf:flags")) {
    g_print("Loading leaf://flags configuration page\n");

    FlagsManager *flags_manager = get_global_flags_manager();
    if (flags_manager) {
      char *html = flags_manager_get_flags_html(flags_manager);
      if (html) {
        webkit_web_view_load_html(webview, html, "leaf://flags");
        g_free(html);
      } else {
        g_warning("Failed to generate flags HTML");
      }
    } else {
      g_warning("Flags manager not initialized");
    }
    return;
  }

  // Custom Homepage
  if (g_str_has_prefix(url, "leaf://newtab") ||
      g_strcmp0(url, "about:blank") == 0) {
    if (profile) {
      char *html = newtab_get_html(profile);
      if (html) {
        webkit_web_view_load_html(webview, html, "leaf://newtab");
        g_free(html);
        return;
      }
    }
    // Fallback
  }

  char *final_url = NULL;

  // Check if input is a valid URL
  if (is_valid_url(url)) {
    // It's a URL - add protocol if needed
    if (strstr(url, "://") == NULL && strncmp(url, "file://", 7) != 0) {
      final_url = g_strdup_printf("https://%s", url);
    } else {
      final_url = g_strdup(url);
    }
  } else {
    // It's a search query - get search engine preference
    char *search_engine = NULL;
    if (profile && profile->db) {
      search_engine = settings_get(profile->db, "search_engine");
    }

    // Generate search URL
    final_url = get_search_url(url, search_engine);

    if (search_engine)
      g_free(search_engine);
  }

  if (final_url) {
    webkit_web_view_load_uri(webview, final_url);
    g_free(final_url);
  }
}

void navigation_load_home(WebKitWebView *webview, Profile *profile) {
  char *home_page = NULL;

  // Get home page from settings
  if (profile && profile->db) {
    home_page = settings_get(profile->db, "home_page");
  }

  // Use default if not set or empty
  if (!home_page || strlen(home_page) == 0) {
    if (home_page)
      g_free(home_page);
    home_page = g_strdup(DEFAULT_HOME_PAGE);
  }

  navigation_load_url_with_profile(webview, home_page, profile);
  g_free(home_page);
}
