const express = require('express');
const fs = require('fs');
const path = require('path');
const testnetService = require('../services/testnetService');
const walletService = require('../services/walletService');
const rewardLedgerService = require('../services/rewardLedgerService');
const nodeParticipantService = require('../services/nodeParticipantService');
const { COIN_CONFIG, toDisplayAmount } = require('../config/coinConfig');

const router = express.Router();

function formatNumber(value, fractionDigits = 2) {
  const number = Number(value || 0);
  if (!Number.isFinite(number)) return '0';
  return new Intl.NumberFormat('ko-KR', {
    maximumFractionDigits: fractionDigits
  }).format(number);
}

function getNetworkMode(status) {
  const explicitMode = String(process.env.AISFOR_CHAIN_PUBLIC_MODE || process.env.AISFOR_CHAIN_MODE || '').toLowerCase();
  if (explicitMode === 'mainnet' || explicitMode === 'testnet') return explicitMode;
  const networkId = String(status?.config?.networkId || '').toLowerCase();
  return networkId.includes('mainnet') ? 'mainnet' : 'testnet';
}

function buildRewardSummary() {
  const entries = rewardLedgerService.listEntries();
  const confirmed = entries.filter((entry) => {
    const blockHeight = Number(entry.ledgerBlockHeight || entry.blockHeight || 0);
    return blockHeight > 0;
  });
  const rows = confirmed.length ? confirmed : entries;
  const net = rows.reduce((sum, entry) => sum + Number(entry.rewardAmount || 0), 0);
  const positive = rows.reduce((sum, entry) => {
    const amount = Number(entry.rewardAmount || 0);
    return amount > 0 ? sum + amount : sum;
  }, 0);
  const negative = rows.reduce((sum, entry) => {
    const amount = Number(entry.rewardAmount || 0);
    return amount < 0 ? sum + amount : sum;
  }, 0);

  return {
    count: rows.length,
    net,
    positive,
    negative
  };
}

function buildHomeModel() {
  const status = testnetService.getStatus();
  const mode = getNetworkMode(status);
  const walletStats = walletService.getStats();
  const rewardSummary = buildRewardSummary();
  const nodes = nodeParticipantService.listNodes();
  const onlineNodes = nodes.filter((node) => ['active', 'online', 'warning'].includes(String(node.status || '').toLowerCase()));
  const readiness = status.readiness || {};
  const checks = Array.isArray(readiness.checks) ? readiness.checks : [];
  const latestBlock = status.latestBlock || {};
  const blockStats = status.blockStats || {};
  const chainOk = !!status.chainVerify?.ok;
  const supplyDisplay = toDisplayAmount(COIN_CONFIG.totalSupply || 0);

  return {
    mode,
    isMainnet: mode === 'mainnet',
    chainName: mode === 'mainnet' ? COIN_CONFIG.chainName : `${COIN_CONFIG.chainName} Testnet`,
    networkId: status.config?.networkId || '',
    symbol: COIN_CONFIG.symbol,
    addressPrefix: COIN_CONFIG.addressPrefix,
    totalSupply: formatNumber(supplyDisplay, 0),
    readinessScore: Number(readiness.score || 0),
    readinessLabel: readiness.score === 100 ? 'READY' : 'PREPARING',
    chainStatus: chainOk ? 'OK' : 'CHECK',
    latestHeight: blockStats.latestHeight || latestBlock.height || 0,
    finalizedBlocks: blockStats.finalizedBlocks || 0,
    walletCount: walletStats.totalWallets || walletStats.walletCount || 0,
    circulating: walletStats.totalBalance || walletStats.circulatingSupply || 0,
    validatorCount: status.validators?.length || 0,
    nodeCount: nodes.length,
    onlineNodeCount: onlineNodes.length,
    rewardSummary,
    checks: checks.slice(0, 7),
    validators: (status.validators || []).slice(0, 6),
    latestBlockHash: latestBlock.blockHash || latestBlock.hash || '',
    genesisHash: status.genesis?.genesisHash || '',
    updatedAt: new Date().toISOString(),
    formatNumber
  };
}

function getSourceManifest() {
  const manifestPath = path.join(__dirname, '..', 'public', 'source-release', 'manifest.json');
  try {
    const raw = fs.readFileSync(manifestPath, 'utf8').replace(/^\uFEFF/, '');
    return JSON.parse(raw);
  } catch (err) {
    return {
      ok: false,
      project: 'PLAI Chain',
      package: '',
      latest: 'plai-chain-source-latest.zip',
      generatedAt: '',
      sizeBytes: 0,
      sha256: '',
      excluded: {}
    };
  }
}

router.get('/', (req, res) => {
  res.render('home', buildHomeModel());
});

router.get('/status', (req, res) => {
  res.render('status', buildHomeModel());
});

router.get('/source', (req, res) => {
  res.render('source', {
    ...buildHomeModel(),
    sourceManifest: getSourceManifest()
  });
});

router.get('/listing', (req, res) => {
  res.render('listing', {
    ...buildHomeModel(),
    sourceManifest: getSourceManifest()
  });
});

router.get('/transparency', (req, res) => {
  res.redirect('/listing');
});

router.get('/listing-materials', (req, res) => {
  res.redirect('/listing');
});

router.get('/whitepaper', (req, res) => {
  res.sendFile(path.join(__dirname, '..', 'docs', 'WHITEPAPER.html'));
});

router.get('/whitepaper/ko', (req, res) => {
  res.sendFile(path.join(__dirname, '..', 'docs', 'WHITEPAPER_KO.html'));
});

router.get('/kr/whitepaper', (req, res) => {
  res.sendFile(path.join(__dirname, '..', 'docs', 'WHITEPAPER_KO.html'));
});

router.get('/en/whitepaper', (req, res) => {
  res.sendFile(path.join(__dirname, '..', 'docs', 'WHITEPAPER.html'));
});

router.get('/WHITEPAPER.html', (req, res) => {
  res.redirect('/whitepaper');
});

router.get('/WHITEPAPER_KO.html', (req, res) => {
  res.redirect('/whitepaper/ko');
});

router.get('/whitepaper.md', (req, res) => {
  res.type('text/markdown').sendFile(path.join(__dirname, '..', 'docs', 'WHITEPAPER.md'));
});

router.get('/WHITEPAPER.md', (req, res) => {
  res.redirect('/whitepaper.md');
});

module.exports = router;
