<?php

namespace DownloadPluginZip;

use WP_PowerSuite\Core\AbstractModule;
use WP_PowerSuite\Core\Contracts\DataLocationsInterface;
use WP_PowerSuite\Core\Export\PluginThemeZipExporter;
use WP_PowerSuite\Core\NetworkScope;

class Module extends AbstractModule implements DataLocationsInterface {

	private const MODULE_ID      = 'download-plugin-zip';
	private const MODULE_VERSION = '1.0.0';

	public function getId(): string {
		return self::MODULE_ID;
	}

	public function getName(): string {
		return __( 'Download Plugin as ZIP', 'wp-powersuite' );
	}

	public function getVersion(): string {
		return self::MODULE_VERSION;
	}

	public function getDescription(): string {
		return __( 'Download ZIP link on each plugin for backup or migration without FTP.', 'wp-powersuite' ); // phpcs:ignore Generic.Files.LineLength.TooLong
	}

	public function getContext(): string|array {
		return [ 'admin' ];
	}

	public function getDependencies(): array {
		return [];
	}

	protected function registerHooks(): void {
		add_action( 'admin_post_wpps_download_plugin_zip', [ $this, 'handleDownload' ] );

		if ( ! is_admin() ) {
			return;
		}

		add_filter( 'plugin_action_links', [ $this, 'addDownloadLink' ], 10, 2 );
		add_filter( 'network_admin_plugin_action_links', [ $this, 'addDownloadLink' ], 10, 2 );
	}

	public function addDownloadLink( array $actions, string $plugin_file ): array {
		$screen = get_current_screen();
		if ( ! $screen || $screen->id !== 'plugins' ) {
			return $actions;
		}

		if ( ! current_user_can( 'install_plugins' ) ) {
			return $actions;
		}

		$download_url = wp_nonce_url(
			NetworkScope::adminUrl(
				'admin-post.php',
				[
					'action' => 'wpps_download_plugin_zip',
					'plugin' => $plugin_file,
				]
			),
			'wpps_download_plugin_' . $plugin_file,
			'nonce'
		);

		$actions['wpps_download_zip'] = sprintf(
			'<a href="%s" title="%s">%s</a>',
			esc_url( $download_url ),
			esc_attr__( 'Download this plugin as a ZIP file', 'wp-powersuite' ),
			esc_html__( 'Download ZIP', 'wp-powersuite' )
		);

		return $actions;
	}

	public function handleDownload(): void {
		if ( ! $this->isEnabled() ) {
			wp_die(
				esc_html__( 'Module is not enabled.', 'wp-powersuite' ),
				esc_html__( 'Error', 'wp-powersuite' ),
				[ 'response' => 403 ]
			);
		}

		$plugin_file = isset( $_GET['plugin'] ) ? sanitize_text_field( wp_unslash( $_GET['plugin'] ) ) : '';
		if ( $plugin_file === '' ) {
			wp_die(
				esc_html__( 'Invalid plugin specified.', 'wp-powersuite' ),
				esc_html__( 'Error', 'wp-powersuite' ),
				[ 'response' => 400 ]
			);
		}

		$nonce = isset( $_GET['nonce'] ) ? sanitize_text_field( wp_unslash( $_GET['nonce'] ) ) : '';
		if ( ! wp_verify_nonce( $nonce, 'wpps_download_plugin_' . $plugin_file ) ) {
			wp_die(
				esc_html__( 'Security check failed.', 'wp-powersuite' ),
				esc_html__( 'Error', 'wp-powersuite' ),
				[ 'response' => 403 ]
			);
		}

		if ( ! current_user_can( 'install_plugins' ) ) {
			wp_die(
				esc_html__( 'You do not have permission to download plugins.', 'wp-powersuite' ),
				esc_html__( 'Permission Denied', 'wp-powersuite' ),
				[ 'response' => 403 ]
			);
		}

		$rate_error = PluginThemeZipExporter::checkRateLimit( 'plugin' );
		if ( $rate_error instanceof \WP_Error ) {
			wp_die(
				esc_html( $rate_error->get_error_message() ),
				esc_html__( 'Error', 'wp-powersuite' ),
				[ 'response' => 429 ]
			);
		}

		$resolved = PluginThemeZipExporter::resolvePluginSource( $plugin_file );
		if ( is_wp_error( $resolved ) ) {
			$status = $resolved->get_error_code() === 'not_found' ? 404 : 403;
			wp_die(
				esc_html( $resolved->get_error_message() ),
				esc_html__( 'Error', 'wp-powersuite' ),
				[ 'response' => $status ]
			);
		}

		$result = PluginThemeZipExporter::createZip(
			$resolved['source'],
			$resolved['slug_for_zip'],
			$resolved['is_single']
		);

		if ( is_wp_error( $result ) ) {
			wp_die(
				'<strong>' . esc_html__( 'Failed to create ZIP file', 'wp-powersuite' ) . '</strong><br><br>' . esc_html( $result->get_error_message() ),
				esc_html__( 'Error', 'wp-powersuite' ),
				[ 'response' => 500 ]
			);
		}

		PluginThemeZipExporter::streamZip( $result, $resolved['filename_base'] );
	}

	/**
	 * {@inheritdoc}
	 */
	public function getDataLocations(): array {
		return [
			'option_store_keys' => [],
		];
	}
}
