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

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.options,
    };
  } 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.options.map((x) => `^${escapeRegExp(x)}$`).join("|"),
      enum: question.options,
    };
  } else if (question.type === "checkbox") {
    obj = {
      type: "array",
      title: question.name,
      uniqueItems: true,
      maxItems: question.options.length,
      items: {
        type: "string",
        enum: question.options,
        pattern: question.options.map((x) => `^${escapeRegExp(x)}$`).join("|"),
      },
    };
  } else if (question.type === "integer") {
    // https://json-schema.org/understanding-json-schema/reference/numeric.html
    if (question.options.length === 1) {
      obj = {
        type: "number",
        title: `${question.name} (Max: ${question.options[0]})`,
        multipleOf: 1.0,
        maximum: Number(question.options[0]),
      };
    } else if (question.options.length === 2) {
      obj = {
        type: "number",
        title: `${question.name} (${question.options[0]} -- ${question.options[1]})`,
        multipleOf: 1.0,
        minimum: Number(question.options[0]),
        maximum: Number(question.options[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 = (signUpForm: SignupForm) => {
  let schemaProps = {};
  const { questions } = signUpForm;
  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: signUpForm.id ? signUpForm.title_fi : "Loading...",
    type: "object",
    required: requiredIds,
    properties: schemaProps,
  };

  return schema;
};

export const buildValidationSchema = (questions: Question[]) => {
  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 validationSchema = {
    type: "object",
    required: requiredIds,
    // minProperties: requiredIds.length,
    // maxProperties: requiredIds.length,
    properties: schemaProps,
  };
  return validationSchema;
};

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

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