import { itGetCached, itPost } from "@/fetchHelpers";
import { deleteCircleDocument } from "@/services/files";
import type {
  CircleDocument,
  CourseSession,
  CourseSessionUser,
  ExpertSessionUser,
} from "@/types";
import _ from "lodash";
import log from "loglevel";
import { defineStore } from "pinia";
import { computed, ref } from "vue";
import { useRoute } from "vue-router";
import { useCircleStore } from "./circle";
import { useUserStore } from "./user";

export type CourseSessionsStoreState = {
  courseSessions: CourseSession[] | undefined;
};

export type LearningSequenceCircleDocument = {
  id: number;
  title: string;
  documents: CircleDocument[];
};

function loadCourseSessionsData(reload = false) {
  log.debug("loadCourseSessionsData called");
  const courseSessions = ref<CourseSession[]>([]);

  async function loadAndUpdate() {
    courseSessions.value = await itGetCached(`/api/course/sessions/`, {
      reload: reload,
    });

    // TODO: refactor after implementing of Klassenkonzept
    await Promise.all(
      courseSessions.value.map(async (cs) => {
        const users = (await itGetCached(
          `/api/course/sessions/${cs.course.slug}/users/`,
          {
            reload: reload,
          }
        )) as CourseSessionUser[];
        cs.users = users;
      })
    );

    const userStore = useUserStore();
    if (!courseSessions.value && userStore.loggedIn) {
      throw `No courseSessionData found for user`;
    }
  }

  loadAndUpdate(); // this will be called asynchronously, but does not block

  // returns the empty sessions array at first, then after loading populates the ref
  return { courseSessions };
}

export const useCourseSessionsStore = defineStore("courseSessions", () => {
  // using setup function seems cleaner, see https://pinia.vuejs.org/core-concepts/#setup-stores

  // this will become a state variable (like each other `ref()`

  // store should do own setup, we don't want to have each component initialize it
  // that's why we call the load function in here
  const { courseSessions } = loadCourseSessionsData();

  // these will become getters
  const coursesFromCourseSessions = computed(() =>
    // TODO: refactor after implementing of Klassenkonzept
    _.uniqBy(courseSessions.value, "course.id")
  );

  const courseSessionForRoute = computed(() => {
    const route = useRoute();
    const routePath = decodeURI(route.path);

    return courseSessions.value.find((cs) => {
      return routePath.startsWith(cs.course_url);
    });
  });

  const hasCockpit = computed(() => {
    if (courseSessionForRoute.value) {
      const userStore = useUserStore();
      return (
        userStore.course_session_experts.includes(courseSessionForRoute.value.id) ||
        userStore.is_superuser
      );
    }

    return false;
  });

  const circleExperts = computed(() => {
    const circleStore = useCircleStore();
    const circleTranslationKey = circleStore.circle?.translation_key;

    if (courseSessionForRoute.value && circleTranslationKey) {
      return courseSessionForRoute.value.users.filter((u) => {
        if (u.role === "EXPERT") {
          return (u as ExpertSessionUser).circles
            .map((c) => c.translation_key)
            .includes(circleTranslationKey);
        }
        return false;
      }) as ExpertSessionUser[];
    }
    return [];
  });

  const canUploadCircleDocuments = computed(() => {
    const userStore = useUserStore();
    return (
      circleExperts.value.filter((expert) => expert.user_id === userStore.id).length > 0
    );
  });

  const circleDocuments = computed(() => {
    const circleStore = useCircleStore();

    return circleStore.circle?.learningSequences
      .map((ls) => ({ id: ls.id, title: ls.title, documents: [] }))
      .map((ls: { id: number; title: string; documents: CircleDocument[] }) => {
        if (courseSessionForRoute.value === undefined) {
          return ls;
        }

        for (const document of courseSessionForRoute.value.documents) {
          if (document.learning_sequence === ls.id) {
            ls.documents.push(document);
          }
        }
        return ls;
      })
      .filter((ls) => ls.documents.length > 0);
  });

  function addDocument(document: CircleDocument) {
    courseSessionForRoute.value?.documents.push(document);
  }

  async function startUpload() {
    log.debug("loadCourseSessionsData called");
    courseSessions.value = await itPost(`/api/core/file/start`, {
      file_type: "image/png",
      file_name: "test.png",
    });
  }

  async function removeDocument(documentId: number) {
    await deleteCircleDocument(documentId);

    if (courseSessionForRoute.value === undefined) {
      return;
    }

    courseSessionForRoute.value.documents =
      courseSessionForRoute.value?.documents.filter((d) => d.id !== documentId);
  }

  return {
    courseSessions,
    coursesFromCourseSessions,
    courseSessionForRoute,
    hasCockpit,
    canUploadCircleDocuments,
    circleDocuments,
    circleExperts,
    addDocument,
    startUpload,
    removeDocument,
  };
});
