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

interface IrrAuditQuery {
  asn?: string;
}

async function fetchWithRetry(url: string, retries = 1, timeout = 20000): 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 irrAuditRoutes(fastify: FastifyInstance): Promise<void> {
  fastify.get<{ Querystring: IrrAuditQuery }>(
    '/irr-audit',
    async (request: FastifyRequest<{ Querystring: IrrAuditQuery }>, 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=1800');

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

      try {
        const nlnogData = await fetchWithRetry(`https://irrexplorer.nlnog.net/api/prefixes/asn/AS${asn}`);
        const prefixes = (nlnogData && nlnogData.directOrigin) || [];
        
        let irrRoutes: string[] = [];
        let irrDetails: any[] = [];
        let goodCount = 0;
        let warnCount = 0;
        let errorCount = 0;

        for (const pfx of prefixes) {
          const hasIrr = pfx.irrRoutes && Object.keys(pfx.irrRoutes).length > 0;
          const sources = hasIrr ? Object.keys(pfx.irrRoutes) : [];
          const cat = pfx.categoryOverall || 'unknown';
          
          if (hasIrr) irrRoutes.push(pfx.prefix);
          
          irrDetails.push({
            prefix: pfx.prefix,
            irr_sources: sources,
            rpki_status: pfx.rpkiRoutes && pfx.rpkiRoutes.length ? pfx.rpkiRoutes[0].rpkiStatus : 'not-found',
            category: cat,
            messages: (pfx.messages || []).map((m: any) => m.text)
          });

          if (cat === 'success') goodCount++;
          else if (cat === 'warning') warnCount++;
          else errorCount++;
        }

        const actualPfx = prefixes.map((p: any) => p.prefix);
        const inBgpNotIrr = actualPfx.filter((p: string) => !irrRoutes.includes(p));
        const score = actualPfx.length ? Math.round((irrRoutes.length / actualPfx.length) * 100) : 0;

        return reply.status(200).send({
          asn: asn,
          irr_routes: irrRoutes,
          actual_prefixes: actualPfx,
          in_irr_not_bgp: [],
          in_bgp_not_irr: inBgpNotIrr,
          score: score,
          details: irrDetails,
          summary: { good: goodCount, warning: warnCount, error: errorCount, total: prefixes.length },
          source: 'NLNOG IRR Explorer'
        });
      } catch (e: any) {
        return reply.status(500).send({ error: e.message });
      }
    }
  );
}
