<?php
/**
 * Masteriyo Content Drip setup.
 *
 * @package Masteriyo\ContentDrip
 *
 * @since 2.5.0
 */

namespace Masteriyo\Addons\ContentDrip;

use Masteriyo\DateTime;
use Masteriyo\Addons\ContentDrip\Enums\ContentDripType;
use Masteriyo\Query\UserCourseQuery;

defined( 'ABSPATH' ) || exit;

/**
 * Main Masteriyo ContentDrip class.
 *
 * @class Masteriyo\Addons\ContentDrip\ContentDrip
 */

class ContentDripAddon {
	/**
	 * Initialize the application.
	 *
	 * @since 2.5.0
	 */
	public function init() {

		$this->init_hooks();
	}

	/**
	 * Initialize hooks.
	 *
	 * @since 2.5.0
	 */
	public function init_hooks() {
		add_filter( 'masteriyo_rest_course_schema', array( $this, 'add_content_drip_schema_to_course' ) );
		add_action( 'masteriyo_new_course', array( $this, 'save_content_drip_data' ), 10, 2 );
		add_action( 'masteriyo_update_course', array( $this, 'save_content_drip_data' ), 10, 2 );
		add_filter( 'masteriyo_rest_response_course_data', array( $this, 'append_content_drip_data_in_response' ), 10, 4 );

		add_filter( 'masteriyo_rest_lesson_schema', array( $this, 'add_content_drip_schema_to_lesson_or_quiz_or_assignment' ) );
		add_action( 'masteriyo_new_lesson', array( $this, 'save_content_drip_data_to_lesson_or_quiz_or_assignment' ), 10, 2 );
		add_action( 'masteriyo_update_lesson', array( $this, 'save_content_drip_data_to_lesson_or_quiz_or_assignment' ), 10, 2 );
		add_filter( 'masteriyo_rest_response_lesson_data', array( $this, 'append_content_drip_data_in_response_of_lesson_or_quiz_or_assignment' ), 10, 4 );

		add_filter( 'masteriyo_rest_quiz_schema', array( $this, 'add_content_drip_schema_to_lesson_or_quiz_or_assignment' ) );
		add_action( 'masteriyo_new_quiz', array( $this, 'save_content_drip_data_to_lesson_or_quiz_or_assignment' ), 10, 2 );
		add_action( 'masteriyo_update_quiz', array( $this, 'save_content_drip_data_to_lesson_or_quiz_or_assignment' ), 10, 2 );
		add_filter( 'masteriyo_rest_response_quiz_data', array( $this, 'append_content_drip_data_in_response_of_lesson_or_quiz_or_assignment' ), 10, 4 );

		add_filter( 'masteriyo_rest_assignment_schema', array( $this, 'add_content_drip_schema_to_lesson_or_quiz_or_assignment' ) );
		add_action( 'masteriyo_new_assignment', array( $this, 'save_content_drip_data_to_lesson_or_quiz_or_assignment' ), 10, 2 );
		add_action( 'masteriyo_update_assignment', array( $this, 'save_content_drip_data_to_lesson_or_quiz_or_assignment' ), 10, 2 );
		add_filter( 'masteriyo_rest_response_assignment_data', array( $this, 'append_content_drip_data_in_response_of_lesson_or_quiz_or_assignment' ), 10, 4 );

		add_filter( 'masteriyo_course_progress_item_data', array( $this, 'add_locked_status_to_course_progress_item' ), 10, 3 );
		add_filter( 'masteriyo_rest_response_course_progress_data', array( $this, 'add_course_enrolled_date' ), 10, 4 );
		add_action( 'masteriyo_set_notification_content_drip_date', array( $this, 'schedule_notification_to_student' ), 10, 1 );
		add_action( 'masteriyo_set_notification_content_drip_days', array( $this, 'schedule_notification_to_student' ), 10, 1 );

	}

	/**
	 * Add locked status to course progress item like (lesson and quiz).
	 *
	 * @since 2.5.0
	 *
	 * @param array $data The course progress item data.
	 * @param \Masteriyo\Models\CourseProgressItem $course_progress_item Course progress item object.
	* @param string $context Context.
	 */
	public function add_locked_status_to_course_progress_item( $data, $course_progress_item, $context ) {
		// Get locked status if sequential or free flow is selected.
		$locked = isset( $data['locked'] ) ? $data['locked'] : false;
		$course = masteriyo_get_course( $course_progress_item->get_course_id() );

		if ( $course && ContentDripType::DATE === $course->get_flow() ) {
			$drip_timestamp = get_post_meta( $course_progress_item->get_item_id(), '_content_drip_timestamp', true );
			$locked         = $drip_timestamp >= time();
		} elseif ( $course && ContentDripType::DAYS === $course->get_flow() ) {
			$unlock_days = absint( get_post_meta( $course_progress_item->get_item_id(), '_content_drip_days', true ) );

			// Get enrolled course.
			$query = new UserCourseQuery(
				array(
					'course_id' => $course->get_id(),
					'user_id'   => masteriyo_get_current_user_id(),
				)
			);

			$enrolled_course = current( $query->get_user_courses() );

			if ( $enrolled_course ) {
				$enroll_date = date_create( $enrolled_course->get_date_start() );
				$unlock_date = date_add( $enroll_date, date_interval_create_from_date_string( sprintf( '%1s days', $unlock_days ) ) );
				$locked      = $unlock_date->getTimestamp() >= time();
			}
		}

		$data['locked'] = $locked;

		return $data;
	}

	/**
	 * Add content drip fields to course schema.
	 *
	 * @since 2.5.0
	 *
	 * @param array $schema
	 * @return array
	 */
	public function add_content_drip_schema_to_course( $schema ) {
		$schema = wp_parse_args(
			$schema,
			array(
				'content_drip' => array(
					'description' => __( 'Content Drip setting', 'learning-management-system' ),
					'type'        => 'object',
					'context'     => array( 'view', 'edit' ),
					'items'       => array(
						'type'       => 'object',
						'properties' => array(
							'enable' => array(
								'description' => __( 'Enable content drip', 'learning-management-system' ),
								'type'        => 'boolean',
								'default'     => false,
								'context'     => array( 'view', 'edit' ),
							),
							'type'   => array(
								'description' => __( 'Content drip type', 'learning-management-system' ),
								'type'        => 'string',
								'default'     => ContentDripType::DATE,
								'enum'        => ContentDripType::all(),
								'context'     => array( 'view', 'edit' ),
							),
						),
					),
				),
			)
		);

		return $schema;
	}

	/**
	 * Add content drip fields to lesson or quiz or assignment schema.
	 *
	 * @since 2.5.0
	 *
	 * @param array $schema
	 * @return array
	 */
	public function add_content_drip_schema_to_lesson_or_quiz_or_assignment( $schema ) {
		$schema = masteriyo_parse_args(
			$schema,
			array(
				'content_drip' => array(
					'description' => __( 'Content Drip setting', 'learning-management-system' ),
					'type'        => 'object',
					'context'     => array( 'view', 'edit' ),
					'items'       => array(
						'type'       => 'object',
						'properties' => array(
							'date' => array(
								'description' => __( 'Content drip date in ISO 8601 UTC.', 'learning-management-system' ),
								'type'        => 'string',
								'format'      => 'date',
								'context'     => array( 'view', 'edit' ),
							),
						),
					),
				),
			)
		);

		return $schema;
	}

	/**
	 * Save content drip data.
	 *
	 * @since 2.5.0
	 *
	 * @param integer $id The course ID.
	 * @param \Masteriyo\Models\Course $object The course object.
	 */
	public function save_content_drip_data( $id, $course ) {
		$request = masteriyo_current_http_request();

		if ( null === $request ) {
			return;
		}

		if ( ! isset( $request['content_drip'] ) ) {
			return;
		}

		if ( isset( $request['content_drip']['enable'] ) ) {
			$course->update_meta_data( '_content_drip_enable', masteriyo_string_to_bool( $request['content_drip']['enable'] ) );
		}

		if ( isset( $request['content_drip']['type'] ) ) {
			$course->update_meta_data( '_content_drip_type', sanitize_text_field( $request['content_drip']['type'] ) );
		}

		if ( ! in_array( $course->get_meta( '_content_drip_type' ), ContentDripType::all(), true ) ) {
			$course->update_meta_data( '_content_drip_type', ContentDripType::DATE );
		}

		$course->save_meta_data();
	}

	/**
	 * Append content drip to course response.
	 *
	 * @since 2.5.0
	 *
	 * @param array $data Course data.
	 * @param \Masteriyo\Models\Course $course Course object.
	 * @param string $context What the value is for. Valid values are view and edit.
	 * @param \Masteriyo\RestApi\Controllers\Version1\CoursesController $controller REST courses controller object.
	 */
	public function append_content_drip_data_in_response( $data, $course, $context, $controller ) {
		$data['content_drip'] = array(
			'enable' => masteriyo_string_to_bool( $course->get_meta( '_content_drip_enable' ) ),
			'type'   => empty( $course->get_meta( '_content_drip_type' ) ) ? ContentDripType::DATE : $course->get_meta( '_content_drip_type' ),
		);

		return $data;
	}

	/**
	 * Save content drip data to lesson or quiz or assignment.
	 *
	 * @since 2.5.0
	 *
	 * @param integer $id The lesson or quiz ID.
	 * @param \Masteriyo\Models\Lesson|\Masteriyo\Models\Quiz $object Lesson Or Quiz object
	 */
	public function save_content_drip_data_to_lesson_or_quiz_or_assignment( $id, $object ) {
		$request = masteriyo_current_http_request();

		if ( null === $request ) {
			return;
		}

		if ( ! isset( $request['content_drip'] ) ) {
			return;
		}

		if ( isset( $request['content_drip']['date'] ) ) {
			$drip_date = new DateTime( $request['content_drip']['date'] );

			if ( $drip_date ) {
				$object->update_meta_data( '_content_drip_date', $drip_date->date( DateTime::ISO8601 ) );
				$object->update_meta_data( '_content_drip_timestamp', $drip_date->getTimestamp() );
			}

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

			$args = array( $object->get_course_id() );

			if ( as_has_scheduled_action( 'masteriyo_set_notification_content_drip_date', $args, 'learning-management-system' ) ) {
				as_unschedule_action( 'masteriyo_set_notification_content_drip_date', $args, 'learning-management-system' );
			}

			if ( isset( $result['enable'] ) && $result['enable'] ) {
				as_schedule_single_action( strtotime( $request['content_drip']['date'] ), 'masteriyo_set_notification_content_drip_date', $args, 'learning-management-system' );
			}
		} elseif ( null === $request['content_drip']['date'] ) {
			/**
			 * As react date picker return null on empty condition.
			 *
			 * @since 2.5.19
			 */
			$object->update_meta_data( '_content_drip_date', null );
			$object->update_meta_data( '_content_drip_timestamp', null );
		}

		if ( isset( $request['content_drip']['days'] ) ) {
			$object->update_meta_data( '_content_drip_days', absint( $request['content_drip']['days'] ) );

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

			$args = array( $object->get_course_id() );

			if ( as_has_scheduled_action( 'masteriyo_set_notification_content_drip_days', $args, 'learning-management-system' ) ) {
				as_unschedule_action( 'masteriyo_set_notification_content_drip_days', $args, 'learning-management-system' );
			}
			if ( null !== $request['content_drip']['days'] ) {
				if ( isset( $result['enable'] ) && $result['enable'] ) {
					if ( null !== $object->get_date_created() ) {
						$notification_timestamp = $object->get_date_created();
					}
					as_schedule_single_action( strtotime( $notification_timestamp->modify( $request['content_drip']['days'] . ' days' ) ), 'masteriyo_set_notification_content_drip_days', $args, 'learning-management-system' );
				}
			}
		}

		$object->save_meta_data();
	}

	/**
	 * Append content drip to lesson or quiz or assignment response.
	 *
	 * @since 2.5.0
	 *
	 * @param array $data Lesson/Quiz data.
	 * @param \Masteriyo\Models\Lesson|\Masteriyo\Models\Quiz $object Lesson or Quiz object. object.
	 * @param string $context What the value is for. Valid values are view and edit.
	 * @param \Masteriyo\RestApi\Controllers\Version1\LessonsController|\Masteriyo\RestApi\Controllers\Version1\QuizesController $controller REST courses controller object.
	 */
	public function append_content_drip_data_in_response_of_lesson_or_quiz_or_assignment( $data, $object, $context, $controller ) {
		$drip_date = $object->get_meta( '_content_drip_date' ) ? new DateTime( $object->get_meta( '_content_drip_date' ) ) : null;
		$drip_days = $object->get_meta( '_content_drip_days' ) ? $object->get_meta( '_content_drip_days' ) : null;

		$data['content_drip'] = array(
			'date' => masteriyo_rest_prepare_date_response( $drip_date ),
			'days' => $drip_days,
		);

		return $data;
	}

	/**
	 * Add course enrolled date to course progress response data.
	 *
	 * @since 2.5.5
	 *
	 * @param array $data Course progress data.
	 * @param \Masteriyo\Models\CourseProgress $course_progress Course progress object.
	 * @param string $context What the value is for. Valid values are view and edit.
	 * @param \Masteriyo\RestApi\Controllers\Version1\CoursesController $controller REST course progress controller object.
	 */
	public function add_course_enrolled_date( $data, $course_progress, $context, $controller ) {
		$course = masteriyo_get_course( $course_progress->get_course_id() );

		if ( $course ) {
			// Get enrolled course.
			$query = new UserCourseQuery(
				array(
					'course_id' => $course->get_id(),
					'user_id'   => get_current_user_id(),
				)
			);

			$enrolled_course     = current( $query->get_user_courses() );
			$data['enrolled_at'] = empty( $enrolled_course ) ? null : masteriyo_rest_prepare_date_response( $enrolled_course->get_date_start() );
		}

		return $data;
	}

	/**
	 * Schedule content unlocked notification to student.
	 *
	 * @since 2.8.0
	 *
	 * @param int $id User course id.
	 */
	public function schedule_notification_to_student( $id ) {

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

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

		$users = masteriyo_get_enrolled_users( $id );

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

		foreach ( $users as $user ) {

			$query = new UserCourseQuery(
				array(
					'course_id' => $id,
					'user_id'   => $user,
				)
			);

			$user_courses = $query->get_user_courses();

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

		}
	}
}
