<?php

namespace HulkPlugins\ElementorPro\Forms\AdvancedFields\Traits;

use HulkPlugins\ElementorPro\Forms\AdvancedFields\Utils\Filesystem;

if ( ! defined( 'ABSPATH' ) ) {
	exit; // Exit if accessed directly.
}

trait DropzoneTrait {

	private static array $upload_errors = [];
	protected string $file_types = 'jpg,jpeg,png,gif,pdf,doc,docx,ppt,pptx,odt,avi,ogg,m4a,mov,mp3,mp4,mpg,wav,wmv';

	protected static function get_Upload_Errors(): array {
		if ( ! self::$upload_errors ) {
			self::$upload_errors = [
				UPLOAD_ERR_OK         => esc_html__( 'There is no error, the file uploaded with success.', 'advanced-fields-for-elementor-forms' ),
				/* translators: 1: upload_max_filesize, 2: php.ini */
				UPLOAD_ERR_INI_SIZE   => sprintf( esc_html__( 'The uploaded file exceeds the %1$s directive in %2$s.', 'advanced-fields-for-elementor-forms' ), 'upload_max_filesize', 'php.ini' ),
				/* translators: %s: MAX_FILE_SIZE */
				UPLOAD_ERR_FORM_SIZE  => sprintf( esc_html__( 'The uploaded file exceeds the %s directive that was specified in the HTML form.', 'advanced-fields-for-elementor-forms' ), 'MAX_FILE_SIZE' ),
				UPLOAD_ERR_PARTIAL    => esc_html__( 'The uploaded file was only partially uploaded.', 'advanced-fields-for-elementor-forms' ),
				UPLOAD_ERR_NO_FILE    => esc_html__( 'No file was uploaded.', 'advanced-fields-for-elementor-forms' ),
				UPLOAD_ERR_NO_TMP_DIR => esc_html__( 'Missing a temporary folder.', 'advanced-fields-for-elementor-forms' ),
				UPLOAD_ERR_CANT_WRITE => esc_html__( 'Failed to write file to disk.', 'advanced-fields-for-elementor-forms' ),
				/* translators: %s: phpinfo() */
				UPLOAD_ERR_EXTENSION  => sprintf( esc_html__( 'A PHP extension stopped the file upload. PHP does not provide a way to ascertain which extension caused the file upload to stop; examining the list of loaded extensions with %s may help.', 'advanced-fields-for-elementor-forms' ), 'phpinfo()' ),
			];
		}
		return self::$upload_errors;
	}

	/**
	 * creates array of upload sizes based on server limits
	 * to use in the file_sizes control
	 * @return array
	 */
	protected function get_upload_file_size_options(): array {
		$max_file_size = wp_max_upload_size() / ( 1024 ** 2 ); //MB

		$sizes = [];

		for ( $file_size = 1; $file_size <= $max_file_size; $file_size++ ) {
			$sizes[ $file_size ] = $file_size . 'MB';
		}

		return $sizes;
	}

	protected function get_mime_type( array $allowed_mime_types, string $name ) {
		foreach ( $allowed_mime_types as $key => $mime_type ) {
			if ( ! empty( $name ) && str_contains( $key, $name ) ) {
				return $mime_type;
			}
		}
		return '';
	}

	/**
	 * Convert a string of file extensions to MIME types allowed in WordPress.
	 *
	 * @param string $extensions Comma-separated list of file extensions (e.g., "jpg, gif, pdf").
	 *
	 * @return array List of corresponding MIME types (e.g., ['image/jpeg', 'image/gif', 'application/pdf']).
	 */
	protected function get_mime_types_from_extensions( string $extensions ): array {
		// Get all allowed MIME types in WordPress
		$allowed_mime_types = get_allowed_mime_types();

		// Convert the input string to an array of trimmed extensions
		$extension_array = array_map( 'trim', explode( ',', $extensions ) );

		// Initialize an array to store the MIME types
		$mime_types = [];

		// Match the input extensions to the allowed MIME types
		foreach ( $extension_array as $ext ) {
			$type = $this->get_mime_type( $allowed_mime_types, $ext );
			if ( ! empty( $type ) ) {
				$mime_types[ $type ] = [];
			}
		}

		return $mime_types;
	}

	/**
	 * Gets the path to uploaded file.
	 *
	 * @return string
	 */
	private function get_upload_dir(): string {
		$wp_upload_dir = wp_upload_dir();

		return $wp_upload_dir['basedir'] . '/elementor/forms';
	}

	/**
	 * Gets the URL to uploaded file.
	 *
	 * @param $file_name
	 *
	 * @return string
	 */
	private function get_file_url( $file_name ): string {
		$wp_upload_dir = wp_upload_dir();

		return $wp_upload_dir['baseurl'] . '/elementor/forms/' . $file_name;
	}

	/**
	 * Gets the Path to uploaded file.
	 *
	 * @param $file_name
	 *
	 * @return string
	 */
	private function get_file_path( $file_name ): string {
		$wp_upload_dir = wp_upload_dir();

		return $wp_upload_dir['basedir'] . '/elementor/forms/' . $file_name;
	}

	/**
	 * This function returns the uploads folder after making sure
	 * it is created and has protection files
	 * @return string
	 */
	private function get_ensure_upload_dir(): string {
		$path = $this->get_upload_dir();
		if ( file_exists( $path . '/index.php' ) ) {
			return $path;
		}

		wp_mkdir_p( $path );

		$files = [
			[
				'file'    => 'index.php',
				'content' => [
					'<?php',
					'// Silence is golden.',
				],
			],
			[
				'file'    => '.htaccess',
				'content' => [
					'Options -Indexes',
					'<ifModule mod_headers.c>',
					'   <Files *.*>',
					'       Header set Content-Disposition attachment',
					'   </Files>',
					'</IfModule>',
				],
			],
		];

		foreach ( $files as $file ) {
			if ( ! file_exists( trailingslashit( $path ) . $file['file'] ) ) {
				$content = implode( PHP_EOL, $file['content'] );
				$wp_filesystem = Filesystem::getInstance();
				$wp_filesystem->put_contents( trailingslashit( $path ) . $file['file'], $content, FS_CHMOD_FILE );
			}
		}

		return $path;
	}

	/**
	 * A blacklist of file extensions.
	 *
	 * @return array
	 */
	private function get_blacklist_file_ext() {
		static $blacklist = false;
		if ( ! $blacklist ) {
			$blacklist = [
				'php',
				'php3',
				'php4',
				'php5',
				'php6',
				'phps',
				'php7',
				'phtml',
				'shtml',
				'pht',
				'swf',
				'html',
				'asp',
				'aspx',
				'cmd',
				'csh',
				'bat',
				'htm',
				'hta',
				'jar',
				'exe',
				'com',
				'js',
				'lnk',
				'htaccess',
				'htpasswd',
				'phtml',
				'ps1',
				'ps2',
				'py',
				'rb',
				'tmp',
				'cgi',
				'svg',
				'php2',
				'phtm',
				'phar',
				'hphp',
				'phpt',
				'svgz',
			];
			$blacklist = apply_filters( 'hulk_affef_elementor_pro_forms_filetypes_blacklist', $blacklist );
		}

		return $blacklist;
	}

	/**
	 * validates uploaded file type against allowed file types
	 *
	 * @param array $field
	 * @param       $file
	 *
	 * @return bool
	 */
	private function is_file_type_valid( array $field, $file ): bool {
		// File type validation
		if ( empty( $field['file_types'] ) ) {
			$field['file_types'] = $this->file_types;
		}

		$allowed_mime_types = $this->get_mime_types_from_extensions( $field['file_types'] );

		if ( empty( $allowed_mime_types ) ) {
			$field['file_types'] = $this->file_types;
		}

		$file_extension = pathinfo( $file, PATHINFO_EXTENSION );
		$file_types_meta = explode( ',', $field['file_types'] );
		$file_types_meta = array_map( 'trim', $file_types_meta );

		$file_types_meta = array_map( 'strtolower', $file_types_meta );
		$file_extension = strtolower( $file_extension );

		return ( in_array( $file_extension, $file_types_meta, true ) && ! in_array( $file_extension, $this->get_blacklist_file_ext(), true ) );
	}

	/**
	 * validate uploaded file size against allowed file size
	 *
	 * @param array $field
	 * @param       $file
	 *
	 * @return bool
	 */
	private function is_file_size_valid( array $field, $file ): bool {
		$allowed_size = ! empty( $field['file_sizes'] ) ? $field['file_sizes'] : ( wp_max_upload_size() / ( 1024 ** 2 ) );
		// File size validation
		$file_size_meta = $allowed_size * ( 1024 ** 2 );
		$upload_file_size = wp_filesize( $file );

		return ( $upload_file_size < $file_size_meta );
	}
}
