class NetworkMonitor {
  static DEFAULT_URL = "https://www.google.com/favicon.ico";
  static DEFAULT_TIMEOUT = 5000;

  /**
   * Fast browser-level connectivity signal
   * @returns {boolean}
   */
  static isBrowserOnline() {
    return typeof navigator !== "undefined" && navigator.onLine === true;
  }

  static isValidHttpUrl(url: string) {
    if (typeof url !== 'string' || url.length > 2048) return false;

    try {
      const parsed = new URL(url);

      if (parsed.protocol !== 'http:' && parsed.protocol !== 'https:') {
        return false;
      }

      // Optional: disallow credentials in URL
      if (parsed.username || parsed.password) {
        return false;
      }

      return true;
    } catch {
      return false;
    }
  }


  /**
   * Real internet connectivity check using fetch
   *
   * @param {Object} [options]
   * @param {string} [options.url] - Endpoint to ping
   * @param {number} [options.timeoutMs] - Timeout in milliseconds
   * @returns {Promise<boolean>}
   */
  static async hasInternetConnection(options: { url?: string | null, timeoutMs?: number | null } = { url: null, timeoutMs: null }) {
    var url = options.url || NetworkMonitor.DEFAULT_URL;
    const timeoutMs = options.timeoutMs || NetworkMonitor.DEFAULT_TIMEOUT;

    if (!NetworkMonitor.isBrowserOnline()) {
      return false;
    }

    if (!NetworkMonitor.isValidHttpUrl(url)) {
      url = NetworkMonitor.DEFAULT_URL;
    }

    const controller = new AbortController();
    const timeoutId = setTimeout(() => controller.abort(), timeoutMs);

    try {
      await fetch(url, {
        method: "HEAD",
        mode: "no-cors",
        cache: "no-cache",
        signal: controller.signal,
      });
      return true;
    } catch (e) {
      return false;
    } finally {
      clearTimeout(timeoutId);
    }
  }

  /**
   * Best possible signal for SDK consumers
   *
   * @param {Object} [options]
   * @returns {Promise<boolean>}
   */
  static async isOnline(options?: { url?: string | null; timeoutMs?: number | null; } | undefined) {
    return NetworkMonitor.hasInternetConnection(options);
  }
}

export default NetworkMonitor;
