const { fetchPeeringDB } = require("../services/peeringdb");

// Peer Matching endpoint: /api/peers/find?ix=NAME&policy=open&min_speed=10000
async function handlePeersFind(req, res, url) {
    const ixName = url.searchParams.get("ix") || "";
    const policy = url.searchParams.get("policy") || "";
    const minSpeed = parseInt(url.searchParams.get("min_speed") || "0");
    const netType = url.searchParams.get("type") || "";

    if (!ixName) {
      res.writeHead(400);
      return res.end(JSON.stringify({ error: "Missing ix parameter (IX name)" }));
    }

    const start = Date.now();
    try {
      // Search for IX by name
      const ixSearch = await fetchPeeringDB("/ix?name__contains=" + encodeURIComponent(ixName));
      const ixResults = ixSearch?.data || [];
      if (ixResults.length === 0) {
        return res.end(JSON.stringify({ error: "No IX found matching: " + ixName, matches: [] }));
      }

      // Use first matching IX
      const ix = ixResults[0];
      const ixId = ix.id;

      // Get ixlan for this IX
      const ixlanData = await fetchPeeringDB("/ixlan?ix_id=" + ixId);
      const ixlans = ixlanData?.data || [];
      if (ixlans.length === 0) {
        return res.end(JSON.stringify({ ix: { id: ixId, name: ix.name }, matches: [] }));
      }

      const ixlanId = ixlans[0].id;

      // Get all networks at this IX
      const netixlanData = await fetchPeeringDB("/netixlan?ixlan_id=" + ixlanId);
      const netixlans = netixlanData?.data || [];

      // Get unique net_ids
      const netIds = [...new Set(netixlans.map(n => n.net_id))];

      // Fetch network details in batches
      const networks = [];
      const batchSize = 20;
      for (let i = 0; i < Math.min(netIds.length, 200); i += batchSize) {
        const batch = netIds.slice(i, i + batchSize);
        const batchResults = await Promise.all(
          batch.map(nid => fetchPeeringDB("/net/" + nid))
        );
        batchResults.forEach(r => {
          if (r?.data?.[0]) networks.push(r.data[0]);
        });
      }

      // Filter and rank
      let filtered = networks.map(net => {
        const nix = netixlans.filter(n => n.net_id === net.id);
        const maxSpeed = Math.max(...nix.map(n => n.speed || 0));
        return {
          asn: net.asn,
          name: net.name || "",
          policy: net.policy_general || "",
          type: net.info_type || "",
          speed_mbps: maxSpeed,
          speed_gbps: maxSpeed >= 1000 ? (maxSpeed / 1000) + " Gbps" : maxSpeed + " Mbps",
          traffic: net.info_traffic || "",
          website: net.website || "",
          peeringdb_id: net.id,
          ipv4: nix[0]?.ipaddr4 || null,
          ipv6: nix[0]?.ipaddr6 || null,
        };
      });

      // Apply filters
      if (policy) {
        filtered = filtered.filter(n => n.policy.toLowerCase().includes(policy.toLowerCase()));
      }
      if (minSpeed > 0) {
        filtered = filtered.filter(n => n.speed_mbps >= minSpeed);
      }
      if (netType) {
        filtered = filtered.filter(n => n.type.toLowerCase().includes(netType.toLowerCase()));
      }

      // Sort by speed desc
      filtered.sort((a, b) => b.speed_mbps - a.speed_mbps);

      // Also find common IXPs for each match (check if they share other IXPs)
      const duration = Date.now() - start;
      return res.end(JSON.stringify({
        meta: { duration_ms: duration, timestamp: new Date().toISOString() },
        ix: { id: ixId, name: ix.name, ixlan_id: ixlanId },
        total_members: netixlans.length,
        filtered_count: filtered.length,
        matches: filtered.slice(0, 50),
      }, null, 2));
    } catch (err) {
      res.writeHead(500);
      return res.end(JSON.stringify({ error: "Peer matching failed", message: err.message }));
    }

}

module.exports = { handlePeersFind };
