import { TResponseData } from "@formbricks/types/responses";
import { TSurvey, TSurveyQuestion, TSurveyQuestionTypeEnum } from "@formbricks/types/surveys/types";

export const getPrefillValue = (
  survey: TSurvey,
  searchParams: URLSearchParams,
  languageId: string
): TResponseData | undefined => {
  const prefillAnswer: TResponseData = {};
  let questionIdxMap: { [key: string]: number } = {};

  survey.questions.forEach((q, idx) => {
    questionIdxMap[q.id] = idx;
  });

  searchParams.forEach((value, key) => {
    const questionId = key;
    const questionIdx = questionIdxMap[questionId];
    const question = survey.questions[questionIdx];
    const answer = value;

    if (question && checkValidity(question, answer, languageId)) {
      prefillAnswer[questionId] = transformAnswer(question, answer, languageId);
    }
  });

  return Object.keys(prefillAnswer).length > 0 ? prefillAnswer : undefined;
};

export const checkValidity = (question: TSurveyQuestion, answer: string, language: string): boolean => {
  if (question.required && (!answer || answer === "")) return false;
  try {
    switch (question.type) {
      case TSurveyQuestionTypeEnum.OpenText: {
        return true;
      }
      case TSurveyQuestionTypeEnum.MultipleChoiceSingle: {
        const hasOther = question.choices[question.choices.length - 1].id === "other";
        if (!hasOther) {
          if (!question.choices.find((choice) => choice.label[language] === answer)) return false;
          return true;
        }

        if (question.choices[question.choices.length - 1].label[language] === answer) {
          return false;
        }

        return true;
      }
      case TSurveyQuestionTypeEnum.MultipleChoiceMulti: {
        const answerChoices = answer.split(",");
        const hasOther = question.choices[question.choices.length - 1].id === "other";
        if (!hasOther) {
          if (
            !answerChoices.every((ans: string) =>
              question.choices.find((choice) => choice.label[language] === ans)
            )
          )
            return false;
          return true;
        }
        return true;
      }
      case TSurveyQuestionTypeEnum.NPS: {
        answer = answer.replace(/&/g, ";");
        const answerNumber = Number(JSON.parse(answer));

        if (isNaN(answerNumber)) return false;
        if (answerNumber < 0 || answerNumber > 10) return false;
        return true;
      }
      case TSurveyQuestionTypeEnum.CTA: {
        if (question.required && answer === "dismissed") return false;
        if (answer !== "clicked" && answer !== "dismissed") return false;
        return true;
      }
      case TSurveyQuestionTypeEnum.Consent: {
        if (question.required && answer === "dismissed") return false;
        if (answer !== "accepted" && answer !== "dismissed") return false;
        return true;
      }
      case TSurveyQuestionTypeEnum.Rating: {
        answer = answer.replace(/&/g, ";");
        const answerNumber = Number(JSON.parse(answer));
        if (answerNumber < 1 || answerNumber > question.range) return false;
        return true;
      }
      case TSurveyQuestionTypeEnum.PictureSelection: {
        const answerChoices = answer.split(",");
        return answerChoices.every((ans: string) => !isNaN(Number(ans)));
      }
      default:
        return false;
    }
  } catch (e) {
    return false;
  }
};

export const transformAnswer = (
  question: TSurveyQuestion,
  answer: string,
  language: string
): string | number | string[] => {
  switch (question.type) {
    case TSurveyQuestionTypeEnum.OpenText:
    case TSurveyQuestionTypeEnum.MultipleChoiceSingle:
    case TSurveyQuestionTypeEnum.Consent:
    case TSurveyQuestionTypeEnum.CTA: {
      return answer;
    }

    case TSurveyQuestionTypeEnum.Rating:
    case TSurveyQuestionTypeEnum.NPS: {
      answer = answer.replace(/&/g, ";");
      return Number(JSON.parse(answer));
    }

    case TSurveyQuestionTypeEnum.PictureSelection: {
      const answerChoicesIdx = answer.split(",");
      const answerArr: string[] = [];

      answerChoicesIdx.forEach((ansIdx) => {
        const choice = question.choices[Number(ansIdx) - 1];
        if (choice) answerArr.push(choice.id);
      });

      if (question.allowMulti) return answerArr;
      return answerArr.slice(0, 1);
    }

    case TSurveyQuestionTypeEnum.MultipleChoiceMulti: {
      let ansArr = answer.split(",");
      const hasOthers = question.choices[question.choices.length - 1].id === "other";
      if (!hasOthers) return ansArr;

      // answer can be "a,b,c,d" and options can be a,c,others so we are filtering out the options that are not in the options list and sending these non-existing values as a single string(representing others) like "a", "c", "b,d"
      const options = question.choices.map((o) => o.label[language]);
      const others = ansArr.filter((a: string) => !options.includes(a));
      if (others.length > 0) ansArr = ansArr.filter((a: string) => options.includes(a));
      if (others.length > 0) ansArr.push(others.join(","));
      return ansArr;
    }

    default:
      return "dismissed";
  }
};
