<?php
/**
 * Registrar of custom post type.
 *
 * @link       https://codingfix.com
 * @since      1.0.0
 *
 * @package    Instalist
 * @subpackage Instalist/includes
 */

/**
 * Registrar of custom post type.
 *
 * Register the new custom post type Plugin List
 *
 * @package    Instalist
 * @subpackage Instalist/includes
 * @author     Marco Gasi <info@codingfix.com>
 */
class Pluginer_Helper {

	/**
	 * Find the main plugin file.
	 *
	 * @param string $plugin_slug The plugin slug.
	 * @param string $extract_to Where to extract the plugin zip archive.
	 * @since    1.0.6
	 */
	public static function find_main_plugin_file( $plugin_slug, $extract_to = '' ) {
		static $cache = array();

		if ( isset( $cache[ $plugin_slug ] ) ) {
			return $cache[ $plugin_slug ];
		}

		WP_Filesystem();
		global $wp_filesystem;
		if ( ! $wp_filesystem ) {
			return false;
		}

		$plugin_dir = empty( $extract_to ) ? WP_PLUGIN_DIR . '/' . $plugin_slug . '/' : $extract_to;

		if ( ! is_dir( $plugin_dir ) ) {
			return false;
		}

		$filelist = $wp_filesystem->dirlist( $plugin_dir );

		if ( ! $filelist ) {
			return false;
		}

		foreach ( $filelist as $filename => $data ) {
			if ( 'f' === $data['type'] ) { // Verifica che sia un file.
				$ext = strtolower( pathinfo( $filename, PATHINFO_EXTENSION ) );
				if ( 'php' === $ext ) { // Controlla che l'estensione sia PHP.
					$file_path = $plugin_dir . $filename;
					// Ottieni i dati del plugin.
					$plugin_data = get_plugin_data( $file_path, false, false );
					if ( ! empty( $plugin_data['Name'] ) ) {
						$cache[ $plugin_slug ] = $plugin_slug . '/' . $filename;
						return $plugin_slug . '/' . $filename; // Restituisci solo il nome del file.
					}
				}
			}
		}
		$cache[ $plugin_slug ] = false;
		return false; // Nessun file principale trovato.
	}

	/**
	 * Check if required plugins are already installed or are in the list.
	 *
	 * @param string $required_plugins The required plugins.
	 * @param int    $post_id The id of the list.
	 * @since    1.0.6
	 */
	public static function check_required_plugins( $required_plugins, $post_id ) {
		$plugin_slugs      = get_post_meta( $post_id, '_plgnr_plugin_slugs', true ) ? get_post_meta( $post_id, '_plgnr_plugin_slugs', true ) : array();
		$not_found_plugins = '';
		if ( ! empty( $required_plugins ) ) {
			$required_plugins_array = explode( ', ', $required_plugins );
			foreach ( $required_plugins_array as $required_plugin ) {
				if ( 'NR' !== $required_plugin ) {
					$slug = self::get_plugin_slug_by_name( $required_plugin );
					if ( ! file_exists( WP_PLUGIN_DIR . '/' . $slug ) && ! in_array( $slug, $plugin_slugs, true ) ) {
						$not_found_plugins .= "$required_plugins, ";
					}
				}
			}
		}
		$response = '';
		if ( ! empty( $not_found_plugins ) ) {
			$response = rtrim( $not_found_plugins, ', ' );
		}
		return $response;
	}

	/**
	 * Get plugin slug by plugin name.
	 *
	 * @param string $plugin_name The plugin name.
	 * @since    1.0.6
	 */
	public static function get_plugin_slug_by_name( $plugin_name ) {
		$transient_key = 'plugin_slug_' . sanitize_title( $plugin_name );

		// Controlla se il valore è già nella cache.
		$cached_slug = get_transient( $transient_key );
		if ( false !== $cached_slug ) {
			return $cached_slug; // Restituisce il valore memorizzato nella cache.
		}

		// Esegui la ricerca tramite l'API di WordPress.
		$args = array(
			'search'   => $plugin_name, // Cerca il nome del plugin.
			'per_page' => 1,            // Limita i risultati a un solo plugin.
			'fields'   => array( 'slug' => true ), // Ottieni solo lo slug.
		);

		$response = plugins_api( 'query_plugins', $args );

		// Controlla se la risposta contiene errori.
		if ( is_wp_error( $response ) || empty( $response->plugins ) ) {
			return false; // Nessun risultato trovato.
		}

		// Restituisci lo slug del primo risultato trovato.
		return $response->plugins[0]['slug'];
	}

	/**
	 * Find required plugins.
	 *
	 * @param string $plugin_slug The plugin slug.
	 * @since    1.0.6
	 */
	public static function find_required_plugins( $plugin_slug ) {
		// URL per scaricare il plugin.
		$url      = 'https://downloads.wordpress.org/plugin/' . $plugin_slug . '.zip';
		$tmp_dir  = wp_upload_dir()['basedir'] . '/temp_plugins/';
		$tmp_file = $tmp_dir . $plugin_slug . '.zip';

		// Crea directory temporanea.
		wp_mkdir_p( $tmp_dir );

		// Scarica il file ZIP.
		$response = wp_remote_get( $url, array( 'timeout' => 30 ) );

		if ( is_wp_error( $response ) || 200 !== wp_remote_retrieve_response_code( $response ) ) {
			return array();
		}

		WP_Filesystem();
		global $wp_filesystem;

		// Salva il file.
		$wp_filesystem->put_contents( $tmp_file, wp_remote_retrieve_body( $response ) );

		// Estrai il contenuto.
		$extract_to = $tmp_dir . $plugin_slug . '/';

		// Crea directory temporanea.
		wp_mkdir_p( $extract_to );

		$unzip = unzip_file( $tmp_file, $extract_to );
		if ( is_wp_error( $unzip ) ) {
			wp_delete_file( $tmp_file );
			return array();
		}

		// Cerca il file principale.
		$main_file = self::find_main_plugin_file( $plugin_slug, $extract_to . $plugin_slug . '/' );

		if ( ! $main_file ) {
			self::cleanup_temp_files( $extract_to, $tmp_file );
			return array();
		}

		// Legge l'header.
		$plugin_headers = array(
			'RequiresPlugins' => 'Requires Plugins',
		);

		$plugin_data = get_file_data( $extract_to . '/' . $main_file, $plugin_headers );

		self::cleanup_temp_files( $tmp_dir, $tmp_file );

		if ( ! empty( $plugin_data['RequiresPlugins'] ) ) {
			$required_plugins = array_map( 'trim', explode( ',', $plugin_data['RequiresPlugins'] ) );
			foreach ( $required_plugins as $required_plugin ) {
				$required_plugin_slug = self::get_plugin_slug_by_name( $required_plugin );
				if ( file_exists( WP_PLUGIN_DIR . '/' . $required_plugin_slug ) ) {
					$required_plugin = 'NR';
				}
			}
			return $required_plugins;
		}

		return array( 'NR' );
	}

	/**
	 * Deletes downaded plugins archives.
	 *
	 * @param string $dir The archive's dir.
	 * @param string $zip_file The archive's file name.
	 * @since    1.0.6
	 */
	private static function cleanup_temp_files( $dir, $zip_file ) {
		// Cancella file e directory temporanei.
		if ( file_exists( $zip_file ) ) {
			wp_delete_file( $zip_file );
		}
		if ( file_exists( $dir ) ) {
			self::delete_dir( $dir );
		}
	}

	/**
	 * Deltes the directory where we had dwnloaded the plugin's archive.
	 *
	 * @param string $dir he archive's dir.
	 * @since    1.0.6
	 */
	private static function delete_dir( $dir ) {
		if ( ! is_dir( $dir ) ) {
			return;
		}
		$files = array_diff( scandir( $dir ), array( '.', '..' ) );
		foreach ( $files as $file ) {
			$path = $dir . DIRECTORY_SEPARATOR . $file;
			is_dir( $path ) ? self::delete_dir( $path ) : wp_delete_file( $path );
		}
		WP_Filesystem();
		global $wp_filesystem;
		if ( $wp_filesystem->is_dir( $dir ) ) {
			$wp_filesystem->delete( $dir, true ); // true => elimina anche il contenuto.
		}
	}

	/**
	 * Builds the list used internally.
	 *
	 * @param array $plugin_slugs The plugins' slugs.
	 * @since    1.0.6
	 */
	public static function get_plugin_list_data( $plugin_slugs ) {
		$response = array();
		foreach ( $plugin_slugs as $plugin_slug ) {
			$plugin_main_file = self::find_main_plugin_file( $plugin_slug );
			$is_installed     = $plugin_main_file && file_exists(
				WP_PLUGIN_DIR . '/'
				. $plugin_main_file
			);
			$installed        = $is_installed ? 1 : 0;
			$response[]       = array(
				'slug'      => $plugin_slug,
				'installed' => (int) $installed,
			);
		}
		return $response;
	}

	/**
	 * Check if a plugin is installed.
	 *
	 * @param string $plugin_main_file The plugin' main file.
	 * @since    1.0.6
	 */
	public static function is_plugin_installed( $plugin_main_file ) {
		$is_installed = $plugin_main_file && file_exists(
			WP_PLUGIN_DIR . '/'
			. $plugin_main_file
		);
		$installed    = $is_installed ? 1 : 0;
		return $installed;
	}
}
