export class RelationLookup {
  constructor(manager) {
    this.manager = manager;
  }

  getDirectRelation(srcId, relation, dstId, options = null) {
    const partialContext = options?.partialGraphContext || null;
    const partialRel = partialContext ? partialContext.getDirectRelation(srcId, relation, dstId) : null;
    // Try cache first - use numeric key for better performance
    const cacheKey = this.manager._makeDirectCacheKey(srcId, relation, dstId);
    const cached = this.manager._caches.relationLookupCache.get(cacheKey);
    if (cached) {
      this.manager._cacheHits++;
      return cached;
    }
    
    if (this.manager.arbiter.snapshotGraph && !this.manager.arbiter.indicesBuilt) {
      const result = this.manager._getSnapshotDirectRelation(srcId, relation, dstId);
      if (result) {
        this.manager._caches.relationLookupCache.set(cacheKey, result);
        this.manager._caches.relationLookupCacheKeys.add(cacheKey);
      }
      this.manager._cacheMisses++;
      if (result) return result;
      return partialRel;
    }

    this.manager._ensureIndicesBuilt();
    const result = this.manager.arbiter.indices.getDirectRelation(srcId, relation, dstId);
    
    // Cache the result if it's frequently accessed
    if (result) {
      this.manager._caches.relationLookupCache.set(cacheKey, result);
      this.manager._caches.relationLookupCacheKeys.add(cacheKey);
    }
    this.manager._cacheMisses++;

    if (result) return result;
    return partialRel;
  }

  getRelationsFromSrc(srcId, relation, options = null) {
    const partialContext = options?.partialGraphContext || null;
    if (partialContext) {
      this.manager._ensureIndicesBuilt();
      const partial = partialContext.getRelationsFromSrc(srcId, relation);
      const persistent = this.manager.arbiter.indices.getRelationsFromSrc(srcId, relation);
      return this.manager._mergeRelationLists(persistent, partial);
    }
    // Try cache first for frequently accessed patterns - use numeric key
    const cacheKey = this.manager._makeSrcRelCacheKey(srcId, relation);
    const cached = this.manager._caches.relationLookupCache.get(cacheKey);
    if (cached) {
      this.manager._cacheHits++;
      return cached;
    }
    
    if (this.manager.arbiter.snapshotGraph && !this.manager.arbiter.indicesBuilt) {
      return this.manager._getSnapshotRelationsFromSrc(srcId, relation);
    }

    this.manager._ensureIndicesBuilt();
    const result = this.manager.arbiter.indices.getRelationsFromSrc(srcId, relation);
    
    // Cache smaller result sets to avoid memory bloat - hLRU will manage size
    if (result && result.length <= 100) {
      this.manager._caches.relationLookupCache.set(cacheKey, result);
      this.manager._caches.relationLookupCacheKeys.add(cacheKey);
    }
    this.manager._cacheMisses++;
    
    return result;
  }

  getRelationsToDst(dstId, relation, options = null) {
    const partialContext = options?.partialGraphContext || null;
    if (partialContext) {
      this.manager._ensureIndicesBuilt();
      const partial = partialContext.getRelationsToDst(dstId, relation);
      const persistent = this.manager.arbiter.indices.getRelationsToDst(dstId, relation);
      return this.manager._mergeRelationLists(persistent, partial);
    }
    // Try cache first - use numeric key
    const cacheKey = this.manager._makeDstRelCacheKey(dstId, relation);
    const cached = this.manager._caches.relationLookupCache.get(cacheKey);
    if (cached) {
      this.manager._cacheHits++;
      return cached;
    }
    
    if (this.manager.arbiter.snapshotGraph && !this.manager.arbiter.indicesBuilt) {
      return this.manager._getSnapshotRelationsToDst(dstId, relation);
    }

    this.manager._ensureIndicesBuilt();
    const result = this.manager.arbiter.indices.getRelationsToDst(dstId, relation);
    
    // Cache smaller result sets - hLRU will manage size
    if (result && result.length <= 100) {
      this.manager._caches.relationLookupCache.set(cacheKey, result);
      this.manager._caches.relationLookupCacheKeys.add(cacheKey);
    }
    this.manager._cacheMisses++;
    
    return result;
  }

  getRelationsByName(relation, options = null) {
    const partialContext = options?.partialGraphContext || null;
    if (partialContext) {
      this.manager._ensureIndicesBuilt();
      const partial = partialContext.getRelationsByName(relation);
      const persistent = this.manager.arbiter.indices.getRelationsByName(relation);
      return this.manager._mergeRelationLists(persistent, partial);
    }
    if (this.manager.arbiter.snapshotGraph && !this.manager.arbiter.indicesBuilt) {
      return this.manager._getSnapshotRelationsByName(relation);
    }

    // Don't cache large result sets for relation name queries
    this.manager._ensureIndicesBuilt();
    return this.manager.arbiter.indices.getRelationsByName(relation);
  }
}
