<?php

defined( 'ABSPATH' ) || exit;

/**
 * Gradebook addon functions.
 *
 * @since 2.5.20
 * @version 2.5.20
 * @package Masteriyo\Helper
 */

use Masteriyo\Addons\Gradebook\Query\GradeQuery;
use Masteriyo\Addons\Gradebook\Enums\GradeResultType;
use Masteriyo\Addons\Gradebook\Query\GradeResultQuery;
use Masteriyo\Addons\Gradebook\Enums\GradeResultStatus;

/**
 * Get grade.
 *
 * @since 2.5.20
 *
 * @param int|\Masteriyo\Addons\Gradebook\Models\Grade|\WP_Post $course Grade id or Grade Model or Post.
 * @return Masteriyo\Addons\Gradebook\Models\GradeResult|null
 */
function masteriyo_get_grade( $grade ) {
	if ( is_a( $grade, 'Masteriyo\Database\Model' ) ) {
		$id = $grade->get_id();
	} elseif ( is_a( $grade, 'WP_Post' ) ) {
		$id = $grade->ID;
	} else {
		$id = absint( $grade );
	}

	try {
		$grade = masteriyo( 'grade' );
		$grade->set_id( $id );

		$grade_repo = masteriyo( 'grade.store' );
		$grade_repo->read( $grade );

		return $grade;
	} catch ( \Exception $e ) {
		return null;
	}
}

/**
 * Get grade result.
 *
 * @since 2.5.20
 *
 * @param int $grade_result_id Grade Result ID.
 * @return Masteriyo\Addons\Gradebook\Models\GradeResult|null
 */
function masteriyo_get_grade_result( $grade_result_id ) {
	try {
		$grade_result = masteriyo( 'grade-result' );
		$grade_result->set_id( $grade_result_id );

		$grade_result_repo = masteriyo( 'grade-result.store' );
		$grade_result_repo->read( $grade_result );

		return $grade_result;
	} catch ( \Exception $e ) {
		return null;
	}
}

/**
 * Create grade result object.
 *
 * @since 2.5.20
 *
 * @return \Masteriyo\Addons\Gradebook\Models\GradeResult
 */
function masteriyo_create_grade_result_object() {
	return masteriyo( 'grade-result' );
}

/**
 * Get grade result.
 *
 * @since 2.5.20
 *
 * @param int $item_id Grade result item ID.
 * @param string|string[] $item_type Item type.
 * @param int $parent_id Parent ID.
 * @param int $user_id User ID.
 *
 * @return Masteriyo\Addons\Gradebook\Models\GradeResult|null
 */
function masteriyo_get_grade_result_item( $item_id, $item_type, $user_id, $parent_id = 0 ) {
	$query = new GradeResultQuery(
		array(
			'item'      => $item_id,
			'item_type' => $item_type,
			'user'      => $user_id,
			'parent'    => $parent_id,
		)
	);

	return current( $query->get_grade_results() );
}

/**
 * Return grades.
 *
 * @since 2.5.20
 *
 * @return \Masteriyo\Addons\Gradebook\Models\Grade[]
 */
function masteriyo_get_grades( $user_id = null ) {
	$args = array( 'limit' => -1 );

	if ( $user_id ) {
		$args['user'] = $user_id;
	}

	$query = new GradeQuery(
		array(
			'limit' => -1,
		)
	);

	return $query->get_grades();
}

/**
 * Return highest grade.
 *
 * @since 2.5.20
 *
 * @return \Masteriyo\Addons\Gradebook\Models\Grade
 */
function masteriyo_get_highest_grade() {
	$grades        = masteriyo_get_grades();
	$highest_grade = null;

	if ( $grades ) {
		$grade_points = array_map(
			function ( $grade ) {
				return $grade->get_points();
			},
			$grades
		);

		$grades = array_combine( $grade_points, $grades );
		ksort( $grades, SORT_NUMERIC );

		$highest_grade = end( $grades );
	}

	return $highest_grade;
}

/**
 * Get grade from percentage.
 *
 * @since 2.5.20
 *
 * @param float $percentage
 * @return \Masteriyo\Addons\Gradebook\Models\Grade
 */
function masteriyo_get_grade_from_percentage( $percentage ) {
	$grades             = masteriyo_get_grades();
	$result             = null;
	$rounded_percentage = masteriyo_round( $percentage );

	foreach ( $grades as $grade ) {
		if ( $rounded_percentage <= $grade->get_max() && $rounded_percentage >= $grade->get_min() ) {
			$result = $grade;
			break;
		}
	}

	return $result;
}

/**
 * Calculate course grade result.
 *
 * @since 2.5.20
 *
 * @since 2.5.20
 *
 * @param int $course_id Course ID.
 * @param int $user_id User ID.
 *
 * @return boolean
 */
function masteriyo_calculate_course_grade_result_status( $course_id, $user_id ) {
	$query = new GradeResultQuery(
		array(
			'parent'    => $course_id,
			'user'      => $user_id,
			'item_type' => array_diff( GradeResultType::all(), array( GradeResultType::COURSE ) ),
		)
	);

	$grade_result_items = $query->get_grade_results();

	$status = GradeResultStatus::COMPLETED;
	foreach ( $grade_result_items as $grade_result_item ) {
		if ( GradeResultStatus::PENDING === $grade_result_item->get_status() ) {
			$status = GradeResultStatus::PENDING;
			break;
		}
	}

	/**
	 * Filter course grade result status.
	 *
	 * @since 2.5.20
	 *
	 * @param string $status
	 * @param int $course_id
	 * @param int $user_id
	 */
	return apply_filters( 'masteriyo_calculate_course_grade_result', $status, $course_id, $user_id );
}
