import { evaluate } from './evaluator';
import { canRun, mark } from './cooldown';
import { execute } from './actions';
import { recordFeedback } from './memory';
import { updateMetrics } from './metrics';
import { DefaultPolicy } from './policy';
import { chooseAction } from './policy';
import type { Signal } from './types';

export async function runFeedbackCycle(signals: Signal[], at: number) {
  const evaln = evaluate(signals);
  const policy = DefaultPolicy;

  let action: any = null;
  let result: any = null;
  let blockedBy: string | null = null;

  try {
    // أمان: كريتيكال + ثقة ضعيفة جدًا → منع
    if (evaln.severity === 'CRITICAL' && (evaln.confidence ?? 1) < 0.2) {
      blockedBy = 'safety';
    } else {
      // اختار الإجراء حسب السياسة
      action = chooseAction(evaln, policy);

      // مهم: الـ cooldown يتحسب **فقط** لو في Action فعلي
      if (action && !canRun('FEEDBACK', at, policy.cooldownMs)) {
        blockedBy = 'cooldown';
        action = null;
      } else if (action) {
        // علّم آخر تنفيذ لنفس الدورة
        mark('FEEDBACK', at, true);
      }

      // تنفيذ الفعل (لو موجود) مع ضمان ok دائمًا
      if (action) {
        try {
          const execResult = await execute(action);
          result = { ...execResult, ok: true };
        } catch (err) {
          result = { ok: false, error: (err as Error).message };
        }
      } else {
        // لا يوجد فعل → اعتبر الدورة ناجحة (ok:true) علشان متريكس تتحدث
        result = { ok: true };
      }
    }

    // سجّل في الذاكرة
    await recordFeedback({
      at,
      evaluation: evaln,
      chosenAction: action,
      result,
      policyVersion: policy.version,
      blockedBy,
    });

    // حدّث المقاييس
    updateMetrics(result, at);

    // ارجع الناتج
    return { evaln, action, result, blockedBy };
  } catch (err) {
    console.error('[runFeedbackCycle] Crash:', err);
    const crash = { ok: false, error: String(err) };
    updateMetrics(crash, at);
    await recordFeedback({
      at,
      evaluation: evaln,
      chosenAction: action,
      result: crash,
      policyVersion: policy.version,
      blockedBy: 'error',
    });
    return { evaln, action, result: crash, blockedBy: 'error' };
  }
}
