// SPDX-License-Identifier: Apache-2.0
/* eslint-disable @typescript-eslint/no-explicit-any */
import "reflect-metadata";
import ValidationResponse from "./ValidationResponse";
import { EmptyValue } from "../error/EmptyValue";
import Mapper from "./Mapper";
import { getOptionalFields } from "../decorator/OptionalDecorator";
import { RuntimeError } from "../error/RuntimeError";
import { Validation } from "./Validation";
export default class ValidatedArgs extends Validation {
    schema;
    constructor(schema) {
        super();
        this.schema = schema;
    }
    validate(key) {
        const vals = [];
        if (!key) {
            const filteredEntries = this.filterSchemaFromProps();
            filteredEntries.forEach((key) => {
                this.pushValidations(key, vals);
            });
        }
        else {
            this.pushValidations(key, vals);
        }
        return vals;
    }
    getOptionalFields() {
        let keys = [];
        keys = Object.keys(getOptionalFields(this) ?? {});
        return keys;
    }
    isOptional(key) {
        return this.getOptionalFields().includes(key);
    }
    getProperty(propertyName) {
        if (this[propertyName] === undefined) {
            const privateKeys = {
                dash: `_${String(propertyName)}`,
                hash: `#${String(propertyName)}`,
            };
            if (this[privateKeys.dash]) {
                return this[privateKeys.dash];
            }
            else {
                return this[privateKeys.hash];
            }
        }
        return this[propertyName];
    }
    runValidation(propertyName, val) {
        if (this?.schema[propertyName] && val !== undefined) {
            try {
                const err = this.schema[propertyName]?.(val);
                if (err?.length && err.length > 0) {
                    return new ValidationResponse(propertyName.toString(), err);
                }
            }
            catch (err) {
                return new ValidationResponse(propertyName.toString(), [err]);
            }
        }
        else if (this?.schema[propertyName] && !this.isOptional(propertyName) && val === undefined) {
            return new ValidationResponse(propertyName.toString(), [new EmptyValue(propertyName)]);
        }
        else if (!this?.schema[propertyName] && !this.isOptional(propertyName)) {
            throw new RuntimeError(`Invalid validation schema for property '${propertyName.toString()}'. Did you forget to add the validation?`);
        }
    }
    filterSchemaFromProps() {
        const schemaEntries = Object.keys(this.schema);
        const entries = Mapper.renamePrivateProps(Object.keys(this));
        const filteredEntries = schemaEntries.filter((value) => entries.includes(value));
        return filteredEntries;
    }
    pushValidations(key, vals) {
        try {
            const err = this.runValidation(key, this.getProperty(key));
            err && vals.push(err);
        }
        catch (err) {
            vals.push(new ValidationResponse(key.toString(), [err]));
        }
    }
}
