import { FastifyInstance, FastifyRequest, FastifyReply } from 'fastify';

// In-memory cache
let globalFacCache: { ts: number; data: any } | null = null;
const FAC_TTL = 24 * 60 * 60 * 1000;

async function fetchWithRetry(url: string, retries = 1, timeout = 30000): Promise<any> {
  for (let i = 0; i <= retries; i++) {
    const controller = new AbortController();
    const timeoutId = setTimeout(() => controller.abort(), timeout);
    try {
      const response = await fetch(url, { signal: controller.signal });
      clearTimeout(timeoutId);
      if (!response.ok) {
        if (i === retries) throw new Error(`HTTP ${response.status}`);
        continue;
      }
      return await response.json();
    } catch (e) {
      clearTimeout(timeoutId);
      if (i === retries) throw e;
      await new Promise(r => setTimeout(r, 1500));
    }
  }
}

export async function globalInfraRoutes(fastify: FastifyInstance): Promise<void> {
  fastify.get(
    '/global-infra',
    async (request: FastifyRequest, reply: FastifyReply) => {
      reply.header('Access-Control-Allow-Origin', '*');
      reply.header('Cache-Control', 'public, max-age=86400');

      if (globalFacCache && Date.now() - globalFacCache.ts < FAC_TTL) {
        return reply.status(200).send(globalFacCache.data);
      }

      try {
        const PEERINGDB_API_URL = 'https://www.peeringdb.com/api';
        
        const [facData, ixData] = await Promise.all([
          fetchWithRetry(`${PEERINGDB_API_URL}/fac?depth=1&limit=3000`, 1, 30000),
          fetchWithRetry(`${PEERINGDB_API_URL}/ix?depth=1&limit=1000`, 1, 30000),
        ]);
        
        const facs = (facData && facData.data || [])
          .filter((f: any) => f.latitude && f.longitude)
          .map((f: any) => ({ 
            id: f.id, 
            name: f.name, 
            city: f.city, 
            country: f.country, 
            lat: +f.latitude, 
            lng: +f.longitude 
          }));
          
        const ixps = (ixData && ixData.data || [])
          .filter((ix: any) => ix.city && ix.country)
          .map((ix: any) => ({ 
            id: ix.id, 
            name: ix.name, 
            city: ix.city, 
            country: ix.country, 
            website: ix.website 
          }));
          
        const result = { facs, ixps };
        globalFacCache = { ts: Date.now(), data: result };
        
        return reply.status(200).send(result);
      } catch (e: any) {
        return reply.status(500).send({ error: e.message });
      }
    }
  );
}
