import { useCSRFFetch } from "@/fetchHelpers";
import type { User } from "@/types";
import { toValue } from "@vueuse/core";
import { t } from "i18next";
import log from "loglevel";
import type { Ref } from "vue";
import { computed, onMounted, ref } from "vue";

export interface FeedbackRequest {
  feedback_id: string;
  learning_unit_id: number;
  circle_name: string;
  title: string;
  // submitted => provider submitted (released) his/her feedback
  feedback_submitted: boolean;
  feedback_requester_user: User;
  feedback_provider_user: User;
  criteria: Criterion[];
}

export interface Criterion {
  course_completion_id: string;
  title: string;
  self_assessment: "FAIL" | "SUCCESS" | "UNKNOWN";
  feedback_assessment: "FAIL" | "SUCCESS" | "UNKNOWN";
}

interface FeedbackSummaryCounts {
  pass: number;
  fail: number;
  unknown: number;
}

export interface FeedbackSummaryAggregates {
  // totals across all learning units in the course session
  self_assessment: FeedbackSummaryCounts;
  feedback_assessment: FeedbackSummaryCounts;
  // does this course have any feedback?
  feedback_assessment_visible: boolean;
}

interface FeedbackAssessmentSummary {
  counts: FeedbackSummaryCounts;
  submitted_by_provider: boolean;
  provider_user: User;
}

interface SelfAssessmentSummary {
  counts: FeedbackSummaryCounts;
}

export interface LearningUnitSummary {
  id: string;
  title: string;
  circle_id: string;
  circle_title: string;
  feedback_assessment?: FeedbackAssessmentSummary;
  self_assessment: SelfAssessmentSummary;
  detail_url: string;
}

interface Circle {
  id: number;
  title: string;
}

/** To keep the backend permissions model simple, we have two endpoints:
 * 1. /requester/: for the user who requested the feedback
 * 2. /provider/: for the user who provides the feedback
 *
 * Design decision: We generally just re-fetch the whole feedback from the backend
 * after each action (e.g. request, release, add-assessment) to keep the frontend simple.
 */
export function useSelfEvaluationFeedback(
  learningUnitId: Ref<string> | string,
  feedbackRole: "requester" | "provider"
) {
  const feedback = ref<FeedbackRequest>();
  const loading = ref(false);
  const error = ref();

  const url = computed(
    () => `/api/self-evaluation-feedback/${feedbackRole}/${learningUnitId}/feedback`
  );

  const fetchFeedback = async () => {
    error.value = undefined;
    loading.value = true;

    log.info("Fetching feedback for learning unit", learningUnitId);
    const { data, statusCode, error: _error } = await useCSRFFetch(url.value).json();
    loading.value = false;

    if (_error.value) {
      error.value = _error;
      feedback.value = undefined;
      return;
    }

    if (statusCode.value === 404) {
      feedback.value = undefined;
    } else {
      feedback.value = data.value;
    }
  };

  const requestFeedback = async (fromProviderUserId: string) => {
    if (feedbackRole !== "requester") {
      console.warn("Cannot request feedback");
      return;
    }

    const url = `/api/self-evaluation-feedback/requester/${toValue(
      learningUnitId
    )}/feedback/start`;
    await useCSRFFetch(url).post({
      feedback_provider_user_id: fromProviderUserId,
    });

    await fetchFeedback();
  };

  const addFeedbackAssessment = async (
    courseCompletionId: string,
    assessment: "FAIL" | "SUCCESS"
  ) => {
    if (feedbackRole !== "provider" || !feedback.value) {
      console.warn("Cannot add feedback assessment");
      return;
    }

    await useCSRFFetch(
      `/api/self-evaluation-feedback/provider/feedback/${feedback.value.feedback_id}/add-assessment`
    ).put({
      course_completion_id: courseCompletionId,
      feedback_assessment: assessment,
    });

    await fetchFeedback();
  };

  const releaseFeedback = async () => {
    if (feedbackRole !== "provider" || !feedback.value) {
      console.warn("Cannot release feedback");
      return;
    }

    await useCSRFFetch(
      `/api/self-evaluation-feedback/provider/feedback/${feedback.value.feedback_id}/release`
    ).put({});

    await fetchFeedback();
  };

  onMounted(fetchFeedback);

  return {
    feedback,
    error,
    loading,
    // feedback requester actions
    requestFeedback,
    // feedback provider actions
    addFeedbackAssessment,
    releaseFeedback,
  };
}

export function useSelfEvaluationFeedbackSummaries(
  courseSessionId: Ref<string> | string
) {
  const summaries = ref<LearningUnitSummary[]>([]);
  const aggregates = ref<FeedbackSummaryAggregates>();
  const circles = ref<Circle[]>([]);
  const loading = ref(false);
  const error = ref();

  const url = computed(
    () =>
      `/api/self-evaluation-feedback/requester/${courseSessionId}/feedbacks/summaries`
  );

  const fetchFeedbackSummaries = async () => {
    error.value = undefined;
    loading.value = true;

    log.info("Fetching feedback summaries for course session", courseSessionId);
    const { data, error: _error } = await useCSRFFetch(url.value).json();
    loading.value = false;

    if (_error.value) {
      error.value = _error;
      summaries.value = [];
      circles.value = [];
      aggregates.value = undefined;
      return;
    }

    summaries.value = data.value.results;
    aggregates.value = data.value.aggregates;
    circles.value = data.value.circles;
  };

  onMounted(fetchFeedbackSummaries);

  return {
    summaries,
    aggregates,
    circles,
    loading,
    error,
  };
}

export const getSmiley = (assessment: "FAIL" | "SUCCESS" | "UNKNOWN") => {
  switch (assessment) {
    case "SUCCESS":
      return "it-icon-smiley-happy";
    case "FAIL":
      return "it-icon-smiley-thinking";
    default:
      return "it-icon-smiley-neutral";
  }
};

export const getSelfEvaluationCaption = (
  assessment: "FAIL" | "SUCCESS" | "UNKNOWN"
) => {
  switch (assessment) {
    case "SUCCESS":
      return t("selfEvaluation.yes");
    case "FAIL":
      return t("selfEvaluation.no");
    case "UNKNOWN":
      return t("a.Nicht bewertet");
  }
};

export const getFeedbackReceivedCaption = (
  assessment: "FAIL" | "SUCCESS" | "UNKNOWN"
) => {
  switch (assessment) {
    case "SUCCESS":
      return t("receivedEvaluation.yes");
    case "FAIL":
      return t("receivedEvaluation.no");
    case "UNKNOWN":
      return t("a.Nicht bewertet");
  }
};

export const getFeedbackEvaluationCaption = (
  assessment: "FAIL" | "SUCCESS" | "UNKNOWN",
  requester: User
) => {
  switch (assessment) {
    case "SUCCESS":
      return t("a.Ja, NAME kann das.", {
        NAME: requester.first_name,
      });
    case "FAIL":
      return t("a.Nein, NAME muss das nochmals anschauen.", {
        NAME: requester.first_name,
      });
    case "UNKNOWN":
      return t("a.Nicht bewertet");
  }
};
