import { Question } from "@components/Widgets/SignupQuestionsWidget/common";
import { SignupFormQuestion } from "@models/Signup";
import { EMAIL_REGEX } from "@utils/regexes";
import escapeRegExp from "lodash/escapeRegExp";
import { Lang } from "../../i18n";

const questionToUISchemaProp = (question: Question) => {
  let obj: Record<"ui:widget", string>;
  if (question.type === "checkbox") {
    obj = {
      "ui:widget": "checkboxes",
    };
  } else if (question.type === "radiobutton") {
    obj = {
      "ui:widget": "radio",
    };
  }
  return {
    [question.id]: obj,
  };
};

const questionToValidationSchema = (question: Question) => {
  let obj: Record<string, unknown>;
  if (question.type === "text" || question.type === "name") {
    obj = {
      type: "string",
      title: question.name,
    };
  } else if (question.type === "info") {
    obj = {
      type: "null",
      title: question.name,
      description: question.description,
    };
  } else if (question.type === "email") {
    // Format is just a "FYI" field, so we also have pattern.
    obj = {
      type: question.required ? ["string"] : ["string", "null"],
      title: question.name,
      format: "email",
      pattern: EMAIL_REGEX.source,
      default: null,
    };
  } else if (question.type === "radiobutton") {
    obj = {
      type: "string",
      title: question.name,
      pattern: question.enum.map((x) => `^${escapeRegExp(x)}$`).join("|"),
      enum: question.enum,
      enumNames: question.enumNames,
    };
  } else if (question.type === "checkbox") {
    obj = {
      type: "array",
      title: question.name,
      uniqueItems: true,
      maxItems: question.enum.length,
      items: {
        type: "string",
        enum: question.enum,
        enumNames: question.enumNames,
        pattern: question.enum.map((x) => `^${escapeRegExp(x)}$`).join("|"),
      },
    };
  } else if (question.type === "integer") {
    // https://json-schema.org/understanding-json-schema/reference/numeric.html
    if (question.enum.length === 1) {
      obj = {
        type: "number",
        title: `${question.name} (Max: ${question.enum[0]})`,
        multipleOf: 1.0,
        maximum: Number(question.enum[0]),
      };
    } else if (question.enum.length === 2) {
      obj = {
        type: "number",
        title: `${question.name} (${question.enum[0]} -- ${question.enum[1]})`,
        multipleOf: 1.0,
        minimum: Number(question.enum[0]),
        maximum: Number(question.enum[1]),
      };
    } else {
      obj = {
        type: "number",
        title: question.name,
        multipleOf: 1.0,
      };
    }
  } else {
    throw new Error(`No mapping to schema prop for question type ${question.type}`);
  }
  return {
    [question.id]: obj,
  };
};

export const buildFormSchema = (questions: Question[], title: string) => {
  let schemaProps = {};
  const requiredIds = questions.filter((q) => q.required).map((q) => q.id);
  const schemaPropsArray = questions.map(questionToValidationSchema);
  schemaPropsArray.forEach((schemaProp) => {
    schemaProps = {
      ...schemaProps,
      ...schemaProp,
    };
  });

  const schema = {
    title,
    type: "object",
    required: requiredIds,
    properties: schemaProps,
  };

  return schema;
};

export const signupFormQuestionToQuestion = ({
  id, title_fi, title_en, description_fi, description_en, type, options, required,
}: SignupFormQuestion, language: Lang): Question => ({
  id,
  type,
  name: language === "fi" ? title_fi : title_en,
  enum: options?.enum,
  enumNames: language === "fi" ? options?.enumNames_fi : options?.enumNames_en,
  description: language === "fi" ? description_fi : description_en,
  required,
});

export const buildValidationSchema = (sfQuestions: SignupFormQuestion[]) => {
  let schemaProps = {};

  // Remove translations. We use Finnish translations as values for validation
  const questions = sfQuestions.map((q) => signupFormQuestionToQuestion(q, "fi"));

  // Force every radiobutton to be required field
  questions.forEach((q) => {
    if (q.type === "radiobutton") {
      // eslint-disable-next-line no-param-reassign
      q.required = true;
    }
  });

  const requiredIds = questions.filter((q) => q.required).map((q) => q.id);
  const schemaPropsArray = questions.map(questionToValidationSchema);
  schemaPropsArray.forEach((schemaProp) => {
    schemaProps = {
      ...schemaProps,
      ...schemaProp,
    };
  });

  const validationSchema = {
    type: "object",
    required: requiredIds,
    // minProperties: requiredIds.length,
    // maxProperties: requiredIds.length,
    properties: schemaProps,
  };
  return validationSchema;
};

export const buildUISchema = (questions: Question[]) => {
  const uiSchemaPropsArray = questions.map(questionToUISchemaProp);
  let uiSchemaProps = {};
  uiSchemaPropsArray.forEach((uiSchemaProp) => {
    uiSchemaProps = {
      ...uiSchemaProps,
      ...uiSchemaProp,
    };
  });

  const uiSchema = {
    ...uiSchemaProps,
  };
  return uiSchema;
};
