// VERA Vault — Service Worker (Background Script)
// BBS+ Zero-Knowledge Proofs generated LOCALLY via WebAssembly
// No server-side API calls for proof generation

import { blsCreateProof } from "@mattrglobal/bbs-signatures";

console.log("🛡️ VERA Vault service worker loaded (WASM-powered)");

// ─── Helper Functions ─────────────────────────────────────────────────────────
// Browser-native encoding/decoding — NO Node.js Buffer used

function base64ToUint8Array(base64) {
  const binary = atob(base64);
  const bytes = new Uint8Array(binary.length);
  for (let i = 0; i < binary.length; i++) {
    bytes[i] = binary.charCodeAt(i);
  }
  return bytes;
}

function uint8ArrayToBase64(uint8Array) {
  let binary = "";
  for (let i = 0; i < uint8Array.length; i++) {
    binary += String.fromCharCode(uint8Array[i]);
  }
  return btoa(binary);
}

function hexToUint8Array(hex) {
  if (hex.startsWith("0x")) hex = hex.slice(2);
  const bytes = new Uint8Array(hex.length / 2);
  for (let i = 0; i < hex.length; i += 2) {
    bytes[i / 2] = parseInt(hex.substr(i, 2), 16);
  }
  return bytes;
}

// ─── Chrome Storage Functions ─────────────────────────────────────────────────

// Store a credential in chrome.storage.local
async function storeCredential(credentialData) {
  const result = await chrome.storage.local.get(["credentials"]);
  const credentials = result.credentials || [];
  credentials.push({
    ...credentialData,
    storedAt: new Date().toISOString(),
    id: `cred-${Date.now()}`,
  });
  await chrome.storage.local.set({ credentials });
  console.log(`[VERA BG] ✅ Credential stored. Total: ${credentials.length}`);

  // Update badge
  chrome.action.setBadgeText({ text: String(credentials.length) });
  chrome.action.setBadgeBackgroundColor({ color: "#4361ee" });
}

// Get all stored credentials
async function getCredentials() {
  const result = await chrome.storage.local.get(["credentials"]);
  return result.credentials || [];
}

// Find a credential matching storeID and itemSKU (returns the most recent one)
async function findCredential(storeID, itemSKU) {
  const credentials = await getCredentials();
  return credentials.reverse().find(
    (c) =>
      c.credential &&
      c.credential.credentialSubject &&
      c.credential.credentialSubject.storeID === storeID &&
      c.credential.credentialSubject.itemSKU === itemSKU
  );
}

// ─── LOCAL Proof Generation (BBS+ WASM) ───────────────────────────────────────

// Generate a selective disclosure proof LOCALLY using BBS+ WASM
// NO server API call — proof runs entirely in the extension's service worker
async function generateProof(request) {
  const { storeID, itemSKU, nonce } = request;

  // Find matching credential
  const credData = await findCredential(storeID, itemSKU);
  if (!credData) {
    throw new Error(`No credential found for Store: ${storeID}, Item: ${itemSKU}`);
  }

  console.log(`[VERA BG] Found credential, generating proof LOCALLY via WASM...`);
  console.log(`[VERA BG] Revealing: StoreID (0), ItemSKU (1)`);
  console.log(`[VERA BG] Hiding: InvoiceID (2), PurchaseTimestamp (3)`);

  // Decode credential components from base64
  const messages = credData.rawMessages.map((m) => {
    const binary = atob(m);
    const bytes = new Uint8Array(binary.length);
    for (let i = 0; i < binary.length; i++) {
      bytes[i] = binary.charCodeAt(i);
    }
    return bytes;
  });
  const signature = base64ToUint8Array(credData.signature);
  const publicKey = base64ToUint8Array(credData.publicKey);

  // Decode nonce from hex string
  const nonceBytes = hexToUint8Array(nonce);

  // Generate BBS+ proof LOCALLY — no server call!
  const proof = await blsCreateProof({
    signature,
    publicKey,
    messages,
    nonce: nonceBytes,
    revealed: [0, 1], // Reveal StoreID + ItemSKU only
  });

  console.log(`[VERA BG] Proof generated successfully (LOCAL WASM)`);

  // Track in verification history
  await addVerificationHistory(storeID, itemSKU, true);

  // Return base64-encoded proof and revealed messages
  return {
    proof: uint8ArrayToBase64(new Uint8Array(proof)),
    revealedMessages: [credData.rawMessages[0], credData.rawMessages[1]],
  };
}

// Track verification events in chrome.storage for the popup History view
async function addVerificationHistory(storeID, itemSKU, verified) {
  const result = await chrome.storage.local.get(["verificationHistory"]);
  const history = result.verificationHistory || [];
  history.push({
    storeID,
    itemSKU,
    verified,
    timestamp: new Date().toISOString(),
  });
  await chrome.storage.local.set({ verificationHistory: history });
}

// ─── Message Handling ─────────────────────────────────────────────────────────

// Handle messages from content script
chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
  console.log("[VERA BG] Received:", message.type);

  if (message.type === "STORE_CREDENTIAL") {
    storeCredential(message)
      .then(() => {
        sendResponse({ success: true, type: "CREDENTIAL_STORED" });
      })
      .catch((err) => {
        console.error("[VERA BG] Store error:", err);
        sendResponse({ success: false, type: "STORE_ERROR", error: err.message });
      });
    return true; // Keep channel open for async response
  }

  if (message.type === "GET_CREDENTIALS") {
    getCredentials().then((credentials) => {
      sendResponse({ type: "CREDENTIALS_LIST", credentials });
    });
    return true;
  }

  if (message.type === "GENERATE_PROOF") {
    generateProof(message)
      .then((result) => {
        sendResponse({ type: "PROOF_GENERATED", ...result });
      })
      .catch((err) => {
        console.error("[VERA BG] Proof error:", err);
        sendResponse({ type: "PROOF_ERROR", error: err.message });
      });
    return true;
  }

  if (message.type === "PING") {
    sendResponse({ status: "VERA_WALLET_ACTIVE", type: "PONG" });
    return true;
  }

  // ─── Extension Notifications (from content script) ──────────
  if (message.type === "SHOW_NOTIFICATION") {
    chrome.notifications.create({
      type: "basic",
      iconUrl: chrome.runtime.getURL("icons/48.png"),
      title: message.title || "VERA Vault",
      message: message.message || "",
      priority: message.isError ? 2 : 1,
    });
    sendResponse({ success: true });
    return true;
  }
});
