import { ShadeSessionManager } from '../../packages/shade-core/src/index.js';
import { SubtleCryptoProvider, MemoryStorage } from '../../packages/shade-crypto-web/src/index.js';

const crypto = new SubtleCryptoProvider();

async function main() {
  console.log('=== Shade Identity Verification ===\n');

  // ─── The Real Bob ────────────────────────────────────
  const realBob = new ShadeSessionManager(crypto, new MemoryStorage());
  await realBob.initialize();

  console.log('Real Bob fingerprint:');
  console.log('  Full:  ', await realBob.getIdentityFingerprint());
  console.log('  Short: ', await realBob.getShortFingerprint());
  console.log();

  // ─── An Imposter ─────────────────────────────────────
  const evilBob = new ShadeSessionManager(crypto, new MemoryStorage());
  await evilBob.initialize();

  console.log('Evil Bob (imposter) fingerprint:');
  console.log('  Full:  ', await evilBob.getIdentityFingerprint());
  console.log('  Short: ', await evilBob.getShortFingerprint());
  console.log();

  console.log('━━━ The fingerprints are completely different ━━━');
  console.log('In a real scenario, Alice would call Real Bob on the phone,');
  console.log('read her safety number, and Real Bob would read his back.');
  console.log('If the numbers match, Alice can trust that her session');
  console.log('is talking to Real Bob and not Evil Bob.\n');

  // ─── Alice connects to (whoever) Bob is ────────────
  const alice = new ShadeSessionManager(crypto, new MemoryStorage());
  await alice.initialize();

  // Imagine the prekey server returns Real Bob's bundle
  const realBobOtpks = await realBob.generateOneTimePreKeys(5);
  const realBobBundle = await realBob.createPreKeyBundle();
  realBobBundle.oneTimePreKey = {
    keyId: realBobOtpks[0].keyId,
    publicKey: realBobOtpks[0].keyPair.publicKey,
  };

  await alice.initSessionFromBundle('bob', realBobBundle);

  // After establishing the session, Alice can verify the identity she received
  const realBobPub = realBob.getPublicIdentity();
  const evilBobPub = evilBob.getPublicIdentity();

  console.log('Alice verifies who she actually connected to:');
  console.log('  Is it Real Bob? ', await alice.verifyRemoteIdentity('bob', realBobPub.dhKey));
  console.log('  Is it Evil Bob? ', await alice.verifyRemoteIdentity('bob', evilBobPub.dhKey));
  console.log();

  // ─── Identity Change Scenario ─────────────────────────
  console.log('━━━ Bob legitimately rotates his identity ━━━');
  const newBundle = await realBob.rotateIdentity();
  console.log('New Bob fingerprint:', await realBob.getIdentityFingerprint());
  console.log();
  console.log('Alice fetches the new bundle and verifies it matches');
  console.log('expected new identity (after out-of-band confirmation).');

  // Alice would compare fingerprints again, then accept the change:
  await alice.acceptIdentityChange('bob', newBundle.identityDHKey);
  console.log('Alice accepted the new identity.');
  console.log();

  console.log('=== Done ===');
}

main().catch(console.error);
