import * as _ from "lodash";

import { Circle } from "@/services/circle";
import type {
  Course,
  CourseCompletion,
  LearningContent,
  LearningPathChild,
  Topic,
  WagtailLearningPath,
} from "@/types";

function getLastCompleted(courseId: number, completionData: CourseCompletion[]) {
  return _.orderBy(completionData, ["updated_at"], "desc").find(
    (c: CourseCompletion) => {
      return (
        c.completion_status === "success" &&
        c.course === courseId &&
        c.page_type === "learnpath.LearningContent"
      );
    }
  );
}

export class LearningPath implements WagtailLearningPath {
  readonly type = "learnpath.LearningPath";
  public topics: Topic[];
  public circles: Circle[];
  public nextLearningContent?: LearningContent;

  public static fromJson(
    json: WagtailLearningPath,
    completionData: CourseCompletion[]
  ): LearningPath {
    return new LearningPath(
      json.id,
      json.slug,
      json.course.title,
      json.translation_key,
      json.frontend_url,
      json.course,
      json.children,
      completionData
    );
  }

  constructor(
    public readonly id: number,
    public readonly slug: string,
    public readonly title: string,
    public readonly translation_key: string,
    public readonly frontend_url: string,
    public readonly course: Course,
    public children: LearningPathChild[],
    completionData?: CourseCompletion[]
  ) {
    // parse children
    this.topics = [];
    this.circles = [];

    let topic: Topic | undefined;

    this.children.forEach((page) => {
      if (page.type === "learnpath.Topic") {
        if (topic) {
          this.topics.push(topic);
        }
        topic = Object.assign(page, { circles: [] });
      }
      if (page.type === "learnpath.Circle") {
        const circle = Circle.fromJson(page, this);
        if (completionData) {
          circle.parseCompletionData(completionData);
        }
        if (topic) {
          topic.circles.push(circle);
        }

        circle.previousCircle = this.circles[this.circles.length - 1];
        if (circle.previousCircle) {
          circle.previousCircle.nextCircle = circle;
        }
        this.circles.push(circle);
      }
    });

    if (topic) {
      this.topics.push(topic);
    }

    if (completionData) {
      this.calcNextLearningContent(completionData);
    }
  }

  public calcNextLearningContent(completionData: CourseCompletion[]): void {
    this.nextLearningContent = undefined;

    const lastCompletedLearningContent = getLastCompleted(
      this.course.id,
      completionData
    );

    if (lastCompletedLearningContent) {
      const lastCircle = this.circles.find((circle) => {
        return circle.flatLearningContents.find(
          (learningContent) =>
            learningContent.translation_key === lastCompletedLearningContent.page_key
        );
      });
      if (lastCircle) {
        const lastLearningContent = lastCircle.flatLearningContents.find(
          (learningContent) =>
            learningContent.translation_key === lastCompletedLearningContent.page_key
        );
        if (lastLearningContent && lastLearningContent.nextLearningContent) {
          this.nextLearningContent = lastLearningContent.nextLearningContent;
        } else {
          if (lastCircle.nextCircle) {
            this.nextLearningContent = lastCircle.nextCircle.flatLearningContents[0];
          }
        }
      }
    } else {
      if (this.circles[0]) {
        this.nextLearningContent = this.circles[0].flatLearningContents[0];
      }
    }
  }
}
