/**
 * OmniFlow - Background Service Worker (Manifest V3)
 * Handles proxy configuration lifecycle, WebRTC leak blocking, and quiet background proxy authentication.
 * ENFORCED SAFE MODE: Always runs in Proxy Mode. Uses IP Leak Lock if proxy is unconfigured.
 */

// Cached proxy credentials in memory for synchronous access during onAuthRequired challenges
let activeProxyConfig = null;
let activeRelayConnection = null;

// Initialize settings on service worker startup
async function init() {
  await setDipclawReady({ status: "starting", source: "dipclaw" });
  try {
    globalThis.OMNI_FLOW_BOOTSTRAP_CONFIG = await loadDipclawBootstrapConfig();
    const bootstrap = getDipclawBootstrap();
    if (bootstrap && bootstrap.sessionFile) {
      await importDipclawSession(bootstrap);
      await maybeAutoConnectRelay();
      return;
    }

    // Enforced Safe Mode: proxyEnabled is implicitly true. Without a
    // Dipclaw-provided session file, use whatever OmniFlow already has in
    // extension storage; a fresh profile falls back to IP Leak Lock.
    let data = await storageGet([
      'proxyConfig',
      'timezoneEnabled',
      'spoofTimezone',
      'webrtcDisabled',
      'languagesEnabled',
      'hardwareMaskingEnabled',
      'antiBotEnabled'
    ]);
    data = await applyDipclawBootstrap(data);
    activeProxyConfig = data.proxyConfig || null;
    await applyProxySettings(activeProxyConfig);

    // Default WebRTC protection to enabled (true)
    const blockWebRTC = data.webrtcDisabled !== false;
    await applyWebRTCSettings(blockWebRTC);
    await setDipclawReady({
      status: "ready",
      source: "dipclaw",
      sessionHash: null,
      cookieCount: 0,
      importedAt: new Date().toISOString()
    });
    await maybeAutoConnectRelay();
  } catch (err) {
    const message = err && err.message ? err.message : String(err);
    console.log("OmniFlow: Dipclaw bootstrap failed:", message);
    await setDipclawReady({
      status: "error",
      source: "dipclaw",
      error: message,
      importedAt: new Date().toISOString()
    });
    await maybeAutoConnectRelay().catch(() => {});
  }
}

// Listen for storage changes from the popup UI
chrome.storage.onChanged.addListener((changes, area) => {
  if (area === 'local') {
    let proxyConfigChanged = 'proxyConfig' in changes;
    let webrtcChanged = 'webrtcDisabled' in changes;

    if (proxyConfigChanged) {
      chrome.storage.local.get(['proxyConfig'], (data) => {
        activeProxyConfig = data.proxyConfig || null;
        void applyProxySettings(activeProxyConfig);
      });
    }

    if (webrtcChanged) {
      void applyWebRTCSettings(changes.webrtcDisabled.newValue);
    }
  }
});

/**
 * Load the dp-worker/dipclaw-generated bootstrap config.
 *
 * Read via fetch with `cache: "no-store"` rather than `importScripts`: Chrome
 * caches importScripts'd resources per extension origin in the persistent
 * profile, so a bootstrap dp-worker regenerates on a later launch (e.g. once a
 * session is uploaded) would be ignored — the service worker would keep running
 * the first launch's stale config and never import the session. A no-store fetch
 * always reads the freshly written file. Returns null when no bootstrap is
 * present (non-dipclaw / manual extension use).
 */
async function loadDipclawBootstrapConfig() {
  try {
    const res = await fetch(chrome.runtime.getURL("dipclaw-config.json"), {
      cache: "no-store",
    });
    if (!res.ok) return null;
    return await res.json();
  } catch (err) {
    return null;
  }
}

function getDipclawBootstrap() {
  const bootstrap = globalThis.OMNI_FLOW_BOOTSTRAP_CONFIG;
  if (!bootstrap || bootstrap.source !== "dipclaw") {
    return null;
  }
  return bootstrap;
}

async function applyDipclawBootstrap(data) {
  const bootstrap = getDipclawBootstrap();
  if (!bootstrap) {
    return data;
  }

  const next = { ...data };
  const writes = {};
  const removals = [];

  if ("proxyConfig" in bootstrap) {
    if (bootstrap.proxyConfig && bootstrap.proxyConfig.host && bootstrap.proxyConfig.port) {
      next.proxyConfig = bootstrap.proxyConfig;
      writes.proxyConfig = bootstrap.proxyConfig;
    } else {
      delete next.proxyConfig;
      removals.push("proxyConfig");
    }
  }

  for (const key of [
    "timezoneEnabled",
    "spoofTimezone",
    "webrtcDisabled",
    "languagesEnabled",
    "hardwareMaskingEnabled",
    "antiBotEnabled"
  ]) {
    if (key in bootstrap) {
      next[key] = bootstrap[key];
      writes[key] = bootstrap[key];
    }
  }

  if (Object.keys(writes).length > 0) {
    await storageSet(writes);
  }
  if (removals.length > 0) {
    await storageRemove(removals);
  }

  return next;
}

async function importDipclawSession(bootstrap) {
  await setDipclawReady({
    status: "importing",
    source: "dipclaw",
    sessionHash: bootstrap.expectedSessionHash || null
  });

  const { payload, raw, hash } = await loadSessionPayload(bootstrap.sessionFile);
  if (bootstrap.expectedSessionHash && hash !== bootstrap.expectedSessionHash) {
    throw new Error(
      `session hash mismatch: expected ${bootstrap.expectedSessionHash}, got ${hash}`
    );
  }

  await clearAllCookies();
  await storageClear();

  const importedStorage = sanitizeImportedStorage(payload.extensionStorage);
  await storageSet(importedStorage);
  await setCookies(payload.cookies);

  activeProxyConfig = importedStorage.proxyConfig || null;
  await applyProxySettings(activeProxyConfig);
  await applyWebRTCSettings(importedStorage.webrtcDisabled !== false);

  await setDipclawReady({
    status: "ready",
    source: "dipclaw",
    sessionHash: hash,
    expectedSessionHash: bootstrap.expectedSessionHash || null,
    cookieCount: payload.cookies.length,
    importedAt: new Date().toISOString()
  });
}

async function loadSessionPayload(filename) {
  const url = chrome.runtime.getURL(filename);
  const res = await fetch(url, { cache: "no-store" });
  if (!res.ok) {
    throw new Error(`failed to read bundled session ${filename}: ${res.status}`);
  }
  const raw = await res.text();
  const hash = await sha256Hex(raw);
  let payload;
  try {
    payload = JSON.parse(raw);
  } catch (err) {
    throw new Error("bundled OmniFlow session is not valid JSON");
  }
  validateSessionPayload(payload);
  return { payload, raw, hash };
}

function validateSessionPayload(payload) {
  if (!payload || payload.app !== "OmniFlow") {
    throw new Error("bundled session is not an OmniFlow export");
  }
  if (!payload.extensionStorage || typeof payload.extensionStorage !== "object") {
    throw new Error("bundled session is missing extensionStorage");
  }
  if (!Array.isArray(payload.cookies)) {
    throw new Error("bundled session cookies must be an array");
  }
}

function sanitizeImportedStorage(storage) {
  const next = { ...storage };
  delete next.formDraft;
  delete next.dipclawReady;
  delete next.standaloneWindowId;
  return next;
}

async function clearAllCookies() {
  const allCookies = await cookiesGetAll({});
  await Promise.all(allCookies.map((cookie) => removeCookieSafe(cookie)));
}

async function setCookies(cookies) {
  await Promise.all(cookies.map((cookie) => setCookieSafe(cookie)));
}

async function removeCookieSafe(cookie) {
  try {
    await cookieRemove({
      url: cookieUrl(cookie),
      name: cookie.name,
      ...(cookie.storeId ? { storeId: cookie.storeId } : {})
    });
  } catch (err) {
    // Some browser/system cookies cannot be removed by extensions. Keep
    // import best-effort, matching the manual popup importer behavior.
  }
}

async function setCookieSafe(cookie) {
  try {
    const setDetails = {
      url: cookieUrl(cookie),
      name: cookie.name,
      value: cookie.value,
      domain: cookie.domain,
      path: cookie.path || "/",
      secure: cookie.secure,
      httpOnly: cookie.httpOnly,
      sameSite: cookie.sameSite,
      expirationDate: cookie.expirationDate,
      ...(cookie.storeId ? { storeId: cookie.storeId } : {})
    };

    if (cookie.session || !cookie.expirationDate) {
      delete setDetails.expirationDate;
    }

    await cookieSet(setDetails);
  } catch (err) {
    const message = err && err.message ? err.message : String(err);
    console.log("OmniFlow Cookie Restorer:", message);
  }
}

function cookieUrl(cookie) {
  const domainName = String(cookie.domain || "").replace(/^\./, "");
  const protocol = cookie.secure ? "https://" : "http://";
  const path = cookie.path || "/";
  return protocol + domainName + path;
}

function storageGet(keys) {
  return new Promise((resolve) => {
    chrome.storage.local.get(keys, (data) => resolve(data || {}));
  });
}

function storageSet(values) {
  return new Promise((resolve, reject) => {
    chrome.storage.local.set(values, () => {
      if (chrome.runtime.lastError) reject(new Error(chrome.runtime.lastError.message));
      else resolve();
    });
  });
}

function storageRemove(keys) {
  return new Promise((resolve, reject) => {
    chrome.storage.local.remove(keys, () => {
      if (chrome.runtime.lastError) reject(new Error(chrome.runtime.lastError.message));
      else resolve();
    });
  });
}

function storageClear() {
  return new Promise((resolve, reject) => {
    chrome.storage.local.clear(() => {
      if (chrome.runtime.lastError) reject(new Error(chrome.runtime.lastError.message));
      else resolve();
    });
  });
}

function cookiesGetAll(details) {
  return new Promise((resolve, reject) => {
    chrome.cookies.getAll(details, (cookies) => {
      if (chrome.runtime.lastError) reject(new Error(chrome.runtime.lastError.message));
      else resolve(cookies || []);
    });
  });
}

function cookieRemove(details) {
  return new Promise((resolve, reject) => {
    chrome.cookies.remove(details, () => {
      if (chrome.runtime.lastError) reject(new Error(chrome.runtime.lastError.message));
      else resolve();
    });
  });
}

function cookieSet(details) {
  return new Promise((resolve, reject) => {
    chrome.cookies.set(details, (cookie) => {
      if (chrome.runtime.lastError) reject(new Error(chrome.runtime.lastError.message));
      else resolve(cookie);
    });
  });
}

async function setDipclawReady(state) {
  globalThis.OMNI_FLOW_READY_STATE = state;
  try {
    await storageSet({ dipclawReady: state });
  } catch (err) {
    // The in-memory state is enough for dp-worker's startup waiter. Storage
    // is only a secondary observable for diagnostics.
  }
}

async function sha256Hex(text) {
  const bytes = new TextEncoder().encode(text);
  const hash = await crypto.subtle.digest("SHA-256", bytes);
  return Array.from(new Uint8Array(hash))
    .map((b) => b.toString(16).padStart(2, "0"))
    .join("");
}

/**
 * Apply proxy settings. If unconfigured, deploy "IP Leak Lock" dummy proxy to prevent domestic IP leak!
 * @param {Object} config 
 */
function applyProxySettings(config) {
  if (!config || !config.host || !config.port) {
    const leakLockRules = {
      mode: "fixed_servers",
      rules: {
        singleProxy: {
          scheme: "http",
          host: "127.0.0.1",
          port: 65535 // Refused port to completely lock network access
        },
        bypassList: [
          "localhost", 
          "127.0.0.1", 
          "<local>", 
          "ipinfo.io", 
          "*.ipinfo.io", 
          "ipapi.co", 
          "*.ipapi.co", 
          "ip-api.com", 
          "*.ip-api.com",
          "freeipapi.com",
          "*.freeipapi.com",
          "api.ip.sb",
          "*.api.ip.sb"
        ]
      }
    };
    return new Promise((resolve, reject) => {
      chrome.proxy.settings.set(
        { value: leakLockRules, scope: 'regular' },
        () => {
          if (chrome.runtime.lastError) {
            reject(new Error(chrome.runtime.lastError.message));
            return;
          }
          console.log("OmniFlow: [IP LEAK LOCK ACTIVE] Proxy is unconfigured. Raw internet access blocked to prevent IP leaks.");
          resolve();
        }
      );
    });
  }

  // Create fixed servers proxy rule
  const proxyRules = {
    mode: "fixed_servers",
    rules: {
      singleProxy: {
        scheme: config.type.toLowerCase(), // 'socks5' or 'http'
        host: config.host,
        port: parseInt(config.port, 10)
      },
      bypassList: ["localhost", "127.0.0.1", "<local>"]
    }
  };

  return new Promise((resolve, reject) => {
    chrome.proxy.settings.set(
      { value: proxyRules, scope: 'regular' },
      () => {
        if (chrome.runtime.lastError) {
          reject(new Error(chrome.runtime.lastError.message));
          return;
        }
        console.log(`OmniFlow: Proxy enabled. Mode: ${config.type}, Server: ${config.host}:${config.port}`);
        resolve();
      }
    );
  });
}

/**
 * Configure WebRTC IP handling policy to block raw local/public IP leaks
 * @param {boolean} block 
 */
function applyWebRTCSettings(block) {
  if (chrome.privacy && chrome.privacy.network && chrome.privacy.network.webRTCIPHandlingPolicy) {
    const policy = block ? 'disable_non_proxied_udp' : 'default';
    return new Promise((resolve, reject) => {
      chrome.privacy.network.webRTCIPHandlingPolicy.set({ value: policy }, () => {
        if (chrome.runtime.lastError) {
          reject(new Error(chrome.runtime.lastError.message));
          return;
        }
        console.log(`OmniFlow: WebRTC Leak Protection set to -> ${policy}`);
        resolve();
      });
    });
  }
  return Promise.resolve();
}

/**
 * Silent proxy authentication using the webRequest API
 */
chrome.webRequest.onAuthRequired.addListener(
  (details) => {
    if (details.isProxy) {
      if (activeProxyConfig && activeProxyConfig.username && activeProxyConfig.password) {
        console.log("OmniFlow: Automatically authenticating proxy connection.");
        return {
          authCredentials: {
            username: activeProxyConfig.username,
            password: activeProxyConfig.password
          }
        };
      }
    }
    return {};
  },
  { urls: ["<all_urls>"] },
  ["blocking"]
);

async function maybeAutoConnectRelay() {
  const bootstrap = getDipclawBootstrap();
  if (!bootstrap || !bootstrap.relay || bootstrap.relay.autoConnect === false) {
    return null;
  }
  return await connectDipclawRelay(bootstrap.relay);
}

async function connectDipclawRelay(relayConfig) {
  const endpoint = normalizeRelayEndpoint(
    relayConfig && relayConfig.extensionWebSocketUrl,
    relayConfig && relayConfig.token
  );
  if (
    activeRelayConnection &&
    activeRelayConnection.endpoint === endpoint &&
    activeRelayConnection.isOpen()
  ) {
    return activeRelayConnection.status();
  }
  if (activeRelayConnection) {
    activeRelayConnection.close();
  }
  const connection = new DipclawRelayConnection(endpoint);
  activeRelayConnection = connection;
  await connection.connect();
  return connection.status();
}

function normalizeRelayEndpoint(rawEndpoint, token) {
  if (!rawEndpoint || typeof rawEndpoint !== "string") {
    throw new Error("relay endpoint is required");
  }
  const url = new URL(rawEndpoint);
  if (url.protocol !== "ws:") {
    throw new Error("relay endpoint must use ws://");
  }
  const host = url.hostname.replace(/^\[/, "").replace(/\]$/, "");
  if (!["127.0.0.1", "localhost", "::1"].includes(host)) {
    throw new Error("relay endpoint must be loopback-only");
  }
  if (token) {
    if (url.searchParams.has("token") && url.searchParams.get("token") !== token) {
      throw new Error("relay token mismatch");
    }
    url.searchParams.set("token", token);
  }
  return url.toString();
}

class DipclawRelayConnection {
  constructor(endpoint) {
    this.endpoint = endpoint;
    this.ws = null;
    this.connectedAt = null;
  }

  connect() {
    return new Promise((resolve, reject) => {
      const ws = new WebSocket(this.endpoint);
      let settled = false;
      this.ws = ws;

      const finish = (fn, value) => {
        if (settled) return;
        settled = true;
        fn(value);
      };

      ws.onopen = async () => {
        this.connectedAt = new Date().toISOString();
        try {
          await this.sendInitialState();
          finish(resolve, undefined);
        } catch (err) {
          finish(reject, err);
        }
      };
      ws.onerror = () => {
        finish(reject, new Error("failed to connect relay websocket"));
      };
      ws.onclose = () => {
        if (activeRelayConnection === this) {
          activeRelayConnection = null;
        }
      };
      ws.onmessage = (event) => {
        void this.handleMessage(event.data);
      };
    });
  }

  isOpen() {
    return this.ws && this.ws.readyState === WebSocket.OPEN;
  }

  status() {
    return {
      connected: this.isOpen(),
      endpoint: this.endpoint,
      connectedAt: this.connectedAt
    };
  }

  close() {
    if (this.ws && this.ws.readyState <= WebSocket.OPEN) {
      this.ws.close(1000, "replaced");
    }
    this.ws = null;
  }

  async sendInitialState() {
    const tabs = await chrome.tabs.query({});
    const targets = await chrome.debugger.getTargets();
    for (const tab of tabs) {
      if (isRelayTab(tab)) {
        this.sendEvent("chrome.tabs.onCreated", [sanitizeTab(tab)]);
      }
    }
    this.sendEvent("extension.initialized", [{
      extensionId: chrome.runtime.id,
      readyState: globalThis.OMNI_FLOW_READY_STATE || null,
      targets
    }]);
  }

  async handleMessage(raw) {
    let message;
    try {
      message = JSON.parse(String(raw));
    } catch (err) {
      return;
    }
    if (!message || typeof message.id !== "number" || typeof message.method !== "string") {
      return;
    }
    try {
      const result = await handleRelayCommand(message.method, message.params || []);
      this.send({ id: message.id, result: result === undefined ? {} : result });
    } catch (err) {
      this.send({
        id: message.id,
        error: {
          message: err && err.message ? err.message : String(err)
        }
      });
    }
  }

  sendEvent(method, params) {
    this.send({ method, params });
  }

  send(payload) {
    if (this.isOpen()) {
      this.ws.send(JSON.stringify(payload));
    }
  }
}

async function handleRelayCommand(method, params) {
  switch (method) {
    case "chrome.debugger.attach":
      await chrome.debugger.attach(params[0], params[1] || "1.3");
      return {};
    case "chrome.debugger.detach":
      await chrome.debugger.detach(params[0]);
      return {};
    case "chrome.debugger.sendCommand":
      return await chrome.debugger.sendCommand(params[0], params[1], params[2] || {});
    case "chrome.debugger.getTargets":
      return await chrome.debugger.getTargets();
    case "chrome.tabs.create":
      return sanitizeTab(await chrome.tabs.create(params[0] || {}));
    case "chrome.tabs.update":
      return sanitizeTab(await chrome.tabs.update(params[0], params[1] || {}));
    case "chrome.tabs.remove":
      await chrome.tabs.remove(params[0]);
      return {};
    case "chrome.tabs.query":
      return (await chrome.tabs.query(params[0] || {})).filter(isRelayTab).map(sanitizeTab);
    default:
      throw new Error(`unsupported relay command: ${method}`);
  }
}

function sanitizeTab(tab) {
  if (!tab) return tab;
  return {
    id: tab.id,
    index: tab.index,
    windowId: tab.windowId,
    openerTabId: tab.openerTabId,
    active: tab.active,
    title: tab.title || "",
    url: tab.url || "about:blank"
  };
}

function isRelayTab(tab) {
  if (!tab || typeof tab.id !== "number") return false;
  const url = tab.url || tab.pendingUrl || "about:blank";
  return !(
    url.startsWith("chrome://") ||
    url.startsWith("chrome-extension://") ||
    url.startsWith("devtools://")
  );
}

function sendRelayEvent(method, params) {
  if (activeRelayConnection && activeRelayConnection.isOpen()) {
    activeRelayConnection.sendEvent(method, params);
  }
}

chrome.tabs.onCreated.addListener((tab) => {
  if (isRelayTab(tab)) {
    sendRelayEvent("chrome.tabs.onCreated", [sanitizeTab(tab)]);
  }
});

chrome.tabs.onUpdated.addListener((tabId, changeInfo, tab) => {
  if (isRelayTab(tab)) {
    sendRelayEvent("chrome.tabs.onUpdated", [tabId, changeInfo, sanitizeTab(tab)]);
  }
});

chrome.tabs.onRemoved.addListener((tabId, removeInfo) => {
  sendRelayEvent("chrome.tabs.onRemoved", [tabId, removeInfo || {}]);
});

chrome.debugger.onEvent.addListener((source, method, params) => {
  sendRelayEvent("chrome.debugger.onEvent", [source, method, params || {}]);
});

chrome.debugger.onDetach.addListener((source, reason) => {
  sendRelayEvent("chrome.debugger.onDetach", [source, reason]);
});

function applyStealthConfigToSender(sender, config, sendResponse) {
  if (!sender || !sender.tab || typeof sender.tab.id !== "number") {
    sendResponse({ ok: false, error: "missing sender tab" });
    return;
  }
  const target = { tabId: sender.tab.id };
  if (typeof sender.frameId === "number") {
    target.frameIds = [sender.frameId];
  }
  chrome.scripting.executeScript({
    target,
    world: "MAIN",
    injectImmediately: true,
    func: (stealthConfig) => {
      Object.defineProperty(globalThis, "__OMNI_FLOW_STEALTH_CONFIG__", {
        value: stealthConfig,
        configurable: true
      });
    },
    args: [config || {}]
  }, () => {
    if (chrome.runtime.lastError) {
      sendResponse({ ok: false, error: chrome.runtime.lastError.message });
      return;
    }
    chrome.scripting.executeScript({
      target,
      world: "MAIN",
      injectImmediately: true,
      files: ["inject.js"]
    }, () => {
      if (chrome.runtime.lastError) {
        sendResponse({ ok: false, error: chrome.runtime.lastError.message });
        return;
      }
      sendResponse({ ok: true });
    });
  });
}

// Call initialization
init();

// ============================================================================
// Standalone Window Front-Focus Manager (Stealth Recall UX) - Persistent State Machine
// ============================================================================

// 1. Initial State Alignment on Service Worker Startup / Browser Restarts:
// Bypasses the MV3 service worker "memory loss" bug by auditing the persistent storage.
chrome.storage.local.get(['standaloneWindowId'], (data) => {
  const winId = data.standaloneWindowId;
  if (winId) {
    chrome.windows.get(winId, (win) => {
      if (chrome.runtime.lastError || !win) {
        // The standalone window was closed while the background worker was asleep or browser restarted
        chrome.storage.local.remove(['standaloneWindowId'], () => {
          chrome.action.setPopup({ popup: "popup.html" }); // Re-enable default dropdown popup
          console.log("OmniFlow Startup: Standalone window not found. Restored default popup.");
        });
      } else {
        // Window exists! Keep the popup cleared so clicking the icon fires action onClicked
        chrome.action.setPopup({ popup: "" });
        console.log("OmniFlow Startup: Standalone window is active. Front-focus trigger enabled.");
      }
    });
  } else {
    chrome.action.setPopup({ popup: "popup.html" });
  }
});

// 2. Listen for standalone window registration message
chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
  if (message && message.action === "dipclaw:getReady") {
    sendResponse(globalThis.OMNI_FLOW_READY_STATE || null);
    return false;
  }

  if (message && message.action === "dipclaw:applyStealth") {
    applyStealthConfigToSender(sender, message.config || {}, sendResponse);
    return true;
  }

  if (message && message.action === "dipclaw:relayConnect") {
    connectDipclawRelay(message.relay || {})
      .then((status) => sendResponse({ ok: true, status }))
      .catch((err) => sendResponse({
        ok: false,
        error: err && err.message ? err.message : String(err)
      }));
    return true;
  }

  if (message && message.action === "dipclaw:relayStatus") {
    sendResponse({
      ok: true,
      status: activeRelayConnection
        ? activeRelayConnection.status()
        : { connected: false }
    });
    return false;
  }

  if (message && message.action === "registerStandaloneWindow") {
    const targetWinId = message.windowId;
    chrome.storage.local.set({ standaloneWindowId: targetWinId }, () => {
      // Clear default popup action so clicking the extension toolbar icon fires onClicked event!
      chrome.action.setPopup({ popup: "" });
      console.log("OmniFlow: Standalone window registered & persisted:", targetWinId);
    });
  }
  return false;
});

// 3. Watch for standalone window close to restore normal dropdown popup behavior
chrome.windows.onRemoved.addListener((windowId) => {
  chrome.storage.local.get(['standaloneWindowId'], (data) => {
    if (data.standaloneWindowId === windowId) {
      chrome.storage.local.remove(['standaloneWindowId'], () => {
        chrome.action.setPopup({ popup: "popup.html" }); // Re-enable default dropdown popup
        console.log("OmniFlow: Standalone window closed. Restored default popup.");
      });
    }
  });
});

// 4. Bring existing standalone window instantly to the front if toolbar icon is clicked!
chrome.action.onClicked.addListener((tab) => {
  chrome.storage.local.get(['standaloneWindowId'], (data) => {
    const targetWinId = data.standaloneWindowId;
    if (targetWinId) {
      chrome.windows.update(targetWinId, { focused: true }, () => {
        if (chrome.runtime.lastError) {
          // Safe recovery if the window was closed silently without background capturing it
          chrome.storage.local.remove(['standaloneWindowId'], () => {
            chrome.action.setPopup({ popup: "popup.html" });
          });
        }
      });
    } else {
      // Safe fallback recovery if we catch a click event but no window exists
      chrome.action.setPopup({ popup: "popup.html" });
    }
  });
});
