'use strict';

const assert = require('assert');
const crypto = require('crypto');
const fs = require('fs');
const os = require('os');
const path = require('path');
const { sha256FileStream } = require('E:\\aisfor\\services\\distributedStorageService');
const { sha256File } = require('E:\\aisfor\\services\\fileIntegrityService');

(async () => {
  const root = fs.mkdtempSync(path.join(os.tmpdir(), 'plai-streaming-hash-'));
  const filePath = path.join(root, 'synthetic-64m.bin');
  const block = crypto.createHash('sha256').update('plai-streaming-hash-self-test').digest();
  const chunk = Buffer.alloc(1024 * 1024);
  for (let offset = 0; offset < chunk.length; offset += block.length) block.copy(chunk, offset);
  const expected = crypto.createHash('sha256');
  const handle = fs.openSync(filePath, 'wx');
  try {
    for (let index = 0; index < 64; index += 1) {
      fs.writeSync(handle, chunk);
      expected.update(chunk);
    }
  } finally {
    fs.closeSync(handle);
  }

  let eventLoopTicks = 0;
  const timer = setInterval(() => { eventLoopTicks += 1; }, 1);
  let actual = '';
  try {
    actual = await sha256FileStream(filePath);
  } finally {
    clearInterval(timer);
  }
  const expectedHash = expected.digest('hex');
  assert.equal(actual, expectedHash);
  assert.equal(sha256File(filePath), expectedHash);
  assert(eventLoopTicks > 0, 'streaming hash must yield to the event loop');
  assert.equal(await sha256FileStream(path.join(root, 'missing.bin')), '');

  fs.rmSync(root, { recursive: true, force: true });
  console.log(JSON.stringify({
    ok: true,
    schemaVersion: 'plai-network-worker-streaming-hash-self-test/v1',
    syntheticBytes: 64 * 1024 * 1024,
    hashVerified: true,
    boundedSyncHashVerified: true,
    eventLoopYielded: true,
    missingFileFailClosed: true,
    temporaryDataDeleted: true,
    productionChanged: false
  }, null, 2));
})().catch(error => {
  console.error(error);
  process.exit(1);
});
