import type { StatusCountKey } from "@/components/ui/ItProgress.vue";
import { itGet } from "@/fetchHelpers";
import type { LearningPath } from "@/services/learningPath";
import { useCockpitStore } from "@/stores/cockpit";
import { useCourseSessionsStore } from "@/stores/courseSessions";
import { useLearningPathStore } from "@/stores/learningPath";
import { useUserStore } from "@/stores/user";
import type {
  Assignment,
  AssignmentCompletion,
  AssignmentCompletionStatus,
  CourseSessionUser,
  LearningContentAssignment,
  LearningContentInterface,
  UserAssignmentCompletionStatus,
} from "@/types";
import { sum } from "d3";
import pick from "lodash/pick";

export interface AssignmentLearningContent extends LearningContentInterface {
  assignmentId: number;
}

export function calcAssignmentLearningContents(learningPath?: LearningPath) {
  // TODO: filter by circle
  if (!learningPath) return [];

  return learningPath.circles.flatMap((circle) => {
    const learningContents = circle.flatLearningContents.filter(
      (lc) =>
        lc.content_type === "learnpath.LearningContentAssignment" &&
        lc.assignment_type === "CASEWORK"
    ) as LearningContentAssignment[];
    return learningContents.map((lc) => {
      return {
        ...lc,
        assignmentId: lc.content_assignment_id,
      };
    });
  }) as AssignmentLearningContent[];
}

export async function loadAssignmentCompletionStatusData(
  assignmentId: number,
  courseSessionId: number
) {
  const cockpitStore = useCockpitStore();

  const assignmentCompletionData = (await itGet(
    `/api/assignment/${assignmentId}/${courseSessionId}/status/`
  )) as UserAssignmentCompletionStatus[];

  const courseSessionUsers = await cockpitStore.loadCourseSessionUsers(courseSessionId);

  return calcUserAssignmentCompletionStatus(
    courseSessionUsers,
    assignmentCompletionData
  );
}

export function calcUserAssignmentCompletionStatus(
  courseSessionUsers: CourseSessionUser[],
  assignmentCompletionStatusData: UserAssignmentCompletionStatus[]
) {
  return courseSessionUsers.map((u) => {
    let userStatus = "unknown" as AssignmentCompletionStatus;
    const userAssignmentStatus = assignmentCompletionStatusData?.find(
      (s) => s.assignment_user_id === u.user_id
    );
    if (userAssignmentStatus) {
      userStatus = userAssignmentStatus.completion_status;
    }
    let progressStatus: StatusCountKey = "unknown";
    if (
      ["SUBMITTED", "EVALUATION_IN_PROGRESS", "EVALUATION_SUBMITTED"].includes(
        userStatus
      )
    ) {
      progressStatus = "success";
    }

    return {
      userId: u.user_id,
      userStatus,
      progressStatus,
      grade: userAssignmentStatus?.evaluation_grade ?? null,
    };
  });
}

export function findAssignmentDetail(assignmentId: number) {
  const learningPathStore = useLearningPathStore();
  const userStore = useUserStore();
  const courseSessionsStore = useCourseSessionsStore();

  // TODO: filter by selected circle
  if (!courseSessionsStore.currentCourseSession) {
    return undefined;
  }

  const learningContents = calcAssignmentLearningContents(
    learningPathStore.learningPathForUser(
      courseSessionsStore.currentCourseSession.course.slug,
      userStore.id
    )
  );

  const learningContent = learningContents.find(
    (lc) => lc.assignmentId === assignmentId
  );

  return courseSessionsStore.findAssignmentDetails(learningContent?.id);
}

export function maxAssignmentPoints(assignment: Assignment) {
  return sum(assignment.evaluation_tasks.map((task) => task.value.max_points));
}

export function userAssignmentPoints(
  assignment: Assignment,
  assignmentCompletion: AssignmentCompletion
) {
  const evaluationTaskIds = assignment.evaluation_tasks.map((task) => {
    return task.id;
  });

  return sum(
    // transform the object of { [expert_id]: { expert_data: { points } } } to an array
    // of [ [expert_id, { expert_data: { points } }], ... ] so that we can easily sum
    // the points of the user
    Object.entries(pick(assignmentCompletion.completion_data, evaluationTaskIds)).map(
      (entry) => {
        return entry[1]?.expert_data?.points ?? 0;
      }
    )
  );
}

export function pointsToGrade(points: number, maxPoints: number) {
  // round to half-grades
  const grade = Math.round((points / maxPoints) * 10);
  const halfGrade = grade / 2;
  return Math.min(halfGrade, 5) + 1;
}
