const fs = require("fs");

// PeeringDB Source Cache (L2) — net/netixlan/netfac per ASN
// Eliminates redundant PDB API calls under load
const pdbSourceCache = {
  net: new Map(),       // key: asn string → {data, ts}
  netixlan: new Map(),  // key: net_id string → {data, ts}
  netfac: new Map(),    // key: net_id string → {data, ts}
  facCoords: new Map(), // key: fac_id string → {lat, lon, ts}
  TTL_NET: 6 * 60 * 60 * 1000,       // 6 hours
  TTL_IXFAC: 6 * 60 * 60 * 1000,     // 6 hours
  TTL_COORDS: 7 * 24 * 60 * 60 * 1000, // 7 days
  MAX_NET: 5000,
  MAX_IXFAC: 5000,
  MAX_COORDS: 10000,
  hits: 0,
  misses: 0,

  get(type, key) {
    const map = this[type];
    const ttl = type === "facCoords" ? this.TTL_COORDS : (type === "net" ? this.TTL_NET : this.TTL_IXFAC);
    const entry = map.get(String(key));
    if (!entry) { this.misses++; return null; }
    if (Date.now() - entry.ts > ttl) { map.delete(String(key)); this.misses++; return null; }
    this.hits++;
    return entry.data;
  },

  set(type, key, data) {
    const map = this[type];
    const max = type === "facCoords" ? this.MAX_COORDS : (type === "net" ? this.MAX_NET : this.MAX_IXFAC);
    if (map.size >= max) {
      // Evict oldest entry (Map preserves insertion order)
      map.delete(map.keys().next().value);
    }
    map.set(String(key), { data, ts: Date.now() });
  },

  // Disk persistence
  saveToDisk(filePath) {
    try {
      const serialize = (map) => {
        const obj = {};
        for (const [k, v] of map) obj[k] = v;
        return obj;
      };
      const data = JSON.stringify({
        ts: Date.now(),
        net: serialize(this.net),
        netixlan: serialize(this.netixlan),
        netfac: serialize(this.netfac),
        facCoords: serialize(this.facCoords),
      });
      fs.writeFileSync(filePath, data);
      console.log("[PDB-CACHE] Saved to disk (net=" + this.net.size + " ix=" + this.netixlan.size + " fac=" + this.netfac.size + ")");
    } catch (e) {
      console.warn("[PDB-CACHE] Disk save failed:", e.message);
    }
  },

  loadFromDisk(filePath) {
    try {
      if (!fs.existsSync(filePath)) return false;
      const raw = fs.readFileSync(filePath, "utf8");
      const data = JSON.parse(raw);
      const now = Date.now();
      const load = (map, obj, ttl) => {
        for (const [k, v] of Object.entries(obj || {})) {
          if (now - v.ts < ttl) map.set(k, v);
        }
      };
      load(this.net, data.net, this.TTL_NET);
      load(this.netixlan, data.netixlan, this.TTL_IXFAC);
      load(this.netfac, data.netfac, this.TTL_IXFAC);
      load(this.facCoords, data.facCoords, this.TTL_COORDS);
      console.log("[PDB-CACHE] Loaded from disk (net=" + this.net.size + " ix=" + this.netixlan.size + " fac=" + this.netfac.size + ")");
      return true;
    } catch (e) {
      console.warn("[PDB-CACHE] Disk load failed:", e.message);
      return false;
    }
  },
};

module.exports = { pdbSourceCache };
