/**
 * Alert engine - runs every rule against every port. Called by the
 * BullMQ recurring job 'alerts-evaluate' every 5 minutes; exposed as a
 * function so integration tests can drive it without a worker.
 */

import { logger } from '@/lib/logger';
import { db } from '@/lib/db';
import { ports } from '@/lib/db/schema/ports';

import { reconcileAlertsForPort } from './alerts.service';
import { RULE_REGISTRY, listRuleIds } from './alert-rules';

export interface EngineRunSummary {
  portsScanned: number;
  rulesEvaluated: number;
  errors: Array<{ portId: string; ruleId: string; message: string }>;
}

/** Evaluate every rule for every port, upsert + auto-resolve. */
export async function runAlertEngine(): Promise<EngineRunSummary> {
  const allPorts = await db.select({ id: ports.id, slug: ports.slug }).from(ports);
  return runAlertEngineForPorts(allPorts.map((p) => p.id));
}

/** Same engine scoped to a specific list of port IDs (used by tests + the
 *  per-port webhook trigger). */
export async function runAlertEngineForPorts(portIds: string[]): Promise<EngineRunSummary> {
  const ruleIds = listRuleIds();
  const errors: EngineRunSummary['errors'] = [];

  for (const portId of portIds) {
    for (const ruleId of ruleIds) {
      try {
        const candidates = await RULE_REGISTRY[ruleId](portId);
        await reconcileAlertsForPort(portId, ruleId, candidates);
      } catch (err) {
        const message = err instanceof Error ? err.message : String(err);
        logger.warn({ portId, ruleId, err }, 'alert rule evaluator failed');
        errors.push({ portId, ruleId, message });
      }
    }
  }

  return {
    portsScanned: portIds.length,
    rulesEvaluated: portIds.length * ruleIds.length,
    errors,
  };
}
