<?php
/**
 * AI Monitor ignore-rule filter.
 *
 * Loads rules in whp.ai_monitor_ignore_rules whose scope applies to the
 * (username, site_id) context, then evaluates each rule's match_* columns
 * against the finding using AND-semantics across set fields. Logs a hit
 * and bumps the rule counters when a rule fully matches.
 */

if (!function_exists('ai_monitor_should_ignore')) {

    function ai_monitor_disable_broken_rule(PDO $db, int $rule_id, string $reason): void {
        try {
            $stmt = $db->prepare("UPDATE whp.ai_monitor_ignore_rules SET enabled = 0 WHERE id = ? AND enabled = 1");
            $stmt->execute([$rule_id]);
            if ($stmt->rowCount() > 0) {
                error_log("ai_monitor_ignore_rules: auto-disabled rule id={$rule_id} ({$reason})");
            }
        } catch (Throwable $e) {
            error_log("ai_monitor_ignore_rules: failed to auto-disable rule id={$rule_id}: " . $e->getMessage());
        }
    }

    function ai_monitor_should_ignore(PDO $db, array $finding, ?int $site_id, ?string $username): bool {
        try {
            $stmt = $db->prepare("
                SELECT id, match_category, match_severity, match_title_substr, match_raw_regex
                FROM whp.ai_monitor_ignore_rules
                WHERE enabled = 1
                  AND (
                        scope = 'global'
                     OR (scope = 'user' AND username = ?)
                     OR (scope = 'site' AND site_id = ?)
                  )
            ");
            $stmt->execute([$username, $site_id]);
            $rules = $stmt->fetchAll(PDO::FETCH_ASSOC);
        } catch (Throwable $e) {
            error_log('ai_monitor_should_ignore: rule load failed: ' . $e->getMessage());
            return false;
        }

        if (!$rules) {
            return false;
        }

        $category = (string)($finding['category'] ?? '');
        $severity = (string)($finding['severity'] ?? '');
        $title    = (string)($finding['title'] ?? '');
        $raw      = (string)($finding['raw_log_excerpt'] ?? ($finding['evidence'] ?? ''));
        $signature = (string)($finding['signature'] ?? '');

        $titleLower = strtolower($title);

        foreach ($rules as $rule) {
            $hasMatchField = false;

            if ($rule['match_category'] !== null && $rule['match_category'] !== '') {
                $hasMatchField = true;
                if ($rule['match_category'] !== $category) {
                    continue;
                }
            }
            if ($rule['match_severity'] !== null && $rule['match_severity'] !== '') {
                $hasMatchField = true;
                if ($rule['match_severity'] !== $severity) {
                    continue;
                }
            }
            if ($rule['match_title_substr'] !== null && $rule['match_title_substr'] !== '') {
                $hasMatchField = true;
                if (stripos($title, $rule['match_title_substr']) === false) {
                    continue;
                }
            }
            if ($rule['match_raw_regex'] !== null && $rule['match_raw_regex'] !== '') {
                $hasMatchField = true;
                $pattern = '/' . str_replace('/', '\\/', $rule['match_raw_regex']) . '/iu';
                $result = @preg_match($pattern, $raw);
                if ($result === false) {
                    ai_monitor_disable_broken_rule($db, (int)$rule['id'], 'preg_match returned false');
                    continue;
                }
                if ($result !== 1) {
                    continue;
                }
            }

            // A rule with NO match_* fields set would match everything in its
            // scope — refuse to honor it (operator almost certainly didn't
            // mean to silence the whole monitor).
            if (!$hasMatchField) {
                continue;
            }

            try {
                $db->beginTransaction();
                $ins = $db->prepare("
                    INSERT INTO whp.ai_monitor_ignore_hits
                        (rule_id, site_id, username, matched_category, matched_title, matched_signature)
                    VALUES (?, ?, ?, ?, ?, ?)
                ");
                $ins->execute([
                    (int)$rule['id'],
                    $site_id,
                    $username,
                    $category !== '' ? $category : null,
                    $title !== '' ? substr($title, 0, 255) : null,
                    $signature !== '' ? substr($signature, 0, 64) : null,
                ]);
                $upd = $db->prepare("
                    UPDATE whp.ai_monitor_ignore_rules
                    SET hit_count = hit_count + 1, last_hit_at = NOW()
                    WHERE id = ?
                ");
                $upd->execute([(int)$rule['id']]);
                $db->commit();
            } catch (Throwable $e) {
                if ($db->inTransaction()) {
                    $db->rollBack();
                }
                error_log('ai_monitor_should_ignore: hit log failed for rule id='
                    . $rule['id'] . ': ' . $e->getMessage());
            }

            return true;
        }

        return false;
    }
}
