<?php

defined( 'ABSPATH' ) || exit;

/**
 * Public profile helper functions.
 *
 * @since 2.6.8
 * @version 2.6.8
 *
 * @package Masteriyo\Pro\Addons\PublicProfile\Helper
 */

use Masteriyo\Addons\PublicProfile\Setting;
use Masteriyo\Enums\CourseProgressStatus;
use Masteriyo\Enums\PostStatus;
use Masteriyo\PostType\PostType;
use Masteriyo\Query\CourseProgressQuery;
use Masteriyo\Roles;

if ( ! function_exists( 'masteriyo_is_role' ) ) {
	/**
	 * Check if a user has a specific role in the masteriyo system.
	 *
	 * @since 2.6.8
	 *
	 * @param string $username The username to check the role for.
	 * @param string $role     The role to check against.
	 *
	 * @return bool True if the user has the specified role, false otherwise.
	 */
	function masteriyo_is_role( $username, $role ) {

		$user = get_user_by( 'login', $username );

		if ( $user && masteriyo_user_has_role( $user, $role ) ) {
			return true;
		}

		return false;
	}
}

if ( ! function_exists( 'masteriyo_get_public_profile_data' ) ) {
	/**
	 * Retrieves public profile data of a user with the given username.
	 *
	 * @since 2.6.8
	 *
	 * @param int|WP_User|Masteriyo\Database\Model $user User ID, WP_User object, or Masteriyo\Database\Model object.
	 *
	 * @return array An array of user profile data if found, empty array otherwise.
	 */
	function masteriyo_get_public_profile_data( $user ) {
		$user = masteriyo_get_user( $user );
		$data = array();

		if ( is_null( $user ) || is_wp_error( $user ) ) {
			return $data;
		}

		if ( ! masteriyo_is_role( $user->get_username(), Roles::STUDENT ) && ! masteriyo_is_role( $user->get_username(), Roles::INSTRUCTOR ) ) {
			return $data;
		}

		$data['user_profile']                     = masteriyo_get_profile_info( $user );
		$data['overview_enrolled_courses']        = masteriyo_get_user_enrolled_courses( $user, 3 );
		$data['overview_enrolled_courses_count']  = masteriyo_get_user_enrolled_courses_count( $user->get_id() );
		$data['overview_progress_courses_count']  = masteriyo_get_user_courses_count_by_course_status( $user->get_id() );
		$data['overview_completed_courses_count'] = masteriyo_get_user_courses_count_by_course_status( $user->get_id(), CourseProgressStatus::COMPLETED );
		$data['enrolled_courses']                 = masteriyo_get_user_enrolled_courses_with_pagination( $user );
		$data['certificates']                     = masteriyo_get_user_certificates( $user );

		if ( masteriyo_is_role( $user->get_username(), Roles::INSTRUCTOR ) ) {
			$data['overview_user_courses_list']       = masteriyo_get_courses_list_html( masteriyo_get_user_courses( $user, 3 ) );
			$data['overview_user_courses_count']      = count( masteriyo_get_instructor_course_ids( $user->get_id() ) );
			$data['overview_enrolled_students_count'] = masteriyo_count_all_enrolled_users( $user->get_id() );
			$data['courses_offered']                  = masteriyo_get_user_courses_with_pagination( $user );
		}

		return $data;
	}
}

if ( ! function_exists( 'masteriyo_validate_username' ) ) {
	/**
	 * Validates a username.
	 *
	 * @since 2.6.8
	 *
	 * @param string $username The username to validate.
	 *
	 * @return string|bool The validated username if valid and exists, false otherwise.
	 */
	function masteriyo_validate_username( $username ) {

		if ( empty( $username ) ) {
			return false;
		}

		$username = sanitize_text_field( $username );
		$user     = get_user_by( 'login', $username );

		if ( $user ) {
			return $username;
		}

		return false;
	}
}

if ( ! function_exists( 'masteriyo_get_user_by_username' ) ) {
	/**
	 * Get the masteriyo user from username.
	 *
	 * @since 2.6.8
	 *
	 * @param string $username The username to validate.
	 *
	 * @return WP_User|Masteriyo\Database\Model|bool Returns Masteriyo\Database\Model object if valid and exists, false otherwise.
	 */
	function masteriyo_get_user_by_username( $username ) {

		$username = masteriyo_validate_username( $username );

		if ( ! $username ) {
			return false;
		}

		$user = get_user_by( 'login', $username );

		if ( $user ) {

			$user = masteriyo_get_user( $user );

			if ( ! $user || is_wp_error( $user ) ) {
				return false;
			}

			if ( ! ( $user->has_role( Roles::STUDENT ) || $user->has_role( Roles::INSTRUCTOR ) ) ) {
				return false;
			}

			return $user;
		}

		return false;
	}
}

if ( ! function_exists( 'masteriyo_user_has_role' ) ) {
	/**
	 * Checks if a user has the specified role.
	 *
	 * @since 2.6.8
	 *
	 * @param WP_User $user The user object.
	 * @param string  $role The role to check.
	 *
	 * @return bool True if the user has the role, false otherwise.
	 */
	function masteriyo_user_has_role( $user, $role ) {

		if ( is_array( $user->roles ) && in_array( $role, $user->roles, true ) ) {
			return true;
		}

		return false;
	}
}

if ( ! function_exists( 'masteriyo_get_public_profile_url' ) ) {
	/**
	 * Retrieve the public profile URL for a masteriyo student/instructor.
	 *
	 * @since 2.6.8
	 *
	 * @param string $username Username of the user.
	 * @return string The URL to the user's public profile.
	 */
	function masteriyo_get_public_profile_url( $username ) {
		$slug = masteriyo_get_public_profile_slug();

		$slug = trailingslashit( $slug );

		$structure = get_option( 'permalink_structure' );

		if ( 'plain' === $structure || '' === $structure ) {
			$slug = $slug . '?username=' . $username;
		} else {
			$slug = $slug . $username;
		}

		return home_url( $slug );
	}
}

if ( ! function_exists( 'masteriyo_get_public_profile_slug' ) ) {
	/**
	 * Retrieves the public profile slug, falling back to 'profile' if empty.
	 *
	 * @since 2.6.8
	 *
	 * @return string The public profile slug.
	 */
	function masteriyo_get_public_profile_slug() {
		$slug = Setting::get( 'slug' );
		/**
		 * Filters the public profile slug for masteriyo student or instructor.
		 *
		 * @since 2.6.8
		 *
		 * @param string $slug The public profile slug.
		 */
		$slug = apply_filters( 'masteriyo_public_profile_slug', $slug );

		return empty( $slug ) ? 'profile' : $slug;
	}
}

if ( ! function_exists( 'masteriyo_is_valid_public_profile_plain_slug' ) ) {
	/**
	 * Check if the public profile plain slug is valid.
	 *
	 * @since 2.6.8
	 *
	 * @return bool True if the public profile plain slug is valid, false otherwise.
	 */
	function masteriyo_is_valid_public_profile_plain_slug() {
		$structure = get_option( 'permalink_structure' );

		if ( 'plain' === $structure || '' === $structure ) {
			$request_uri         = trim( strtok( $_SERVER['REQUEST_URI'], '?' ), '/' );
			$public_profile_slug = trim( masteriyo_get_public_profile_slug(), '/' );

			return $public_profile_slug === $request_uri;
		}

		return true;
	}
}

if ( ! function_exists( 'masteriyo_get_profile_info' ) ) {
	/**
	 * Retrieves profile data for a user.
	 *
	 * @since 2.6.8
	 *
	 * @param int|WP_User|Masteriyo\Database\Model $user User ID, WP_User object, or Masteriyo\Database\Model object.
	 *
	 * @return array The profile data.
	 */
	function masteriyo_get_profile_info( $user ) {

		$user = masteriyo_get_user( $user );

		if ( is_null( $user ) || is_wp_error( $user ) ) {
			return array();
		}

		$profile_data = array(
			'id'          => $user->get_id(),
			'full_name'   => $user->get_first_name() . ' ' . $user->get_last_name(),
			'username'    => $user->get_username(),
			'avatar_url'  => $user->profile_image_url(),
			'description' => masteriyo_get_public_profile_biographical_info( $user ),
			'email'       => $user->get_email(),
			'address'     => masteriyo_get_public_profile_address( $user ),
			'phone'       => $user->get_public_profile_phone(),
			'role'        => masteriyo_is_role( $user->get_username(), Roles::INSTRUCTOR ) ? Roles::INSTRUCTOR : Roles::STUDENT,
			'links'       => masteriyo_get_public_profile_links( $user ),
			'created_at'  => date_i18n( 'F j, Y', strtotime( $user->get_date_created() ) ),
		);

		return $profile_data;
	}
}

if ( ! function_exists( 'masteriyo_get_user_courses' ) ) {
	/**
	 * Retrieves the courses of a user.
	 *
	 * @since 2.6.8
	 *
	 * @param int|WP_User|Masteriyo\Database\Model $user User ID, WP_User object, or Masteriyo\Database\Model object.
	 * @param int $limit The maximum number of courses to retrieve. Default is -1 (unlimited).
	 *
	 * @return array The user's courses.
	 */
	function masteriyo_get_user_courses( $user, $limit = -1 ) {
		$id = masteriyo_get_user( $user )->get_id();

		$course_ids = masteriyo_get_instructor_course_ids( $id );

		$all_courses = array_map(
			function( $course_id ) {
				$course = masteriyo_get_course( $course_id );

				if ( is_null( $course ) ) {
					return null;
				}

				return $course;
			},
			$course_ids
		);

		return array_filter( $all_courses );
	}
}

if ( ! function_exists( 'masteriyo_count_all_enrolled_users' ) ) {
	/**
	 * Count total enrolled users from all courses.
	 *
	 * @since 2.6.8
	 *
	 * @param int|WP_User|Masteriyo\Database\Model $user User ID, WP_User object, or Masteriyo\Database\Model object.
	 *
	 * @return integer
	 */
	function masteriyo_count_all_enrolled_users( $user ) {
		$total_count = 0;

		// Get all courses.
		$all_courses = get_posts(
			array(
				'post_type'      => PostType::COURSE,
				'post_status'    => PostStatus::PUBLISH,
				'author'         => masteriyo_get_user( $user )->get_id(),
				'posts_per_page' => -1,
				'fields'         => 'ids',
			)
		);

		// Iterate through each course and count enrolled users.
		foreach ( $all_courses as $course_id ) {
				$total_count += masteriyo_count_enrolled_users( $course_id );
		}

		return $total_count;
	}
}

if ( ! function_exists( 'masteriyo_count_user_courses' ) ) {
	/**
	 * Get the count of courses created by a user.
	 *
	 * @since 2.6.8
	 *
	 * @param int|WP_User|Masteriyo\Database\Model $user User ID, WP_User object, or Masteriyo\Database\Model object.
	 *
	 * @return int The count of courses created by the user.
	 */
	function masteriyo_count_user_courses( $user ) {
		$user = masteriyo_get_user( $user );

		if ( is_null( $user ) || is_wp_error( $user ) ) {
			return 0;
		}

		return count( masteriyo_get_instructor_course_ids( $user->get_id() ) );
	}
}

if ( ! function_exists( 'masteriyo_get_public_profile_site_title' ) ) {
	/**
	 * Retrieves the public profile site title.
	 *
	 * @since 2.6.8
	 *
	 * @param string $name The name of the user.
	 *
	 * @return string The filtered site title.
	 */
	function masteriyo_get_public_profile_site_title( $name ) {

		/**
		 * Filters the public profile site title.
		 *
		 * @since 2.6.8
		 *
		 * @param string $name The original site title.
		 *
		 * @return string The filtered site title.
		 */
		$site_title = apply_filters( 'masteriyo_public_profile_site_title', $name . html_entity_decode( ' &ndash; ' ) . get_bloginfo( 'name' ) );

		return $site_title;
	}
}

if ( ! function_exists( 'masteriyo_get_courses_list_html' ) ) {
	/**
	 * Displays the overview of user courses.
	 *
	 * @since 2.6.8
	 *
	 * @param array The  array of courses.
	 *
	 * @return string The HTML output of the user course overview.
	 */
	function masteriyo_get_courses_list_html( $courses, $columns = 3 ) {

		masteriyo_set_loop_prop( 'columns', $columns );

		\ob_start();

		echo '<div class="masteriyo-courses--content">';

		if ( count( $courses ) > 0 ) {
			$original_course = isset( $GLOBALS['course'] ) ? $GLOBALS['course'] : null;

			masteriyo_course_loop_start();

			foreach ( $courses as $course ) {
				$GLOBALS['course'] = $course;

				\masteriyo_get_template_part( 'content', 'course' );
			}

			$GLOBALS['course'] = $original_course;

			masteriyo_course_loop_end();

			masteriyo_reset_loop();
		} else {
			masteriyo_display_template_notice( 'No courses offered.' );
		}

		echo '</div>';

		return \ob_get_clean();
	}
}

if ( ! function_exists( 'masteriyo_get_public_profile_biographical_info' ) ) {
	/**
	 * Undocumented function
	 *
	 * @param Masteriyo\Models\User $user User object.
	 *
	 * @return string The user's profile biographical information.
	 */
	function masteriyo_get_public_profile_biographical_info( $user ) {
		return $user->get_public_profile_biographical_info() ? $user->get_public_profile_biographical_info() : $user->get_description();
	}
}

if ( ! function_exists( 'masteriyo_get_public_profile_address' ) ) {
	/**
	 * Get the user's public address.
	 *
	 * @param Masteriyo\Models\User $user User object.
	 *
	 * @return string The user's public address.
	 */
	function masteriyo_get_public_profile_address( $user ) {
		$address_parts = array(
			$user->get_public_profile_city(),
			$user->get_public_profile_postcode(),
			$user->get_public_profile_address_2(),
			$user->get_public_profile_address_1(),
			$user->get_public_profile_country(),
		);

		$address_parts = array_filter( $address_parts ); // Remove empty address parts.

		return implode( ', ', $address_parts );
	}
}

if ( ! function_exists( 'masteriyo_get_public_profile_links' ) ) {
	/**
	 * Get the user's public links.
	 *
	 * @param Masteriyo\Models\User $user User object.
	 *
	 * @return array The user's public links.
	 */
	function masteriyo_get_public_profile_links( $user ) {

		$links = array(
			'facebook_url' => $user->get_public_profile_facebook_url(),
			'website_url'  => ! empty( $user->get_public_profile_website_url() ) ? $user->get_public_profile_website_url() : $user->get_url(),
			'linkedin_url' => $user->get_public_profile_linkedin_url(),
			'behance_url'  => $user->get_public_profile_behance_url(),
		);

		return $links;
	}
}

if ( ! function_exists( 'masteriyo_display_template_notice' ) ) {
	/**
	 * Display a notice.
	 *
	 * This function is used to show a notice with a specified message and type.
	 *
	 * @since 2.6.8
	 *
	 * @param string $message The notice message to be displayed.
	 * @param string $type    Optional. The type of the notice. Default is 'info'.
	 */
	function masteriyo_display_template_notice( $message, $type = 'info' ) {
		echo '<div class="masteriyo-courses-wrapper">';
		masteriyo_get_template(
			"notices/$type.php",
			array(
				'message' =>
					/* translators: %s: Notice message to display. */
					sprintf( __( '%s', 'learning-management-system' ), esc_html( $message ) ),
			)
		);
		echo '</div>';
	}
}

if ( ! function_exists( 'masteriyo_get_user_enrolled_courses_with_pagination' ) ) {
	/**
	 * Retrieves the enrolled courses for a user with pagination.
	 *
	 * @since 2.6.8
	 *
	 * @param int|WP_User|Masteriyo\Database\Model $user User ID, WP_User object, or Masteriyo\Database\Model object.
	 * @param int                                 $page     The current page number (default: 1).
	 * @param int                                 $per_page The number of courses to display per page (default: 6).
	 *
	 * @return array An array containing the enrolled courses, total pages, and current page number.
	 */
	function masteriyo_get_user_enrolled_courses_with_pagination( $user, $page = 1, $per_page = 6 ) {

		$id                     = masteriyo_get_user( $user )->get_id();
		$total_enrolled_courses = masteriyo_get_user_enrolled_courses_count( $id );
		$total_pages            = ceil( $total_enrolled_courses / $per_page ); // Calculate the total number of pages.
		$offset                 = ( absint( $page ) - 1 ) * absint( $per_page ); // Calculate the offset based on the current page.

		if ( ! $total_enrolled_courses ) {
			return array(
				array(),
				$total_pages,
				$page,
			);
		}

		$args = array(
			'user_id'  => $id,
			'per_page' => $per_page,
			'page'     => $page,
			'offset'   => $offset,
			'paginate' => true,
		);

		$query = new CourseProgressQuery( $args );

		$progresses = $query->get_course_progress();

		$enrolled_courses = array_filter(
			array_map(
				function( $progress ) {
					$course = masteriyo_get_course( $progress->get_course_id() );

					if ( is_null( $course ) ) {
						return null;
					}

					$course->progress = $progress;
					return $course;
				},
				$progresses
			)
		);

		return array(
			$enrolled_courses,
			$total_pages,
			$page,
		);
	}
}

if ( ! function_exists( 'masteriyo_get_user_courses_with_pagination' ) ) {
	/**
	 * Retrieves the courses offered list by a user with pagination.
	 *
	 * @since 2.6.8
	 *
	 * @param int|WP_User|Masteriyo\Database\Model $user User ID, WP_User object, or Masteriyo\Database\Model object.
	 * @param int                                 $page     The current page number (default: 1).
	 * @param int                                 $per_page The number of courses to display per page (default: 6).
	 *
	 * @return array An array containing the offered courses list, total pages, and current page number.
	 */
	function masteriyo_get_user_courses_with_pagination( $user, $page = 1, $per_page = 3 ) {
		$user = masteriyo_get_user( $user );

		if ( is_null( $user ) || is_wp_error( $user ) ) {
			return array(
				'',
				1,
				$page,
			);
		}

		$user_id    = $user->get_id();
		$course_ids = masteriyo_get_instructor_course_ids( $user_id );

		if ( empty( $course_ids ) ) {
			return array(
				'',
				1,
				$page,
			);
		}

		$total_courses = count( $course_ids );

		$total_pages = ceil( $total_courses / $per_page );
		$offset      = ( absint( $page ) - 1 ) * absint( $per_page );

		$args = array(
			'post_type'      => PostType::COURSE,
			'post_status'    => PostStatus::PUBLISH,
			'post__in'       => $course_ids,
			'fields'         => 'ids',
			'posts_per_page' => $per_page,
			'paged'          => $page,
			'offset'         => $offset,
		);

		$course_ids = get_posts( $args );

		$offered_courses = array_filter(
			array_map(
				function( $course_id ) {
					$course = masteriyo_get_course( $course_id );

					if ( is_null( $course ) ) {
						return null;
					}

					return $course;
				},
				$course_ids
			)
		);

		$offered_courses_list = masteriyo_get_courses_list_html( $offered_courses );

		return array(
			$offered_courses_list,
			$total_pages,
			$page,
		);
	}
}

if ( ! function_exists( 'masteriyo_get_user_certificates' ) ) {
	/**
	 * Get a collection of user's certificates.
	 *
	 * @since 2.6.8
	 *
	 * @param int|WP_User|Masteriyo\Database\Model $user User ID, WP_User object, or Masteriyo\Database\Model object.
	 *
	 * @return array $certificates The array of user's certificates.
	 */
	function masteriyo_get_user_certificates( $user ) {
		$user_id = masteriyo_get_user( $user )->get_id();

		$query = new CourseProgressQuery(
			array(
				'user_id'  => masteriyo_get_user( $user )->get_id(),
				'status'   => CourseProgressStatus::COMPLETED,
				'per_page' => -1,
			)
		);

		$progresses = $query->get_course_progress();

		$certificates = array();

		foreach ( $progresses as $progress ) {
			$course = masteriyo_get_course( $progress->get_course_id() );

			if ( is_null( $course ) || ! is_callable( 'masteriyo_is_certificate_enabled_for_course' ) || ! masteriyo_is_certificate_enabled_for_course( $course->get_id() ) ) {
				continue;
			}

			$certificate = array(
				'id'       => $progress->get_id(),
				'view_url' => masteriyo_get_certificate_view_url( $course, $user_id ),
				'course'   => array(
					'id'                 => $course->get_id(),
					'permalink'          => $course->get_permalink(),
					'name'               => wp_specialchars_decode( $course->get_name() ),
					'featured_image_url' => $course->get_featured_image_url( 'masteriyo_thumbnail' ),
					'started_at'         => $progress->get_started_at(),
				),
			);

			$certificates[] = $certificate;
		}

		return $certificates;
	}
}

if ( ! function_exists( 'masteriyo_get_certificate_view_url' ) ) {
	/**
	 * Get the certificate view url of a user.
	 *
	 * @since 2.6.8
	 *
	 * @param \Masteriyo\Models\Course $course The course object.
	 * @param int|WP_User|Masteriyo\Database\Model $user User ID, WP_User object, or Masteriyo\Database\Model object.
	 *
	 * @return string $view_url The certificate view url.
	 */
	function masteriyo_get_certificate_view_url( $course, $user ) {
		$certificate_id = masteriyo_get_course_certificate_id( $course->get_id() );
		$certificate    = masteriyo_get_certificate( $certificate_id );

		if ( is_null( $certificate ) || is_wp_error( $certificate ) ) {
			return '';
		}

		$view_url = add_query_arg(
			array(
				'course_id'      => $course->get_id(),
				'certificate_id' => $certificate_id,
			),
			masteriyo_get_public_profile_url( masteriyo_get_user( $user )->get_username() )
		);

		return $view_url;
	}
}

if ( ! function_exists( 'masteriyo_get_user_role_title' ) ) {
	/**
	 * Get the title of a user role.
	 *
	 * This function retrieves and formats the title of a user role by removing the "masteriyo_" prefix and capitalizing the first letter.
	 *
	 * @since 2.6.8
	 *
	 * @param string $role The user role.
	 *
	 * @return string The formatted role title.
	 */
	function masteriyo_get_user_role_title( $role ) {
			$formatted_role = str_replace( 'masteriyo_', '', $role );
			return ucfirst( $formatted_role );
	}
}
