const SC = (() => {
  async function genKeys() { return crypto.subtle.generateKey({name:'ECDH',namedCurve:'P-256'},true,['deriveKey']); }

  function bytesToB64(bytes) {
    let s = '';
    const chunk = 0x8000;
    for (let i = 0; i < bytes.length; i += chunk) s += String.fromCharCode(...bytes.subarray(i, i + chunk));
    return btoa(s);
  }
  function b64ToBytes(b64) { return Uint8Array.from(atob(b64), c => c.charCodeAt(0)); }

  async function exportPub(kp) { const r=await crypto.subtle.exportKey('spki',kp.publicKey); return bytesToB64(new Uint8Array(r)); }
  async function exportKeyPair(kp) {
    return {
      publicKey: await crypto.subtle.exportKey('jwk', kp.publicKey),
      privateKey: await crypto.subtle.exportKey('jwk', kp.privateKey)
    };
  }
  async function importKeyPair(jwk) {
    return {
      publicKey: await crypto.subtle.importKey('jwk', jwk.publicKey, {name:'ECDH',namedCurve:'P-256'}, true, []),
      privateKey: await crypto.subtle.importKey('jwk', jwk.privateKey, {name:'ECDH',namedCurve:'P-256'}, true, ['deriveKey'])
    };
  }
  async function importPub(b64) { const b=b64ToBytes(b64); return crypto.subtle.importKey('spki',b,{name:'ECDH',namedCurve:'P-256'},false,[]); }
  async function deriveKey(myPriv,theirPub) { return crypto.subtle.deriveKey({name:'ECDH',public:theirPub},myPriv,{name:'AES-GCM',length:256},false,['encrypt','decrypt']); }
  async function encrypt(key,txt) {
    const iv=crypto.getRandomValues(new Uint8Array(12));
    const c=await crypto.subtle.encrypt({name:'AES-GCM',iv},key,new TextEncoder().encode(txt));
    return {cipherText:bytesToB64(new Uint8Array(c)),iv:bytesToB64(iv)};
  }
  async function decrypt(key,ctB64,ivB64) {
    const c=b64ToBytes(ctB64);
    const iv=b64ToBytes(ivB64);
    const p=await crypto.subtle.decrypt({name:'AES-GCM',iv},key,c);
    return new TextDecoder().decode(p);
  }
  async function derivePasswordKey(username, password) {
    const salt = new TextEncoder().encode('SpaceshipKeyBackup:v1:' + String(username || '').toLowerCase());
    const base = await crypto.subtle.importKey('raw', new TextEncoder().encode(password), 'PBKDF2', false, ['deriveKey']);
    return crypto.subtle.deriveKey(
      {name:'PBKDF2', salt:salt, iterations:150000, hash:'SHA-256'},
      base,
      {name:'AES-GCM', length:256},
      false,
      ['encrypt','decrypt']
    );
  }
  async function encryptKeyPairBackup(username, password, kp) {
    const key = await derivePasswordKey(username, password);
    const iv = crypto.getRandomValues(new Uint8Array(12));
    const payload = JSON.stringify({v:1, keyPair: await exportKeyPair(kp)});
    const cipher = await crypto.subtle.encrypt({name:'AES-GCM', iv}, key, new TextEncoder().encode(payload));
    return {keyBackup: bytesToB64(new Uint8Array(cipher)), keyBackupIv: bytesToB64(iv)};
  }
  async function decryptKeyPairBackup(username, password, keyBackup, keyBackupIv) {
    const key = await derivePasswordKey(username, password);
    const cipher = b64ToBytes(keyBackup);
    const iv = b64ToBytes(keyBackupIv);
    const plain = await crypto.subtle.decrypt({name:'AES-GCM', iv}, key, cipher);
    const parsed = JSON.parse(new TextDecoder().decode(plain));
    if (!parsed || parsed.v !== 1 || !parsed.keyPair) throw new Error('Unsupported key backup');
    return importKeyPair(parsed.keyPair);
  }
  function hexPrev(b64,n=10){try{return Array.from(b64ToBytes(b64).slice(0,n)).map(b=>b.toString(16).padStart(2,'0')).join(' ')+'…';}catch{return '—';}}
  return {genKeys,exportPub,exportKeyPair,importKeyPair,importPub,deriveKey,encrypt,decrypt,encryptKeyPairBackup,decryptKeyPairBackup,hexPrev};
})();
