'use strict';

class PolicyEngine {
  constructor(rules = []) {
    this.rules = [...rules].sort((a, b) => Number(b.priority || 0) - Number(a.priority || 0));
  }

  evaluate(context = {}) {
    const matches = [];
    for (const rule of this.rules) {
      if (matchesRule(rule, context)) {
        matches.push({
          id: rule.id || '',
          action: rule.action || 'none',
          reason: rule.reason || rule.id || '',
          priority: Number(rule.priority || 0),
          rule,
        });
        if (rule.stop) break;
      }
    }
    return {
      action: matches[0]?.action || 'allow',
      matches,
      blocked: matches.some((match) => match.action === 'block'),
      recover: matches.find((match) => /^recover/.test(String(match.action))) || null,
      escalate: matches.some((match) => match.action === 'escalate'),
    };
  }
}

function matchesRule(rule = {}, context = {}) {
  const conditions = Array.isArray(rule.when) ? rule.when : (rule.when ? [rule.when] : []);
  if (conditions.length === 0) return true;
  return conditions.every((condition) => conditionMatches(condition, context));
}

function conditionMatches(condition, context) {
  if (typeof condition === 'function') return Boolean(condition(context));
  const text = String(condition || '');
  if (!text) return true;
  if (text.includes('=')) {
    const [key, expected] = text.split('=');
    return String(getPath(context, key.trim())) === expected.trim();
  }
  if (text.startsWith('!')) return !Boolean(getPath(context, text.slice(1)));
  return Boolean(getPath(context, text));
}

function createDefaultCodingPolicy() {
  return new PolicyEngine([
    {
      id: 'block-diverged-merge',
      priority: 100,
      when: ['merge.requested', 'branch.diverged'],
      action: 'block',
      reason: 'branch_diverged',
      stop: true,
    },
    {
      id: 'recover-prompt-delivery-once',
      priority: 80,
      when: ['failure.promptDelivery', '!recovery.attempted'],
      action: 'recover_once',
      reason: 'prompt_delivery',
    },
    {
      id: 'escalate-repeated-prompt-delivery',
      priority: 70,
      when: ['failure.promptDelivery', 'recovery.attempted'],
      action: 'escalate',
      reason: 'prompt_delivery_repeated',
    },
    {
      id: 'warn-stale-running',
      priority: 40,
      when: ['branch.stale', 'session.running'],
      action: 'warn',
      reason: 'branch_stale_while_running',
    },
    {
      id: 'allow-scoped-green-review',
      priority: 10,
      when: ['green.ok', 'diff.scoped'],
      action: 'allow_review',
      reason: 'green_scoped_diff',
    },
  ]);
}

function getPath(obj, path) {
  return String(path || '').split('.').filter(Boolean).reduce((cur, key) => {
    if (cur == null) return undefined;
    return cur[key];
  }, obj);
}

module.exports = {
  PolicyEngine,
  conditionMatches,
  createDefaultCodingPolicy,
  matchesRule,
};
