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

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

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

  try {
    resetBase1State();

    const firstPublic = getCurrentBase1Public();
    const firstHead = firstPublic.latest_head_guard;
    const firstAccepted = submitBase1Candidate({
      solver: 'head-guard-a',
      candidateStep: candidateForCurrentStep(),
      expectedHead: firstHead,
    });
    if (!firstAccepted.correct) throw new Error(`Expected first submit to pass: ${firstAccepted.code || firstAccepted.message}`);

    const staleRejected = submitBase1Candidate({
      solver: 'head-guard-b',
      candidateStep: candidateForCurrentStep(),
      expectedHead: firstHead,
    });
    if (staleRejected.code !== 'STALE_PARENT_BLOCK') {
      throw new Error(`Expected stale submit to be rejected, got ${staleRejected.code || staleRejected.message}`);
    }

    const secondPublic = getCurrentBase1Public();
    const secondAccepted = submitBase1Candidate({
      solver: 'head-guard-c',
      candidateStep: candidateForCurrentStep(),
      expectedHead: secondPublic.latest_head_guard,
    });
    if (!secondAccepted.correct) throw new Error(`Expected refreshed submit to pass: ${secondAccepted.code || secondAccepted.message}`);

    const chain = verifyBase1Chain();
    if (!chain.ok) throw new Error(`Chain verification failed: ${chain.code}`);

    console.table([
      {
        case: 'first submit on latest head',
        result: firstAccepted.correct,
        solve_block: firstAccepted.solve_block.height,
        parent: firstAccepted.solved.parent_block_hash.slice(0, 16),
      },
      {
        case: 'stale submit with old head',
        result: staleRejected.code,
        mismatches: staleRejected.mismatches.join(','),
        latest_height: staleRejected.latest_head.height,
      },
      {
        case: 'refreshed submit on new head',
        result: secondAccepted.correct,
        solve_block: secondAccepted.solve_block.height,
        parent: secondAccepted.solved.parent_block_hash.slice(0, 16),
      },
      {
        case: 'chain verify',
        result: chain.ok,
        height: chain.height,
        cumulative_work_score: chain.cumulative_work_score,
      },
    ]);
  } finally {
    if (hadState) {
      fs.writeFileSync(BASE1_DATA_PATH, backup, 'utf8');
    } else if (fs.existsSync(BASE1_DATA_PATH)) {
      fs.unlinkSync(BASE1_DATA_PATH);
    }
  }
}

main();
