<?php
/**
 * api/coraza-rules-save.php — POST endpoint for server-wide rule state changes,
 * clear-state, and host-exception add/remove. Root-only, CSRF-enforced.
 *
 * Request body (form-encoded):
 *   action     = set_state | clear_state | add_host | remove_host
 *   rule_id    = <int>
 *   state      = enforce|detect|off                  (action=set_state)
 *   hostname   = <string>                            (action=add_host|remove_host)
 *   note       = <string, optional>
 *
 * Response (JSON):
 *   { ok: true, regen: { ok: bool, output: string } }
 *   { ok: false, error: string }
 */

require_once('/docker/whp/web/libs/permission_checker.php');
require_once('/docker/whp/web/libs/coraza_rule_manager.php');

header('Content-Type: application/json');

if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
    http_response_code(405);
    echo json_encode(['ok' => false, 'error' => 'POST required']);
    return;
}
if (!validate_csrf_token()) {
    http_response_code(403);
    echo json_encode(['ok' => false, 'error' => 'CSRF']);
    return;
}
if (!is_root_user()) {
    http_response_code(403);
    echo json_encode(['ok' => false, 'error' => 'admin only']);
    return;
}

$action  = (string)($_POST['action'] ?? '');
$rule_id = (int)($_POST['rule_id'] ?? 0);
$note    = isset($_POST['note']) && $_POST['note'] !== '' ? (string)$_POST['note'] : null;
$actor   = defined('AUTH_USER') ? AUTH_USER : 'unknown';

if ($rule_id < 1 || $rule_id > 999999) {
    http_response_code(400);
    echo json_encode(['ok' => false, 'error' => 'invalid rule_id']);
    return;
}

try {
    $m = new coraza_rule_manager();
    switch ($action) {
        case 'set_state':
            $state = (string)($_POST['state'] ?? '');
            $m->set_rule_state($rule_id, $state, $actor, $note);
            break;
        case 'clear_state':
            $m->clear_rule_state($rule_id, $actor);
            break;
        case 'add_host':
            $m->add_host_exception($rule_id, (string)($_POST['hostname'] ?? ''), $actor, $note);
            break;
        case 'remove_host':
            $m->remove_host_exception($rule_id, (string)($_POST['hostname'] ?? ''), $actor);
            break;
        default:
            throw new InvalidArgumentException('unknown action');
    }
    $regen = $m->regenerate_and_reload();
    echo json_encode(['ok' => true, 'regen' => $regen]);
} catch (Throwable $e) {
    http_response_code(400);
    echo json_encode(['ok' => false, 'error' => $e->getMessage()]);
}
