const fs = require('fs');
const path = require('path');
const { parseUnits } = require('ethers');
const { CANONICAL_ASSET_POLICY, LEGACY_ASSET_POLICY } = require('../config/assetPolicyConfig');
const {
  BASIS_POINTS,
  TOKEN_DISTRIBUTION_POLICY
} = require('../config/tokenDistributionConfig');

const genesisPath = path.join(__dirname, '..', 'runtime', 'plais-qbft', 'generated', 'genesis.json');

function normalizeSymbol(value) {
  return String(value || '').trim().toUpperCase();
}

function readGenesisAllocation() {
  const genesis = JSON.parse(fs.readFileSync(genesisPath, 'utf8'));
  const balances = Object.values(genesis.alloc || {}).map((entry) => BigInt(entry.balance || '0x0'));
  return {
    accountCount: balances.length,
    totalWei: balances.reduce((sum, value) => sum + value, 0n)
  };
}

function getStatus() {
  let allocation = { accountCount: 0, totalWei: 0n };
  let genesisError = '';
  try {
    allocation = readGenesisAllocation();
  } catch (error) {
    genesisError = error.message;
  }
  const expectedWei = parseUnits(
    String(CANONICAL_ASSET_POLICY.genesisSupply),
    CANONICAL_ASSET_POLICY.decimals
  );
  const distributionAllocationBps = TOKEN_DISTRIBUTION_POLICY.categories
    .reduce((sum, row) => sum + Number(row.allocationBps || 0), 0);
  const distributionTgeBps = TOKEN_DISTRIBUTION_POLICY.categories
    .reduce((sum, row) => sum + Number(row.tgeUnlockBps || 0), 0);
  const checks = [
    {
      key: 'canonical_asset_genesis_supply',
      ok: !genesisError && allocation.totalWei === expectedWei,
      detail: genesisError || `${allocation.accountCount} genesis allocation account(s); configured supply matches wei allocation.`
    },
    {
      key: 'canonical_asset_identity',
      ok: normalizeSymbol(CANONICAL_ASSET_POLICY.symbol) === normalizeSymbol(LEGACY_ASSET_POLICY.storedSymbol)
        && CANONICAL_ASSET_POLICY.decimals === 18,
      detail: `Canonical ${CANONICAL_ASSET_POLICY.symbol}/${CANONICAL_ASSET_POLICY.decimals}; legacy storage ${LEGACY_ASSET_POLICY.storedSymbol}/${LEGACY_ASSET_POLICY.decimals}.`
    },
    {
      key: 'legacy_point_separation',
      ok: LEGACY_ASSET_POLICY.role === 'legacy-application-point'
        && LEGACY_ASSET_POLICY.convertibleToCanonical === false
        && LEGACY_ASSET_POLICY.issuance === 'legacy-simulation-locked',
      detail: 'Legacy balances are application points, not canonical EVM coin balances, and conversion is disabled.'
    },
    {
      key: 'asset_policy_locks',
      ok: CANONICAL_ASSET_POLICY.publicIssuance === false
        && LEGACY_ASSET_POLICY.publicIssuance === 'disabled'
        && LEGACY_ASSET_POLICY.rewardMode === 'simulation'
        && LEGACY_ASSET_POLICY.resettable === false,
      detail: `Public issuance, legacy simulated rewards, and token reset are locked; canonical wallet external transfers are ${CANONICAL_ASSET_POLICY.externalTransfersEnabled ? 'enabled' : 'locked'}.`
    },
    {
      key: 'token_distribution_policy',
      ok: TOKEN_DISTRIBUTION_POLICY.supply === String(CANONICAL_ASSET_POLICY.genesisSupply)
        && TOKEN_DISTRIBUTION_POLICY.decimals === CANONICAL_ASSET_POLICY.decimals
        && distributionAllocationBps === BASIS_POINTS
        && distributionTgeBps === TOKEN_DISTRIBUTION_POLICY.tgeMaximumCirculationBps
        && TOKEN_DISTRIBUTION_POLICY.currentPublicCirculation === '0'
        && TOKEN_DISTRIBUTION_POLICY.publicIssuanceApproved === false
        && TOKEN_DISTRIBUTION_POLICY.externalTransfersEnabled === CANONICAL_ASSET_POLICY.externalTransfersEnabled,
      detail: `${TOKEN_DISTRIBUTION_POLICY.version}; ${distributionAllocationBps / 100}% allocated; TGE ceiling ${distributionTgeBps / 100}%; wallet transfer policy is ${TOKEN_DISTRIBUTION_POLICY.externalTransfersEnabled ? 'enabled' : 'locked'}.`
    }
  ];
  return {
    ok: checks.every((check) => check.ok),
    canonical: CANONICAL_ASSET_POLICY,
    legacy: LEGACY_ASSET_POLICY,
    distribution: TOKEN_DISTRIBUTION_POLICY,
    genesis: {
      allocationAccountCount: allocation.accountCount,
      allocationMatchesConfiguredSupply: !genesisError && allocation.totalWei === expectedWei
    },
    checks
  };
}

module.exports = { getStatus };
