<?php
namespace AcademyProScorm\Lesson;

if ( ! defined( 'ABSPATH' ) ) {
	exit;
}
use WP_REST_Request;
use WP_REST_Response;
use Academy\Lesson\LessonApi\Lesson;
class Hooks {

	public static function init() {
		ProgressTracker::init();
		add_action( 'rest_api_init', function() : void {
			$namespace = ACADEMY_PRO_PLUGIN_SLUG . '/v1';
			register_rest_route(
				$namespace,
				'/lesson/(?P<lesson_id>[\d-]+)/scorm-upload',
				[
					[
						'methods'             => 'POST',
						'permission_callback' => [ static::CLASS, 'admin_can' ],
						'callback'            => [ static::CLASS, 'upload' ],
					],
					[
						'methods'             => 'DELETE',
						'permission_callback' => [ static::CLASS, 'admin_can' ],
						'callback'            => [ static::CLASS, 'delete' ],
					]
				]
			);
		} );

		add_filter( 'academy/api/lesson/rest_prepare_meta_item', [ static::CLASS, 'rest_prepare_meta_item' ], 10, 2 );
		add_filter( 'academy/lesson', [ static::CLASS, 'lesson_data' ], 10, 2 );
		add_filter( 'academy/api/lesson/public_item_schema', [ static::CLASS, 'public_item_schema' ] );

		add_action(
			'academy/frontend/before_mark_topic_complete',
			[ static::CLASS, 'before_mark_lesson_complete' ],
			10,
			4
		);
	}

	public static function lesson_data( array $data, ?int $id ) : array {
		if ( isset( $data['meta']['scorm_data'] ) && is_string( $data['meta']['scorm_data'] ) ) {
			$data['meta']['scorm_data'] = json_decode( $data['meta']['scorm_data'], true );
		}
		return $data;
	}

	public static function rest_prepare_meta_item( array $data, array $lesson_data ) : array {
		$data['scorm_data'] = isset( $lesson_data['scorm_data'] ) ? $lesson_data['scorm_data'] : '';
		return $data;
	}

	public static function public_item_schema( array $schema ) : array {
		$schema['properties']['meta']['properties'] = array_merge( $schema['properties']['meta']['properties'], static::schema() );
		return $schema;
	}

	public static function schema() : array {
		return [
			'scorm_data' => [
				'type'       => 'object',
				'properties' => [
					'filename' => [
						'type'              => 'string',
						'sanitize_callback' => 'sanitize_text_field',
					],
					'url' => [
						'type'              => 'string',
						'sanitize_callback' => 'esc_url_raw',
					],
					'version' => [
						'type'              => 'string',
						'sanitize_callback' => 'sanitize_text_field',
					],
				],
			],
		];
	}
	public static function admin_can() : bool {
		return current_user_can( 'manage_academy_instructor' ) || current_user_can( 'manage_options' );
	}

	public static function upload( WP_REST_Request $req ) : WP_REST_Response {
		$meta = [];
		try {
			$lesson = Lesson::get_by_id( absint( $req['lesson_id'] ) );
		} catch ( \Throwable $e ) {
			return new WP_REST_Response( [
				'success' => false,
				'message' => $e->getMessage()
			], 404 );
		}
		if ( empty( $_FILES['file'] ) || empty( $_FILES['file']['tmp_name'] ) ) {
			return new WP_REST_Response( [
				'success' => false,
				'message' => __( 'File not found', 'academy-pro' )
			], 422 );
		}

		$file = $_FILES['file'];
		$ext = strtolower( pathinfo( $file['name'], PATHINFO_EXTENSION ) );

		if ( $ext !== 'zip' ) {
			return new WP_REST_Response( [
				'success' => false,
				'message' => __( 'Invalid file', 'academy-pro' )
			], 422 );
		}

		$filename     = md5( time() ) . '_' . basename( $file['name'] );
		$file_content = file_get_contents( $file['tmp_name'] );
		$upload_file  = wp_upload_bits( $filename, null, $file_content );

		if ( ! empty( $upload_file['error'] ) ) {
			return new WP_REST_Response( [
				'success' => false,
				'message' => __( 'Error during upload file', 'academy-pro' )
			], 422 );
		}

		$zip_path = $upload_file['file'];
		$zip      = new \ZipArchive();

		if ( $zip->open( $zip_path ) !== true ) {
			return new WP_REST_Response( [
				'success' => false,
				'message' => __( 'Error during unpac archive', 'academy-pro' )
			], 422 );
		}

		$upload_dir    = wp_upload_dir();
		$scorm_folder  = $upload_dir['basedir'] . '/academy_uploads/' . sanitize_title( pathinfo( $filename, PATHINFO_FILENAME ) );
		wp_mkdir_p( $scorm_folder );

		$zip->extractTo( $scorm_folder );
		$zip->close();
        // phpcs:ignore WordPress.WP.AlternativeFunctions.unlink_unlink	
		unlink( $zip_path );

		// Get version and launch URL
		$version     = self::get_scorm_version( $scorm_folder );
		$iframe_url  = self::get_scorm_iframe_url( $scorm_folder );

		if ( $iframe_url ) {
			$meta['scorm_data'] = [
				'filename' => sanitize_text_field( basename( $file['name'] ) ),
				'url'     => esc_url_raw( $iframe_url ),
				'version' => sanitize_text_field( $version )
			];
		}

		if ( empty( $meta ) ) {
			return new WP_REST_Response( [
				'success' => false,
				'message' => __( 'Invalid file', 'academy-pro' )
			], 422 );
		}

		try {
			$lesson->set_meta_data( $meta );
			$lesson->save_meta_data();
		} catch ( \Throwable $e ) {
			return new WP_REST_Response( [
				'success' => false,
				'message' => $e->getMessage()
			], 404 );
		}
		$data = $lesson->get_data();
		$data['meta'] = array_merge( $data['meta'], $meta );
		return new WP_REST_Response( $data );
	}

	public static function delete( WP_REST_Request $req ) : WP_REST_Response {

		try {
			$lesson = Lesson::get_by_id( absint( $req['lesson_id'] ) );
		} catch ( \Throwable $e ) {
			return new WP_REST_Response( [
				'success' => false,
				'message' => $e->getMessage()
			], 404 );
		}
		$data       = $lesson->get_data();
		$scorm_meta = $data['meta']['scorm_data'] ?? '';
		if ( empty( $scorm_meta ) ) {
			return new WP_REST_Response( [
				'success' => false,
				'message' => __( 'Scorm not exists', 'academy-pro' )
			], 404 );
		}
		$scorm_folder_url = $scorm_meta['url'];
		$upload_dir       = wp_upload_dir();
		$scorm_folder     = str_replace(
			$upload_dir['baseurl'], '', dirname( $scorm_folder_url )
		);

		// Delete folder
		if ( is_dir( $scorm_folder ) ) {
			static::rmdir_recursive( $scorm_folder, true );
		}

		try {
			$meta = [];
			$meta['scorm_data'] = null;
			$lesson->set_meta_data( $meta );
			$lesson->save_meta_data();
		} catch ( \Throwable $e ) {
			return new WP_REST_Response( [
				'success' => false,
				'message' => $e->getMessage()
			], 404 );
		}

		return new WP_REST_Response( [ 'status' => __( 'Scorm deleted', 'academy-pro' ) ] );
	}

	public static function rmdir_recursive( string $dir ): bool {
		if ( ! is_dir( $dir ) ) {
			error_log( "Not a directory: $dir" );
			return false;
		}

		$items = scandir( $dir );
		if ( ! $items ) {
			error_log( "Failed to scan directory: $dir" );
			return false;
		}

		foreach ( $items as $item ) {
			if ( $item === '.' || $item === '..' ) {
				continue;
			}

			$path = $dir . DIRECTORY_SEPARATOR . $item;

			if ( is_dir( $path ) ) {
				error_log( "Recursing into: $path" );
				self::rmdir_recursive( $path );
			} elseif ( is_file( $path ) ) {
				error_log( "Deleting file: $path" );
                // phpcs:ignore WordPress.WP.AlternativeFunctions.unlink_unlink	
				if ( ! unlink( $path ) ) {
					error_log( "Failed to delete file: $path" );
				}
			} else {
				error_log( "Unknown item: $path" );
			}
		}

		error_log( "Removing dir: $dir" );
        // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_rmdir	
		return rmdir( $dir );
	}


	protected static function get_scorm_manifest( $path ) {
		$manifest_path = rtrim( $path, '/' ) . '/imsmanifest.xml';
		return ( file_exists( $manifest_path ) ) ? $manifest_path : false;
	}

	protected static function get_scorm_version( $scorm_path ) {
		$scorm_version = '1.2';
		$manifest      = self::get_scorm_manifest( $scorm_path );

		if ( ! $manifest ) {
			return $scorm_version;
		}

		$xml = simplexml_load_file( $manifest );

		if ( ! empty( $xml->metadata ) && count( $xml->metadata ) >= 1 ) {
			$schema_version = $xml->metadata[0]->schemaversion;
			if ( ! empty( $schema_version ) && (string) $schema_version !== '1.2' ) {
				$scorm_version = '2004';
			}
		} elseif ( ! empty( $xml['version'] ) ) {
			$scorm_version = (string) $xml['version'];
		}

		return $scorm_version;
	}

	protected static function get_scorm_iframe_url( $scorm_path ) {
		$upload_dir = wp_upload_dir();
		$scorm_url  = $upload_dir['baseurl'] . '/academy_uploads/' . basename( $scorm_path );

		$manifest_path = self::get_scorm_manifest( $scorm_path );
		if ( ! $manifest_path ) {
			return false;
		}

		$xml = simplexml_load_file( $manifest_path );

		if (
			! empty( $xml )
			&& ! empty( $xml->resources )
			&& ! empty( $xml->resources->resource )
			&& ! empty( $xml->resources->resource->attributes() )
		) {
			$atts = $xml->resources->resource->attributes();
			if ( ! empty( $atts->href ) ) {
				return trailingslashit( $scorm_url ) . ltrim( (string) $atts->href, '/' );
			}
		}

		return false;
	}

	public static function before_mark_lesson_complete( ?string $topic_type, ?int $course_id, ?int $topic_id, ?int $user_id ) : void {
		if ( 'lesson' !== $topic_type ) {
			return;
		}

		try {
			$lesson = Lesson::get_by_id( absint( $topic_id ) );
			$data       = $lesson->get_data();
			$scorm_meta = $data['meta']['scorm_data'] ?? '';
			if ( empty( $scorm_meta ) ) {
				return;
			}

			$option_name        = 'academy_course_' . $course_id . '_completed_topics';
			$is_complete = true;
			$saved_topics_lists = json_decode( get_user_meta( $user_id, $option_name, true ), true );

			if ( isset( $saved_topics_lists[ $topic_type ][ $topic_id ] ) ) {
				return;
			}

			$tracker = new ProgressTracker();
			$lesson_data = $tracker->get_data( $course_id, $topic_id )['lessons'] ?? '';

			if ( ! empty( $lesson_data ) && ! static::is_completed( $lesson_data ) ) {
				wp_send_json_error( __( 'You need to complete scorm.', 'academy-pro' ) );
			}
		} catch ( \Throwable $e ) {
			return;
		}//end try
	}

	public static function is_completed( string $str ): bool {
		if ( trim( $str ) === '' ) {
			return true;
		}

		$items = explode( ',', $str );

		foreach ( $items as $item ) {
			$item = trim( $item );
			if ( $item === '0' ) {
				return false;
			} elseif ( $item !== '1' && $item !== '0' ) {
				continue;
			}
		}

		return true;
	}
}
