
import { supabase } from '@/integrations/supabase/client';

/**
 * Evaluates a single condition against an entry.
 */
export const evaluateCondition = (condition, entry) => {
  const fieldValue = entry[condition.field];
  const stringVal = (fieldValue || '').toString().toLowerCase();
  const targetVal = (condition.value || '').toString().toLowerCase();
  const numVal = parseFloat(fieldValue);
  const targetNum = parseFloat(condition.value);

  switch (condition.operator) {
    case 'equals': return stringVal === targetVal;
    case 'not_equals': return stringVal !== targetVal;
    case 'contains': return stringVal.includes(targetVal);
    case 'not_contains': return !stringVal.includes(targetVal);
    case 'starts_with': return stringVal.startsWith(targetVal);
    case 'ends_with': return stringVal.endsWith(targetVal);
    case 'greater_than': return !isNaN(numVal) && !isNaN(targetNum) && numVal > targetNum;
    case 'less_than': return !isNaN(numVal) && !isNaN(targetNum) && numVal < targetNum;
    case 'is_empty': return !fieldValue || stringVal === '';
    case 'is_not_empty': return !!fieldValue && stringVal !== '';
    default: return false;
  }
};

/**
 * Applies a single action to an entry.
 */
export const applyAction = (action, entry) => {
  let updatedEntry = { ...entry };
  let blocked = false;
  let message = '';

  switch (action.action_type) {
    case 'set_field':
      if (action.field) {
        updatedEntry[action.field] = action.value;
        message = `Set ${action.field} to ${action.value}`;
      }
      break;
    case 'append_description':
      updatedEntry.description = `${updatedEntry.description || ''} ${action.value || ''}`.trim();
      message = `Appended to description: ${action.value}`;
      break;
    case 'flag_review':
      updatedEntry.needs_review = true;
      message = `Flagged for review.`;
      break;
    case 'prevent_save':
      blocked = true;
      message = `Blocked by rule: ${action.value || 'Condition matched.'}`;
      break;
    default:
      break;
  }

  return { updatedEntry, blocked, message };
};

/**
 * Main engine entry point.
 */
export const processEntryWithRules = async (entry, ruleType) => {
  if (!ruleType || !entry) return { entry, logs: [], blocked: false, blockReason: null };

  try {
    const { data: rules } = await supabase
      .from('accounting_rules')
      .select('*, rule_conditions(*), rule_actions(*)')
      .eq('rule_type', ruleType)
      .eq('status', 'active')
      .order('priority', { ascending: false });

    if (!rules || rules.length === 0) {
      return { entry, logs: [], blocked: false, blockReason: null };
    }

    let currentEntry = { ...entry };
    let logs = [];
    let isBlocked = false;
    let blockReason = null;

    for (const rule of rules) {
      const conditions = (rule.rule_conditions || []).sort((a, b) => a.order_index - b.order_index);
      const actions = (rule.rule_actions || []).sort((a, b) => a.order_index - b.order_index);

      if (conditions.length === 0) continue;

      let ruleMatched = false;
      let currentGroupResult = evaluateCondition(conditions[0], currentEntry);

      for (let i = 1; i < conditions.length; i++) {
        const cond = conditions[i];
        const res = evaluateCondition(cond, currentEntry);
        
        if (cond.logical_operator === 'AND') {
          currentGroupResult = currentGroupResult && res;
        } else if (cond.logical_operator === 'OR') {
          currentGroupResult = currentGroupResult || res;
        }
      }
      
      ruleMatched = currentGroupResult;

      if (ruleMatched) {
        logs.push(`Rule matched: [${rule.name}]`);
        
        for (const act of actions) {
          const { updatedEntry, blocked, message } = applyAction(act, currentEntry);
          currentEntry = updatedEntry;
          logs.push(`- Action applied: ${message}`);
          
          if (blocked) {
            isBlocked = true;
            blockReason = message;
            break;
          }
        }
        
        if (!currentEntry._applied_rules) currentEntry._applied_rules = [];
        currentEntry._applied_rules.push(rule.name);
      }

      if (isBlocked) break;
    }

    return { entry: currentEntry, logs, blocked: isBlocked, blockReason };

  } catch (error) {
    console.error("Rule Engine Error:", error);
    return { entry, logs: [`Error processing rules: ${error.message}`], blocked: false, blockReason: null };
  }
};
