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

interface AspathQuery {
  asn?: string;
}

async function fetchWithRetry(url: string, retries = 1, timeout = 10000): 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 aspathRoutes(fastify: FastifyInstance): Promise<void> {
  fastify.get<{ Querystring: AspathQuery }>(
    '/aspath',
    async (request: FastifyRequest<{ Querystring: AspathQuery }>, reply: FastifyReply) => {
      let asnStr = request.query.asn || '';
      const asn = asnStr.replace(/[^0-9]/g, '');
      
      reply.header('Access-Control-Allow-Origin', '*');
      reply.header('Cache-Control', 'public, max-age=300');

      if (!asn) {
        return reply.status(400).send({ error: 'asn required' });
      }

      try {
        const pfxUrl = `https://stat.ripe.net/data/announced-prefixes/data.json?resource=AS${asn}`;
        const pfxData = await fetchWithRetry(pfxUrl, 1, 6000);
        
        let targetPrefix = '';
        if (pfxData && pfxData.data && pfxData.data.prefixes && pfxData.data.prefixes.length > 0) {
          targetPrefix = pfxData.data.prefixes[0].prefix;
        }
        
        if (!targetPrefix) {
          return reply.status(200).send({ resource: `AS${asn}`, rrcs: [], error: 'No prefixes announced' });
        }
        
        const lgUrl = `https://stat.ripe.net/data/looking-glass/data.json?resource=${encodeURIComponent(targetPrefix)}`;
        const lgData = await fetchWithRetry(lgUrl, 1, 10000);
        
        const rrcs = (lgData && lgData.data && lgData.data.rrcs) || [];
        const results = rrcs.map((r: any) => ({
          rrc: r.rrc,
          location: r.location,
          peers: (r.peers || []).map((p: any) => ({
            asn: p.asn,
            as_path: p.as_path,
            community: p.community,
            next_hop: p.next_hop,
          }))
        }));
        
        return reply.status(200).send({ 
          resource: targetPrefix, 
          rrcs: results, 
          total_rrcs: rrcs.length 
        });
      } catch (e: any) {
        return reply.status(500).send({ error: e.message });
      }
    }
  );
}
