<?php
/**
 * The admin-specific functionality of the plugin.
 *
 * @link       https://codingfix.com
 * @since      1.0.0
 *
 * @package    Instalist
 * @subpackage Instalist/admin
 */

/**
 * The admin-specific functionality of the plugin.
 *
 * Defines the plugin name, version, and two examples hooks for how to
 * enqueue the admin-specific stylesheet and JavaScript.
 *
 * @package    Instalist
 * @subpackage Instalist/admin
 * @author     Marco Gasi <info@codingfix.com>
 */
class Pluginer_Admin {

	/**
	 * The ID of this plugin.
	 *
	 * @since    1.0.0
	 * @access   private
	 * @var      string    $plugin_name    The ID of this plugin.
	 */
	private $plugin_name;

	/**
	 * The version of this plugin.
	 *
	 * @since    1.0.0
	 * @access   private
	 * @var      string    $version    The current version of this plugin.
	 */
	private $version;

	/**
	 * The plugins list.
	 *
	 * @since    1.0.0
	 * @var      array    $plugins    The current version of this plugin.
	 */
	private $plgnr_plugins;

	/**
	 * The global args.
	 *
	 * @since    1.0.0
	 * @var      array    $args    The argument for the plugins.
	 */
	private $wp_plugins_path;

	/**
	 * The current page number.
	 *
	 * @since    1.0.0
	 * @var      string    $page_number    The number of the page in the wp repo.
	 */
	private $page_number;

	/**
	 * The installer given by the concatenation of the plugin slug and the plugin main file.
	 *
	 * @since    1.0.0
	 * @var      string    $page_number    The number of the page in the wp repo.
	 */
	private $installer;

	/**
	 * The array of plugins in the current list.
	 *
	 * @since    1.0.0
	 * @var      array    $plugins_in_list    The array of plugins in the current list.
	 */
	private $plugins_in_list;

	/**
	 * The array of plugins to install.
	 *
	 * @since    1.0.0
	 * @var      array    $plugins_to_activate    The array of plugins to install.
	 */
	private $plugins_to_activate;

	/**
	 * The array of plugins whose activation failed.
	 *
	 * @since    1.0.0
	 * @var      bool    $plugins_not_activates   The array of plugins whose activation failed.
	 */
	private $plugin_not_activated;

	/**
	 * Download errors.
	 *
	 * @since    1.0.0
	 * @var      array    $plugins_to_activate    Download errors.
	 */
	private $download_errors;

	/**
	 * The custom post registrar.
	 *
	 * @since    1.0.0
	 * @var      array    $plugins_to_activate    The array of plugins to install.
	 */
	private $plgnr_cpt;

	/**
	 * The custom post metabox.
	 *
	 * @since    1.0.0
	 * @var      array    $plugins_to_activate    The array of plugins to install.
	 */
	private $plgnr_metabox;

	/**
	 * The page number of the paginated list.
	 *
	 * @since    1.0.0
	 * @var      string    $plugins_page_number    The plugin page number in wp repo.
	 */
	private $plugins_page_number;

	/**
	 * The highest page number reached.
	 *
	 * @since    1.0.0
	 * @var      string    $highest_page_number    The highest page number reached.
	 */
	private $highest_page_number;

	/**
	 * The plugins options.
	 *
	 * @since    1.0.0
	 * @var      array    $options    The options of this plugin.
	 */
	private $options;

	/**
	 * Initialize the class and set its properties.
	 *
	 * @since    1.0.0
	 * @param      string $plugin_name       The name of this plugin.
	 * @param      string $version    The version of this plugin.
	 */
	public function __construct( $plugin_name, $version ) {

		$this->options             = get_option( 'plgnr_options' );
		$this->plugin_name         = $plugin_name;
		$this->version             = $version;
		$this->wp_plugins_path     = preg_replace( '#\\\\#', '/', ABSPATH ) . 'wp-content/plugins/';
		$this->download_errors     = array();
		$this->plugins_in_list     = array();
		$this->plugins_to_activate = array();
		$this->plgnr_cpt           = new Pluginer_CPT();
		$this->plgnr_metabox       = new Pluginer_Metabox();
	}

	/**
	 * Register the stylesheets for the admin area.
	 *
	 * @since    1.0.0
	 */
	public function enqueue_styles() {
		$version        = wp_rand( 100, 999 );
		$current_screen = get_current_screen();
		if ( 'plgnr_plugin_list' === $current_screen->post_type || 'pluginer_page_plgnr_settings' === $current_screen->id
		|| 'pluginer_page_plgnr_import' === $current_screen->id || 'pluginer_page_pluginer-premium' === $current_screen->id ) {
			wp_enqueue_style( $this->plugin_name, plugin_dir_url( __FILE__ ) . 'css/pluginer-admin.css', array(), $version, 'all' );
			wp_enqueue_style( $this->plugin_name . 'sweeetalert-style', plugin_dir_url( __FILE__ ) . 'css/sweetalert2.min.css', array(), $this->version, 'all' );
		}
	}

	/**
	 * Register the JavaScript for the admin area.
	 *
	 * @since    1.0.0
	 */
	public function enqueue_scripts() {
		$current_screen = get_current_screen();
		if ( 'plgnr_plugin_list' === $current_screen->post_type || 'pluginer_page_plgnr_settings' === $current_screen->id
		|| 'pluginer_page_plgnr_import' === $current_screen->id || 'pluginer_page_pluginer-premium' === $current_screen->id ) {
			wp_enqueue_script( 'pluginer-admin-js' );
			wp_localize_script( 'pluginer-admin-js', 'pluginerAdmin', array( 'nonce' => wp_create_nonce( $this->plugin_name . '_admin_nonce' ) ) );
		}
		// blocchi autosave.
		wp_dequeue_script( 'autosave' );
		wp_deregister_script( 'autosave' );
	}

	/**
	 * Inizializza le rotte della licenza.
	 *
	 * @since 1.0.0
	 */
	public function init_license_routes() {
		Pluginer_License_Manager::register_routes();
	}

	/**
	 * Inizializza il cron per la validazione della licenza.
	 *
	 * @since 1.0.0
	 */
	public function init_schedule_cron() {
		Pluginer_License_Manager::schedule_cron();
	}

	/**
	 * Esegue la validazione della licenza all'inizio di ogni caricamento della pagina admin.
	 *
	 * @since 1.0.0
	 */
	public function init_cron_validate_license() {
		Pluginer_License_Manager::cron_validate_license();
	}

	/**
	 * Register the shared scripts for the admin area.
	 *
	 * @since    1.0.0
	 */
	public function register_shared_scripts() {
		$version = wp_rand( 100, 999 );
		wp_register_script(
			'pluginer-sweetalert2',
			plugin_dir_url( __FILE__ ) . 'js/sweetalert2.min.js',
			array(),
			$version,
			true
		);

		wp_register_script(
			'pluginer-common-js',
			plugin_dir_url( __FILE__ ) . 'js/pluginer-common.js',
			array( 'jquery' ),
			$version,
			true
		);

		wp_register_script(
			'pluginer-admin-js',
			plugin_dir_url( __FILE__ ) . 'js/pluginer-admin.js',
			array( 'jquery', 'jquery-form', 'pluginer-sweetalert2', 'pluginer-common-js' ),
			$version,
			true
		);
	}

	/**
	 * Sends header to avoid CORS errors.
	 *
	 * @since    1.0.0
	 */
	public function plgnr_send_headers() {
		// phpcs:disable
		if ( defined( 'DOING_AJAX' ) && DOING_AJAX ) {
			// $_POST['action'] is not an external data so there is no risk here to acces it directly without nonce verification. On the other hand, I don't see how it would be possible add here a nonce verification since my code doesn't call admin_init via Ajax or in any other way.
			$action = isset( $_POST['action'] ) ? sanitize_text_field( wp_unslash( $_POST['action'] ) ) : '';
			// phpcs:enable
			if ( in_array( $action, array( 'plgnr_get_plugins_in_list', 'plgnr_install_single_plugin' ), true ) ) {
				header( 'Access-Control-Allow-Origin: ' . esc_url( site_url() ) );
				header( 'Access-Control-Allow-Credentials: true' );
			}
		}
	}

	/**
	 * Load the premium features.
	 */
	public function trigger_premium_loaded() {
		if ( defined( 'PLUGINER_PREMIUM_ACTIVE' ) ) {
			do_action( 'pluginer_premium_loaded' );
		}
	}


	/**
	 * If list name is not set shows an error.
	 *
	 * @since    1.0.0
	 */
	public function plgnr_show_title_error_notice() {
		if ( isset( $_GET['_wpnonce'] ) ) {
			if ( wp_verify_nonce( sanitize_text_field( wp_unslash( $_GET['_wpnonce'] ) ), 'nolistnameerror' ) ) {
				if ( isset( $_GET['title_error'] ) && '1' === $_GET['title_error'] ) {
					echo '<div class="error notice"><p>The list name cannot be empty.</p></div>';
				}
			}
		}
	}

	/**
	 * Adds settings page to menu.
	 *
	 * @since    1.0.0
	 */
	public function admin_menu() {
		add_menu_page(
			'Pluginer',
			'Pluginer',
			apply_filters( 'plgnr_admin_capability', 'edit_posts', 'plugin_list_list' ),
			'pluginer',
			array( $this, 'plugin_list_page' ),
			'dashicons-list-view',
			6
		);

		add_submenu_page(
			'pluginer',
			__( 'Add New Plugin List', 'pluginer' ),
			__( 'Add New Plugin List', 'pluginer' ),
			apply_filters( 'plgnr_admin_capability', 'edit_posts', 'plugin_list_list' ),
			'post-new.php?post_type=plgnr_plugin_list'
		);

		add_submenu_page(
			'pluginer',
			__( 'Import', 'pluginer' ),
			__( 'Import', 'pluginer' ),
			apply_filters( 'plgnr_import', 'manage_options', 'plgnr_import' ),
			'plgnr_import',
			array( $this, 'plgnr_display_plugin_admin_page' )
		);

		add_submenu_page(
			'pluginer',
			__( 'Pluginer Premium', 'pluginer' ),
			__( 'Premium', 'pluginer' ),
			apply_filters( 'plgnr_admin_capability', 'edit_posts', 'plugin_list_list' ), // stessa capability del menu principale.
			'pluginer-premium',
			array( $this, 'plgnr_render_license_page' )
		);
	}

	/**
	 * Add a links near Deactivate link in the plugin list
	 *
	 * @param string $links add link to Settings page in plugin page.
	 * @since    1.0.0
	 */
	public function plgnr_add_action_links( $links ) {
		/*
		*  Documentation : https://codex.wordpress.org/Plugin_API/Filter_Reference/plugin_action_links_(plugin_file_name)
		*/
		$settings_link = array(
			'<a href="' . admin_url( 'admin.php?page=pluginer' ) . '">' . __( 'Settings', 'pluginer' ) . '</a>',
		);
		return array_merge( $settings_link, $links );
	}

	/**
	 * Callback function for the admin settings page.
	 *
	 * @since    1.0.0
	 */
	public function plgnr_display_plugin_admin_page() {
		require_once plugin_dir_path( __DIR__ ) . 'admin/partials/pluginer-admin-display.php';
	}

	/**
	 * Renderizza la pagina Premium (usa il partial)
	 */
	public function plgnr_render_license_page() {
		$data = Pluginer_License_Manager::get_license_data();
		include plugin_dir_path( __DIR__ ) . 'admin/partials/pluginer-admin-license-display.php';
	}

	/**
	 * Gets all plugins from a list
	 *
	 * @since    1.0.6
	 */
	public function plgnr_get_plugins_in_list() {
		// Enforce nonce and capability checks for AJAX handlers.
		$nonce_ok = check_ajax_referer( 'plgnr_installpluginlist', 'nonce', false );
		if ( false === $nonce_ok ) {
			wp_send_json_error(
				array(
					'result'  => 'failure',
					'message' => 'Invalid nonce',
				)
			);
			wp_die();
		}
		$nonce = isset( $_POST['nonce'] ) ? sanitize_text_field( wp_unslash( $_POST['nonce'] ) ) : '';

		if ( ! current_user_can( 'install_plugins' ) ) {
			wp_send_json_error(
				array(
					'result'  => 'failure',
					'message' => 'Insufficient permissions',
				)
			);
			wp_die();
		}

		if ( isset( $_POST['post_id'] ) ) {
			$post_id = absint( sanitize_text_field( wp_unslash( $_POST['post_id'] ) ) );
		} else {
			wp_send_json_error(
				array(
					'result'  => 'failure',
					'message' => 'Missing post_id.',
				)
			);
		}

		if ( ! apply_filters( 'pluginer_can_install_list', true, $post_id ) ) {
			wp_send_json_error(
				array(
					'result'  => 'failure',
					'message' => 'You are not allowed to install this list. Please upgrade to Pluginer Premium.',
				)
			);
		}

		$plugin_slugs = get_post_meta( $post_id, '_plgnr_plugin_slugs', true ) ? get_post_meta( $post_id, '_plgnr_plugin_slugs', true ) : array();

		if ( empty( $plugin_slugs ) ) {
			wp_send_json_error( array( 'plugins' => 'This list is empty.' ) );
		}

		$response = array();
		foreach ( $plugin_slugs as $plugin_slug ) {
			$plugin_main_file = Pluginer_Helper::find_main_plugin_file( $plugin_slug );
			$installed        = Pluginer_Helper::is_plugin_installed( $plugin_main_file );
			$response[]       = array(
				'slug'      => $plugin_slug,
				'installed' => (int) $installed,
			);
		}

		$plugins_number = count( $plugin_slugs );
		if ( 0 === $plugins_number ) {
			wp_send_json_error( array( 'plugins' => 'This list is empty.' ) );
		}
		wp_send_json_success(
			array(
				'plugins' => $response,
				'nonce'   => $nonce,
			)
		);
		exit;
	}

	/**
	 * Install and activate a single plugin.
	 *
	 * @since    1.0.6
	 */
	public function plgnr_install_single_plugin() {
		// Enforce nonce and capability checks.
		$nonce_ok = check_ajax_referer( 'plgnr_installpluginlist', 'nonce', false );
		if ( false === $nonce_ok ) {
			wp_send_json_error(
				array(
					'result'  => 'failure',
					'message' => 'Invalid nonce',
				)
			);
			wp_die();
		}
		if ( ! current_user_can( 'install_plugins' ) ) {
			wp_send_json_error(
				array(
					'result'  => 'failure',
					'message' => 'Insufficient permissions',
				)
			);
			wp_die();
		}

		$plugin_slug = isset( $_POST['plugin_slug'] ) ? sanitize_text_field( wp_unslash( $_POST['plugin_slug'] ) ) : '';

		if ( empty( $plugin_slug ) ) {
			wp_send_json_error( 'Invalid plugin slug' );
		}

		// Validate slug format: only lowercase letters, numbers and hyphens are allowed.
		if ( ! preg_match( '/^[a-z0-9\-]+$/', $plugin_slug ) ) {
			wp_send_json_error( 'Invalid plugin slug' );
		}

		$wprepopath = 'https://downloads.wordpress.org/plugin/' . $plugin_slug . '.zip';
		$response   = wp_remote_get( $wprepopath, array( 'timeout' => 60 ) );

		if ( is_wp_error( $response ) ) {
			wp_send_json_error( array( 'message' => $response->get_error_message() ) );
		}

		$code         = (int) wp_remote_retrieve_response_code( $response );
		$content_type = wp_remote_retrieve_header( $response, 'content-type' );
		$body         = wp_remote_retrieve_body( $response );

		// Basic validation: expect HTTP 200 and a zip-like content-type and reasonable size.
		if ( 200 !== $code || ( false === stripos( $content_type, 'zip' ) && false === stripos( $content_type, 'octet-stream' ) ) || strlen( $body ) < 1024 ) {
			wp_send_json_error( array( 'message' => 'Download failed — plugin may require a license or be inaccessible.' ) );
		}

		$file = tempnam( sys_get_temp_dir(), 'plgnr_' ) . '.zip';

		WP_Filesystem();
		global $wp_filesystem;
		$wp_filesystem->put_contents( $file, $body );

		$unzip_result = unzip_file( $file, $this->wp_plugins_path );
		if ( is_wp_error( $unzip_result ) ) {
			wp_delete_file( $file );
			wp_send_json_error( array( 'message' => 'Unzip failed: ' . $unzip_result->get_error_message() ) );
		} elseif ( true === $unzip_result ) {
			wp_delete_file( $file );
		} else {
			// Unexpected return value — remove temp and fail.
			wp_delete_file( $file );
			wp_send_json_error( array( 'message' => 'Unknown unzip result.' ) );
		}

		$this->installer = Pluginer_Helper::find_main_plugin_file( $plugin_slug );
		if ( $this->installer ) {
			$this->plugin_not_activated = false;

			$validated = validate_plugin_requirements( $this->installer );

			if ( is_wp_error( $validated ) ) {
				$this->plugin_not_activated = true;
			}
			$message = 'Probably, one or more required plugins are missing in your WordPress installation.';

			if ( ! $this->plugin_not_activated ) {
				// Assicurati che il file del plugin esista.
				if ( file_exists( WP_PLUGIN_DIR . '/' . $this->installer ) ) {
					// Pulisci la cache prima di attivare il plugin.
					wp_cache_flush();
					$activated = activate_plugin( $this->installer, '', false, true );
					if ( is_wp_error( $activated ) ) {
						$message = $activated->get_error_message();
					}
				} else {
					$message = 'Plugin file does not exist: ' . WP_PLUGIN_DIR . '/' . $this->installer;
				}
			}

			sleep( 2 );
			wp_cache_flush();
			if ( is_plugin_active( $this->installer ) ) {
				wp_send_json_success(
					array(
						'status' => 'active',
						'plugin' => $plugin_slug,
					)
				);
			} else {
				delete_transient( $this->installer );
				wp_send_json_error(
					array(
						'status'  => 'inactive',
						'plugin'  => $plugin_slug,
						'message' => $message,
					)
				);
			}
			exit;
		} else {
			wp_send_json_error( 'Main plugin file not found' );
		}
	}

	/**
	 * Export a plugin list
	 *
	 * @since    1.0.0
	 */
	public function plgnr_export_plugin_list() {
		// Enforce nonce and capability checks for export.
		// The export form posts the nonce in the `security` field (see admin JS),
		// so check that parameter name here to avoid mismatches.
		$nonce_ok = check_ajax_referer( 'plgnrexportpluginlist', 'security', false );
		if ( false === $nonce_ok ) {
			wp_send_json(
				array(
					'result'  => 'failure',
					'message' => 'Invalid nonce',
				)
			);
			wp_die();
		}
		if ( ! current_user_can( 'manage_options' ) ) {
			wp_send_json(
				array(
					'result'  => 'failure',
					'message' => 'Insufficient permissions',
				)
			);
			wp_die();
		}

		if ( ! isset( $_POST['post_id'] ) ) {
			wp_send_json(
				array(
					'result'  => 'failure',
					'message' => 'No post id found',
				)
			);
			die;
		}

		$post_id = intval( $_POST['post_id'] );
		$post    = get_post( $post_id );

		if ( ! apply_filters( 'pluginer_can_export_list', true, $post_id ) ) {
			wp_send_json_error(
				array(
					'result'  => 'failure',
					'message' => 'You are not allowed to export this list. Please upgrade to Pluginer Premium.',
				)
			);
		}

		if ( ! $post ) {
			wp_send_json_error( array( 'message' => 'Invalid post ID.' . $post_id ) );
		}
		if ( 'plgnr_plugin_list' !== $post->post_type ) {
			wp_send_json_error( array( 'message' => 'Invalid post type.' ) );
		}

		// Recupera le notes (possono essere multilinea).
		$plugin_notes = get_post_meta( $post_id, '_plgnr_plugin_list_notes', true );

		// Costruisce il contenuto CSV.
		$csv_content = '';
		if ( ! empty( $plugin_notes ) ) {
			$csv_content .= rtrim( $plugin_notes, "\r\n" ) . "\n\n"; // notes + riga vuota.
		} else {
			$csv_content .= "\n"; // Solo riga vuota.
		}

		$plugin_icons     = get_post_meta( $post_id, '_plgnr_plugin_icons', true );
		$plugin_names     = get_post_meta( $post_id, '_plgnr_plugin_names', true );
		$plugin_slugs     = get_post_meta( $post_id, '_plgnr_plugin_slugs', true );
		$required_plugins = get_post_meta( $post->ID, '_plgnr_plugin_required_plugins', true ) ? get_post_meta( $post->ID, '_plgnr_plugin_required_plugins', true ) : array();

		if ( ! empty( $plugin_names ) && ! empty( $plugin_slugs ) ) {
			foreach ( $plugin_names as $index => $name ) {
				$icon         = isset( $plugin_icons[ $index ] ) ? $plugin_icons[ $index ] : '';
				$slug         = isset( $plugin_slugs[ $index ] ) ? $plugin_slugs[ $index ] : '';
				$req          = isset( $required_plugins[ $index ] ) ? $required_plugins[ $index ] : '';
				$csv_content .= "{$icon}#{$name}#{$slug}#{$req}\n";
			}
		}

		$file_name = preg_replace( '/\s/', '_', get_the_title( $post ) ) . '.csv';

		header( 'Content-Type: text/csv' );
		header( 'Content-Disposition: attachment; filename="' . $file_name . '"' );
		header( 'Pragma: no-cache' );
		header( 'Expires: 0' );

		echo esc_html( $csv_content );
		exit;
	}

	/**
	 * Import_list() is a core function available in the Lite version.
	 * Note: since in Lite version only one list is allowed, certain restrictions apply.
	 * For example, importing over an existing list manually created or previously imported list
	 * requires Pluginer Premium.
	 *
	 * Lite version enforces these restrictions via hooks like 'pluginer_can'
	 * and overlays to prevent unauthorized usage.
	 */

	/**
	 * Import a plugin list
	 *
	 * @since    1.0.0
	 */
	public function plgnr_import_plugin_list() {
		if ( ! current_user_can( 'manage_options' ) ) {
			wp_die( 'Not allowed' );
		}

		$is_premium = apply_filters( 'pluginer_is_premium', false );
		$args       = array(
			'post_type'      => 'plgnr_plugin_list',
			'posts_per_page' => -1,
		);
		$query      = new WP_Query( $args );
		if ( $query->found_posts >= 1 && ! $is_premium ) {
			wp_send_json( array( 'result' => 'upgrade_needed' ) );
		}

		check_admin_referer( 'plgnrimportpluginlist' );

		if ( isset( $_FILES['import_list']['tmp_name'] ) && isset( $_FILES['import_list']['name'] ) ) {
			$original_name = sanitize_text_field( wp_unslash( $_FILES['import_list']['name'] ) );

			// Use WP API to handle uploads (avoids direct use of move_uploaded_file and satisfies PHPCS).
			require_once ABSPATH . 'wp-admin/includes/file.php';
			$overrides = array(
				'test_form' => false,
				'mimes'     => array(
					'csv' => 'text/csv',
					'txt' => 'text/plain',
				),
			);

			$uploaded = wp_handle_upload( wp_unslash( $_FILES['import_list'] ), $overrides );
			if ( isset( $uploaded['error'] ) ) {
				wp_die( 'Upload failed: ' . esc_html( $uploaded['error'] ) );
			}

			$temp_path = isset( $uploaded['file'] ) ? $uploaded['file'] : '';
			if ( empty( $temp_path ) || ! file_exists( $temp_path ) ) {
				wp_die( 'Upload failed' );
			}

			// **Verifica il MIME type per garantire che sia un CSV valido**.
			$file_info = finfo_open( FILEINFO_MIME_TYPE );
			$mime_type = finfo_file( $file_info, $temp_path );
			finfo_close( $file_info );

			if ( ( 'text/plain' !== $mime_type && 'text/csv' !== $mime_type ) ) {
				wp_delete_file( $temp_path ); // Cancella il file se non è valido.
				wp_send_json( array( 'result' => 'invalid_file_type' ) );
			}

			// Ora processiamo il file temporaneo direttamente dal filesystem usando l'API di WP.
			WP_Filesystem();
			global $wp_filesystem;
			$file_contents = $wp_filesystem->get_contents( $temp_path );
			if ( false === $file_contents || null === $file_contents ) {
				wp_delete_file( $temp_path );
				wp_die( 'Error reading uploaded file.' );
			}

			// Split cross-platform.
			$rows = preg_split( '/\r\n|\r|\n/', $file_contents );

			$plugin_notes     = '';
			$plugin_icons     = array();
			$plugin_names     = array();
			$plugin_slugs     = array();
			$required_plugins = array();

			$csv_started = false;
			$i           = 0;
			foreach ( $rows as $row ) {
				if ( '' === trim( $row ) && ! $csv_started ) {
					// Riga vuota → da qui iniziano i dati CSV.
					$csv_started = true;
					continue;
				}

				if ( ! $csv_started ) {
					// Parte delle notes.
					$plugin_notes .= $row . "\n";
					continue;
				}

				$csv_data = array_map( 'trim', explode( '#', $row ) );
				if ( count( $csv_data ) < 4 ) {
					continue;
				}

				$plugin_icons[]     = $csv_data[0];
				$plugin_names[]     = $csv_data[1];
				$plugin_slugs[]     = $csv_data[2];
				$required_plugins[] = $csv_data[3];
				++$i;
			}

			// 🔹 Creazione di un nome univoco per evitare duplicati 🔹
			$original_name = pathinfo( $original_name, PATHINFO_FILENAME ); // Rimuove l'estensione.
			$list_name     = $original_name;
			$i             = 1;

			// Se esiste già un post con lo stesso nome, aggiunge un numero progressivo.
			while ( post_exists( $list_name, '', '', 'inslst_plugin_list' ) ) {
				$list_name = $original_name . ' ' . $i;
				++$i;
			}

			// Creazione del CPT.
			$post_id = wp_insert_post(
				array(
					'post_title'  => $list_name,
					'post_status' => 'publish',
					'post_type'   => 'plgnr_plugin_list',
				)
			);

			if ( ! is_wp_error( $post_id ) ) {
				update_post_meta( $post_id, '_plgnr_plugin_list_notes', rtrim( $plugin_notes, "\n" ) );
				update_post_meta( $post_id, '_plgnr_plugin_icons', $plugin_icons );
				update_post_meta( $post_id, '_plgnr_plugin_names', $plugin_names );
				update_post_meta( $post_id, '_plgnr_plugin_slugs', $plugin_slugs );
				update_post_meta( $post_id, '_plgnr_plugin_required_plugins', $required_plugins );

				// Prima lista → primaria.
				$primary_exists = get_posts(
					array(
						'post_type'      => 'plgnr_plugin_list',
						'posts_per_page' => 1,
						'meta_key'       => '_is_primary_list', //phpcs:ignore
						'meta_value'     => '1', //phpcs:ignore
						'fields'         => 'ids',
					)
				);
				if ( empty( $primary_exists ) ) {
						update_post_meta( $post_id, '_is_primary_list', '1' );
				}
			}

			wp_delete_file( $temp_path );
			wp_send_json( array( 'result' => 'success' ) );
		}

		exit;
	}


	/**
	 * Validate license on admin load if user can manage options.
	 *
	 * @param WP_Screen $screen Current screen object.
	 * @since    1.0.0
	 */
	public function validate_on_admin_load( $screen ) {
		if ( 'plgnr_plugin_list' === $screen->post_type || 'pluginer_page_plgnr_settings' === $screen->id || 'pluginer_page_plgnr_import' === $screen->id ) {
			Pluginer_License_Manager::rest_validate();
		}
	}

	/**
	 * Block non primary list creation and editing if not premium.
	 *
	 * @since    1.0.0
	 */
	public function plgnr__block_non_primary_edit() {
		global $typenow, $post;

		if ( 'plgnr_plugin_list' === $typenow ) {
			$is_premium = apply_filters( 'pluginer_is_premium', false );
			$post_id    = isset( $post->ID ) ? (int) $post->ID : 0;

			// Controllo esistenza liste.
			$query       = new WP_Query(
				array(
					'post_type'      => 'plgnr_plugin_list',
					'posts_per_page' => -1,
				)
			);
			$found_posts = (int) $query->found_posts;

			// Solo utenti non Premium.
			if ( ! $is_premium ) {
				// Permetti sempre l'editing della lista esistente
				// Blocca solo se ci sono altre liste e questa non è primaria.
				if ( $found_posts > 1 ) {
					$is_primary = $post_id ? (int) get_post_meta( $post_id, '_is_primary_list', true ) : 0;

					if ( 1 !== $is_primary ) {
						wp_die(
							esc_html__( 'You cannot create or edit additional lists without an active license.', 'pluginer' ),
							esc_html__( 'Restricted', 'pluginer' ),
							array( 'back_link' => true )
						);
					}
				}
			}
		}
	}


	/**
	 * Block non primary list creation and editing if not premium - strict version to avoid bypassing via direct URL.
	 *
	 * @since    1.0.7
	 */
	public function plgnr_block_non_primary_edit_strict() {
		global $pagenow;

		if ( in_array( $pagenow, array( 'post.php', 'post-new.php' ), true ) ) {
			// Non è un dato esterno, non serve sanitizzazione.
			$post_id   = isset( $_GET['post'] ) ? (int) $_GET['post'] : 0; // phpcs:ignore WordPress.Security.NonceVerification.Recommended
			$post_type = $post_id ? get_post_type( $post_id ) : ( isset( $_GET['post_type'] ) ? sanitize_key( $_GET['post_type'] ) : '' ); // phpcs:ignore WordPress.Security.NonceVerification.Recommended

			if ( 'plgnr_plugin_list' === $post_type ) {
				$is_premium = apply_filters( 'pluginer_is_premium', false );

				// Controllo esistenza liste.
				$query       = new WP_Query(
					array(
						'post_type'      => 'plgnr_plugin_list',
						'posts_per_page' => -1,
					)
				);
				$found_posts = (int) $query->found_posts;

				// Solo utenti non Premium.
				if ( ! $is_premium ) {
					// Permetti la creazione se non ci sono liste.
					if ( $found_posts > 0 ) {
						$is_primary = $post_id ? (int) get_post_meta( $post_id, '_is_primary_list', true ) : 0;

						// Blocca se non è la lista primaria.
						if ( 1 !== $is_primary ) {
							wp_die(
								esc_html__( 'You cannot create or edit additional lists without an active license.', 'pluginer' ),
								esc_html__( 'Restricted', 'pluginer' ),
								array( 'back_link' => true )
							);
						}
					}
				}
			}
		}
	}

	/**
	 * Restituisce l'ID della prima lista creata (se esiste)
	 *
	 * @param booloean $allowed Se true la action può essere eseguita.
	 * @param int      $post_id ID della lista su cui si vuole eseguire la action.
	 *
	 * @return int|null ID della prima lista o null se non esiste.
	 */
	public function maybe_allow_list_action( $allowed, $post_id ) {
		$license = Pluginer_License_Manager::get_license_data();

		$has_license = ( isset( $license['status'] ) && 'active' === $license['status'] );
		$has_addon   = defined( 'PLUGINER_PREMIUM_VERSION' ) || class_exists( 'Pluginer_Premium' );

		// Se manca licenza o addon → controlla se è lista primaria.
		if ( ! ( $has_license && $has_addon ) ) {
			$is_primary = get_post_meta( $post_id, '_is_primary_list', true );
			return ( '1' === $is_primary );
		}

		// Licenza + Premium attivi → consenti sempre.
		return true;
	}

	/**
	 * Aggiunge la classe 'restricted' alle liste se la licenza non è attiva.
	 *
	 * @param string[] $classes Array delle classi CSS.
	 * @param string   $class   Classe CSS corrente (non usata).
	 * @param int      $post_id ID del post (lista).
	 *
	 * @return string[] Array delle classi CSS eventualmente modificate.
	 */
	public function block_lists( $classes, $class, $post_id ) { // phpcs:ignore Universal.NamingConventions.NoReservedKeywordParameterNames.classFound
		if ( $post_id && 'plgnr_plugin_list' === get_post_type( $post_id ) ) {
			if ( ! apply_filters( 'pluginer_can', true, $post_id ) ) {
				$classes[] = 'restricted';
			} else {
				$classes[] = 'allowed';
			}
		}
		return $classes;
	}

	/**
	 * Resets the page number to 1 when a new list is created.
	 *
	 * @since    1.0.0
	 */
	public function plgnr_reset_page_number() {
		$this->options['plugins_page'] = 1;
		update_option( 'plgnr_options', $this->options );
	}

	/**
	 * Get plugins from wp repo
	 *
	 * @param    string $plugin The plugin slug.
	 * @param    array  $installed_plugins The active plugins array.
	 *
	 * @since    1.0.0
	 */
	public function plgnr_is_installed( $plugin, $installed_plugins ) {
		foreach ( $installed_plugins as $ip ) {
			if ( false !== stripos( $ip, $plugin ) ) {
				return true;
			}
		}
		return false;
	}

	/**
	 * Updates the plugin list after having added required plugins
	 *
	 * @since    1.1.0
	 */
	public function plgnr_update_plugin_list() {
		// Verifica nonce per sicurezza.
		check_ajax_referer( 'plgnr_installpluginlist', 'security' );

		// Recupera i dati dalla richiesta AJAX.
		$post_id = isset( $_POST['post_id'] ) ? intval( $_POST['post_id'] ) : 0;

		// Controlla che il post esista.
		if ( ! $post_id || 'plgnr_plugin_list' !== get_post_type( $post_id ) ) {
			wp_send_json_error( 'Post non valido.' );
		}

		$current_title = get_the_title( $post_id );

		// Aggiorna il post con dati fittizi (puoi modificare questi campi).
		$post_data = array(
			'ID'         => $post_id,
			'post_title' => $current_title,
		);

		// Esegui l'update.
		$result = wp_update_post( $post_data, true );

		if ( is_wp_error( $result ) ) {
			wp_send_json_error( 'Error during the update process.' );
		}

		// Recupera i metadati esistenti.
		$plugin_notes     = get_post_meta( $post_id, '_plgnr_plugin_list_notes', true ) ? get_post_meta( $post_id, '_plgnr_plugin_list_notes', true ) : '';
		$plugin_names     = get_post_meta( $post_id, '_plgnr_plugin_names', true ) ? get_post_meta( $post_id, '_plgnr_plugin_names', true ) : array();
		$plugin_slugs     = get_post_meta( $post_id, '_plgnr_plugin_slugs', true ) ? get_post_meta( $post_id, '_plgnr_plugin_slugs', true ) : array();
		$plugin_icons     = get_post_meta( $post_id, '_plgnr_plugin_icons', true ) ? get_post_meta( $post_id, '_plgnr_plugin_icons', true ) : array();
		$required_plugins = get_post_meta( $post_id, '_plgnr_plugin_required_plugins', true ) ? get_post_meta( $post_id, '_plgnr_plugin_required_plugins', true ) : array();

		// Aggiungi i nuovi valori.
		if ( isset( $_POST['plugin_name'] ) && isset( $_POST['plugin_slug'] ) && isset( $_POST['plugin_icon'] ) && isset( $_POST['required_plugin'] ) ) {
			$plugin_names[]     = sanitize_text_field( wp_unslash( $_POST['plugin_name'] ) );
			$plugin_slugs[]     = sanitize_text_field( wp_unslash( $_POST['plugin_slug'] ) );
			$plugin_icons[]     = sanitize_text_field( wp_unslash( $_POST['plugin_icon'] ) );
			$required_plugins[] = sanitize_text_field( wp_unslash( $_POST['required_plugin'] ) );
		}
		if ( isset( $_POST['plugin_list_notes'] ) ) {
			$plugin_list_notes = sanitize_textarea_field( wp_unslash( $_POST['plugin_list_notes'] ) );
		}

		// Aggiorna i metadati del post.
		update_post_meta( $post_id, '_plgnr_plugin_list_notes', $plugin_list_notes );
		update_post_meta( $post_id, '_plgnr_plugin_names', $plugin_names );
		update_post_meta( $post_id, '_plgnr_plugin_slugs', $plugin_slugs );
		update_post_meta( $post_id, '_plgnr_plugin_icons', $plugin_icons );
		update_post_meta( $post_id, '_plgnr_plugin_required_plugins', $required_plugins );

		// Risposta di successo.
		wp_send_json_success( 'Plugin List updated!' );
	}

	/**
	 * Send response back to javascript ajax caller.
	 *
	 * @param    array $response The result of the API query.
	 *
	 * @since    1.0.0
	 */
	public function plgnr_return_response( $response ) {
		echo wp_json_encode( $response );
		wp_die();
	}

	/**
	 * Get required plugin from wp repo
	 *
	 * @since    1.1.0
	 */
	public function plgnr_get_required_plugin() {
		$plugin_name = filter_input( INPUT_POST, 'plugin_name', FILTER_UNSAFE_RAW );

		$args = array(
			'search'   => $plugin_name, // Cerca il nome del plugin.
			'per_page' => 1,            // Limita i risultati a un solo plugin.
			'fields'   => array(
				'slug'  => true,
				'icons' => true,
			), // Ottieni slug e icone.
		);

		$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.
		}
		$plugin_data = array(
			'plugin_name' => $response->plugins[0]['name'],
			'plugin_slug' => $response->plugins[0]['slug'],
			'icons'       => $response->plugins[0]['icons'],
			'imgurl'      => plugin_dir_path( __FILE__ ) . 'img/image-not-found.png',
		);
		// Restituisci lo slug del primo risultato trovato.
		$this->plgnr_return_response( $plugin_data );
	}

	/**
	 * Get plugins from wp repo
	 *
	 * @since    1.0.0
	 */
	public function plgnr_get_plugins_from_repo() {
		// Ensure the request is authorized.
		$nonce_ok = check_ajax_referer( $this->plugin_name . '_admin_nonce', 'security', false );
		if ( false === $nonce_ok ) {
			wp_send_json_error(
				array(
					'result'  => 'failure',
					'message' => 'Invalid nonce',
				)
			);
			wp_die();
		}
		if ( ! current_user_can( 'install_plugins' ) ) {
			wp_send_json_error(
				array(
					'result'  => 'failure',
					'message' => 'Insufficient permissions',
				)
			);
			wp_die();
		}

		$needle = filter_input( INPUT_POST, 'needle', FILTER_UNSAFE_RAW );

		$active_plugins = get_option( 'active_plugins' );

		$this->plugins_page_number = filter_input( INPUT_POST, 'page', FILTER_UNSAFE_RAW );
		if ( 1 === $this->plugins_page_number ) {
			$this->plgnr_reset_page_number();
		}

		if ( $this->plugins_page_number > 1 ) {
			$this->highest_page_number = $this->plugins_page_number;
		}

		$plugins_collection = plugins_api(
			'query_plugins',
			array(
				'search'   => $needle,
				'per_page' => 36,
				'page'     => $this->plugins_page_number,
				'fields'   => array(
					'icons' => true,
				),
			)
		);

		// If plugins_api returned an error, return a JSON error (helps debugging on local environments).
		if ( is_wp_error( $plugins_collection ) ) {
			wp_send_json_error( array( 'message' => $plugins_collection->get_error_message() ) );
			wp_die();
		}

		// Guard: if no plugins property or empty result, return an informative response.
		if ( empty( $plugins_collection ) || empty( $plugins_collection->plugins ) ) {
			wp_send_json_error( array( 'message' => 'No results from WordPress.org API or connection blocked.' ) );
			wp_die();
		}

		if ( count( $plugins_collection->plugins ) > 1 ) {
			$this->options['plugins_page'] = ++$this->plugins_page_number;
			$this->highest_page_number     = $this->options['plugins_page'];
		} else {
			$this->options['plugins_page'] = 1;
		}

		// increment the page, or when no results, reset to 1.
		update_option( 'plgnr_options', $this->options );

		$plugins_matches = array();
		foreach ( $plugins_collection->plugins as $single_plugin ) {

			$installed = 0;
			if ( $this->plgnr_is_installed( $single_plugin['name'], $active_plugins ) ) {
				$installed = 1;
			}
				$plugins_matches[] = array(
					'plugin_name' => $single_plugin['name'],
					'plugin_slug' => $single_plugin['slug'],
					'icons'       => $single_plugin['icons'],
					'installed'   => $installed,
					'imgurl'      => plugin_dir_path( __FILE__ ) . 'img/image-not-found.png',
				);
		}

		// 🔹 Se abbiamo ricevuto meno di 100 plugin, significa che siamo all'ultima pagina.
		$has_more_pages = count( $plugins_matches ) === 36;
		// 🔹 Otteniamo il numero totale stimato di risultati
		$total_results = $plugins_collection->info['results'] ?? null;
		$total_pages   = $total_results ? ceil( $total_results / 36 ) : null;

		// 🔹 Restituisci anche il numero totale di plugin trovati
		$response = array(
			'plugins'       => $plugins_matches,
			'current_page'  => $this->plugins_page_number,
			'has_more'      => $has_more_pages,
			'total_pages'   => $total_pages, // 👈 Aggiunto
			'total_results' => $total_results, // 👈 Aggiunto
		);

		$this->plgnr_return_response( $response );
		exit;
	}

	/**
	 * Check plugin list count
	 *
	 * @since    1.0.0
	 */
	public function plgnr_check_plugin_list_count() {
		check_ajax_referer( $this->plugin_name . '_admin_nonce', 'security' );

		// Verifica il numero di liste esistenti.
		$args  = array(
			'post_type'      => 'plgnr_plugin_list',
			'posts_per_page' => -1,
		);
		$query = new WP_Query( $args );
		wp_send_json( array( 'found_posts' => $query->found_posts ) );
		exit;
	}

	/**
	 * Remove the "Save Draft" button from the plugin list edit screen.
	 *
	 * @since    1.0.7
	 */
	public function pluginer_remove_save_draft() {
		global $post, $typenow;

		if ( 'plgnr_plugin_list' !== $typenow ) {
			return;
		}

		// Elimina il markup del bottone draft.
		?>
	<script>
	jQuery(function($){
		$('#minor-publishing').remove(); // più pulito che solo .remove().
	});
	</script>
		<?php
	}

	/**
	 * Fix the "Save List" button label to prevent WP from changing it.
	 *
	 * @since    1.0.7
	 */
	public function pluginer_fix_publish_caption() {
			global $typenow;
		if ( 'plgnr_plugin_list' !== $typenow ) {
			return;
		}
		?>
	<script>
	jQuery(document).ready(function($){
		const publishButton = $('#publish');
		
		// mantieni il testo personalizzato
		const customLabel = '<?php echo esc_js( __( 'Save List', 'pluginer' ) ); ?>';
		publishButton.val(customLabel);

		// intercetta cambiamenti forzati da WP
		const observer = new MutationObserver(function(){
			publishButton.val(customLabel);
		});
		observer.observe(publishButton[0], { attributes: true, childList: true, characterData: true });
	});
	</script>
		<?php
	}

	/**
	 * Exclude 'auto-draft' posts from the admin list of 'plgnr_plugin_list' post type.
	 *
	 * @param WP_Query $query The WP_Query instance (passed by reference).
	 * @since    1.0.7
	 */
	public function pluginer_exclude_auto_drafts( $query ) {
		// Solo admin e solo query principale.
		if ( is_admin() && $query->is_main_query() ) {
			$screen = get_current_screen();
			if ( isset( $screen->post_type ) && 'plgnr_plugin_list' === $screen->post_type ) {
				// Escludi auto-draft aggiungendo un array di post_status.
				$query->set( 'post_status', array( 'publish', 'pending', 'draft', 'future', 'private' ) );
			}
		}
	}
}
