const express = require('express');
const walletService = require('../services/walletService');
const { requireServiceAuth } = require('../middleware/serviceAuth');

const router = express.Router();

function publicRecovery(recovery) {
  if (!recovery) return null;
  return {
    enabled: !!recovery.enabled,
    version: recovery.version || null,
    algorithm: recovery.algorithm || null,
    kdf: recovery.kdf || null,
    encryptedPrivateKeyStored: !!recovery.encryptedPrivateKeyStored,
    recoveryConfirmedAt: recovery.recoveryConfirmedAt || null,
    restoredAt: recovery.restoredAt || null,
    createdAt: recovery.createdAt || null,
    updatedAt: recovery.updatedAt || null
  };
}
function publicWallet(wallet) {
  if (!wallet) return null;
  const metadata = { ...(wallet.metadata || {}) };
  delete metadata.pinHash;
  delete metadata.recoveryVault;
  return {
    id: wallet.id,
    address: wallet.address,
    label: wallet.label,
    ownerType: wallet.ownerType,
    ownerId: wallet.ownerId,
    publicKey: wallet.publicKey,
    balance: wallet.balance,
    lockedBalance: wallet.lockedBalance,
    rewardBalance: wallet.rewardBalance,
    nonce: wallet.nonce,
    status: wallet.status,
    metadata,
    pinEnabled: walletService.walletHasPin(wallet.address),
    recovery: publicRecovery(walletService.getWalletRecoveryStatus(wallet)),
    createdAt: wallet.createdAt,
    updatedAt: wallet.updatedAt
  };
}

function publicWallets(wallets) {
  return (wallets || []).map(publicWallet).filter(Boolean);
}

function sendWalletError(res, error, fallback = 'WALLET_ERROR') {
  return res.status(error.status || 400).json({
    ok: false,
    error: error.code || fallback,
    message: error.message || fallback
  });
}

router.get('/', (req, res) => {
  res.json({
    ok: true,
    stats: walletService.getStats(),
    wallets: publicWallets(walletService.listWallets())
  });
});

router.post('/', (req, res, next) => {
  try {
    const wallet = walletService.createWallet(req.body || {});
    res.status(201).json({ ok: true, wallet: publicWallet(wallet) });
  } catch (err) {
    next(err);
  }
});

router.get('/stats', (req, res) => {
  res.json({ ok: true, stats: walletService.getStats() });
});

router.get('/tx', (req, res) => {
  res.json({ ok: true, transactions: walletService.listWalletTransactions() });
});

router.post('/transfer', (req, res, next) => {
  try {
    walletService.verifyWalletPin(req.body.fromAddress, req.body.pin);
    const transaction = walletService.transfer(req.body || {});
    res.status(201).json({ ok: true, transaction });
  } catch (err) {
    next(err);
  }
});

router.post('/point-conversion', requireServiceAuth, (req, res, next) => {
  try {
    const result = walletService.creditPointConversion({
      userId: req.body.userId,
      pointAmount: req.body.pointAmount,
      coinAmount: req.body.coinAmount,
      conversionRate: req.body.conversionRate || 1000,
      requestId: req.body.requestId,
      idempotencyKey: req.body.idempotencyKey,
      label: req.body.label
    });
    res.status(result.duplicate ? 200 : 201).json({
      ok: true,
      mode: 'point-conversion-auto-approved',
      serviceIdentity: req.serviceIdentity,
      duplicate: result.duplicate,
      wallet: publicWallet(result.wallet),
      transaction: result.transaction
    });
  } catch (err) {
    next(err);
  }
});

router.get('/user/:userId', (req, res, next) => {
  try {
    const result = walletService.ensureUserWallet({
      userId: req.params.userId,
      label: req.query.label,
      faucetAmount: 0
    });
    res.json({ ok: true, wallet: publicWallet(result.wallet), created: result.created, faucetTransaction: result.faucetTransaction, transactions: walletService.getWalletTransactions(result.wallet.address) });
  } catch (err) {
    next(err);
  }
});

router.post('/user/:userId', (req, res, next) => {
  try {
    const result = walletService.ensureUserWallet({
      userId: req.params.userId,
      label: req.body.label,
      metadata: req.body.metadata || {},
      faucetAmount: req.body.faucetAmount || 0
    });
    res.status(result.created ? 201 : 200).json({ ok: true, wallet: publicWallet(result.wallet), created: result.created, faucetTransaction: result.faucetTransaction });
  } catch (err) {
    next(err);
  }
});

router.get('/users/list', (req, res) => {
  res.json({ ok: true, wallets: publicWallets(walletService.listUserWallets()) });
});


router.post('/:address/pin', (req, res) => {
  try {
    const wallet = walletService.setWalletPin(req.params.address, req.body.pin);
    return res.json({ ok: true, wallet: publicWallet(wallet) });
  } catch (error) {
    return sendWalletError(res, error, 'PIN_SET_FAILED');
  }
});
router.get('/:address/recovery', (req, res) => {
  const wallet = walletService.getWallet(req.params.address);
  if (!wallet) return res.status(404).json({ ok: false, error: 'wallet_not_found' });
  return res.json({ ok: true, recovery: publicRecovery(walletService.getWalletRecoveryStatus(wallet)) });
});

router.post('/:address/recovery/enable', (req, res) => {
  try {
    const result = walletService.enableWalletRecovery(req.params.address, req.body.pin);
    return res.json({ ok: true, recovery: publicRecovery(result.status), export: result.export });
  } catch (error) {
    return sendWalletError(res, error, 'recovery_enable_failed');
  }
});

router.post('/:address/recovery/export', (req, res) => {
  try {
    const exported = walletService.exportWalletRecovery(req.params.address, req.body.pin);
    return res.json({ ok: true, export: exported });
  } catch (error) {
    return sendWalletError(res, error, 'recovery_export_failed');
  }
});

router.post('/:address/recovery/confirm', (req, res) => {
  try {
    const recovery = walletService.confirmWalletRecovery(req.params.address, req.body.pin, req.body.recoveryPhrase);
    return res.json({ ok: true, recovery: publicRecovery(recovery) });
  } catch (error) {
    return sendWalletError(res, error, 'recovery_confirm_failed');
  }
});

router.post('/recovery/restore', (req, res) => {
  try {
    const result = walletService.restoreWalletWithRecoveryPhrase(req.body.recoveryPhrase, req.body.newPin);
    return res.json({ ok: true, wallet: publicWallet(result.wallet), recovery: publicRecovery(result.recovery) });
  } catch (error) {
    return sendWalletError(res, error, 'recovery_restore_failed');
  }
});
router.get('/:address', (req, res) => {
  const wallet = walletService.getWallet(req.params.address);
  if (!wallet) return res.status(404).json({ ok: false, error: 'WALLET_NOT_FOUND' });
  res.json({
    ok: true,
    wallet: publicWallet(wallet),
    transactions: walletService.getWalletTransactions(wallet.address)
  });
});

module.exports = router;
