const assert = require('assert');
const fs = require('fs');
const path = require('path');

const ROOT = path.resolve(__dirname, '..');
const sampleDir = path.join(ROOT, 'data', 'confidential-storage-sample');
fs.rmSync(sampleDir, { recursive: true, force: true });
fs.mkdirSync(sampleDir, { recursive: true });

process.env.MAZEX_DATA_DIR = sampleDir;
process.env.MAZEX_SHARDED_STORAGE = '1';
process.env.MAZEX_SHARDED_STORAGE_READ = '1';

const {
  getBase1PrivateVaultStatus,
  getBase1StorageStatus,
  getCurrentBase1Public,
  loadBase1State,
  makeCandidateFromOfficial,
  resetBase1State,
  sampleBase1Point,
  snapshotBase1State,
  submitBase1Candidate,
} = require('../src/lib/base1_state');

function walkFiles(dir) {
  if (!fs.existsSync(dir)) return [];
  const out = [];
  for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
    const p = path.join(dir, entry.name);
    if (entry.isDirectory()) out.push(...walkFiles(p));
    else out.push(p);
  }
  return out;
}

function readAllText(dir) {
  return walkFiles(dir)
    .map((file) => fs.readFileSync(file, 'utf8'))
    .join('\n');
}

function currentCandidate() {
  const state = loadBase1State();
  const step = state.officialStepsByKey[state.currentStepKey];
  assert(step, 'Current official Step must be hydrated from private vault');
  return makeCandidateFromOfficial(step);
}

function assertPublicTextIsClean(text, label) {
  const forbidden = [
    '"officialStepsByKey":{"',
    '"seedSourcesByKey":{"',
    '"commitmentsByKey":{"',
    '"seasonSeed"',
    '"season_seed"',
    '"step_seed"',
    '"operator_units":',
    '"trees":',
  ];
  for (const token of forbidden) {
    assert.strictEqual(text.includes(token), false, `${label} leaked ${token}`);
  }
}

function main() {
  resetBase1State();
  const accepted = submitBase1Candidate({
    solver: 'confidential-solver',
    candidateStep: currentCandidate(),
    expectedHead: getCurrentBase1Public().latest_head_guard,
    chargeFee: true,
  });
  assert.strictEqual(accepted.correct, true);

  const sample = sampleBase1Point({ userId: 'confidential-solver', x: 3, y: 7 });
  assert(Number.isInteger(sample.u));
  assert(Number.isInteger(sample.v));

  const publicStorage = getBase1StorageStatus();
  const privateVault = getBase1PrivateVaultStatus();
  assert.strictEqual(publicStorage.exists, true);
  assert.strictEqual(privateVault.exists, true);
  assert.strictEqual(privateVault.current_exists, true);
  assert(privateVault.step_record_count >= 1);

  const publicText = readAllText(publicStorage.root);
  assertPublicTextIsClean(publicText, 'public sharded storage');

  const publicSnapshot = snapshotBase1State(loadBase1State(), { includePrivate: false });
  const publicSnapshotText = JSON.stringify(publicSnapshot);
  assertPublicTextIsClean(publicSnapshotText, 'public snapshot');
  assert.strictEqual(Object.keys(publicSnapshot.state.officialStepsByKey || {}).length, 0);
  assert.strictEqual(Object.keys(publicSnapshot.state.seedSourcesByKey || {}).length, 0);
  assert.strictEqual(Boolean(publicSnapshot.state.seasonSeed), false);

  const hydrated = loadBase1State();
  assert(hydrated.officialStepsByKey[hydrated.currentStepKey]);
  assert(hydrated.seedSourcesByKey[hydrated.currentStepKey]);
  assert(hydrated.seasonSeed);

  console.log(
    JSON.stringify(
      {
        status: 'pass',
        public_root: publicStorage.root,
        private_root: privateVault.root,
        private_step_records: privateVault.step_record_count,
        public_block_count: publicStorage.block_count,
        public_bytes: publicStorage.bytes.total,
        checked: [
          'public latest sanitized',
          'public snapshots sanitized',
          'private vault hydrates verifier state',
          'sampling still works after hydration',
        ],
      },
      null,
      2,
    ),
  );
}

main();
