(() => {
  const PAGE_SOURCE = "ADDC_AUTODARTS_PAGE_WEBSOCKET_HOOK";
  const CONTENT_SOURCE = "ADDC_AUTODARTS_CONTENT";
  let lastMatchUrl = "";
  let mainWorldInjectionRequested = false;

  window.addEventListener("message", (event) => {
    if (event.source !== window || event.origin !== "https://play.autodarts.io") return;
    const data = event.data || {};
    if (data.source !== PAGE_SOURCE || data.target !== CONTENT_SOURCE) return;

    if (data.type === "WEBSOCKET_DETECTED" && typeof data.websocketUrl === "string") {
      const matchPageUrl = stringField(data.matchPageUrl) || window.location.href;
      const match = detectMatch(matchPageUrl);
      const metadata = websocketUrlMetadata(data.websocketUrl);
      console.info("content script received websocketUrl", metadata);
      chrome.runtime.sendMessage({
        source: CONTENT_SOURCE,
        type: "socket_detected",
        websocketUrl: data.websocketUrl,
        hasWebSocketUrl: true,
        websocketUrlLength: metadata.websocketUrlLength,
        websocketUrlHashPrefix: metadata.websocketUrlHashPrefix,
        pageMirrorAttached: data.pageMirrorAttached === true,
        mirrorAttachedCount: Number.isFinite(data.mirrorAttachedCount) ? data.mirrorAttachedCount : 0,
        matchId: match?.matchId || "",
        matchUrl: match?.matchUrl || matchPageUrl,
        pageUrl: window.location.href
      });
    }

    if (data.type === "WEBSOCKET_URL_CAPTURED") {
      chrome.runtime.sendMessage({
        source: CONTENT_SOURCE,
        type: "WEBSOCKET_URL_CAPTURED",
        matchUrl: window.location.href
      });
    }

    if (data.type === "PAGE_MIRROR_ATTACHED") {
      const matchPageUrl = stringField(data.matchPageUrl) || window.location.href;
      const match = detectMatch(matchPageUrl);
      chrome.runtime.sendMessage({
        source: CONTENT_SOURCE,
        type: "PAGE_MIRROR_ATTACHED",
        matchId: match?.matchId || "",
        matchUrl: match?.matchUrl || matchPageUrl,
        mirrorAttachedCount: Number.isFinite(data.mirrorAttachedCount) ? data.mirrorAttachedCount : 0,
        pageUrl: window.location.href
      });
    }

    if (data.type === "PAGE_MIRROR_ATTACH_FAILED") {
      chrome.runtime.sendMessage({
        source: CONTENT_SOURCE,
        type: "PAGE_MIRROR_ATTACH_FAILED",
        matchUrl: window.location.href,
        error: stringField(data.error) || "Page mirror attach failed"
      });
    }

    if (data.type === "WEBSOCKET_MESSAGE") {
      const matchPageUrl = stringField(data.matchPageUrl) || window.location.href;
      const match = detectMatch(matchPageUrl);
      chrome.runtime.sendMessage({
        source: CONTENT_SOURCE,
        type: "WEBSOCKET_MESSAGE",
        matchId: match?.matchId || "",
        matchUrl: match?.matchUrl || matchPageUrl,
        frameType: stringField(data.frameType) || "unknown",
        payloadText: typeof data.payloadText === "string" ? data.payloadText : "",
        payloadBase64: typeof data.payloadBase64 === "string" ? data.payloadBase64 : "",
        byteLength: Number.isFinite(data.byteLength) ? data.byteLength : 0,
        payloadHashPrefix: stringField(data.payloadHashPrefix),
        decodeError: stringField(data.decodeError),
        mirrorMessageCount: Number.isFinite(data.mirrorMessageCount) ? data.mirrorMessageCount : 0,
        pageUrl: window.location.href
      });
    }

    if (data.type === "WEBSOCKET_OPEN" || data.type === "WEBSOCKET_CLOSE" || data.type === "WEBSOCKET_ERROR") {
      const matchPageUrl = stringField(data.matchPageUrl) || window.location.href;
      const match = detectMatch(matchPageUrl);
      chrome.runtime.sendMessage({
        source: CONTENT_SOURCE,
        type: data.type,
        matchId: match?.matchId || "",
        matchUrl: match?.matchUrl || matchPageUrl,
        closeCode: Number.isFinite(data.closeCode) ? data.closeCode : null,
        closeReasonLength: Number.isFinite(data.closeReasonLength) ? data.closeReasonLength : 0,
        pageUrl: window.location.href
      });
    }

    if (data.type === "PAGE_HOOK_INJECTED") {
      chrome.runtime.sendMessage({
        source: CONTENT_SOURCE,
        type: "PAGE_HOOK_INJECTED",
        matchUrl: window.location.href,
        method: data.method || "page"
      });
    }

    if (data.type === "WEBSOCKET_CONSTRUCTOR_HOOKED") {
      chrome.runtime.sendMessage({
        source: CONTENT_SOURCE,
        type: "WEBSOCKET_CONSTRUCTOR_HOOKED",
        matchUrl: window.location.href,
        hookedConstructors: data.hookedConstructors || []
      });
    }

    if (data.type === "WEBSOCKET_RECONNECT_DETECTION") {
      chrome.runtime.sendMessage({
        source: CONTENT_SOURCE,
        type: "WEBSOCKET_RECONNECT_DETECTION",
        matchUrl: window.location.href,
        reason: stringField(data.reason) || "Socket may have opened before hook."
      });
    }

    if (data.type === "PAGE_HOOK_ERROR") {
      chrome.runtime.sendMessage({
        source: CONTENT_SOURCE,
        type: "PAGE_HOOK_ERROR",
        error: stringField(data.error) || "Page hook injection failed"
      });
    }
  });

  requestMainWorldHook();
  setTimeout(injectPageHookFallback, 60);
  observeUrlChanges();

  function requestMainWorldHook() {
    if (mainWorldInjectionRequested) return;
    mainWorldInjectionRequested = true;
    chrome.runtime.sendMessage({
      source: CONTENT_SOURCE,
      type: "INJECT_MAIN_WORLD_HOOK"
    }, (response) => {
      if (chrome.runtime.lastError || response?.ok === false) {
        injectPageHookFallback();
      }
    });
  }

  function injectPageHookFallback() {
    if (document.getElementById("addc-autodarts-websocket-hook")) return;
    const script = document.createElement("script");
    script.id = "addc-autodarts-websocket-hook";
    script.src = chrome.runtime.getURL("src/page-websocket-hook.js");
    script.onload = () => script.remove();
    script.onerror = () => {
      chrome.runtime.sendMessage({
        source: CONTENT_SOURCE,
        type: "PAGE_HOOK_ERROR",
        error: "Page hook injection failed"
      });
      script.remove();
    };
    (document.documentElement || document.head || document.body).appendChild(script);
  }

  function observeUrlChanges() {
    notifyMatchIfPresent("initial");
    window.addEventListener("hashchange", () => notifyMatchIfPresent("hashchange"));
    window.addEventListener("popstate", () => notifyMatchIfPresent("popstate"));
    setInterval(() => notifyMatchIfPresent("poll"), 1000);
  }

  function notifyMatchIfPresent(source) {
    const match = detectMatch(window.location.href);
    if (!match || match.matchUrl === lastMatchUrl) return;
    lastMatchUrl = match.matchUrl;
    chrome.runtime.sendMessage({
      source: CONTENT_SOURCE,
      type: "MATCH_DETECTED",
      sourceEvent: source,
      matchId: match.matchId,
      matchUrl: match.matchUrl
    });
  }

  function detectMatch(rawUrl) {
    try {
      const url = new URL(rawUrl);
      if (url.host !== "play.autodarts.io") return null;

      const candidates = [url.href, url.pathname, url.search, url.hash];
      for (const candidate of candidates) {
        const match = String(candidate).match(/(?:^|[/?#&=])matches\/([0-9A-Za-z][0-9A-Za-z_-]{7,})/i);
        if (match?.[1]) {
          return {
            matchId: match[1],
            matchUrl: `https://play.autodarts.io/matches/${match[1]}`
          };
        }
      }
    } catch {}
    return null;
  }

  function stringField(value) {
    return typeof value === "string" ? value.trim() : "";
  }

  function websocketUrlMetadata(value) {
    const text = stringField(value);
    return {
      websocketUrlPresent: Boolean(text),
      websocketUrlLength: text.length,
      websocketUrlHashPrefix: safeHashPrefix(text)
    };
  }

  function safeHashPrefix(value) {
    let hash = 2166136261;
    for (let index = 0; index < value.length; index += 1) {
      hash ^= value.charCodeAt(index);
      hash = Math.imul(hash, 16777619);
    }
    return (hash >>> 0).toString(16).padStart(8, "0").slice(0, 8);
  }
})();
