import { BaseRule } from './BaseRule.js';
import { extractRemediation } from '../remediation.js';

/**
 * ComputedRule - Recursively evaluates a relation through the authorization checker
 * 
 * This rule delegates to the main authorization checker to recursively evaluate
 * a computed relation. It's essentially a way to invoke the full authorization
 * logic as part of a rule evaluation.
 * 
 * Configuration:
 * {
 *   type: 'computed',
 *   relation: string      // Relation to recursively evaluate
 * }
 */
export class ComputedRule extends BaseRule {
  constructor(arbiter) {
    super(arbiter);
  }

  /**
   * Evaluate computed relation by delegating to authorization checker
   * @protected
   */
  _evaluateRule(userId, userKey, objectId, objectKey, rule, visited, currentRelation, options) {
    const computedRelation = rule.relation;
    
    // Track evaluation details if requested
    const evaluation = options.trackEvaluation ? {
      type: 'computed',
      userKey,
      objectKey,
      computedRelation,
      evaluationStarted: Date.now()
    } : null;
    
    // Delegate to authorization checker with proper context (including valueContext)
    const res = this.arbiter.authChecker.check(userKey, computedRelation, objectKey, {
      ...options,
      _visited: visited,
      _currentRelation: currentRelation
    });

    const remediation = extractRemediation(res);
    
    if (evaluation) {
      evaluation.evaluationCompleted = Date.now();
      evaluation.evaluationDuration = evaluation.evaluationCompleted - evaluation.evaluationStarted;
      evaluation.delegatedResult = res;
    }
    
    // Convert the check result to standardized rule evaluation format
    const result = {
      possibility: res.possibility || 0,
      reliability: res.reliability !== undefined ? res.reliability : 1.0,
      // Propagate collected values from delegated result
      collectedValues: res.collectedValues || [],
      ...(options.includeMeta && {
        meta: {
          ...(res.meta || {}),
          ...(remediation ? { remediation } : {}),
          ruleType: 'computed',
          computedRelation,
          delegated: true
        }
      }),
      ...(remediation ? { remediation } : {}),
      reason: res.reason || 'computed_delegation'
    };
    
    if (evaluation) {
      result.evaluation = evaluation;
    }
    
    return result;
  }
} 
