const enc = new TextEncoder();
function b64uEnc(u: Uint8Array){return btoa(String.fromCharCode(...u)).replace(/\+/g,'-').replace(/\//g,'_').replace(/=+$/,'');}
function b64uDec(s:string){s=s.replace(/-/g,'+').replace(/_/g,'/');while(s.length%4)s+='=';return Uint8Array.from(atob(s),c=>c.charCodeAt(0));}
function hex(u:Uint8Array){return [...u].map(x=>x.toString(16).padStart(2,'0')).join('');}

// 5.1 Does WebCrypto ECDSA sign return raw r||s (P1363) or DER?
const kp = await crypto.subtle.generateKey({name:'ECDSA',namedCurve:'P-256'}, true, ['sign','verify']);
const msg = enc.encode("header.claims");
const sig = new Uint8Array(await crypto.subtle.sign({name:'ECDSA',hash:'SHA-256'}, kp.privateKey, msg));
console.log("ECDSA P-256 sig length =", sig.length);
console.log("first byte = 0x"+sig[0].toString(16), "(DER would start 0x30 and be ~70-72 bytes)");
console.log("VERDICT:", sig.length===64 ? "RAW r||s (P1363, JOSE ES256 ready)" : "NOT 64 bytes -> likely DER");
console.log("sig hex:", hex(sig));

// 5.2 exact repro of index.ts createPKCS8FromRaw path
function createPKCS8FromRaw(raw: Uint8Array): ArrayBuffer {
  const pkcs8Header = new Uint8Array([
    0x30,0x41,0x02,0x01,0x00,0x30,0x13,0x06,0x07,0x2a,0x86,0x48,0xce,0x3d,0x02,0x01,
    0x06,0x08,0x2a,0x86,0x48,0xce,0x3d,0x03,0x01,0x07,0x04,0x27,0x30,0x25,0x02,0x01,
    0x01,0x04,0x20]);
  const result = new Uint8Array(pkcs8Header.length + raw.length);
  result.set(pkcs8Header); result.set(raw, pkcs8Header.length);
  return result.buffer;
}
// generate a real key, export pkcs8 + jwk to get a real raw d
const kp2 = await crypto.subtle.generateKey({name:'ECDSA',namedCurve:'P-256'}, true, ['sign','verify']);
const jwk = await crypto.subtle.exportKey('jwk', kp2.privateKey) as JsonWebKey;
const d = b64uDec(jwk.d!);
console.log("\nraw d length =", d.length);
try {
  const k = await crypto.subtle.importKey('pkcs8', createPKCS8FromRaw(d), {name:'ECDSA',namedCurve:'P-256'}, false, ['sign']);
  const s2 = new Uint8Array(await crypto.subtle.sign({name:'ECDSA',hash:'SHA-256'}, k, msg));
  // verify against the real public key -> proves the pkcs8 wrapper produced the right key
  const okv = await crypto.subtle.verify({name:'ECDSA',hash:'SHA-256'}, kp2.publicKey, s2, msg);
  console.log("createPKCS8FromRaw importKey: OK, siglen", s2.length, "verify-with-real-pubkey:", okv);
} catch(e){ console.log("createPKCS8FromRaw importKey FAILED:", (e as Error).name, (e as Error).message); }

// 5.3 what does a real generated VAPID private key look like? web-push generateVAPIDKeys
console.log("\n-- what happens if VAPID_PRIVATE_KEY is a b64url 32-byte raw (web-push format) --");
const wpPriv = b64uEnc(d);
console.log("b64url(32B) length =", wpPriv.length, "(web-push generateVAPIDKeys privateKey len was 43)");
// index.ts does: rawKey = Uint8Array.from(atob(priv.replace(/-/g,'+').replace(/_/g,'/')), ...)  -- NOTE: no '=' padding added
try {
  const rawKey = Uint8Array.from(atob(wpPriv.replace(/-/g,'+').replace(/_/g,'/')), c=>c.charCodeAt(0));
  console.log("index.ts atob() without padding -> length", rawKey.length, "(expected 32)");
} catch(e){ console.log("index.ts atob() without padding THREW:", (e as Error).name, (e as Error).message); }
