const assert = require('assert');
const {
  appendBlock,
  chainSummary,
  createTransaction,
  initializeChain,
  selectBestChain,
  verifyLocalChain,
} = require('../src/lib/chain');

function makeState(label) {
  const state = {
    version: `chain-selection-${label}`,
    currentLayer: 1,
    currentStep: 1,
    gridSize: 20,
    solvedSteps: [],
    leaderboard: {},
  };
  state.chain = initializeChain(state, '2026-05-01T00:00:00.000Z');
  return state;
}

function solveBlock(state, workScore, solver) {
  return appendBlock(state, {
    producer: solver,
    createdAt: `2026-05-01T00:00:0${state.chain.blocks.length}.000Z`,
    transactions: [
      createTransaction({
        type: 'SOLVE_STEP',
        nonce: 0,
        createdAt: `2026-05-01T00:00:0${state.chain.blocks.length}.000Z`,
        payload: {
          layer_no: 1,
          step_no: state.chain.blocks.length,
          solver,
          answer_hash: `0x${solver}`,
          behavior_hash: `0x${solver}`,
          work_score: workScore,
        },
      }),
    ],
  });
}

function main() {
  const chainA = makeState('A');
  const chainB = makeState('B');
  const chainC = makeState('C');

  solveBlock(chainA, 100, 'solver-a');
  solveBlock(chainA, 100, 'solver-a');

  solveBlock(chainB, 250, 'solver-b');

  solveBlock(chainC, 100, 'solver-c');
  solveBlock(chainC, 100, 'solver-c');
  solveBlock(chainC, 100, 'solver-c');

  assert.strictEqual(verifyLocalChain(chainA.chain).ok, true);
  assert.strictEqual(verifyLocalChain(chainB.chain).ok, true);
  assert.strictEqual(verifyLocalChain(chainC.chain).ok, true);

  const best = selectBestChain([chainA.chain, chainB.chain, chainC.chain]);
  assert.strictEqual(best.head_hash, chainC.chain.head_hash);
  assert.strictEqual(chainSummary(best).cumulative_work_score, 300);

  const corrupted = JSON.parse(JSON.stringify(chainC.chain));
  corrupted.blocks[1].cumulative_work_score += 1;
  const corruptedResult = verifyLocalChain(corrupted);
  assert.strictEqual(corruptedResult.ok, false);
  assert.strictEqual(corruptedResult.code, 'CUMULATIVE_WORK_SCORE_MISMATCH');

  console.table(
    [chainA.chain, chainB.chain, chainC.chain].map((chain, index) => ({
      chain: ['A', 'B', 'C'][index],
      height: chain.height,
      cumulative_work_score: chainSummary(chain).cumulative_work_score,
      selected: chain.head_hash === best.head_hash,
    })),
  );
  console.log('Chain selection sample passed: highest cumulative work chain wins and forged cumulative work is rejected.');
}

main();
