require('../config/loadEnv')();

const crypto = require('crypto');
const fs = require('fs');
const path = require('path');
const { computeAddress } = require('ethers');

const projectRoot = path.join(__dirname, '..');
const activeRoot = path.join(projectRoot, 'runtime', 'plais-qbft');
const migrationRoot = path.join(projectRoot, 'runtime', 'plais-qbft-canonical-migration');
const templatePath = path.join(projectRoot, 'config', 'qbftCanonicalMigration.example.json');
const topologyPath = path.join(migrationRoot, 'topology.json');

function sha256File(filePath) {
  return crypto.createHash('sha256').update(fs.readFileSync(filePath)).digest('hex');
}

function readPublicKey(nodeName) {
  return fs.readFileSync(path.join(activeRoot, nodeName, 'data', 'key.pub'), 'utf8')
    .trim().replace(/^0x/, '').replace(/^04/, '').toLowerCase();
}

function main() {
  if (fs.existsSync(topologyPath)) {
    throw new Error(`Canonical migration topology already exists: ${topologyPath}`);
  }
  const networkPath = path.join(activeRoot, 'network.json');
  const genesisPath = path.join(activeRoot, 'generated', 'genesis.json');
  for (const required of [templatePath, networkPath, genesisPath]) {
    if (!fs.existsSync(required)) throw new Error(`Required canonical file is missing: ${required}`);
  }

  const template = JSON.parse(fs.readFileSync(templatePath, 'utf8'));
  const network = JSON.parse(fs.readFileSync(networkPath, 'utf8'));
  const activeValidators = (network.nodes || []).filter((node) => node.role === 'validator');
  if (network.consensus !== 'QBFT' || activeValidators.length !== 4) {
    throw new Error('Active canonical network must be the four-validator QBFT network.');
  }
  if (Number(template.chainId) !== Number(network.chainId)) {
    throw new Error('Migration template chain ID does not match the active canonical network.');
  }

  const validators = template.validators.map((entry) => {
    const active = activeValidators.find((node) => node.name === entry.nodeName);
    if (!active) throw new Error(`Unknown active validator: ${entry.nodeName}`);
    const publicKey = readPublicKey(active.name);
    const derivedAddress = computeAddress(`0x04${publicKey}`).toLowerCase();
    if (derivedAddress !== String(active.address).toLowerCase()) {
      throw new Error(`Public key identity mismatch for ${active.name}.`);
    }
    return {
      ...entry,
      validatorAddress: derivedAddress,
      publicKey,
      currentP2pPort: Number(active.p2pPort)
    };
  });

  const topology = {
    ...template,
    state: 'AWAITING_PRIVATE_NETWORK_ADDRESSES',
    networkName: 'PLAI Chain canonical QBFT host migration',
    consensus: 'QBFT',
    genesisSha256: sha256File(genesisPath),
    initializedAt: new Date().toISOString(),
    validators
  };
  fs.mkdirSync(migrationRoot, { recursive: true });
  fs.writeFileSync(topologyPath, `${JSON.stringify(topology, null, 2)}\n`);
  console.log(JSON.stringify({
    ok: true,
    state: topology.state,
    mode: topology.mode,
    chainId: topology.chainId,
    validatorCount: validators.length,
    topologyPath
  }, null, 2));
}

try { main(); } catch (error) { console.error(error.message); process.exit(1); }
