<?php

/**
 * Validate that all required fields are present and non-empty in the body.
 * Calls json_error on failure (never returns in that case).
 */
function require_fields(array $body, array $fields): void {
    $missing = [];
    foreach ($fields as $f) {
        if (!isset($body[$f]) || (is_string($body[$f]) && trim($body[$f]) === '')) {
            $missing[] = $f;
        }
    }
    if ($missing) {
        json_error('MISSING_FIELDS', 'Required fields: ' . implode(', ', $missing), 400);
    }
}

/**
 * Validate a string value with optional min/max length.
 * Returns the trimmed string or calls json_error.
 */
function validate_string(mixed $value, string $fieldName, int $min = 0, int $max = 0): string {
    if (!is_string($value) && !is_numeric($value)) {
        json_error('INVALID_FIELD', "$fieldName must be a string", 400);
    }
    $s = trim((string)$value);
    if ($min > 0 && strlen($s) < $min) {
        json_error('INVALID_FIELD', "$fieldName must be at least $min characters", 400);
    }
    if ($max > 0 && strlen($s) > $max) {
        json_error('INVALID_FIELD', "$fieldName must be at most $max characters", 400);
    }
    return $s;
}

/**
 * Validate that a value is one of the allowed options.
 * Returns the value or calls json_error.
 */
function validate_enum(mixed $value, string $fieldName, array $allowed): string {
    $s = trim((string)$value);
    if (!in_array($s, $allowed, true)) {
        json_error('INVALID_FIELD', "$fieldName must be one of: " . implode(', ', $allowed), 400);
    }
    return $s;
}

/**
 * Validate and return an integer from body, with optional min/max bounds.
 */
function validate_int(mixed $value, string $fieldName, ?int $min = null, ?int $max = null): int {
    $i = (int)$value;
    if ($min !== null && $i < $min) {
        json_error('INVALID_FIELD', "$fieldName must be at least $min", 400);
    }
    if ($max !== null && $i > $max) {
        json_error('INVALID_FIELD', "$fieldName must be at most $max", 400);
    }
    return $i;
}

/**
 * Require the request method to match, or exit with 405.
 */
function require_method(string ...$allowed): void {
    $method = $_SERVER['REQUEST_METHOD'];
    if (!in_array($method, $allowed, true)) {
        json_error('METHOD_NOT_ALLOWED', 'Method not allowed', 405);
    }
}
