/**
 * Synor Perpetuals Trading Engine
 * Leveraged trading with 2x-100x positions
 *
 * Port: 17510 (REST), 17511 (WebSocket)
 * Endpoints:
 *   GET /health - Health check
 *   GET /markets - Available markets
 *   GET /market/:id - Market details
 *   GET /positions/:address - User positions
 *   GET /funding - Current funding rates
 *   POST /order - Place order (simulated)
 */

const http = require('http');

const PORT = process.env.PORT || 17510;
const WS_PORT = process.env.WS_PORT || 17511;
const ORACLE_URL = process.env.ORACLE_URL || 'http://localhost:17500';
const MIN_LEVERAGE = parseInt(process.env.MIN_LEVERAGE) || 2;
const MAX_LEVERAGE = parseInt(process.env.MAX_LEVERAGE) || 100;
const MAINTENANCE_MARGIN_BPS = parseInt(process.env.MAINTENANCE_MARGIN_BPS) || 50;
const FUNDING_INTERVAL_HOURS = parseInt(process.env.FUNDING_INTERVAL_HOURS) || 8;

// Markets (in-memory state)
const markets = new Map([
  [1, { id: 1, symbol: 'BTC/USD', tickSize: 0.1, lotSize: 0.001, maxLeverage: MAX_LEVERAGE }],
  [2, { id: 2, symbol: 'ETH/USD', tickSize: 0.01, lotSize: 0.01, maxLeverage: MAX_LEVERAGE }],
  [3, { id: 3, symbol: 'SYNOR/USD', tickSize: 0.0001, lotSize: 1.0, maxLeverage: 50 }],
  [4, { id: 4, symbol: 'SOL/USD', tickSize: 0.01, lotSize: 0.1, maxLeverage: MAX_LEVERAGE }],
]);

// Open positions (in-memory)
const positions = new Map();
let positionIdCounter = 1;

// Funding rates (simulated)
const fundingRates = new Map([
  [1, { marketId: 1, rate: 0.0001, nextFundingTime: Date.now() + 8 * 3600 * 1000 }],
  [2, { marketId: 2, rate: 0.00012, nextFundingTime: Date.now() + 8 * 3600 * 1000 }],
  [3, { marketId: 3, rate: 0.0002, nextFundingTime: Date.now() + 8 * 3600 * 1000 }],
  [4, { marketId: 4, rate: 0.00008, nextFundingTime: Date.now() + 8 * 3600 * 1000 }],
]);

// Insurance fund (simulated)
let insuranceFund = 10000000; // $10M

// Calculate PnL
function calculatePnL(position, currentPrice) {
  const priceDiff = currentPrice - position.entryPrice;
  const multiplier = position.direction === 'long' ? 1 : -1;
  return priceDiff * position.size * multiplier;
}

// Calculate margin ratio
function calculateMarginRatio(position, currentPrice) {
  const pnl = calculatePnL(position, currentPrice);
  const equity = position.collateral + pnl;
  const notional = position.size * currentPrice;
  return (equity / notional) * 10000; // in BPS
}

// Parse JSON body
function parseBody(req) {
  return new Promise((resolve, reject) => {
    let body = '';
    req.on('data', chunk => body += chunk);
    req.on('end', () => {
      try {
        resolve(body ? JSON.parse(body) : {});
      } catch (e) {
        reject(e);
      }
    });
  });
}

// HTTP Server
const server = http.createServer(async (req, res) => {
  res.setHeader('Content-Type', 'application/json');
  res.setHeader('Access-Control-Allow-Origin', '*');
  res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS');
  res.setHeader('Access-Control-Allow-Headers', 'Content-Type');

  if (req.method === 'OPTIONS') {
    res.writeHead(200);
    res.end();
    return;
  }

  const url = new URL(req.url, `http://localhost:${PORT}`);
  const path = url.pathname;

  try {
    // Health check
    if (path === '/health') {
      res.writeHead(200);
      res.end(JSON.stringify({
        status: 'healthy',
        markets: markets.size,
        openPositions: positions.size,
        insuranceFund,
        timestamp: Date.now(),
      }));
      return;
    }

    // All markets
    if (path === '/markets') {
      res.writeHead(200);
      res.end(JSON.stringify({
        markets: Array.from(markets.values()),
        config: { minLeverage: MIN_LEVERAGE, maxLeverage: MAX_LEVERAGE, maintenanceMarginBps: MAINTENANCE_MARGIN_BPS },
      }));
      return;
    }

    // Single market
    if (path.startsWith('/market/')) {
      const marketId = parseInt(path.slice(8));
      const market = markets.get(marketId);
      if (market) {
        const funding = fundingRates.get(marketId);
        res.writeHead(200);
        res.end(JSON.stringify({ ...market, funding }));
      } else {
        res.writeHead(404);
        res.end(JSON.stringify({ error: 'Market not found' }));
      }
      return;
    }

    // User positions
    if (path.startsWith('/positions/')) {
      const address = path.slice(11);
      const userPositions = Array.from(positions.values()).filter(p => p.owner === address);
      res.writeHead(200);
      res.end(JSON.stringify({ address, positions: userPositions }));
      return;
    }

    // Funding rates
    if (path === '/funding') {
      res.writeHead(200);
      res.end(JSON.stringify({
        rates: Array.from(fundingRates.values()),
        interval: `${FUNDING_INTERVAL_HOURS}h`,
      }));
      return;
    }

    // Insurance fund
    if (path === '/insurance') {
      res.writeHead(200);
      res.end(JSON.stringify({ insuranceFund, timestamp: Date.now() }));
      return;
    }

    // Place order (simulated)
    if (path === '/order' && req.method === 'POST') {
      const body = await parseBody(req);
      const { marketId, direction, size, collateral, leverage, owner } = body;

      // Validate
      if (!marketId || !direction || !size || !collateral || !leverage || !owner) {
        res.writeHead(400);
        res.end(JSON.stringify({ error: 'Missing required fields' }));
        return;
      }

      if (leverage < MIN_LEVERAGE || leverage > MAX_LEVERAGE) {
        res.writeHead(400);
        res.end(JSON.stringify({ error: `Leverage must be between ${MIN_LEVERAGE}x and ${MAX_LEVERAGE}x` }));
        return;
      }

      const market = markets.get(marketId);
      if (!market) {
        res.writeHead(400);
        res.end(JSON.stringify({ error: 'Invalid market' }));
        return;
      }

      // Create position (simulated - in production would interact with smart contract)
      const positionId = positionIdCounter++;
      const position = {
        id: positionId,
        owner,
        marketId,
        direction,
        size,
        collateral,
        entryPrice: 45000, // Would fetch from oracle
        leverage,
        openedAt: Date.now(),
        isOpen: true,
      };

      positions.set(positionId, position);

      res.writeHead(201);
      res.end(JSON.stringify({ success: true, position }));
      return;
    }

    // Default
    res.writeHead(404);
    res.end(JSON.stringify({ error: 'Not found' }));
  } catch (err) {
    res.writeHead(500);
    res.end(JSON.stringify({ error: err.message }));
  }
});

server.listen(PORT, '0.0.0.0', () => {
  console.log(`Perpetuals Engine running on port ${PORT}`);
  console.log(`Leverage: ${MIN_LEVERAGE}x - ${MAX_LEVERAGE}x`);
  console.log(`Maintenance Margin: ${MAINTENANCE_MARGIN_BPS / 100}%`);
  console.log(`Markets: ${markets.size}`);
  console.log('Endpoints:');
  console.log('  GET /health - Health check');
  console.log('  GET /markets - Available markets');
  console.log('  GET /market/:id - Market details');
  console.log('  GET /positions/:address - User positions');
  console.log('  GET /funding - Current funding rates');
  console.log('  POST /order - Place order');
});
