module util.validation.common;

import handy_http_primitives.optional;
import std.datetime;

struct ValidationError {
    string field;
    string message;
}

interface ValidationRule(T) {
    Optional!ValidationError validate(in T payload);
}

ValidationError[] applyValidationRules(T)(ValidationRule!(T)[] rules, in T payload) {
    import std.array;
    auto app = appender!(ValidationError[]);
    foreach (rule; rules) {
        auto result = rule.validate(payload);
        if (result) app ~= result.value;
    }
    return app[];
}

// Helper functions:

void validateTags(in string[] tags) {
    import std.regex;
    import handy_http_primitives: HttpStatus, HttpStatusException;
    foreach (tag; tags) {
        import std.regex;
        auto r = ctRegex!(`^[a-z0-9-_]{3,32}$`);
        if (!matchFirst(tag, r)) {
            throw new HttpStatusException(HttpStatus.BAD_REQUEST, "Invalid tag: \"" ~ tag ~ "\".");
        }
    }
}

SysTime validateTimestampFormat(string timestampStr) {
    import handy_http_primitives: HttpStatus, HttpStatusException;
    try {
        return SysTime.fromISOExtString(timestampStr, UTC());
    } catch (TimeException e) {
        throw new HttpStatusException(HttpStatus.BAD_REQUEST, "Invalid timestamp format. Expected ISO-8601 datetime.");
    }
}
