/*
 * sabr-live-test.mjs — LIVE proof that driveSabr (the addon's SABR client,
 * includes/sabr_downloader.js) pulls real media from HARVESTED age-gated creds.
 *
 * sabr-drive-test.mjs proves the protocol against synthetic UMP (no network).
 * This proves the CREDS: it drives the real client against real googlevideo
 * with a bundle harvested in-browser, so —
 *   non-zero video+audio bytes => cookies + harvested poToken download
 *     age-restricted content with NO web-service and NO signature decryption.
 *   403 / 0 bytes / "session rejected" => the creds were not accepted.
 *
 * Usage:
 *   1. Paste tools/harvest-sabr-bundle.js into the youtube.com console (signed
 *      in), play the age-restricted video, copy the printed JSON to bundle.json
 *   2. node tools/sabr-live-test.mjs bundle.json [--full]
 *      Default stops after a few MB (enough to prove media flows); --full pulls
 *      the whole file. Writes video.bin / audio.bin next to the bundle.
 *
 * The signed URL expires (~6 h) and the poToken sooner — harvest and run promptly.
 */
import { readFileSync, writeFileSync } from 'node:fs';
import { dirname, join } from 'node:path';
import { driveSabr } from '../includes/sabr_downloader.js';

const bundlePath = process.argv[2];
const full = process.argv.includes('--full');
if (!bundlePath) { console.error('usage: node tools/sabr-live-test.mjs <bundle.json> [--full]'); process.exit(2); }

const b = JSON.parse(readFileSync(bundlePath, 'utf8'));
for (const k of ['serverAbrStreamingUrl', 'ustreamerConfig', 'poToken', 'video', 'audio']) {
  if (!b[k]) { console.error(`bundle missing "${k}"`); process.exit(2); }
}

console.log(`[live] video itag=${b.video.itag} lmt=${b.video.lastModified} xtags="${b.video.xtags}"`);
console.log(`[live] audio itag=${b.audio.itag} lmt=${b.audio.lastModified} xtags="${b.audio.xtags}"`);
const expire = +(b.serverAbrStreamingUrl.match(/[?&]expire=(\d+)/) || [])[1];
if (expire) {
  const minsLeft = Math.round((expire - Date.now() / 1000) / 60);
  console.log(`[live] signed URL expires in ${minsLeft} min`);
  if (minsLeft <= 0) console.warn('[live] WARNING: URL already past expiry — re-harvest for a valid test');
}

// WEB SABR clientInfo, mirroring background.js buildSabrJob (clientName 1 = WEB).
const clientInfo = { clientName: 1, clientVersion: b.cver || '2.20260529.01.00', osName: 'Windows', osVersion: '10.0' };

const out = { video: [], audio: [] };
let vBytes = 0, aBytes = 0;
const STOP_V = 3_000_000, STOP_A = 300_000; // "enough to prove media flows"
const DONE = Symbol('done');

// Node global fetch (undici). SABR auth is the signed URL + poToken in the body
// — no cookies/Origin needed here (the addon strips Origin via DNR; node never
// adds it).
const fetchFn = (url, init) => fetch(url, init);

let stoppedEarly = false;
try {
  await driveSabr({
    serverAbrStreamingUrl: b.serverAbrStreamingUrl,
    ustreamerConfig: b.ustreamerConfig,
    poToken: b.poToken,
    clientInfo,
    video: b.video,
    audio: b.audio,
    fetchFn,
    onChunk: (kind, bytes) => {
      out[kind].push(Buffer.from(bytes));
      if (kind === 'video') vBytes += bytes.length; else aBytes += bytes.length;
      if (!full && vBytes >= STOP_V && aBytes >= STOP_A) { stoppedEarly = true; throw DONE; }
    },
    onProgress: () => process.stdout.write(`\r[live] video=${(vBytes / 1e6).toFixed(2)}MB audio=${(aBytes / 1e6).toFixed(2)}MB   `)
  });
} catch (e) {
  if (e !== DONE) { process.stdout.write('\n'); console.error('[live] driveSabr error:', (e && e.message) || e); }
}
process.stdout.write('\n');

const dir = dirname(bundlePath);
writeFileSync(join(dir, 'video.bin'), Buffer.concat(out.video));
writeFileSync(join(dir, 'audio.bin'), Buffer.concat(out.audio));

console.log(`[live] RESULT: video=${vBytes} bytes, audio=${aBytes} bytes${stoppedEarly ? ' (stopped early — proof only; --full for whole file)' : ''}`);
console.log(`[live] wrote ${join(dir, 'video.bin')} + audio.bin`);
if (vBytes > 0 && aBytes > 0) {
  console.log('[live] ✅ MEDIA FLOWED — harvested creds drive a real age-gated SABR download (no web-service, no decipher).');
  process.exit(0);
} else {
  console.log('[live] ❌ no media — creds rejected (403 / dead session). See error above.');
  process.exit(1);
}
