const crypto = require('crypto');
const blockService = require('./blockService');
const callbackService = require('./callbackService');
const chainTransactionService = require('./chainTransactionService');
const nodeParticipantService = require('./nodeParticipantService');
const proofLedgerService = require('./proofLedgerService');
const { COIN_CONFIG } = require('../config/coinConfig');

const TESTNET_CONFIG = Object.freeze({
  chainName: `${COIN_CONFIG.chainName} Testnet`,
  networkId: process.env.AISFOR_CHAIN_NETWORK_ID || 'plai-testnet-0',
  nativeSymbol: COIN_CONFIG.symbol,
  coinIssuance: 'disabled',
  coinIssuanceGuaranteed: false,
  rpcMode: 'mock-local-first',
  consensus: 'mock-proof-ledger-validator',
  blockTimeTargetSec: 15,
  genesisVersion: '0.1.0-testnet-preview',
  externalWallet: 'disabled',
  faucet: 'disabled'
});

function stableHash(payload) {
  return `0x${crypto.createHash('sha256').update(JSON.stringify(payload)).digest('hex')}`;
}

function getValidators() {
  return blockService.getEligibleValidators().map((node) => ({
    nodeId: node.nodeId,
    userIdHash: node.userIdHash || node.userId || '',
    displayName: node.deviceName || node.serviceName || node.nodeId,
    status: node.status,
    role: node.role,
    lockedPoint: node.lockedPoint || 0,
    proofSuccessRate: node.proofSuccessRate || 0,
    lastHeartbeatAt: node.lastHeartbeatAt || null
  }));
}

function getGenesisPreview() {
  const validators = getValidators();
  const payload = {
    chainName: TESTNET_CONFIG.chainName,
    networkId: TESTNET_CONFIG.networkId,
    nativeSymbol: TESTNET_CONFIG.nativeSymbol,
    coinIssuance: TESTNET_CONFIG.coinIssuance,
    genesisVersion: TESTNET_CONFIG.genesisVersion,
    validators: validators.map((validator) => ({
      nodeId: validator.nodeId,
      userIdHash: validator.userIdHash,
      lockedPoint: validator.lockedPoint
    }))
  };

  return {
    ...payload,
    genesisHash: stableHash(payload),
    createdAt: new Date().toISOString(),
    note: `Preview only. ${COIN_CONFIG.symbol} mock coin and internal wallet are enabled for testnet UI validation.`
  };
}

function countConfirmedCallbacks(callbacks) {
  return callbacks.filter((row) => {
    const status = String(row.status || '').toUpperCase();
    return status === 'DELIVERED' || status === 'MOCK_DELIVERED' || status === 'CONFIRMED';
  }).length;
}

function getReadiness() {
  const blockStats = blockService.getBlockStats();
  const chainVerify = blockService.verifyBlockChain();
  const callbacks = callbackService.listCallbacks();
  const proofs = proofLedgerService.listProofs();
  const transactions = chainTransactionService.listTransactions();
  const validators = getValidators();
  const serviceConfirmations = callbackService.getServiceConfirmationRows();

  const checks = [
    {
      key: 'coin_guardrail',
      label: 'Coin issuance is disabled',
      ok: TESTNET_CONFIG.coinIssuance === 'disabled',
      detail: `${COIN_CONFIG.symbol} symbol is reserved only. No public wallet, faucet, or exchange flow is active.`
    },
    {
      key: 'ledger_chain',
      label: 'Proof ledger chain verifies',
      ok: !!chainVerify.ok,
      detail: chainVerify.ok ? 'Proof ledger hash chain is valid.' : (chainVerify.error || 'Proof ledger hash chain needs attention.')
    },
    {
      key: 'validator_pool',
      label: 'Validator pool is available',
      ok: validators.length > 0,
      detail: `${validators.length} eligible validator node(s).`
    },
    {
      key: 'finalized_blocks',
      label: 'Mock blocks are finalized',
      ok: (blockStats.finalizedBlocks || 0) > 0,
      detail: `${blockStats.finalizedBlocks || 0} finalized block(s), latest height ${blockStats.latestHeight || 0}.`
    },
    {
      key: 'service_confirmations',
      label: 'Service confirmations are visible',
      ok: serviceConfirmations.some((row) => row.chainConfirmed),
      detail: `${serviceConfirmations.filter((row) => row.chainConfirmed).length}/${serviceConfirmations.length} service confirmation row(s).`
    },
    {
      key: 'callbacks',
      label: 'Confirmation callback flow works',
      ok: countConfirmedCallbacks(callbacks) > 0,
      detail: `${countConfirmedCallbacks(callbacks)}/${callbacks.length} callback(s) delivered.`
    },
    {
      key: 'proof_tx_flow',
      label: 'Proof and transaction flow exists',
      ok: proofs.length > 0 && transactions.length > 0,
      detail: `${proofs.length} proof(s), ${transactions.length} transaction(s).`
    }
  ];

  const passed = checks.filter((check) => check.ok).length;
  const score = Math.round((passed / checks.length) * 100);

  return {
    status: score === 100 ? 'ready_mock_testnet' : 'preparing_mock_testnet',
    score,
    passed,
    total: checks.length,
    checks
  };
}

function getStatus() {
  return {
    config: TESTNET_CONFIG,
    readiness: getReadiness(),
    genesis: getGenesisPreview(),
    validators: getValidators(),
    latestBlock: blockService.getLatestBlock(),
    blockStats: blockService.getBlockStats(),
    chainVerify: blockService.verifyBlockChain()
  };
}

module.exports = {
  TESTNET_CONFIG,
  getGenesisPreview,
  getReadiness,
  getStatus,
  getValidators
};
