const fs = require('fs');
const {
  BASE1_DATA_PATH,
  getBase1BlocksSince,
  getCurrentBase1Public,
  loadBase1State,
  makeCandidateFromOfficial,
  resetBase1State,
  saveBase1State,
  snapshotBase1State,
  submitBase1Blocks,
  submitBase1Candidate,
  verifyBase1Chain,
} = require('../src/lib/base1_state');

function candidateForCurrentStep() {
  const state = loadBase1State();
  return makeCandidateFromOfficial(state.officialStepsByKey[state.currentStepKey]);
}

function solveOne(solver) {
  const result = submitBase1Candidate({
    solver,
    candidateStep: candidateForCurrentStep(),
    expectedHead: getCurrentBase1Public().latest_head_guard,
  });
  if (!result.correct) throw new Error(`Solve failed: ${result.code || result.message}`);
  return result;
}

function main() {
  const hadState = fs.existsSync(BASE1_DATA_PATH);
  const backup = hadState ? fs.readFileSync(BASE1_DATA_PATH, 'utf8') : null;

  try {
    resetBase1State();
    const base = snapshotBase1State();

    solveOne('block-sync-node-a');
    const nodeA = snapshotBase1State();

    saveBase1State(base.state);
    const before = verifyBase1Chain();
    const missing = getBase1BlocksSince({
      afterHeight: before.height,
      afterHash: before.head_hash,
      limit: 10,
    });

    saveBase1State(base.state);
    const accepted = submitBase1Blocks({
      blocks: nodeA.state.chain.blocks.slice(1),
      source: 'node-a-blocks',
    });
    if (!accepted.ok || accepted.accepted_count !== 2 || accepted.status !== 'adopted_by_replay') {
      throw new Error(`Expected verified block-only sync, got ${accepted.status || accepted.code}`);
    }

    console.table([
      {
        phase: 'node-b before',
        height: before.height,
        work: before.cumulative_work_score,
        head: before.head_hash.slice(0, 16),
      },
      {
        phase: 'node-a exported blocks',
        height: nodeA.summary.height,
        work: nodeA.summary.cumulative_work_score,
        head: nodeA.summary.head_hash.slice(0, 16),
      },
      {
        phase: 'blocks replayed on node-b',
        height: accepted.candidate_chain.height,
        work: accepted.candidate_chain.cumulative_work_score,
        head: accepted.candidate_chain.head_hash.slice(0, 16),
      },
      {
        phase: 'blocks-since local sample',
        height: missing.blocks.length,
        work: missing.chain.cumulative_work_score,
        head: missing.chain.head_hash.slice(0, 16),
      },
    ]);
  } finally {
    if (hadState) {
      fs.writeFileSync(BASE1_DATA_PATH, backup, 'utf8');
    } else if (fs.existsSync(BASE1_DATA_PATH)) {
      fs.unlinkSync(BASE1_DATA_PATH);
    }
  }
}

main();
