/**
 * Synor DEX API Gateway
 * Unified trading interface for all DEX services
 *
 * Port: 17530 (REST), 17531 (WebSocket)
 * Endpoints:
 *   GET /health - Health check
 *   GET /status - System status
 *   GET /v1/oracle/* - Oracle proxy
 *   GET /v1/perps/* - Perps proxy
 *   GET /v1/aggregator/* - Aggregator proxy
 *   GET /v1/markets - All markets overview
 */

const http = require('http');

const PORT = process.env.PORT || 17530;
const ORACLE_URL = process.env.ORACLE_URL || 'http://localhost:17500';
const PERPS_URL = process.env.PERPS_URL || 'http://localhost:17510';
const AGGREGATOR_URL = process.env.AGGREGATOR_URL || 'http://localhost:17520';

// Service status tracking
const serviceStatus = {
  oracle: { healthy: false, lastCheck: 0 },
  perps: { healthy: false, lastCheck: 0 },
  aggregator: { healthy: false, lastCheck: 0 },
};

// Fetch helper
async function fetchJSON(url, options = {}) {
  return new Promise((resolve, reject) => {
    const urlObj = new URL(url);
    const reqOptions = {
      hostname: urlObj.hostname,
      port: urlObj.port,
      path: urlObj.pathname + urlObj.search,
      method: options.method || 'GET',
      headers: options.headers || { 'Content-Type': 'application/json' },
      timeout: 5000,
    };

    const req = http.request(reqOptions, (res) => {
      let data = '';
      res.on('data', chunk => data += chunk);
      res.on('end', () => {
        try {
          resolve({ status: res.statusCode, data: JSON.parse(data) });
        } catch {
          resolve({ status: res.statusCode, data });
        }
      });
    });

    req.on('error', reject);
    req.on('timeout', () => {
      req.destroy();
      reject(new Error('Timeout'));
    });

    if (options.body) {
      req.write(JSON.stringify(options.body));
    }
    req.end();
  });
}

// Health check for services
async function checkServiceHealth() {
  const checks = [
    { name: 'oracle', url: `${ORACLE_URL}/health` },
    { name: 'perps', url: `${PERPS_URL}/health` },
    { name: 'aggregator', url: `${AGGREGATOR_URL}/health` },
  ];

  for (const check of checks) {
    try {
      const result = await fetchJSON(check.url);
      serviceStatus[check.name] = {
        healthy: result.status === 200,
        lastCheck: Date.now(),
        latency: Date.now() - serviceStatus[check.name].lastCheck,
      };
    } catch {
      serviceStatus[check.name] = { healthy: false, lastCheck: Date.now() };
    }
  }
}

// Check health every 30 seconds
setInterval(checkServiceHealth, 30000);
checkServiceHealth();

// Proxy request to service
async function proxyRequest(targetUrl, req, res) {
  try {
    let body = '';
    for await (const chunk of req) {
      body += chunk;
    }

    const result = await fetchJSON(targetUrl, {
      method: req.method,
      body: body ? JSON.parse(body) : undefined,
    });

    res.writeHead(result.status);
    res.end(JSON.stringify(result.data));
  } catch (err) {
    res.writeHead(502);
    res.end(JSON.stringify({ error: 'Service unavailable', message: err.message }));
  }
}

// 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, Authorization');

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

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

  // Health check
  if (path === '/health') {
    const allHealthy = Object.values(serviceStatus).every(s => s.healthy);
    res.writeHead(allHealthy ? 200 : 503);
    res.end(JSON.stringify({
      status: allHealthy ? 'healthy' : 'degraded',
      timestamp: Date.now(),
    }));
    return;
  }

  // System status
  if (path === '/status') {
    const allHealthy = Object.values(serviceStatus).every(s => s.healthy);
    res.writeHead(200);
    res.end(JSON.stringify({
      status: allHealthy ? 'operational' : 'degraded',
      services: serviceStatus,
      version: '1.0.0',
      timestamp: Date.now(),
    }));
    return;
  }

  // API documentation
  if (path === '/' || path === '/docs') {
    res.writeHead(200);
    res.end(JSON.stringify({
      name: 'Synor DEX API',
      version: '1.0.0',
      endpoints: {
        '/health': 'Health check',
        '/status': 'System status with all services',
        '/v1/oracle/prices': 'Get all price feeds',
        '/v1/oracle/price/:symbol': 'Get price for symbol',
        '/v1/oracle/twap/:symbol': 'Get TWAP for symbol',
        '/v1/perps/markets': 'Get all perpetual markets',
        '/v1/perps/positions/:address': 'Get user positions',
        '/v1/perps/funding': 'Get funding rates',
        '/v1/aggregator/sources': 'Get liquidity sources',
        '/v1/aggregator/quote': 'Get swap quote',
        '/v1/aggregator/swap': 'Execute swap',
        '/v1/markets': 'Combined market overview',
      },
    }));
    return;
  }

  // Proxy to Oracle
  if (path.startsWith('/v1/oracle/')) {
    const targetPath = path.replace('/v1/oracle', '');
    const targetUrl = `${ORACLE_URL}${targetPath}${url.search}`;
    await proxyRequest(targetUrl, req, res);
    return;
  }

  // Proxy to Perps
  if (path.startsWith('/v1/perps/')) {
    const targetPath = path.replace('/v1/perps', '');
    const targetUrl = `${PERPS_URL}${targetPath}${url.search}`;
    await proxyRequest(targetUrl, req, res);
    return;
  }

  // Proxy to Aggregator
  if (path.startsWith('/v1/aggregator/')) {
    const targetPath = path.replace('/v1/aggregator', '');
    const targetUrl = `${AGGREGATOR_URL}${targetPath}${url.search}`;
    await proxyRequest(targetUrl, req, res);
    return;
  }

  // Combined markets overview
  if (path === '/v1/markets') {
    try {
      const [perpsResult, oracleResult, sourcesResult] = await Promise.allSettled([
        fetchJSON(`${PERPS_URL}/markets`),
        fetchJSON(`${ORACLE_URL}/prices`),
        fetchJSON(`${AGGREGATOR_URL}/sources`),
      ]);

      res.writeHead(200);
      res.end(JSON.stringify({
        perpetuals: perpsResult.status === 'fulfilled' ? perpsResult.value.data : null,
        prices: oracleResult.status === 'fulfilled' ? oracleResult.value.data : null,
        liquiditySources: sourcesResult.status === 'fulfilled' ? sourcesResult.value.data : null,
        timestamp: Date.now(),
      }));
    } catch (err) {
      res.writeHead(500);
      res.end(JSON.stringify({ error: err.message }));
    }
    return;
  }

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

server.listen(PORT, '0.0.0.0', () => {
  console.log(`DEX API Gateway running on port ${PORT}`);
  console.log('');
  console.log('Service URLs:');
  console.log(`  Oracle: ${ORACLE_URL}`);
  console.log(`  Perps: ${PERPS_URL}`);
  console.log(`  Aggregator: ${AGGREGATOR_URL}`);
  console.log('');
  console.log('Endpoints:');
  console.log('  GET /health - Health check');
  console.log('  GET /status - System status');
  console.log('  GET /docs - API documentation');
  console.log('  GET /v1/oracle/* - Oracle proxy');
  console.log('  GET /v1/perps/* - Perps proxy');
  console.log('  GET /v1/aggregator/* - Aggregator proxy');
  console.log('  GET /v1/markets - Combined market overview');
});
