<?php
/**
 * Notification service provider.
 *
 * @since 1.4.1
 */

namespace Masteriyo\Providers;

defined( 'ABSPATH' ) || exit;

use League\Container\ServiceProvider\AbstractServiceProvider;
use League\Container\ServiceProvider\BootableServiceProviderInterface;
use Masteriyo\Enums\CourseProgressStatus;
use Masteriyo\Models\Notification;
use Masteriyo\Repository\NotificationRepository;
use Masteriyo\RestApi\Controllers\Version1\NotificationsController;
use Masteriyo\Query\UserCourseQuery;


class NotificationServiceProvider extends AbstractServiceProvider implements BootableServiceProviderInterface {


	/**
	 * This method is called after all service providers are registered.
	 *
	 * @since 1.7.1
	 */
	public function boot(): void {
		add_action( 'masteriyo_new_user_course', array( $this, 'schedule_course_start_notification_to_student' ), 10, 2 );
		add_action( 'masteriyo_course_progress_status_changed', array( $this, 'schedule_course_end_notification_to_student' ), 10, 4 );
		add_action( 'masteriyo_order_status_completed', array( $this, 'schedule_completed_order_notification_to_student' ), 10, 2 );
		add_action( 'masteriyo_order_status_on-hold', array( $this, 'schedule_on_hold_order_notification_to_student' ), 10, 2 );
		add_action( 'masteriyo_order_status_cancelled', array( $this, 'schedule_cancelled_order_notification_to_student' ), 10, 2 );
		add_action( 'masteriyo_checkout_order_created', array( $this, 'schedule_order_created_notification_to_student' ), 10, 1 );
		add_action( 'masteriyo_new_course_qa', array( $this, 'schedule_new_course_qa_notification_to_student' ), 10, 2 );
		add_action( 'masteriyo_new_lesson_review', array( $this, 'schedule_new_lesson_comment_reply_notification_to_student' ), 10, 2 );
	}


	/**
	 * Schedule course start notification to student.
	 *
	 * @since 1.7.1
	 *
	 * @param int $id User course id.
	 * @param \Masteriyo\Models\UserCourse $object The user course object.
	 * @param \Masteriyo\Models\Order $order
	 */
	public function schedule_course_start_notification_to_student( $id, $user_course ) {
		$result = masteriyo_get_setting( 'notification.student.course_enroll' );
		if ( ! isset( $result ) ) {
			return;
		}
		if ( ! masteriyo_is_current_user_student( $user_course->get_id() ) ) {
			return;
		}

		$order_id = $user_course->get_order_id();
		if ( 0 !== $order_id ) {
			return;
		}

		masteriyo_set_notification( $id, $user_course, $result );
	}


	/**
	 * Schedule course end notifications to student.
	 *
	 * @since 1.7.1
	 *
	 * @param integer $id Course progress ID.
	 * @param string $old_status Old status.
	 * @param string $new_status New status.
	 * @param \Masteriyo\Models\CourseProgress $course_progress The course progress object.
	 */
	public function schedule_course_end_notification_to_student( $id, $old_status, $new_status, $user_course ) {
		$result = masteriyo_get_setting( 'notification.student.course_complete' );
		if ( ! isset( $result ) ) {
			return;
		}
		if ( ! masteriyo_is_current_user_student( $user_course->get_id() ) || CourseProgressStatus::COMPLETED !== $new_status ) {
			return;
		}

		$query = new UserCourseQuery(
			array(
				'course_id' => $user_course->get_course_id(),
				'user_id'   => get_current_user_id(),
			)
		);

		$user_courses = $query->get_user_courses();

		masteriyo_set_notification( $id, current( $user_courses ), $result );
	}

	/**
	 * Schedule order completed notification to student.
	 *
	 * @since 1.7.1
	 *
	 * @param int $order_id
	 * @param \Masteriyo\Models\Order $order
	 */
	public function schedule_completed_order_notification_to_student( $id, $user_course ) {
		if ( ! $user_course ) {
			return;
		}
		$result = masteriyo_get_setting( 'notification.student.completed_order' );
		if ( ! isset( $result ) ) {
			return;
		}

		$course_items = $user_course->get_items( 'course' );

		$data = array();

		foreach ( $course_items as $course_item ) {
			$data[] = array(
				'course_id' => $course_item->get_course_id(),
			);
		}

		foreach ( $data as $data_entry ) {
			$query = new UserCourseQuery(
				array(
					'course_id' => $data_entry['course_id'],
					'user_id'   => $user_course->get_customer_id(),
				)
			);

			$user_courses = $query->get_user_courses();

			masteriyo_set_notification( null, current( $user_courses ), $result );
		}
	}

	/**
	 * Schedule order onhold notification to student.
	 *
	 * @since 1.7.1
	 *
	 * @param int $order_id
	 * @param \Masteriyo\Models\Order $order
	 */
	public function schedule_on_hold_order_notification_to_student( $id, $user_course ) {
		if ( ! $user_course ) {
			return;
		}
		$result = masteriyo_get_setting( 'notification.student.onhold_order' );
		if ( ! isset( $result ) ) {
			return;
		}

		$course_items = $user_course->get_items( 'course' );

		$data = array();

		foreach ( $course_items as $course_item ) {
			$data[] = array(
				'course_id' => $course_item->get_course_id(),
			);
		}

		foreach ( $data as $data_entry ) {
			$query = new UserCourseQuery(
				array(
					'course_id' => $data_entry['course_id'],
					'user_id'   => $user_course->get_customer_id(),
				)
			);

			$user_courses = $query->get_user_courses();

			masteriyo_set_notification( null, current( $user_courses ), $result );
		}
	}

	/**
	 * Schedule order cancelled notification to student.
	 *
	 * @since 1.7.1
	 *
	 * @param int $order_id
	 * @param \Masteriyo\Models\Order $order
	 */
	public function schedule_cancelled_order_notification_to_student( $id, $user_course ) {
		$result = masteriyo_get_setting( 'notification.student.cancelled_order' );
		if ( ! isset( $result ) ) {
			return;
		}
		if ( ! $user_course ) {
			return;
		}

		$course_items = $user_course->get_items( 'course' );

		$data = array();

		foreach ( $course_items as $course_item ) {
			$data[] = array(
				'course_id' => $course_item->get_course_id(),
			);
		}

		foreach ( $data as $data_entry ) {
			$query = new UserCourseQuery(
				array(
					'course_id' => $data_entry['course_id'],
					'user_id'   => $user_course->get_customer_id(),
				)
			);

			$user_courses = $query->get_user_courses();

			masteriyo_set_notification( null, current( $user_courses ), $result );
		}
	}


	/**
	 * Schedule order created notification to student.
	 *
	 * @since 1.7.1
	 *
	 * @param int $order_id
	 * @param \Masteriyo\Models\Order $order
	 */
	public function schedule_order_created_notification_to_student( $user_course ) {
		if ( ! masteriyo_is_current_user_student( $user_course->get_id() ) ) {
			return;
		}
		$result = masteriyo_get_setting( 'notification.student.created_order' );

		if ( ! isset( $result ) ) {
			return;
		}

		$course_items = $user_course->get_items( 'course' );

		$data = array();

		foreach ( $course_items as $course_item ) {
			$data[] = array(
				'course_id' => $course_item->get_course_id(),
			);
		}

		foreach ( $data as $data_entry ) {
			$query = new UserCourseQuery(
				array(
					'course_id' => $data_entry['course_id'],
					'user_id'   => get_current_user_id(),
				)
			);

			$user_courses = $query->get_user_courses();

			masteriyo_set_notification( null, current( $user_courses ), $result );
		}

	}

	/**
	 * Schedule course qa notification to student.
	 *
	 * @since 1.20.0
	 *
	 * @param int $id Course QA id.
	 * @param \Masteriyo\Models\CourseQA $object The user course object.
	 * @param \Masteriyo\Models\CourseQA $course_qa
	 */
	public function schedule_new_course_qa_notification_to_student( $id, $course_qa ) {

		$result = masteriyo_get_setting( 'notification.student.course_qa' );

		if ( isset( $result['enable'] ) && ! $result['enable'] ) {
			return;
		}

		if ( $course_qa->get_parent() === 0 ) {
			return;
		}

		$course_qa_parent_data = masteriyo_get_course_qa( $course_qa->get_parent() );

		if ( ! $course_qa_parent_data ) {
			return;
		}

		$query = new UserCourseQuery(
			array(
				'course_id' => $course_qa_parent_data->get_course_id(),
				'user_id'   => $course_qa_parent_data->get_user_id(),
			)
		);

		$user_courses = $query->get_user_courses();

		if ( empty( $user_courses ) ) {
			return;
		}

		$user_course = current( $user_courses );

		if ( ! is_object( $user_course ) ) {
			return;
		}

		if ( $course_qa->get_user_id() === $user_course->get_user_id() ) {
			return;
		}

		masteriyo_set_notification( $id, $user_course, $result );
	}

	/**
	 * Schedule lesson comment reply notification to student.
	 *
	 * @since x.x.x
	 *
	 * @param int $id Lesson comment id.
	 * @param \Masteriyo\Models\LessonReview $reply The lesson comment object.
	 */
	public function schedule_new_lesson_comment_reply_notification_to_student( $id, $reply ) {

		$result = masteriyo_get_setting( 'notification.student.lesson_comment' );

		if ( null === $result ) {
			$result = array(
				'enable'  => true,
				'type'    => 'lesson_comment',
				'content' => __( 'You have a new reply to your comment.', 'learning-management-system' ),
			);
		}

		if ( isset( $result['enable'] ) && ! $result['enable'] ) {
			return;
		}

		if ( $reply->get_parent() === 0 ) {
			return;
		}

		$parent_comment = masteriyo_get_lesson_review( $reply->get_parent() );

		if ( ! $parent_comment ) {
			return;
		}

		$lesson = masteriyo_get_lesson( $parent_comment->get_lesson_id() );
		if ( ! $lesson ) {
			return;
		}

		$query = new UserCourseQuery(
			array(
				'course_id' => $lesson->get_course_id(),
				'user_id'   => $parent_comment->get_author_id(),
			)
		);

		$user_courses = $query->get_user_courses();

		if ( empty( $user_courses ) ) {
			return;
		}

		$user_course = current( $user_courses );

		if ( ! is_object( $user_course ) ) {
			return;
		}

		if ( $reply->get_author_id() === $user_course->get_user_id() ) {
			return;
		}

		masteriyo_set_notification( $id, $user_course, $result );
	}

	/**
	 * This is where the magic happens, within the method you can
	 * access the container and register or retrieve anything
	 * that you need to, but remember, every alias registered
	 * within this method must be declared in the `$provides` array.
	 *
	 * @since 1.4.1
	 */
	public function register(): void {
		$this->getContainer()->add( 'notification.store', NotificationRepository::class );

		$this->getContainer()->add( 'notification.rest', NotificationsController::class )
			->addArgument( 'permission' );

		$this->getContainer()->add( 'notification', Notification::class )
			->addArgument( 'notification.store' );
	}

	/**
	 * The provided array is a way to let the container
	 * know that a service is provided by this service
	 * provider. Every service that is registered via
	 * this service provider must have an alias added
	 * to this array or it will be ignored
	 *
	 * Check if the service provider provides a specific service.
	 *
	 * @since 2.1.0
	 *
	 * @param string $id Service identifier.
	 * @return bool True if the service is provided, false otherwise.
	 */
	public function provides( string $id ): bool {
		return in_array(
			$id,
			array(
				'notification',
				'notification.store',
				'notification.rest',
			),
			true
		);
	}
}
