const REGIONS = {
  nyc: { url: "https://us.slotshark.xyz", label: "New York" },
  fra: { url: "https://eu.slotshark.xyz", label: "Frankfurt" },
};
const DEFAULT_REGION = "nyc";

async function getRegionConfig() {
  const data = await chrome.storage.local.get(["slotshark.region", "apiKey"]);
  const region = data["slotshark.region"] || DEFAULT_REGION;
  const apiKeyName = `slotshark.apiKey.${region}`;
  const keyData = await chrome.storage.local.get([apiKeyName]);
  const apiKey = keyData[apiKeyName] || (region === "nyc" ? data.apiKey : null);
  return {
    region,
    serverUrl: REGIONS[region]?.url || REGIONS[DEFAULT_REGION].url,
    apiKey,
  };
}

// 30s ping keeps the HTTPS connection to the server warm (under nginx's 75s
// keepalive_timeout). The long-lived port below prevents MV3 SW sleep so the
// interval actually fires. chrome.alarms deliberately avoided — extra permission.
let _warmupInterval = null;
let _lastPingAt = 0;
const _axiomTabs = new Set();

async function pingServer() {
  try {
    _lastPingAt = Date.now();
    const { serverUrl } = await getRegionConfig();
    fetch(serverUrl + "/ping", { method: "GET" }).catch(() => {});
  } catch {}
}

function pingIfStale() {
  if (Date.now() - _lastPingAt > 20_000) pingServer();
}

function startWarmup() {
  if (_warmupInterval) return;
  pingServer();
  _warmupInterval = setInterval(pingServer, 30_000);
}

function stopWarmup() {
  if (_warmupInterval) {
    clearInterval(_warmupInterval);
    _warmupInterval = null;
  }
}

chrome.tabs.onUpdated.addListener((tabId, changeInfo, tab) => {
  if (tab.url && tab.url.includes("axiom.trade")) {
    if (!_axiomTabs.has(tabId)) {
      _axiomTabs.add(tabId);
      startWarmup();
    }
  } else if (_axiomTabs.has(tabId)) {
    _axiomTabs.delete(tabId);
    if (_axiomTabs.size === 0) stopWarmup();
  }
});

chrome.tabs.onRemoved.addListener((tabId) => {
  if (_axiomTabs.has(tabId)) {
    _axiomTabs.delete(tabId);
    if (_axiomTabs.size === 0) stopWarmup();
  }
});

chrome.tabs.onActivated.addListener(({ tabId }) => {
  if (_axiomTabs.has(tabId)) pingIfStale();
});

chrome.webNavigation.onCompleted.addListener(
  (details) => { if (details.frameId === 0) pingIfStale(); },
  { url: [{ hostEquals: "axiom.trade" }] }
);

chrome.tabs.query({ url: "*://axiom.trade/*" }, (tabs) => {
  for (const tab of tabs) _axiomTabs.add(tab.id);
  if (_axiomTabs.size > 0) startWarmup();
});

chrome.webNavigation.onHistoryStateUpdated.addListener(
  (details) => {
    chrome.tabs.sendMessage(details.tabId, {
      type: "SPA_NAVIGATE",
      url: details.url,
    }).catch(() => {});
  },
  { url: [{ hostEquals: "axiom.trade" }] }
);

const _keepaliveports = new Set();
chrome.runtime.onConnect.addListener((port) => {
  if (port.name !== "slotshark-keepalive") return;
  _keepaliveports.add(port);
  if (_warmupInterval === null) startWarmup();
  port.onDisconnect.addListener(() => { _keepaliveports.delete(port); });
});

chrome.runtime.onMessage.addListener((message, _sender, sendResponse) => {
  if (message.type === "OPEN_SETTINGS") {
    chrome.tabs.create({ url: chrome.runtime.getURL(`settings.html#${message.hash || ""}`) });
    return false;
  }

  if (message.type === "API_CALL") {
    (async () => {
      try {
        const { serverUrl, apiKey } = await getRegionConfig();

        const url = `${serverUrl}${message.path}`;
        const headers = { "Content-Type": "application/json" };
        if (apiKey) headers["Authorization"] = `Bearer ${apiKey}`;

        const opts = { method: message.method || "GET", headers };
        if (message.body && opts.method !== "GET") {
          opts.body = JSON.stringify(message.body);
        }

        const res = await fetch(url, opts);
        const data = await res.json();
        sendResponse({ status: res.status, data });
      } catch (err) {
        sendResponse({ error: err.message || "Network error" });
      }
    })();

    return true;
  }

  if (message.type === "API_BATCH") {
    (async () => {
      try {
        const { serverUrl, apiKey } = await getRegionConfig();
        const headers = { "Content-Type": "application/json" };
        if (apiKey) headers["Authorization"] = `Bearer ${apiKey}`;

        const results = await Promise.all(
          message.calls.map(async (call) => {
            try {
              const url = `${serverUrl}${call.path}`;
              const opts = { method: call.method || "GET", headers };
              if (call.body && opts.method !== "GET") {
                opts.body = JSON.stringify(call.body);
              }
              const res = await fetch(url, opts);
              const data = await res.json();
              return { status: res.status, data };
            } catch (err) {
              return { error: err.message || "Network error" };
            }
          })
        );

        sendResponse({ results });
      } catch (err) {
        sendResponse({ error: err.message || "Batch error" });
      }
    })();

    return true;
  }

  return false;
});
