<?php
namespace AcademyProGoogleClassroom\Admin;

if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

use AcademyPro\Google\Service\Classroom\Course;
use AcademyPro\Google\Service\Classroom;
use AcademyPro\Google\Client;

class Ajax {
	public static $course_class_id = 'academy_google_classroom_id';
	public static $classroom_data = 'academy_google_classroom_courses';
	public static $class_code = 'academy_classroom_invite_code';
	public $redirect_url;
	public $service;
	public $client;
	/**
	 * Google classroom required scopes
	 *
	 * @var array
	 */
	private $required_scopes = [
		Classroom::CLASSROOM_COURSES,
		Classroom::CLASSROOM_COURSES_READONLY,
		Classroom::CLASSROOM_ROSTERS_READONLY,
		Classroom::CLASSROOM_PROFILE_PHOTOS,
		Classroom::CLASSROOM_PROFILE_EMAILS,
		Classroom::CLASSROOM_TOPICS_READONLY,
		Classroom::CLASSROOM_ANNOUNCEMENTS_READONLY,
		Classroom::CLASSROOM_COURSEWORK_ME_READONLY,
		Classroom::CLASSROOM_COURSEWORK_STUDENTS_READONLY,
	];
	public static function init() {
		$self = new self();
		add_action( 'wp_ajax_academy_pro_google_classroom/upload_classroom_credentials', array( $self, 'upload_classroom_credentials' ) );
		add_action( 'wp_ajax_academy_pro_google_classroom/save_classroom_credentials', array( $self, 'save_classroom_credentials' ) );
		add_action( 'wp_ajax_academy_pro_google_classroom/get_auth_code', array( $self, 'get_access_token' ) );
		add_action( 'wp_ajax_academy_pro_google_classroom/get_classroom_credential', array( $self, 'get_classroom_credential' ) );
		add_action( 'wp_ajax_academy_pro_google_classroom/import_google_classroom', array( $self, 'import_google_classroom' ) );
		add_action( 'wp_ajax_academy_pro_google_classroom/fetch_all_google_classroom', array( $self, 'fetch_all_google_classroom' ) );
		add_action( 'wp_ajax_academy_pro_google_classroom/publish_course', array( $self, 'publish_course' ) );
		add_action( 'wp_ajax_academy_pro_google_classroom/delete_course', array( $self, 'delete_course' ) );
		add_action( 'wp_ajax_academy_pro_google_classroom/create_new_google_classroom', array( $self, 'create_new_google_classroom' ) );
		add_action( 'wp_ajax_academy_pro_google_classroom/import_students_from_google_classroom', array( $self, 'import_students_from_google_classroom' ) );
	}
	public function __construct() {
		$this->redirect_url = esc_url_raw( admin_url( 'admin.php?page=academy-google-classroom' ) );
	}
	public function upload_classroom_credentials() {
		check_ajax_referer( 'academy_nonce', 'security' );

		if ( ! current_user_can( 'manage_academy_instructor' ) ) {
			wp_die();
		}
		if ( ! isset( $_FILES['upload_file'] ) ) {
			wp_send_json_error( __( 'Upload File is empty.', 'academy-pro' ) );
		}
		// phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
		$file = $_FILES['upload_file'];
		if ( 'json' !== pathinfo( $file['name'] )['extension'] ) {
			wp_send_json_error( __( 'Wrong File Format! Please import JSON file.', 'academy-pro' ) );
		}

		$upload_dir = wp_upload_dir();
		$target_dir = $upload_dir['path'] . '/classroom_credential.json';
		// phpcs:ignore Generic.PHP.ForbiddenFunctions.Found
		if ( move_uploaded_file( $file['tmp_name'], $target_dir ) ) {
			$file_path = str_replace( $upload_dir['basedir'], '', $target_dir );
			update_user_meta( get_current_user_id(), 'academy_pro_google_classroom_credential_filepath', $file_path );
			wp_send_json_success( __( 'Google Classroom Credential File uploaded successfully.', 'academy-pro' ) );
		} else {
			wp_send_json_error( __( 'Failed to upload the file.', 'academy-pro' ) );
		}
	}
	public function save_classroom_credentials() {
		check_ajax_referer( 'academy_nonce', 'security' );
		if ( ! current_user_can( 'manage_academy_instructor' ) ) {
			wp_die();
		}
		$auth_url = $this->get_authorization_url( $this->redirect_url );

		if ( $auth_url ) {
			wp_send_json_success( $auth_url );
		} else {
			wp_send_json_error( 'Failed to generate authorization URL' );
		}
	}

	private function get_authorization_url( $redirect_url ) {
		$client = $this->get_google_api_client();

		$client->setRedirectUri( $redirect_url );

		$client->addScope( $this->required_scopes );
		$auth_url = $client->createAuthUrl();

		return $auth_url;
	}

	private function get_google_api_client() {
		$client = new Client();
		$user_id = get_current_user_id();
		$upload_dir = wp_upload_dir();
		$credential_path = get_user_meta( $user_id, 'academy_pro_google_classroom_credential_filepath', true );
		$file = $upload_dir['basedir'] . '/' . $credential_path;
		$client->setApplicationName( 'Academy LMS Google Classroom' );
		$client->setAuthConfig( $file );
		$client->setRedirectUri( admin_url( 'admin.php?page=academy-google-classroom' ) );
		$client->addScope( $this->required_scopes );
		$client->setAccessType( 'offline' );
		$client->setApprovalPrompt( 'force' );

		return $client;
	}

	public function get_access_token( $authorizationCode ) {
		check_ajax_referer( 'academy_nonce', 'security' );
		if ( ! current_user_can( 'manage_academy_instructor' ) ) {
			wp_die();
		}

		$client = $this->get_google_api_client();
		// phpcs:ignore WordPress.Security.ValidatedSanitizedInput.MissingUnslash 
		$authorizationCode = isset( $_POST['authCode'] ) ? sanitize_text_field( $_POST['authCode'] ) : '';

		if ( ! empty( $authorizationCode ) ) {
			$accessToken = $client->fetchAccessTokenWithAuthCode( $authorizationCode );

			if ( isset( $accessToken['error'] ) ) {
				wp_send_json_error( 'Error fetching access token: ' . $accessToken['error_description'] );
				return false;
			}

			update_user_meta( get_current_user_id(), 'academy_pro_google_classroom_access_token', $accessToken );
			$client->setAccessToken( $accessToken );
		}
		return true;
	}

	public function get_classroom_credential() {
		check_ajax_referer( 'academy_nonce', 'security' );
		if ( ! current_user_can( 'manage_academy_instructor' ) ) {
			wp_die();
		}

		$classroom_credentials = get_user_meta( get_current_user_id(), 'academy_pro_google_classroom_access_token', true );
		$response = [
			'google_classroom' => $classroom_credentials
		];

		wp_send_json_success( $response );
	}

	public function fetch_all_google_classroom() {
		check_ajax_referer( 'academy_nonce', 'security' );
		if ( ! current_user_can( 'manage_academy_instructor' ) ) {
			wp_die();
		}
		// phpcs:ignore WordPress.Security.ValidatedSanitizedInput.MissingUnslash, WordPress.Security.ValidatedSanitizedInput.InputNotValidated 
		if ( sanitize_text_field( $_POST['class'] ) !== 'all' ) {
			wp_send_json_error(
				__( 'Invalid status error', 'academy-pro' )
			);
		}
		// phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotValidated, WordPress.Security.ValidatedSanitizedInput.MissingUnslash
		$keyword = sanitize_text_field( $_POST['search'] );
		$page = isset( $_POST['page'] ) ? sanitize_text_field( wp_unslash( $_POST['page'] ) ) : 1;
		$per_page = isset( $_POST['per_page'] ) ? sanitize_text_field( wp_unslash( $_POST['per_page'] ) ) : 10;
		$offset = ( $page - 1 ) * $per_page;
		$client = $this->set_client();
		$this->service = new Classroom( $client );
		$get_course = [];
		// check search keyword
		if ( $keyword ) {
			$courses = get_transient( self::$classroom_data );
			$results = array_filter($courses, function( $course ) use ( $keyword ) {
				return stripos( $course->name, $keyword ) !== false;
			});
			foreach ( $results as $result ) {
				$get_course[] = $result;
			}
			wp_send_json_success( $get_course );
		} else {
			// retrieve list courses
			try {
				$results = $this->service->courses->listCourses( [ 'courseStates' => 'ACTIVE' ] );
			} catch ( \Exception $e ) {
				wp_send_json_error( __( 'Failed to fetch Google Classroom courses.', 'academy-pro' ) );
				return;
			}
		}
		$courses_data = array();
		foreach ( $results->getCourses() as $course ) {
			$course->actionlink = $this->get_action_link( $course->id );
			$courses_data[] = $course;
		}
		// store course data in set transient
		set_transient( self::$classroom_data, $courses_data );
		header( 'X-Wp-Total: ' . count( $courses_data ) );
		wp_send_json_success( array_slice( $courses_data, $offset, $per_page ) );
	}

	public function publish_course() {
		check_ajax_referer( 'academy_nonce', 'security' );
		if ( ! current_user_can( 'manage_academy_instructor' ) ) {
			wp_die();
		}
		// phpcs:ignore WordPress.Security.ValidatedSanitizedInput.MissingUnslash 
		$course_id = isset( $_POST['course_id'] ) ? sanitize_text_field( $_POST['course_id'] ) : 0;
		if ( ! $course_id ) {
			return false;
		}

		$post_id = $this->get_course_by_google_class_id( (int) $course_id );
		$post = get_post( $post_id );
		if ( isset( $post_id ) && 'publish' !== $post->post_status ) {
			wp_update_post([
				'ID' => $post_id,
				'post_status' => 'publish'
			]);
			wp_send_json_success( __( 'Successfully Course Publish', 'academy-pro' ) );
		}
		wp_send_json_error( __( 'Failed to update post', 'academy-pro' ) );
	}

	public function import_students_from_google_classroom() {
		check_ajax_referer( 'academy_nonce', 'security' );
		$client = $this->set_client();
		$service = new Classroom( $client );
		// phpcs:ignore WordPress.Security.ValidatedSanitizedInput.MissingUnslash, WordPress.Security.ValidatedSanitizedInput.InputNotValidated 
		$class_course_id = sanitize_text_field( $_POST['course_id'] );
		try {
			$response = $service->courses_students->listCoursesStudents( $class_course_id );
			$student_email = [];
			foreach ( $response->getStudents() as $student ) {
				$student_email[] = $student->getProfile()->getEmailAddress();
			}

			// get course id
			$course_id = $this->get_course_by_google_class_id( (int) $class_course_id );
			if ( count( $student_email ) ) {
				foreach ( $student_email as $email ) {
					$user_id = email_exists( $email );
					if ( empty( $user_id ) ) {
						$user_id = \Academy\Helper::insert_student( $email );
					}
					\Academy\Helper::do_enroll( $course_id, $user_id );
				}
			}
			wp_send_json_success( esc_html__( 'Successfully Student imported.', 'academy-pro' ) );
		} catch ( \Exception $e ) {
			wp_send_json_error( 'Error: ' . $e->getMessage() );
		}//end try
	}

	public function create_new_google_classroom() {
		check_ajax_referer( 'academy_nonce', 'security' );
		$client = $this->set_client();
		$service = new Classroom( $client );
		// phpcs:ignore WordPress.Security.ValidatedSanitizedInput.MissingUnslash, WordPress.Security.ValidatedSanitizedInput.InputNotValidated 
		$section = (string) sanitize_text_field( $_POST['section'] );
		// phpcs:ignore WordPress.Security.ValidatedSanitizedInput.MissingUnslash, WordPress.Security.ValidatedSanitizedInput.InputNotValidated 
		$name = (string) sanitize_text_field( $_POST['class_name'] );
		// phpcs:ignore WordPress.Security.ValidatedSanitizedInput.MissingUnslash, WordPress.Security.ValidatedSanitizedInput.InputNotValidated 
		$subject = (string) sanitize_text_field( $_POST['subject'] );
		try {
			$course = new Course([
				'name' => $name,
				'section' => $section,
				'descriptionHeading' => $name . ' ' . $section,
				'description' => 'Subject : ' . $subject,
				// phpcs:ignore WordPress.Security.ValidatedSanitizedInput.MissingUnslash, WordPress.Security.ValidatedSanitizedInput.InputNotValidated 
				'room' => (string) sanitize_text_field( $_POST['room'] ),
				'ownerId' => 'me',
				'courseState' => 'PROVISIONED',
			]);
			$created = $service->courses->create( $course );
			if ( ! empty( $created ) ) {
				wp_send_json_success( __( $created->alternateLink, 'academy-pro' ) ); // phpcs:ignore
			}
		} catch ( \Exception $e ) {
			wp_send_json_success( 'Error: ' . $e->getMessage() );
		}
	}

	public function import_google_classroom() {
		check_ajax_referer( 'academy_nonce', 'security' );
		if ( ! current_user_can( 'manage_academy_instructor' ) ) {
			wp_die();
		}
		// phpcs:ignore WordPress.Security.ValidatedSanitizedInput.MissingUnslash
		$course_id = isset( $_POST['course_id'] ) ? sanitize_text_field( $_POST['course_id'] ) : '';
		if ( ! isset( $course_id ) ) {
			return false;
		}
		$google_classes = get_transient( self::$classroom_data );
		foreach ( $google_classes as $class ) {
			if ( $course_id === $class->id ) {
				$is_academy_course = $this->get_course_by_google_class_id( (int) $course_id );
				if ( $is_academy_course ) {
					wp_send_json_success( __( 'Sorry, You have already Imported Course', 'academy-pro' ) );
				}
				$class_data = array(
					'post_title' => $class->name,
					'post_status' => 'draft',
					'post_type' => 'academy_courses',
				);
				$post_id = wp_insert_post( $class_data );
				add_post_meta( $post_id, 'academy_google_classroom_title', $class->name );
				add_post_meta( $post_id, self::$course_class_id, $class->id );
				add_post_meta( $post_id, self::$class_code, $class->enrollmentCode ); // phpcs:ignore WordPress.NamingConventions.ValidVariableName.UsedPropertyNotSnakeCase
				add_post_meta( $post_id, 'academy_classroom_alternative_link', $class->alternateLink ); // phpcs:ignore
				add_post_meta( $post_id, 'academy_course_expire_enrollment', false );
				add_post_meta( $post_id, 'academy_is_enabled_course_announcements', true );
				add_post_meta( $post_id, 'academy_is_enabled_course_qa', true );
				add_post_meta( $post_id, 'academy_course_materials_included', '' );
				add_post_meta( $post_id, 'academy_course_requirements', '' );
				add_post_meta( $post_id, 'academy_course_language', '' );
				add_post_meta( $post_id, 'academy_course_benefits', '' );
				add_post_meta( $post_id, 'academy_course_duration', array( 0, 0, 0 ) );
				add_post_meta( $post_id, 'academy_course_intro_video', '' );
				add_post_meta( $post_id, 'academy_course_drip_content_enabled', false );
				add_post_meta( $post_id, 'academy_course_drip_content_type', 'schedule_by_date' );
				add_post_meta( $post_id, 'academy_prerequisite_type', 'course' );
				add_post_meta( $post_id, 'academy_prerequisite_courses', array() );
				add_post_meta( $post_id, 'academy_prerequisite_categories', array() );
				add_post_meta( $post_id, 'academy_course_max_students', 0 );
				add_post_meta( $post_id, '_thumbnail_id', 0 );
				add_post_meta( $post_id, 'academy_course_audience', '' );
				add_post_meta( $post_id, 'academy_course_difficulty_level', 'beginner' );
				add_post_meta( $post_id, 'academy_course_curriculum', array() );
				add_user_meta( get_current_user_id(), 'academy_instructor_course_id', $post_id );
				add_post_meta( $post_id, 'academy_course_product_id', 0 );
				add_post_meta( $post_id, 'academy_course_type', 'free' );
			}//end if
		}//end foreach

		if ( isset( $post_id ) ) {
			wp_send_json_success( (object) $this->get_action_link( $course_id ) );
		}
		wp_send_json_error( __( "Sorry, Google Classroom couldn't be imported", 'academy-pro' ) );
	}

	public function delete_course() {
		check_ajax_referer( 'academy_nonce', 'security' );
		if ( ! current_user_can( 'manage_academy_instructor' ) ) {
			wp_send_json_error( __( 'Unauthorized.', 'academy-pro' ), 401 );
		}
		global $wpdb;
		// phpcs:ignore WordPress.Security.ValidatedSanitizedInput.MissingUnslash
		$course_id = isset( $_POST['course_id'] ) ? sanitize_text_field( $_POST['course_id'] ) : 0;
		$course_id = $this->get_course_by_google_class_id( (int) $course_id, true );

		if ( ! $course_id ) {
			wp_send_json_error( __( 'Sorry, No Course Found', 'academy-pro' ) );
		}

		if ( ! empty( wp_delete_post( $course_id, true ) ) ) {
			delete_user_meta( get_current_user_id(), 'academy_instructor_course_id', $course_id );
			wp_send_json_success( __( 'Successfully Course Deleted', 'academy-pro' ) );
		}
		wp_send_json_error( __( "Sorry, Course Couldn't be Deleted", 'academy-pro' ) );
	}

	public function get_action_link( $course_id ) {
		$academy_course_id = $this->get_course_by_google_class_id( (int) $course_id );
		if ( null === $academy_course_id ) {
			return null;
		}

		$actionlink = array(
			'status' => get_post_status( $academy_course_id ),
			'preview_link' => html_entity_decode( esc_url_raw( get_preview_post_link( $academy_course_id ) ) ),
			'post_id'  => (int) $academy_course_id,
		);
		if ( $actionlink ) {
			return $actionlink;
		}
		return null;
	}

	public static function get_course_by_google_class_id( int $classroom_id, bool $clear = false ) : ?int {
		global $wpdb;
		if ( ! $classroom_id ) {
			return null;
		}

		$key = "course_id_by_google_class_id:{$classroom_id}";

		if ( $clear ) {
			wp_cache_delete( $key );
		}

		$course_id = wp_cache_get( $key );

		if ( ! empty( $course_id ) ) {
			return (int) $course_id;
		}

		// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
		$res = $wpdb->get_row(
			$wpdb->prepare(
				"SELECT post_id FROM {$wpdb->postmeta} WHERE meta_key = %s AND meta_value = %d LIMIT 1",
				self::$course_class_id,
				$classroom_id
			),
			ARRAY_A
		);

		$course_id = intval( $res['post_id'] ?? null );

		if ( $clear === false ) {
			wp_cache_set( $key, $course_id );
		}

		return $course_id;
	}

	public function set_client() {
		$client = new Client();
		$user_id = get_current_user_id();
		$upload_dir = wp_upload_dir();
		$credential_path = get_user_meta( $user_id, 'academy_pro_google_classroom_credential_filepath', true );
		$file = $upload_dir['basedir'] . '/' . $credential_path;
		$client->setAuthConfig( $file );
		$client->addScope( $this->required_scopes );
		$client->setAccessType( 'offline' );
		$token = get_user_meta( $user_id, 'academy_pro_google_classroom_access_token', true );
		$client->setAccessToken( $token );
		if ( $client->isAccessTokenExpired() ) {
			$client->fetchAccessTokenWithRefreshToken( $client->getRefreshToken() );
			update_user_meta( $user_id, 'academy_pro_google_classroom_access_token', $client->getAccessToken() );
		}
		return $client;
	}
}
