/**
 * Synor Oracle Service
 * Multi-source price aggregation with TWAP support
 *
 * Port: 17500
 * Endpoints:
 *   GET /health - Health check
 *   GET /prices - All current prices
 *   GET /price/:symbol - Price for specific symbol
 *   GET /twap/:symbol - Time-weighted average price
 */

const http = require('http');

const PORT = process.env.PORT || 17500;
const UPDATE_INTERVAL = parseInt(process.env.UPDATE_INTERVAL_MS) || 1000;
const STALE_THRESHOLD = parseInt(process.env.STALE_THRESHOLD_MS) || 60000;

// Price state (in-memory cache)
const prices = new Map();
const priceHistory = new Map();
const MAX_HISTORY = 3600; // 1 hour of 1-second updates

// Initialize default prices (testnet)
const DEFAULT_PRICES = {
  'BTC/USD': 45000,
  'ETH/USD': 2500,
  'SYNOR/USD': 1.50,
  'SOL/USD': 95,
  'ATOM/USD': 8.50,
  'OSMO/USD': 0.75,
};

// Initialize prices
Object.entries(DEFAULT_PRICES).forEach(([symbol, price]) => {
  prices.set(symbol, {
    symbol,
    price,
    timestamp: Date.now(),
    sources: ['simulator'],
    confidence: 1.0,
  });
  priceHistory.set(symbol, [{ price, timestamp: Date.now() }]);
});

// Calculate TWAP
function calculateTWAP(symbol, windowMs = 300000) { // 5 minute default
  const history = priceHistory.get(symbol) || [];
  const cutoff = Date.now() - windowMs;
  const relevantPrices = history.filter(p => p.timestamp >= cutoff);

  if (relevantPrices.length === 0) return null;

  const sum = relevantPrices.reduce((acc, p) => acc + p.price, 0);
  return sum / relevantPrices.length;
}

// Update price with simulated volatility
function updatePrice(symbol, basePrice, volatility = 0.001) {
  const change = (Math.random() - 0.5) * 2 * volatility * basePrice;
  const newPrice = Math.max(basePrice + change, 0.01);
  const timestamp = Date.now();

  prices.set(symbol, {
    symbol,
    price: newPrice,
    timestamp,
    sources: ['simulator'],
    confidence: 1.0,
  });

  // Update history
  const history = priceHistory.get(symbol) || [];
  history.push({ price: newPrice, timestamp });
  if (history.length > MAX_HISTORY) history.shift();
  priceHistory.set(symbol, history);

  return newPrice;
}

// Periodic price updates
setInterval(() => {
  Object.entries(DEFAULT_PRICES).forEach(([symbol, basePrice]) => {
    const current = prices.get(symbol);
    updatePrice(symbol, current?.price || basePrice);
  });
}, UPDATE_INTERVAL);

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

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

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

  // All prices
  if (path === '/prices') {
    const allPrices = {};
    prices.forEach((data, symbol) => {
      const isStale = Date.now() - data.timestamp > STALE_THRESHOLD;
      allPrices[symbol] = { ...data, stale: isStale };
    });
    res.writeHead(200);
    res.end(JSON.stringify({ prices: allPrices, timestamp: Date.now() }));
    return;
  }

  // Single price
  if (path.startsWith('/price/')) {
    const symbol = decodeURIComponent(path.slice(7)).toUpperCase();
    const data = prices.get(symbol);
    if (data) {
      const isStale = Date.now() - data.timestamp > STALE_THRESHOLD;
      res.writeHead(200);
      res.end(JSON.stringify({ ...data, stale: isStale }));
    } else {
      res.writeHead(404);
      res.end(JSON.stringify({ error: 'Symbol not found', symbol }));
    }
    return;
  }

  // TWAP
  if (path.startsWith('/twap/')) {
    const symbol = decodeURIComponent(path.slice(6)).toUpperCase();
    const window = parseInt(url.searchParams.get('window')) || 300000;
    const twap = calculateTWAP(symbol, window);
    if (twap !== null) {
      res.writeHead(200);
      res.end(JSON.stringify({ symbol, twap, windowMs: window, timestamp: Date.now() }));
    } else {
      res.writeHead(404);
      res.end(JSON.stringify({ error: 'No price history for symbol', symbol }));
    }
    return;
  }

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

server.listen(PORT, '0.0.0.0', () => {
  console.log(`Oracle Service running on port ${PORT}`);
  console.log(`Tracking ${prices.size} price feeds`);
  console.log('Endpoints:');
  console.log('  GET /health - Health check');
  console.log('  GET /prices - All current prices');
  console.log('  GET /price/:symbol - Price for specific symbol');
  console.log('  GET /twap/:symbol - Time-weighted average price');
});
