<script setup lang="ts">
import { graphql } from "@/gql";
import FeedbackCompletition from "@/pages/learningPath/learningContentPage/feedback/FeedbackCompletition.vue";
import LearningContentMultiLayout from "@/pages/learningPath/learningContentPage/layouts/LearningContentMultiLayout.vue";
import type { LearningContentFeedbackUK, LearningContentFeedbackVV } from "@/types";
import { useMutation } from "@urql/vue";
import { useRouteQuery } from "@vueuse/router";
import log from "loglevel";
import { computed, onMounted, reactive, ref } from "vue";
import { useCourseSessionDetailQuery, useCurrentCourseSession } from "@/composables";
import { bustItGetCache } from "@/fetchHelpers";
import { useUserStore } from "@/stores/user";

const props = defineProps<{
  content: LearningContentFeedbackVV | LearningContentFeedbackUK;
  stepLabels: string[];
  questionData: any[];
  introduction: string;
  title: string;
  completionTitle: string;
  completionDescription: string;
  showAvatar: boolean;
}>();
const courseSession = useCurrentCourseSession();
const courseSessionDetailResult = useCourseSessionDetailQuery();

const stepNo = useRouteQuery("step", "0", { transform: Number, mode: "push" });

const title = computed(() => `«${props.content.circle?.title}»: ${props.title}`);

const circleExperts = computed(() => {
  if (props.content?.circle?.slug) {
    return courseSessionDetailResult.filterCircleExperts(props.content.circle.slug);
  }
  return [];
});

const localStepLabels = ref(props.stepLabels);
const localQuestionData = ref(props.questionData);
const feedbackData: FeedbackData = reactive(feedbackDataFactory());

const numSteps = computed(() => localStepLabels.value.length);
const textQuestionKeys = computed(() =>
  props.questionData.filter((item) => isTextNode(item)).map((item) => item.modelKey)
);
const avatarUrl = computed(() => circleExperts.value[0]?.avatar_url);

// noinspection GraphQLUnresolvedReference -> mute IntelliJ warning
const sendFeedbackMutation = graphql(`
  mutation SendFeedbackMutation(
    $courseSessionId: ID!
    $learningContentId: ID!
    $learningContentType: String!
    $data: GenericScalar!
    $submitted: Boolean
  ) {
    send_feedback(
      course_session_id: $courseSessionId
      learning_content_page_id: $learningContentId
      learning_content_type: $learningContentType
      data: $data
      submitted: $submitted
    ) {
      feedback_response {
        id
        data
        submitted
      }
      errors {
        field
        messages
      }
    }
  }
`);

const feedbackSubmitted = ref(false);

const { executeMutation } = useMutation(sendFeedbackMutation);

interface FeedbackData {
  [key: string]: number | string | null;
}

const previousStep = () => {
  if (stepNo.value > 0) {
    stepNo.value -= 1;
  }
};

const nextStep = () => {
  if (stepNo.value < numSteps.value && hasStepValidInput(stepNo.value)) {
    stepNo.value += 1;
  }
  log.debug(`next step ${stepNo.value} of ${numSteps.value}`);
  mutateFeedback(feedbackData);
};

function hasStepValidInput(stepNumber: number) {
  const question = localQuestionData.value[stepNumber - 1];
  if (question) {
    if (textQuestionKeys.value.includes(question.modelKey)) {
      // text response questions need to have a "truthy" value (not "" or null)
      return feedbackData[question.modelKey];
    } else {
      // other responses need to have data, can be `0` or `false`
      return feedbackData[question.modelKey] !== null;
    }
  }
  return true;
}

function mutateFeedback(data: FeedbackData, submit = false) {
  log.debug("mutate feedback", feedbackData);
  return executeMutation({
    courseSessionId: courseSession.value.id,
    learningContentId: props.content.id,
    learningContentType: props.content.content_type,
    data: data,
    submitted: submit,
  })
    .then((result) => {
      log.debug("feedback mutation result", result);
      if (result.data?.send_feedback?.feedback_response?.data) {
        const responseData = result.data.send_feedback.feedback_response.data;
        textQuestionKeys.value.map((key) => {
          if (!responseData[key]) {
            responseData[key] = "";
          }
        });
        Object.assign(feedbackData, responseData);
        log.debug("feedback data", feedbackData);
        feedbackSubmitted.value =
          result.data?.send_feedback?.feedback_response?.submitted || false;
      }
      bustItGetCache(
        `/api/course/completion/${courseSession.value.id}/${useUserStore().id}/`
      );
    })
    .catch((e) => log.error(e));
}

function feedbackDataFactory() {
  const data: FeedbackData = {};
  localQuestionData.value.map((item) => {
    data[item.modelKey] = isTextNode(item) ? "" : null;
  });
  return data;
}

function isTextNode(item: any) {
  return item.component.props.placeholder;
}

onMounted(async () => {
  log.debug("Feedback mounted");
  await mutateFeedback({});
  if (feedbackSubmitted.value) {
    stepNo.value = numSteps.value - 1;
  }
});
</script>

<template>
  <LearningContentMultiLayout
    :title="title"
    sub-title="Feedback"
    :learning-content="content"
    :show-start-button="stepNo === 0"
    :show-next-button="stepNo > 0 && stepNo + 1 < numSteps"
    :disable-next-button="!hasStepValidInput(stepNo)"
    :show-previous-button="stepNo > 0 && !feedbackSubmitted"
    :show-exit-button="stepNo + 1 === numSteps"
    :current-step="stepNo"
    :steps-count="numSteps"
    :start-badge-text="$t('general.introduction')"
    :end-badge-text="$t('general.submission')"
    :base-url="props.content.frontend_url"
    close-button-variant="close"
    @previous="previousStep()"
    @next="nextStep()"
  >
    <div>
      <p v-if="stepNo === 0" class="mt-10" data-cy="introduction">
        {{ introduction }}
      </p>
      <p
        v-if="stepNo > 0 && stepNo + 1 < numSteps"
        class="pb-2"
        :data-cy="`question-${stepNo}`"
      >
        {{ localStepLabels[stepNo] }}
      </p>
      <div v-for="(question, index) in questionData" :key="index">
        <!-- eslint-disable -->
        <!-- eslint does not like the dynamic v-model... -->
        <component
          :is="question.component"
          v-if="index + 1 === stepNo && feedbackData != undefined"
          v-model="feedbackData[question.modelKey] as any"
          :items="question['items']"
          :cy-key="question.modelKey"
        />
        <!-- eslint-enable -->
      </div>
      <FeedbackCompletition
        v-if="stepNo === numSteps - 1"
        :avatar-url="avatarUrl"
        :show-avatar="showAvatar"
        :title="completionTitle"
        :description="completionDescription"
        :feedback-sent="feedbackSubmitted"
        @send-feedback="mutateFeedback(feedbackData, true)"
      />
    </div>
  </LearningContentMultiLayout>
</template>
