import { validators } from "@inkline/inkline/validation/register";
import { reservedValidationFields } from "@inkline/inkline/constants";
import { translate } from "@inkline/inkline/i18n";
import {
  isFormFieldArray,
  isFormGroupArray,
  isFormField,
  isFormGroup
} from "@inkline/inkline/types";
export async function validateFormField(schema, path = "", rootSchema) {
  const errors = [];
  const resolvedSchema = {
    ...schema
  };
  let valid = true;
  for (const rawValidator of resolvedSchema.validators || []) {
    const validator = {
      ...typeof rawValidator === "string" ? { name: rawValidator } : rawValidator,
      schema: rootSchema,
      path
    };
    const valueIsValid = await validators[validator.name](
      resolvedSchema.value,
      validator
    );
    if (!valueIsValid) {
      const { name, message, ...params } = validator;
      const i18nParams = {
        name: path.split(".").pop(),
        value: schema.value,
        params
      };
      const errorMessage = (message instanceof Function ? message() : message) || translate(`validation.${name}`, i18nParams);
      errors.push({ name, message: errorMessage, path });
    }
    valid = valid && valueIsValid;
  }
  resolvedSchema.valid = valid;
  resolvedSchema.invalid = !valid;
  resolvedSchema.errors = errors;
  return resolvedSchema;
}
export async function validateFormFieldArray(schema, path = "", rootSchema) {
  return Promise.all(
    schema.map((item, index) => {
      return validateFormField(item, path ? `${path}.${index}` : `${index}`, rootSchema);
    })
  );
}
export async function validateFormArray(schema, path = "", rootSchema) {
  return Promise.all(
    schema.map((item, index) => {
      return validateForm(item, path ? `${path}.${index}` : `${index}`, rootSchema);
    })
  );
}
export async function validateForm(schema, name = "", rootSchema) {
  const resolvedSchema = {
    ...schema
  };
  let valid = true;
  const resolvedSchemaKeys = Object.keys(resolvedSchema).filter(
    (key) => !reservedValidationFields.includes(key)
  );
  for (const key of resolvedSchemaKeys) {
    const field = resolvedSchema[key];
    let fieldIsValid = true;
    if (isFormFieldArray(field)) {
      resolvedSchema[key] = await validateFormFieldArray(
        field,
        name ? `${name}.${key}` : `${key}`,
        rootSchema
      );
    } else if (isFormGroupArray(field)) {
      resolvedSchema[key] = await validateFormArray(
        field,
        name ? `${name}.${key}` : `${key}`,
        rootSchema
      );
    } else if (isFormField(field)) {
      resolvedSchema[key] = await validateFormField(
        field,
        name ? `${name}.${key}` : key,
        rootSchema
      );
    } else if (isFormGroup(field)) {
      resolvedSchema[key] = await validateForm(
        field,
        name ? `${name}.${key}` : key,
        rootSchema
      );
    }
    if (Array.isArray(resolvedSchema[key])) {
      fieldIsValid = resolvedSchema[key].every(
        (item) => item.valid
      );
    } else {
      fieldIsValid = resolvedSchema[key].valid;
    }
    valid = valid && fieldIsValid;
  }
  resolvedSchema.valid = valid;
  resolvedSchema.invalid = !valid;
  return resolvedSchema;
}
export async function validateSchema(schema) {
  return validateForm(schema, "", schema);
}
