const { fetchRipeStatCached } = require("../services/ripe-stat");
const { resolveASNames } = require("../resolve-as-names");
const { ensureAspaCache, lookupAspaFromRpki } = require("../services/rpki");
const { aspaResultCache, resultCacheGet, resultCacheSet } = require("../caches/response-caches");

// ASPA Check endpoint: /api/aspa?asn=X (existing, kept for compat)
async function handleAspaLegacy(req, res, url) {
    const rawAsn = (url.searchParams.get("asn") || "").replace(/[^0-9]/g, "");
    if (!rawAsn) {
      res.writeHead(400);
      return res.end(JSON.stringify({ error: "Missing or invalid ASN parameter" }));
    }
    const cachedAspa = resultCacheGet(aspaResultCache, rawAsn);
    if (cachedAspa !== undefined) {
      res.writeHead(200, { "Content-Type": "application/json" });
      return res.end(JSON.stringify(cachedAspa));
    }
    const start = Date.now();
    let _aspaDone = false;
    const _aspaTimer = setTimeout(() => {
      if (!_aspaDone) {
        _aspaDone = true;
        res.writeHead(200, { "Content-Type": "application/json" });
        res.end(JSON.stringify({ error: "ASPA data temporarily unavailable (timeout)", asn: parseInt(rawAsn) }));
      }
    }, 12000);
    try {
      const [lgData, neighbourData] = await Promise.all([
        fetchRipeStatCached("https://stat.ripe.net/data/looking-glass/data.json?resource=AS" + rawAsn, { timeout: 3000 }).catch(() => null),
        fetchRipeStatCached("https://stat.ripe.net/data/asn-neighbours/data.json?resource=AS" + rawAsn, { timeout: 4000 }),
      ]);

      const rrcs = lgData?.data?.rrcs || [];
      const asPaths = [];

      rrcs.forEach((rrc) => {
        const peers = rrc.peers || [];
        peers.forEach((peer) => {
          const path = peer.as_path || "";
          const pathArr = path.split(" ").map(Number).filter(Boolean);
          if (pathArr.length > 1) {
            asPaths.push({ rrc: rrc.rrc, path: pathArr, prefix: peer.prefix || "" });
          }
        });
      });

      // Provider detection: ONLY use RIPE Stat "left" neighbours (verified upstreams)
      const neighbours = neighbourData?.data?.neighbours || [];
      const leftNeighbours = neighbours.filter((n) => n.type === "left");
      const upstreamSet = new Set();
      leftNeighbours.forEach((n) => upstreamSet.add(n.asn));

      // Classify left neighbours: high-power = likely upstream, low-power = likely peer
      const maxPower = leftNeighbours.reduce((m, n) => Math.max(m, n.power || 0), 1);
      const detectedProviders = [...upstreamSet].map((asn) => {
        const nb = leftNeighbours.find((n) => n.asn === asn);
        const power = nb ? (nb.power || 0) : 0;
        const powerPct = Math.round((power / maxPower) * 100);
        const classification = powerPct >= 10 ? "likely_upstream" : "likely_peer";
        return { asn, name: nb && nb.as_name ? nb.as_name : "", power, power_pct: powerPct, classification };
      });

      await resolveASNames(detectedProviders);

      // Check Cloudflare RPKI feed for ASPA object
      await ensureAspaCache();
      const aspaLookup = lookupAspaFromRpki(rawAsn);
      const aspaObjectExists = aspaLookup.exists;
      const aspaDeclaredProviders = aspaLookup.providers;

      const providerList = detectedProviders.map((p) => "AS" + p.asn).join(", ");
      let recommendedAspa =
        "aut-num:        AS" + rawAsn + "\n" +
        "# Recommended ASPA object:\n" +
        "# customer:     AS" + rawAsn + "\n" +
        "# provider-set: " + providerList + "\n" +
        "# AFI:          ipv4, ipv6\n" +
        "#\n" +
        "# Detected providers from BGP path analysis:\n" +
        detectedProviders.map((p) => "#   AS" + p.asn + (p.name ? " (" + p.name + ")" : "")).join("\n");

      // If ASPA object exists, show RPKI-declared providers
      if (aspaObjectExists && aspaDeclaredProviders.length > 0) {
        recommendedAspa += "\n#\n# RPKI-declared providers (from Cloudflare RPKI feed):\n" +
          aspaDeclaredProviders.map((a) => "#   AS" + a).join("\n");
      }

      const samplePaths = asPaths.slice(0, 10).map((p) => {
        const pathStr = p.path.map((a) => "AS" + a).join(" -> ");
        const idx = p.path.indexOf(parseInt(rawAsn));
        const provider = idx > 0 ? p.path[idx - 1] : null;
        return {
          rrc: p.rrc,
          prefix: p.prefix,
          path: pathStr,
          detected_provider: provider ? "AS" + provider : null,
          provider_in_set: provider ? upstreamSet.has(provider) : false,
        };
      });

      if (_aspaDone) return; // hard timeout already responded
      _aspaDone = true;
      clearTimeout(_aspaTimer);
      const duration = Date.now() - start;
      const aspaResult = {
        meta: { query: "AS" + rawAsn, duration_ms: duration, timestamp: new Date().toISOString() },
        asn: parseInt(rawAsn),
        detected_providers: detectedProviders,
        provider_count: detectedProviders.length,
        aspa_object_exists: aspaObjectExists,
        aspa_feed_healthy: aspaLookup.feedLoaded,
        aspa_declared_providers: aspaDeclaredProviders.map((a) => ({ asn: a })),
        aspa_declared_count: aspaDeclaredProviders.length,
        recommended_aspa: recommendedAspa,
        path_analysis: {
          total_paths_seen: asPaths.length,
          sample_paths: samplePaths,
        },
      };
      resultCacheSet(aspaResultCache, rawAsn, aspaResult);
      return res.end(JSON.stringify(aspaResult, null, 2));
    } catch (err) {
      if (!_aspaDone) {
        _aspaDone = true;
        clearTimeout(_aspaTimer);
        res.writeHead(500);
        return res.end(JSON.stringify({ error: "ASPA check failed", message: err.message }));
      }
    }

}

module.exports = { handleAspaLegacy };
