<script setup lang="ts">
import { useCourseSessionDetailQuery, useCurrentCourseSession } from "@/composables";
import { UPSERT_ASSIGNMENT_COMPLETION_MUTATION } from "@/graphql/mutations";
import { ASSIGNMENT_COMPLETION_QUERY } from "@/graphql/queries";
import AssignmentIntroductionView from "@/pages/learningPath/learningContentPage/assignment/AssignmentIntroductionView.vue";
import AssignmentSubmissionView from "@/pages/learningPath/learningContentPage/assignment/AssignmentSubmissionView.vue";
import AssignmentTaskView from "@/pages/learningPath/learningContentPage/assignment/AssignmentTaskView.vue";
import LearningContentMultiLayout from "@/pages/learningPath/learningContentPage/layouts/LearningContentMultiLayout.vue";
import { useUserStore } from "@/stores/user";
import type {
  Assignment,
  AssignmentCompletion,
  AssignmentTask,
  LearningContentAssignment,
} from "@/types";
import { useMutation, useQuery } from "@urql/vue";
import { useRouteQuery } from "@vueuse/router";
import * as log from "loglevel";
import { computed, onMounted, ref, watchEffect } from "vue";
import { useTranslation } from "i18next-vue";
import { learningContentTypeData } from "@/utils/typeMaps";
import EvaluationSummary from "@/components/assignment/evaluation/EvaluationSummary.vue";
import { bustItGetCache } from "@/fetchHelpers";

const { t } = useTranslation();
const courseSession = useCurrentCourseSession();
const userStore = useUserStore();

const props = defineProps<{
  learningContent: LearningContentAssignment;
}>();

const queryResult = useQuery({
  query: ASSIGNMENT_COMPLETION_QUERY,
  variables: {
    courseSessionId: courseSession.value.id,
    assignmentId: props.learningContent.content_assignment.id,
    learningContentId: props.learningContent.id,
  },
  pause: true,
});

const courseSessionDetailResult = useCourseSessionDetailQuery();

const upsertAssignmentCompletionMutation = useMutation(
  UPSERT_ASSIGNMENT_COMPLETION_MUTATION
);

const submissionDeadline = computed(() => {
  return courseSessionDetailResult.findAssignment(props.learningContent.id)
    ?.submission_deadline;
});

// FIXME daniel: `useRouteQuery` from usevue is currently the reason that we have to
// fix the version of @vueuse/router and @vueuse/core to 10.1.0
// it fails with version 10.2.0. I have a reminder to check out the situation
// at the end of July 2023
// 0 = introduction, 1 - n = tasks, n+1 = submission
const stepIndex = useRouteQuery("step", "0", { transform: Number, mode: "push" });

const assignment = computed(
  () => queryResult.data.value?.assignment as Assignment | undefined
);
const assignmentCompletion = computed(
  () =>
    queryResult.data.value?.assignment_completion as AssignmentCompletion | undefined
);

const completionStatus = computed(() => {
  return assignmentCompletion.value?.completion_status ?? "IN_PROGRESS";
});

const hasRunUseQueryPostFetch = ref(false);
watchEffect(() => {
  if (
    queryResult.data.value &&
    !queryResult.error.value &&
    !hasRunUseQueryPostFetch.value
  ) {
    // workaround for setting step to last when not IN_PROGRESS anymore
    hasRunUseQueryPostFetch.value = true;
    try {
      if (
        stepIndex.value === 0 &&
        (completionStatus.value ?? "IN_PROGRESS") !== "IN_PROGRESS"
      ) {
        stepIndex.value = numPages.value - 1;
      }
    } catch (error) {
      log.error(error);
    }
  }
});

onMounted(async () => {
  log.debug(
    "AssignmentView mounted",
    props.learningContent.content_assignment.id,
    props.learningContent
  );

  // create initial `AssignmentCompletion` first, so that it exists and we don't
  // have reactivity problem accessing it.
  await initUpsertAssignmentCompletion();
  queryResult.resume();
});

const numTasks = computed(() => assignment.value?.tasks?.length ?? 0);
const numPages = computed(() => {
  return numTasks.value + 2;
});
const showPreviousButton = computed(() => stepIndex.value != 0);
const showNextButton = computed(() => stepIndex.value + 1 < numPages.value);

const currentTask = computed(() => {
  if (stepIndex.value > 0 && stepIndex.value <= numTasks.value) {
    return assignment.value?.tasks[stepIndex.value - 1];
  }
  return undefined;
});

const initUpsertAssignmentCompletion = async () => {
  try {
    await upsertAssignmentCompletionMutation.executeMutation({
      assignmentId: props.learningContent.content_assignment.id,
      courseSessionId: courseSession.value.id,
      learningContentId: props.learningContent.id,
      completionDataString: JSON.stringify({}),
      completionStatus: "IN_PROGRESS",
      // eslint-disable-next-line @typescript-eslint/ban-ts-comment
      // @ts-ignore
      id: assignmentCompletion.value?.id,
      initializeCompletion: true,
    });
    bustItGetCache(
      `/api/course/completion/${courseSession.value.id}/${useUserStore().id}/`
    );
  } catch (error) {
    log.error("Could not submit assignment", error);
  }
};

const handleBack = () => {
  log.debug("handleBack");
  if (stepIndex.value > 0) {
    stepIndex.value -= 1;
  }
  log.debug(`pageIndex: ${stepIndex.value}`);
};

const handleContinue = () => {
  log.debug("handleContinue");
  if (stepIndex.value + 1 < numPages.value) {
    stepIndex.value += 1;
  }
  log.debug(`pageIndex: ${stepIndex.value}`);
};

const jumpToTask = (task: AssignmentTask) => {
  log.debug("jumpToTask", task);
  const index = assignment.value?.tasks.findIndex((t) => t.id === task.id);
  if (index && index >= 0) {
    stepIndex.value = index + 1;
  }
  log.debug(`pageIndex: ${stepIndex.value}`);
};

const getTitle = () => {
  if (0 === stepIndex.value) {
    return t("general.introduction");
  } else if (stepIndex.value === numPages.value - 1) {
    return t("general.submission");
  }
  return currentTask?.value?.value.title ?? "Unknown";
};

const subTitle = computed(() => {
  if (assignment.value) {
    const prefix = learningContentTypeData(props.learningContent).title;
    return `${prefix}: ${assignment.value?.title ?? ""}`;
  }
  return "";
});

const assignmentUser = computed(() => {
  return (courseSessionDetailResult.courseSessionDetail.value?.users ?? []).find(
    (u) => u.user_id === userStore.id
  );
});
</script>

<template>
  <div v-if="queryResult.fetching.value"></div>
  <div v-else-if="queryResult.error.value">{{ queryResult.error.value }}</div>
  <div v-else>
    <div v-if="assignment && assignmentCompletion && assignmentUser">
      <div class="flex flex-col lg:flex-row">
        <div
          v-if="assignmentCompletion?.completion_status === 'EVALUATION_SUBMITTED'"
          class="min-w-2/5 mr-4 bg-gray-200 px-6 py-6 lg:order-last"
        >
          <EvaluationSummary
            :assignment-user="assignmentUser"
            :assignment="assignment"
            :assignment-completion="assignmentCompletion"
            :show-evaluation-user="true"
          ></EvaluationSummary>
        </div>
        <LearningContentMultiLayout
          :current-step="stepIndex"
          :sub-title="subTitle"
          :title="getTitle()"
          :learning-content="props.learningContent"
          :steps-count="numPages"
          :show-next-button="showNextButton && stepIndex !== 0"
          :show-exit-button="false"
          :show-start-button="showNextButton && stepIndex === 0"
          :show-previous-button="showPreviousButton"
          :base-url="props.learningContent.frontend_url"
          step-query-param="step"
          :start-badge-text="$t('general.introduction')"
          :end-badge-text="$t('general.submission')"
          close-button-variant="close"
          @previous="handleBack()"
          @next="handleContinue()"
        >
          <div class="flex">
            <div>
              <AssignmentIntroductionView
                v-if="stepIndex === 0"
                :assignment="assignment"
                :submission-deadline-start="submissionDeadline?.start"
              ></AssignmentIntroductionView>
              <AssignmentTaskView
                v-else-if="currentTask"
                :task="currentTask"
                :assignment-id="props.learningContent.content_assignment.id"
                :assignment-completion="assignmentCompletion"
                :learning-content-id="props.learningContent.id"
              ></AssignmentTaskView>
              <AssignmentSubmissionView
                v-else-if="stepIndex + 1 === numPages"
                :assignment="assignment"
                :assignment-completion="assignmentCompletion"
                :learning-content-id="props.learningContent.id"
                :course-session-id="courseSession.id"
                :submission-deadline-start="submissionDeadline?.start"
                @edit-task="jumpToTask($event)"
              ></AssignmentSubmissionView>
            </div>
          </div>
        </LearningContentMultiLayout>
      </div>
    </div>
    <div v-else>Could not load all data</div>
  </div>
</template>
