<?php
/**
 * Custom App main class file.
 *
 * @since 1.0.2
 * @package sureforms-pro
 */

namespace SRFM_Pro\Inc\Business\Custom_App;

use SRFM\Inc\Helper;
use SRFM_Pro\Inc\Helper as Pro_Helper;
use SRFM_Pro\Inc\Traits\Get_Instance;
use WP_Post;

// Exit if accessed directly.
defined( 'ABSPATH' ) || exit;

/**
 * Load custom app feature related functionalities.
 *
 * @since 1.0.2
 */
class Load {
	use Get_Instance;

	/**
	 * Initialize custom app.
	 *
	 * @since 1.0.2
	 */
	public function __construct() {
		add_action( 'wp', [ $this, 'initialize_custom_app_cookie' ] );
		$this->download_attachment(); // Download attachment file.
		add_action( 'rest_api_init', [ $this, 'init_rest_response_url' ] );
		add_action( 'enqueue_block_editor_assets', [ $this, 'enqueue_block_editor_scripts' ] );
		add_action( 'srfm_localize_conditional_logic_data', [ $this, 'enqueue_custom_app_scripts' ] );

		add_filter( 'srfm_suretriggers_integration_data_filter', [ $this, 'add_response_url_on_sample' ], 10, 2 );
		add_filter( 'srfm_form_submit_response', [ $this, 'add_response_url_on_form_submit' ] );

		add_filter( 'register_meta_args', [ $this, 'extend_srfm_form_confirmation_args' ], 10, 4 );
		add_filter( 'srfm_form_confirmation_params', [ $this, 'srfm_form_confirmation_params' ], 10, 2 );

		add_filter( 'srfm_frontend_validation_messages', [ $this, 'add_translatable_strings' ] );
	}

	/**
	 * Initialize custom app cookie if the current post is a form or has a form block.
	 *
	 * @return void
	 * @since 1.9.0
	 */
	public function initialize_custom_app_cookie() {
		if ( is_admin() ) {
			return;
		}

		global $post;

		if ( ! ( $post instanceof WP_Post ) ) {
			return;
		}

		$form_id = 0;

		if ( 'sureforms_form' === $post->post_type ) {
			// Case 1: For instant form.
			$form_id = $post->ID;

			if ( Utils::is_custom_app_enabled( $form_id ) ) {
				Utils::get_user_session_id();
			}
		} else {
			// Case 2: For embedded form.
			$blocks = parse_blocks( $post->post_content );

			foreach ( $blocks as $block ) {
				if ( isset( $block['blockName'] ) && 'srfm/form' === $block['blockName'] ) {
					$form_id = isset( $block['attrs']['id'] ) ? (int) $block['attrs']['id'] : 0;

					if ( Utils::is_custom_app_enabled( $form_id ) ) {
						Utils::get_user_session_id();
						break;
					}
				}
			}
		}
	}

	/**
	 * Add the custom app related translatable strings for the frontend.
	 *
	 * @param array<string,string> $translatable_array Default translatable strings array.
	 * @since 1.1.0
	 * @return array<string,string> Extended translatable strings array.
	 */
	public function add_translatable_strings( $translatable_array ) {
		return array_merge(
			$translatable_array,
			[
				'custom_app_audio_files_ready' => __( 'Your audio files are ready!', 'sureforms-pro' ),
				'custom_app_img_files_ready'   => __( 'Your image files are ready!', 'sureforms-pro' ),
				'custom_app_files_ready'       => __( 'Your files are ready!', 'sureforms-pro' ),
				'custom_app_back_btn'          => __( 'Back', 'sureforms-pro' ),
				'custom_app_download_all_btn'  => __( 'Download All', 'sureforms-pro' ),
				'custom_app_copy_text_btn'     => __( 'Copy Text', 'sureforms-pro' ),
				'custom_app_text_copied_btn'   => __( 'Copied', 'sureforms-pro' ),
				'custom_app_error_msg'         => __( 'Something went wrong. We could not get the result at the moment. Please reload the page and try again later.', 'sureforms-pro' ),
			]
		);
	}

	/**
	 * Load and Localize the custom app form confirmation data for JS use.
	 *
	 * @param int $form_id Current form ID.
	 * @since 1.1.0
	 * @return void
	 */
	public function enqueue_custom_app_scripts( $form_id ) {
		if ( ! $form_id ) {
			return;
		}

		if ( ! Utils::is_custom_app_enabled( $form_id ) ) {
			return;
		}

		$file_prefix = defined( 'SRFM_DEBUG' ) && SRFM_DEBUG ? '' : '.min';
		$dir_name    = defined( 'SRFM_DEBUG' ) && SRFM_DEBUG ? 'unminified' : 'minified';
		$css_uri     = SRFM_PRO_URL . 'assets/css/' . $dir_name . '//package/business/';

		// Load the frontend custom app styles.
		wp_enqueue_style( SRFM_PRO_SLUG . '-custom-app', $css_uri . 'custom-app' . $file_prefix . '.css', [], SRFM_PRO_VER );

		// Load markdown library.
		wp_enqueue_script(
			SRFM_PRO_SLUG . '-markdown-it',
			SRFM_PRO_URL . 'assets/js/minified/deps/markdown-it.min.js',
			[],
			'14.1.0',
			true
		);

		// Load the frontend custom app script.
		wp_enqueue_script(
			SRFM_PRO_SLUG . '-custom-app-frontend', // Handle.
			SRFM_PRO_URL . 'dist/package/business/srfmCustomAppFrontend.js',
			[ 'wp-api-fetch', 'wp-i18n' ],
			SRFM_PRO_VER,
			true // Enqueue the script in the footer.
		);

		$form_confirmation = Helper::get_array_value( get_post_meta( $form_id, '_srfm_form_confirmation', true ) );

		$confirmation_data = isset( $form_confirmation[0] ) ? Helper::get_array_value( $form_confirmation[0] ) : [];

		if ( ! isset( $confirmation_data['response_loading_text'] ) ) {
			// Sometimes default will not work due to priority order, this will help prevent that scenario.
			$confirmation_data['response_loading_text'] = esc_html__( 'We are generating your response', 'sureforms-pro' );
		}

		if ( ! isset( $confirmation_data['response_wait_time'] ) ) {
			// Sometimes default will not work due to priority order, this will help prevent that scenario.
			$confirmation_data['response_wait_time'] = 30;
		}

		wp_localize_script(
			SRFM_PRO_SLUG . '-custom-app-frontend',
			'srfm_pro_custom_app_' . $form_id,
			[
				'nonce'             => wp_create_nonce( Utils::get_user_session_id() ),
				'endpoint'          => sprintf( 'sureforms-pro/v1/%1$s?session_id=%2$s', Utils::REST_ROUTE, Utils::get_user_session_id() ),
				'session_id'        => Utils::get_user_session_id(),
				'form_confirmation' => $confirmation_data,
			]
		);
	}

	/**
	 * Extends the SRFM form confirmation arguments.
	 *
	 * @param array<string, mixed> $args The extended arguments.
	 * @param array<string, mixed> $defaults The default arguments.
	 * @param string               $object_type The type of object.
	 * @param string               $meta_key The meta key.
	 *
	 * @since 1.1.0
	 * @return array<string, mixed> The extended arguments.
	 */
	public function extend_srfm_form_confirmation_args( $args, $defaults, $object_type, $meta_key ) {
		if ( 'sureforms_form' !== $object_type && '_srfm_form_confirmation' !== $meta_key ) {
			return $args;
		}

		if ( empty( $defaults ) ) {
			return $args;
		}

		$args = array_merge_recursive(
			$args,
			[
				'show_in_rest' => [
					'schema' => [
						'context' => [ 'edit' ],
						'items'   => [
							'properties' => [
								'response_loading_text' => [
									'type' => 'string',
								],
								'response_wait_time'    => [
									'type' => 'number',
								],
								'hide_copy'             => [
									'type' => 'boolean',
								],
								'hide_download_all'     => [
									'type' => 'boolean',
								],
							],
						],
					],
				],
			]
		);

		$args['default'][0]['response_loading_text'] = esc_html__( 'We are generating your response', 'sureforms-pro' );
		$args['default'][0]['response_wait_time']    = 30;
		$args['default'][0]['hide_copy']             = false;
		$args['default'][0]['hide_download_all']     = false;

		return $args;
	}

	/**
	 * Extends the SRFM form confirmation arguments for sanitization.
	 *
	 * @param array<string, mixed> $sanitized The sanitized arguments.
	 * @param array<string, mixed> $item The item data.
	 *
	 * @since 1.7.2
	 * @return array<string, mixed> The sanitized values.
	 */
	public function srfm_form_confirmation_params( $sanitized, $item ) {
		if ( empty( $item ) ) {
			return $sanitized;
		}

		$sanitized_new = [
			'response_loading_text' => isset( $item['response_loading_text'] ) ? sanitize_text_field( Helper::get_string_value( $item['response_loading_text'] ) ) : esc_html( __( 'We are generating your response', 'sureforms-pro' ) ),
			'response_wait_time'    => isset( $item['response_wait_time'] ) ? intval( Helper::get_integer_value( $item['response_wait_time'] ) ) : 30,
			'hide_copy'             => isset( $item['hide_copy'] ) ? filter_var( $item['hide_copy'], FILTER_VALIDATE_BOOLEAN ) : false,
			'hide_download_all'     => isset( $item['hide_download_all'] ) ? filter_var( $item['hide_download_all'], FILTER_VALIDATE_BOOLEAN ) : false,
		];

		return array_merge( $sanitized, $sanitized_new );
	}

	/**
	 * Downloads the file attachment(s) to the user.
	 *
	 * @since 1.0.2
	 * @return void
	 */
	public function download_attachment() {
		if ( ! isset( $_GET['srfm-custom-app-download'] ) || ! isset( $_GET['nonce'] ) ) {
			return;
		}

		$form_id      = isset( $_GET['form_id'] ) ? absint( wp_unslash( $_GET['form_id'] ) ) : 0;
		$index        = isset( $_GET['attachment-index'] ) ? absint( wp_unslash( $_GET['attachment-index'] ) ) : false;
		$download_all = isset( $_GET['download-all'] ) && 'true' === sanitize_text_field( wp_unslash( $_GET['download-all'] ) );

		if ( ! $form_id || ( ! $download_all && false === $index ) ) {
			return;
		}

		if ( ! Utils::is_custom_app_enabled( $form_id ) ) {
			return;
		}

		$base_url   = remove_query_arg( [ 'attachment-index', 'download-all', 'nonce' ] ); // Downloads base url which can be used for other redirects.
		$session_id = Utils::get_user_session_id();

		if ( ! wp_verify_nonce( sanitize_text_field( wp_unslash( $_GET['nonce'] ) ), $session_id ) ) {
			wp_safe_redirect( add_query_arg( 'error', __( 'Nonce verification failed.', 'sureforms-pro' ), $base_url ) );
			exit;
		}

		$result = Helper::get_array_value( Utils::get_result_transient( Helper::get_string_value( $session_id ), $form_id ) );

		if ( empty( $result['attachments'] ) || ! is_array( $result['attachments'] ) ) {
			wp_safe_redirect( add_query_arg( 'error', __( 'No attachment files found.', 'sureforms-pro' ), $base_url ) );
			exit;
		}

		// Check if download-all is true.
		if ( $download_all ) {
			if ( ! class_exists( 'ZipArchive' ) ) {
				wp_safe_redirect( add_query_arg( 'error', __( 'Your server does not support ZipArchive library.', 'sureforms-pro' ), $base_url ) );
				exit;
			}

			// Create a temporary file for the ZIP archive.
			$temp_zip = tempnam( sys_get_temp_dir(), 'attachments' ) . '.zip';
			$zip      = new \ZipArchive();

			if ( $zip->open( $temp_zip, \ZipArchive::CREATE ) !== true ) {
				wp_safe_redirect( add_query_arg( 'error', __( 'Failed to create ZIP file.', 'sureforms-pro' ), $base_url ) );
				exit;
			}

			$success = 0;

			foreach ( $result['attachments'] as $key => $attachment ) {
				$attachment_url = esc_url_raw( Helper::get_string_value( $attachment['link'] ) );
				$attachment_res = wp_remote_head( $attachment_url );

				if ( 200 !== wp_remote_retrieve_response_code( $attachment_res ) ) {
					// We will display errors at once after this foreach by calculating $success.
					continue;
				}

				$content_type = Helper::get_string_value( wp_remote_retrieve_header( $attachment_res, 'content-type' ) );
				$filename     = $this->get_attachment_filename( $attachment_url, $content_type, "-{$form_id}-{$key}-{$session_id}" );

				// Download the file content.
				$file_contents = file_get_contents( $attachment_url ); // phpcs:ignore -- We are not using WP_Filesystem here as we need file_get_contents functionality.

				if ( false === $file_contents ) {
					// Something went wrong. We will display errors at once after this foreach by calculating $success.
					continue;
				}

				// Add file to the zip.
				if ( $zip->addFromString( $filename, $file_contents ) ) {
					$success++;
				}
			}

			$zip->close();

			if ( $success > 0 ) {
				// Set headers to download the zip.
				header( 'Content-Type: application/zip' );
				header( "Content-disposition: attachment; filename=\"attachments-{$form_id}-{$session_id}.zip\"" );
				header( 'Content-Length: ' . filesize( $temp_zip ) );

				// Output the zip file.
				readfile( $temp_zip );  // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_read_readfile -- We are not using WP_Filesystem here as we need readfile functionality.
				unlink( $temp_zip ); // Clean up the temporary zip file.
				exit;
			}

			// Redirect with error message.
			wp_safe_redirect(
				add_query_arg(
					'error',
					sprintf(
						'%1$s %2$s',
						__( 'Failed to zip all the files.', 'sureforms-pro' ),
						sprintf(
							/* Translators: %s is the number of corrupt files. */
							_nx(
								'%s file is either corrupt or does not exists.',
								'%s files are either corrupt or does not exists.',
								count( $result['attachments'] ) - $success,
								'Number of corrupt files',
								'sureforms-pro'
							)
						)
					),
					$base_url
				)
			);
			exit;
		}

		// Single file download as before.
		if ( ! isset( $result['attachments'][ $index ] ) ) {
			wp_safe_redirect( add_query_arg( 'error', __( 'Attachment file not found', 'sureforms-pro' ), $base_url ) );
			exit;
		}

		$attachment     = $result['attachments'][ $index ];
		$attachment_url = esc_url_raw( Helper::get_string_value( $attachment['link'] ) );
		$attachment_res = wp_remote_head( $attachment_url );

		if ( 200 !== wp_remote_retrieve_response_code( $attachment_res ) ) {
			wp_safe_redirect( add_query_arg( 'error', __( 'Selected file is not downloadable or does not exists.', 'sureforms-pro' ), $base_url ) );
			exit;
		}

		$content_type = Helper::get_string_value( wp_remote_retrieve_header( $attachment_res, 'content-type' ) );
		$filename     = $this->get_attachment_filename( $attachment_url, $content_type, "-{$form_id}-{$index}-{$session_id}" );

		// Set headers to force download.
		header( "Content-Type: {$content_type}" );
		header( "Content-disposition: attachment; filename=\"{$filename}\"" );

		// Read and output the file content.
		readfile( $attachment_url ); // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_read_readfile -- We are not using WP_Filesystem here as we need readfile functionality.
		exit;
	}

	/**
	 * Init rest api for the custom app.
	 *
	 * @since 1.0.2
	 * @return void
	 */
	public function init_rest_response_url() {
		register_rest_route(
			'sureforms-pro/v1',
			Utils::REST_ROUTE,
			[
				'methods'             => \WP_REST_Server::READABLE,
				'callback'            => [ $this, 'get_custom_app_data' ],
				'permission_callback' => '__return_true',
			]
		);

		register_rest_route(
			'sureforms-pro/v1',
			Utils::REST_ROUTE,
			[
				'methods'             => \WP_REST_Server::CREATABLE,
				'callback'            => [ $this, 'save_custom_app_data' ],
				'permission_callback' => '__return_true',
			]
		);
	}

	/**
	 * Send the custom app saved data to internal requests.
	 *
	 * @param \WP_REST_Request $request Full details about the request.
	 * @since 1.0.2
	 * @return mixed
	 */
	public function get_custom_app_data( $request ) {
		$nonce = sanitize_text_field( Helper::get_string_value( $request->get_header( 'X-WP-Nonce' ) ) );
		if ( ! wp_verify_nonce( $nonce, 'wp_rest' ) ) {
			return false;
		}
		return Utils::get_result_transient(
			sanitize_text_field( wp_unslash( Helper::get_string_value( $request->get_param( 'session_id' ) ) ) ),
			absint( wp_unslash( $request->get_param( 'form_id' ) ) )
		);
	}

	/**
	 * Response URL callback function to save the data sent from OttoKit Platform.
	 *
	 * @param \WP_REST_Request $request Full details about the request.
	 * @since 1.0.2
	 * @return \WP_Error|array Returns WP_Error object on failure or array data on success.
	 */
	public function save_custom_app_data( $request ) {
		$token = Helper::get_string_value( $request->get_param( 'token' ) );

		if ( empty( $token ) ) {
			return new \WP_Error( 'SRFM_EMPTY_TOKEN', __( 'Token cannot be empty. You must provide a valid token.', 'sureforms-pro' ) );
		}

		$user_agent = Helper::get_string_value( $request->get_header( 'user_agent' ) );

		if ( 'suretriggers' !== strtolower( $user_agent ) && 'ottokit' !== strtolower( $user_agent ) ) {
			return new \WP_Error( 'SRFM_INVALID_USER_AGENT', __( 'Request must be made only from the OttoKit platform.', 'sureforms-pro' ) );
		}

		/**
		 * Parsed data from token.
		 *
		 * @var array<string,string> $parsed Parsed data from token.
		 */
		$parsed = json_decode( Helper::get_string_value( base64_decode( $token ) ), true ); // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions.obfuscation_base64_decode

		if ( empty( $parsed['nonce'] ) || empty( $parsed['session_id'] ) || empty( $parsed['form_id'] ) ) {
			return new \WP_Error( 'SRFM_INVALID_TOKEN', __( 'Provided token seems invalid. You must provide a valid token.', 'sureforms-pro' ) );
		}

		$form_id    = absint( wp_unslash( $parsed['form_id'] ) );
		$session_id = sanitize_text_field( wp_unslash( $parsed['session_id'] ) );

		if ( ! Utils::verify_nonce( $parsed['nonce'], $session_id ) ) {
			return new \WP_Error( 'SRFM_NONCE_VERIFICATION_FAILED', __( 'Nonce verification failed.', 'sureforms-pro' ) );
		}

		$st_body        = Helper::get_string_value( $request->get_param( 'body' ) ); // This "$st_body" will have the data provided by the user ( + OttoKit ) using the editor or text formatter.
		$st_body_raw    = sanitize_text_field( trim( strip_tags( $st_body ) ) ); // phpcs:ignore -- We need strip_tags here. This "$st_body_raw" will have the raw data provided by the user ( + OttoKit ) without any formatting.
		$st_attachments = Helper::get_array_value( $request->get_param( 'attachment' ) );  // Array of attachment URLs.

		if ( empty( $st_body_raw ) && empty( $st_attachments ) ) {
			return new \WP_Error( 'SRFM_EMPTY_RESPONSE_SENT', __( 'Response data body cannot be empty.', 'sureforms-pro' ) );
		}

		$filetypes   = [];
		$attachments = [];

		// Process the attachment if we have attachment URL.
		if ( ! empty( $st_attachments ) && is_array( $st_attachments ) ) {
			foreach ( $st_attachments as $st_attachment ) {
				if ( empty( $st_attachment['sf_response_file'] ) ) {
					continue;
				}

				$attachment_url = esc_url_raw( Helper::get_string_value( $st_attachment['sf_response_file'] ) );
				$attachment_res = wp_remote_head( $attachment_url );
				$response_code  = absint( wp_remote_retrieve_response_code( $attachment_res ) );

				if ( ! is_wp_error( $attachment_res ) && 200 === $response_code ) {
					$content_type   = Helper::get_string_value( wp_remote_retrieve_header( $attachment_res, 'content-type' ) );
					$content_length = Helper::get_integer_value( wp_remote_retrieve_header( $attachment_res, 'content-length' ) );
					$filetype       = $this->get_file_type( $content_type );

					$attachments[] = [
						'status'       => wp_remote_retrieve_response_code( $attachment_res ),
						'filetype'     => $filetype,
						'content-type' => $content_type,
						'size'         => [
							'bytes'     => $content_length,
							'formatted' => $content_length ? size_format( $content_length ) : __( 'Unknown File Size', 'sureforms-pro' ),
						],
						'filename'     => $this->get_attachment_filename( $attachment_url, $content_type ),
						'link'         => $attachment_url,
					];

					$filetypes[ $filetype ] = true;
				}
			}
		}

		$attachments_type = 'none';

		if ( count( $filetypes ) > 1 ) {
			$attachments_type = 'multi';
		} elseif ( count( $filetypes ) === 1 ) {
			$attachments_type = array_keys( $filetypes )[0];
		}

		$data = [
			'body'             => wp_kses_post( $st_body ), // If any markdown is present, it will be parsed by markdown-it JS library.
			'body_raw'         => $st_body_raw,
			'attachments'      => $attachments,
			'attachments_type' => $attachments_type,
		];

		// Temporary saved data for the user.
		Utils::set_result_transient( $session_id, $form_id, $data );

		// Return the formatted data back to the OttoKit platform.
		return $data;
	}

	/**
	 * Hook response URL on the sample data.
	 *
	 * @param array<string,array<string,mixed>> $body Sample data args.
	 * @param int                               $form_id Form id.
	 * @since 1.0.2
	 * @return array Modified sample data args.
	 */
	public function add_response_url_on_sample( $body, $form_id ) {
		if ( ! isset( $body['sample_response'] ) ) {
			// Bail early if proper structure is not provided.
			return $body;
		}

		$form_id = absint( $form_id );

		$session_id = Utils::get_user_session_id();

		Utils::delete_result_transient( $session_id, $form_id );

		$response_url = Utils::get_response_url( $session_id, $form_id );

		if ( ! $response_url ) {
			// Bail if we don't have response url created.
			return $body;
		}

		$body['sample_response']['response_url'] = Utils::get_response_url( $session_id, $form_id );

		return $body;
	}

	/**
	 * Hook response url on form submit.
	 *
	 * @param array<string,array<string,mixed>> $args Form submitted data args.
	 * @since 1.0.2
	 * @return array Modified form submitted data args.
	 */
	public function add_response_url_on_form_submit( $args ) {
		if ( empty( $args['form_id'] ) ) {
			return $args;
		}

		$form_id = absint( $args['form_id'] );

		if ( ! Utils::is_custom_app_enabled( $form_id ) ) {
			return $args;
		}

		$session_id = Utils::get_user_session_id();

		Utils::delete_result_transient( $session_id, $form_id );

		$args['response_url'] = Utils::get_response_url( $session_id, $form_id );

		return $args;
	}

	/**
	 * Enqueue Admin Scripts.
	 *
	 * @return void
	 * @since 1.0.2
	 */
	public function enqueue_block_editor_scripts() {

		$scripts = [
			[
				'unique_file'        => 'srfmCustomApp',
				'unique_handle'      => 'custom-app',
				'extra_dependencies' => [],
			],
		];

		foreach ( $scripts as $script ) {

			$script_dep_path = SRFM_PRO_DIR . 'dist/package/business/' . $script['unique_file'] . '.asset.php';
			$script_dep_data = file_exists( $script_dep_path )
				? include $script_dep_path
				: [
					'dependencies' => [],
					'version'      => SRFM_PRO_VER,
				];
			$script_dep      = array_merge( $script_dep_data['dependencies'], $script['extra_dependencies'] );

			// Scripts.
			wp_enqueue_script(
				SRFM_PRO_SLUG . '-' . $script['unique_handle'], // Handle.
				SRFM_PRO_URL . 'dist/package/business/' . $script['unique_file'] . '.js',
				$script_dep, // Dependencies, defined above.
				$script_dep_data['version'], // SRFM_VER.
				true // Enqueue the script in the footer.
			);

			// Register script translations.
			Pro_Helper::register_script_translations( SRFM_PRO_SLUG . '-' . $script['unique_handle'] );
		}
	}

	/**
	 * Returns files content type prefix.
	 *
	 * @param string $content_type Response header file content type.
	 * @since 1.1.0
	 * @return string Returns file type prefix.
	 */
	protected function get_file_type( $content_type ) {
		if ( ! $content_type ) {
			return '';
		}

		return Helper::get_string_value( strstr( $content_type, '/', true ) );
	}

	/**
	 * Returns the attachment filename according to the provided content type.
	 *
	 * @param string $attachment_url Response attachment file URL.
	 * @param string $content_type Response header file content type.
	 * @param string $suffix Optional. Any suffix you may want to add to the filename.
	 * @since 1.0.2
	 * @return string Returns filename.
	 */
	protected function get_attachment_filename( $attachment_url, $content_type, $suffix = '' ) {
		$pathinfo  = pathinfo( Helper::get_string_value( wp_parse_url( $attachment_url, PHP_URL_PATH ) ) );
		$filename  = ! empty( $pathinfo['filename'] ) ? $pathinfo['filename'] : '';
		$extension = ! empty( $pathinfo['extension'] ) ? $pathinfo['extension'] : '';

		if ( ! $extension ) {
			$extension = ltrim( Helper::get_string_value( strrchr( $content_type, '/' ) ), '/' );
		}

		$prefix = $this->get_file_type( $content_type );

		if ( 'application' === $prefix ) {
			$prefix = 'file';
		}

		return $prefix . '-' . sanitize_title( $filename ) . $suffix . '.' . $extension;
	}
}
