import {
  ReturnProcess,
  ReturnProcessQuestion,
  ReturnProcessQuestionKey,
  ReturnProcessQuestionSelectOptions,
  ReturnProcessSelectQuestion,
} from '../../models';
import {
  CategoryQuestions,
  ProductCategory,
  YesNoAnswer,
} from '../../questions';

/**
 * Dynamically returns the question set for the Tolino return process
 * based on user input collected so far (`process.answers`).
 *
 * This function adjusts the flow of questions by updating the `nextQuestion`
 * of the "Item Defective" question’s "No" option, depending on the
 * answers to "Device Power" and "Item Defective".
 *
 * This dynamic behavior ensures that the correct follow-up question
 * is shown depending on prior selections, making the return flow conditional
 * and tailored to the specific situation of the customer.
 *
 * @param process - The current return process state, including previously answered questions.
 * @returns A list of updated `ReturnProcessQuestion`s for the Tolino category.
 */
export const tolinoQuestions = (
  process: ReturnProcess,
): ReturnProcessQuestion[] => {
  const questions = CategoryQuestions[ProductCategory.Tolino];

  const devicePower = process.answers[
    ReturnProcessQuestionKey.DevicePower
  ] as YesNoAnswer;
  const itemDefective = process.answers[
    ReturnProcessQuestionKey.ItemDefective
  ] as YesNoAnswer;

  const itemDefectiveOption = getSelectOptionFromQuestion(
    questions,
    ReturnProcessQuestionKey.ItemDefective,
    YesNoAnswer.No,
  );

  itemDefectiveOption.nextQuestion = getNextQuestionKey(
    devicePower,
    itemDefective,
  );

  return questions;
};

/**
 * Retrieves a specific option from a select-type question in a given question list.
 *
 * Throws an error if the question or the option does not exist,
 * ensuring that the returned value is always valid and non-undefined.
 *
 * @param questions - The list of questions to search within.
 * @param questionKey - The key identifying the target question.
 * @param optionValue - The value of the option to retrieve from the question.
 * @returns The matching `ReturnProcessQuestionSelectOptions` object.
 */
const getSelectOptionFromQuestion = (
  questions: ReturnProcessQuestion[],
  questionKey: ReturnProcessQuestionKey,
  optionValue: string,
): ReturnProcessQuestionSelectOptions => {
  const question = questions.find((q) => q.key === questionKey);
  if (!question) throw new Error(`Question '${questionKey}' not found`);

  const option = (question as ReturnProcessSelectQuestion).options.find(
    (o) => o.value === optionValue,
  );
  if (!option)
    throw new Error(
      `Option '${optionValue}' not found in question '${questionKey}'`,
    );

  return option;
};

/**
 * Determines the next question in the Tolino return process flow
 * based on the combination of answers to "Device Power" and "Item Defective".
 *
 * This logic defines the branching decision for what should follow
 * depending on the customer’s answers.
 *
 * @param devicePower - Whether the device powers on (Yes or No).
 * @param itemDefective - Whether the item is defective (Yes or No).
 * @returns The key of the next question in the process flow.
 */
const getNextQuestionKey = (
  devicePower: YesNoAnswer,
  itemDefective: YesNoAnswer,
): ReturnProcessQuestionKey => {
  if (devicePower === YesNoAnswer.Yes && itemDefective === YesNoAnswer.No) {
    return ReturnProcessQuestionKey.ReturnReason;
  } else if (
    devicePower === YesNoAnswer.No &&
    itemDefective === YesNoAnswer.No
  ) {
    return ReturnProcessQuestionKey.ItemDamaged;
  } else {
    return ReturnProcessQuestionKey.CaseDamaged;
  }
};
