<?php
/**
 * FileUploader Component Class.
 *
 * @package Tutor\Components
 * @author Themeum
 * @link https://themeum.com
 * @since 4.0.0
 */

namespace Tutor\Components;

defined( 'ABSPATH' ) || exit;

use Tutor\Components\Constants\Size;
use Tutor\Components\Constants\Variant;
use TUTOR\Icon;
use Tutor\Components\Button;
use Tutor\Components\AttachmentCard;


/**
 * Class FileUploader
 *
 * Example Usage (Native Multiple):
 * FileUploader::make()
 *     ->name( 'course_attachments' )
 *     ->uploader_title( __( 'Upload Assignments', 'tutor' ) )
 *     ->uploader_subtitle( __( 'Support PDF, DOCX (Max 20MB)', 'tutor' ) )
 *     ->accept( '.pdf,.docx' )
 *     ->multiple( true )
 *     ->max_files( 3 )
 *     ->max_size( 20 * 1024 * 1024 )
 *     ->render();
 *
 * Example Usage (Native Single):
 * FileUploader::make()
 *     ->name( 'resume' )
 *     ->accept( '.pdf,.doc' )
 *     ->render();
 *
 * Example Usage (WP Media Image):
 * FileUploader::make()
 *     ->variant( FileUploader::IMAGE_UPLOADER )
 *     ->use_wp_media( true )
 *     ->wp_media_library_type( 'image' )
 *     ->name( 'profile_photo' )
 *     ->render();
 *
 * Example Usage (WP Media Multiple Documents):
 * FileUploader::make()
 *     ->use_wp_media( true )
 *     ->multiple( true )
 *     ->wp_media_library_type( 'application/pdf,application/msword' )
 *     ->name( 'shared_files' )
 *     ->render();
 *
 * Example Usage (Native Image):
 * FileUploader::make()
 *     ->variant( FileUploader::IMAGE_UPLOADER )
 *     ->name( 'cover_photo' )
 *     ->render();
 *
 * Example Usage (Custom UI):
 * FileUploader::make()
 *     ->name( 'custom_upload' )
 *     ->uploader_icon( Icon::RESOURCES )
 *     ->uploader_title( __( 'Resource Center', 'tutor' ) )
 *     ->uploader_subtitle( __( 'Add any relevant documents here', 'tutor' ) )
 *     ->uploader_button_text( __( 'Choose Resources', 'tutor' ) )
 *     ->render();
 *
 * @since 4.0.0
 */
class FileUploader extends BaseComponent {

	/**
	 * Variant constants.
	 *
	 * @since 4.0.0
	 */
	public const FILE_UPLOADER  = 'file-uploader';
	public const IMAGE_UPLOADER = 'image-uploader';


	/**
	 * File uploader accept attribute.
	 *
	 * @since 4.0.0
	 *
	 * @var string
	 */
	protected $accept = '.pdf,.doc,.docx,.jpg,.jpeg,.png';

	/**
	 * File uploader max size.
	 *
	 * @since 4.0.0
	 *
	 * @var int
	 */
	protected $max_size = null;

	/**
	 * File uploader max files.
	 *
	 * @since 4.0.0
	 *
	 * @var int|null
	 */
	protected $max_files = null;

	/**
	 * File uploader icon.
	 *
	 * @since 4.0.0
	 *
	 * @var string
	 */
	protected $uploader_icon = Icon::UPLOAD_FILE;

	/**
	 * File uploader title.
	 *
	 * @since 4.0.0
	 *
	 * @var string
	 */
	protected $uploader_title = '';

	/**
	 * File uploader subtitle.
	 *
	 * @since 4.0.0
	 *
	 * @var string
	 */
	protected $uploader_subtitle = '';

	/**
	 * File uploader button text.
	 *
	 * @since 4.0.0
	 *
	 * @var string
	 */
	protected $uploader_button_text = '';

	/**
	 * Component variant.
	 *
	 * @since 4.0.0
	 *
	 * @var string
	 */
	protected $variant = self::FILE_UPLOADER;

	/**
	 * Whether to use WordPress media library instead of native file input.
	 *
	 * @since 4.0.0
	 *
	 * @var bool
	 */
	protected $use_wp_media = false;

	/**
	 * Title for WordPress media modal.
	 *
	 * @since 4.0.0
	 *
	 * @var string
	 */
	protected $wp_media_title = '';

	/**
	 * Button text for WordPress media modal.
	 *
	 * @since 4.0.0
	 *
	 * @var string
	 */
	protected $wp_media_button_text = '';

	/**
	 * Library type filter for WordPress media (image, video, audio, application).
	 *
	 * @since 4.0.0
	 *
	 * @var string
	 */
	protected $wp_media_library_type = '';

	/**
	 * Whether multiple option can be selected in input.
	 *
	 * @since 4.0.0
	 *
	 * @var boolean
	 */
	protected $multiple = false;

	/**
	 * InputField name attribute.
	 *
	 * @since 4.0.0
	 *
	 * @var string
	 */
	protected $name = '';

	/**
	 * InputField ID attribute.
	 *
	 * @since 4.0.0
	 *
	 * @var string
	 */
	protected $id = '';

	/**
	 * Whether input is required.
	 *
	 * @since 4.0.0
	 *
	 * @var bool
	 */
	protected $required = false;

	/**
	 * InputField value.
	 *
	 * @since 4.0.0
	 *
	 * @var string
	 */
	protected $value = '';

	/**
	 * Upload icon size.
	 *
	 * @since 4.0.0
	 *
	 * @var integer
	 */
	protected $upload_icon_size = 24;

	/**
	 * Set uploader accept attribute.
	 *
	 * Common types: .pdf, .doc, .docx, .jpg, .jpeg, .png
	 * For WP Media: image, video, audio, application
	 *
	 * @since 4.0.0
	 *
	 * @param string $accept Accept attribute.
	 *
	 * @return $this
	 */
	public function accept( $accept ) {
		$this->accept = $accept;

		return $this;
	}

	/**
	 * Set uploader max size.
	 *
	 * @since 4.0.0
	 *
	 * @param int $max_size Max size in bytes.
	 *
	 * @return $this
	 */
	public function max_size( $max_size = null ) {
		if ( null === $max_size ) {
			$max_size = wp_max_upload_size();
		}
		$this->max_size = $max_size;

		return $this;
	}

	/**
	 * Set uploader max files.
	 *
	 * @since 4.0.0
	 *
	 * @param int|null $max_files Maximum number of selectable files.
	 *
	 * @return $this
	 */
	public function max_files( $max_files = null ) {
		$this->max_files = null !== $max_files ? (int) $max_files : null;

		return $this;
	}

	/**
	 * Set uploader icon.
	 *
	 * @since 4.0.0
	 *
	 * @param string $icon Icon name.
	 *
	 * @return $this
	 */
	public function uploader_icon( $icon ) {
		$this->uploader_icon = $icon;

		return $this;
	}

	/**
	 * Set uploader icon size.
	 *
	 * @since 4.0.0
	 *
	 * @param int $size Icon size.
	 *
	 * @return $this
	 */
	public function uploader_icon_size( $size ) {
		$this->upload_icon_size = $size;

		return $this;
	}

	/**
	 * Set uploader title.
	 *
	 * @since 4.0.0
	 *
	 * @param string $title Title text.
	 *
	 * @return $this
	 */
	public function uploader_title( $title ) {
		$this->uploader_title = $title;

		return $this;
	}

	/**
	 * Set uploader subtitle.
	 *
	 * @since 4.0.0
	 *
	 * @param string $subtitle Subtitle text.
	 *
	 * @return $this
	 */
	public function uploader_subtitle( $subtitle ) {
		$this->uploader_subtitle = $subtitle;

		return $this;
	}

	/**
	 * Set uploader button text.
	 *
	 * @since 4.0.0
	 *
	 * @param string $button_text Button text.
	 *
	 * @return $this
	 */
	public function uploader_button_text( $button_text ) {
		$this->uploader_button_text = $button_text;

		return $this;
	}

	/**
	 * Set component variant.
	 *
	 * @since 4.0.0
	 *
	 * @param string $variant Component variant (file-uploader|image-uploader).
	 *
	 * @return $this
	 */
	public function variant( $variant ) {
		$this->variant = $variant;

		return $this;
	}

	/**
	 * Set use WordPress media library.
	 *
	 * @since 4.0.0
	 *
	 * @param bool $use_wp_media Use WP media library.
	 *
	 * @return $this
	 */
	public function use_wp_media( $use_wp_media = true ) {
		$this->use_wp_media = (bool) $use_wp_media;

		return $this;
	}

	/**
	 * Set WP media title.
	 *
	 * @since 4.0.0
	 *
	 * @param string $wp_media_title WP media title.
	 *
	 * @return $this
	 */
	public function wp_media_title( $wp_media_title ) {
		$this->wp_media_title = $wp_media_title;

		return $this;
	}

	/**
	 * Set WP media button text.
	 *
	 * @since 4.0.0
	 *
	 * @param string $wp_media_button_text WP media button text.
	 *
	 * @return $this
	 */
	public function wp_media_button_text( $wp_media_button_text ) {
		$this->wp_media_button_text = $wp_media_button_text;

		return $this;
	}

	/**
	 * Set WP media library type.
	 *
	 * Common types: image, video, audio, application, text
	 *
	 * @since 4.0.0
	 *
	 * @param string $wp_media_library_type WP media library type.
	 *
	 * @return $this
	 */
	public function wp_media_library_type( $wp_media_library_type ) {
		$this->wp_media_library_type = $wp_media_library_type;

		return $this;
	}

	/**
	 * Set multiple.
	 *
	 * @since 4.0.0
	 *
	 * @param bool $multiple Multiple.
	 *
	 * @return $this
	 */
	public function multiple( $multiple = true ) {
		$this->multiple = (bool) $multiple;

		return $this;
	}

	/**
	 * Set input name.
	 *
	 * @since 4.0.0
	 *
	 * @param string $name Name.
	 *
	 * @return $this
	 */
	public function name( $name ) {
		$this->name = sanitize_key( $name );

		return $this;
	}

	/**
	 * Set input ID.
	 *
	 * @since 4.0.0
	 *
	 * @param string $id InputField ID.
	 *
	 * @return $this
	 */
	public function id( $id ) {
		$this->id = sanitize_key( $id );

		return $this;
	}

	/**
	 * Set required.
	 *
	 * @since 4.0.0
	 *
	 * @param bool $required Required.
	 *
	 * @return $this
	 */
	public function required( $required = true ) {
		$this->required = $required;

		return $this;
	}

	/**
	 * Set value.
	 *
	 * @since 4.0.0
	 *
	 * @param string $value Value.
	 *
	 * @return $this
	 */
	public function value( $value ) {
		$this->value = $value;

		return $this;
	}

	/**
	 * Get component content
	 *
	 * @return string
	 */
	public function get(): string {
		$multiple            = $this->multiple;
		$accept              = $this->accept;
		$max_size            = $this->max_size ?? wp_max_upload_size();
		$max_files           = $this->max_files;
		$icon                = $this->uploader_icon;
		$title               = ! empty( $this->uploader_title ) ? $this->uploader_title : __( 'Drop files here or click to upload', 'tutor' );
		$subtitle            = ! empty( $this->uploader_subtitle ) ? $this->uploader_subtitle : '';
		$button_text         = ! empty( $this->uploader_button_text ) ? $this->uploader_button_text : __( 'Select Files', 'tutor' );
		$on_file_select      = $this->attributes['onFileSelect'] ?? 'null';
		$on_error            = $this->attributes['onError'] ?? 'null';
		$on_file_remove      = $this->attributes['onFileRemove'] ?? 'null';
		$variant             = $this->variant;
		$uploader_attributes = $this->attributes;

		// Remove Alpine specific attributes from HTML attributes.
		unset( $uploader_attributes['onFileSelect'] );
		unset( $uploader_attributes['onError'] );

		$this->attributes = $uploader_attributes;

		ob_start();
		?>
		<div 
			class="tutor-file-uploader-wrapper"
			x-data="tutorFileUploader({
				multiple: <?php echo $multiple ? 'true' : 'false'; ?>,
				maxFiles: <?php echo null !== $max_files ? (int) $max_files : 'undefined'; ?>,
				accept: '<?php echo esc_attr( $accept ); ?>',
				maxSize: <?php echo (int) $max_size; ?>,
				onFileSelect: <?php echo esc_js( $on_file_select ); ?>,
				onFileRemove: <?php echo esc_js( $on_file_remove ); ?>,
				onError: <?php echo esc_js( $on_error ); ?>,
				variant: '<?php echo esc_attr( $variant ); ?>',
				value: values.<?php echo esc_attr( $this->name ); ?>,
				name: '<?php echo esc_attr( $this->name ); ?>',
				required: <?php echo is_bool( $this->required ) ? ( $this->required ? 'true' : 'false' ) : "'" . esc_js( $this->required ) . "'"; ?>,
				useWPMedia: <?php echo $this->use_wp_media ? 'true' : 'false'; ?>,
				wpMediaTitle: '<?php echo esc_js( $this->wp_media_title ); ?>',
				wpMediaButtonText: '<?php echo esc_js( $this->wp_media_button_text ); ?>',
				wpMediaLibraryType: '<?php echo esc_js( $this->wp_media_library_type ); ?>',
			})"
		>
			<template x-if="imagePreview">
				<div class="tutor-file-preview">
					<img :src="imagePreview" alt="Preview">
					<div class="tutor-file-preview-overlay">
						<div class="tutor-file-preview-actions">
							<?php
								Button::make()
									->label( __( 'Delete', 'tutor' ) )
									->variant( Variant::DESTRUCTIVE )
									->size( Size::SMALL )
									->attr( 'type', 'button' )
									->attr( '@click.stop', 'removeFile()' )
									->render();

								Button::make()
									->label( __( 'Upload New', 'tutor' ) )
									->variant( Variant::PRIMARY )
									->size( Size::SMALL )
									->attr( 'type', 'button' )
									->attr( '@click.stop', 'openFileDialog()' )
									->render();
							?>
						</div>
					</div>
				</div>
			</template>

			<template x-if="variant === 'file-uploader' && selectedFiles.length > 0">
				<div class="tutor-flex tutor-flex-column tutor-gap-5">
					<div class="tutor-grid tutor-grid-cols-2 tutor-sm-grid-cols-1 tutor-gap-5">
						<template x-for="(file, index) in selectedFiles" :key="index">
							<div class="tutor-attachment-card-wrapper">
								<?php
								AttachmentCard::make()
									->title_attr( 'x-text', 'file.name' )
									->meta_attr( 'x-text', 'formatBytes(file.size)' )
									->action_attr( '@click.stop', 'removeFile(index)' )
									->render();
								?>
							</div>
						</template>
					</div>
					<div x-show="maxFiles > selectedFiles.length" class="tutor-mt-1">
						<button type="button" class="tutor-btn tutor-btn-primary-soft tutor-sm-w-full" @click="openFileDialog()">
							<?php $this->multiple ? esc_html_e( 'Upload More Files', 'tutor' ) : esc_html_e( 'Upload Again', 'tutor' ); ?>
						</button>
					</div>
				</div>
			</template>

			<!-- Upload Area -->
			<div
				x-show="!imagePreview && (variant !== 'file-uploader' || selectedFiles.length === 0)"
				class="tutor-file-uploader"
				:class="{
					'tutor-file-uploader-drag-over': isDragOver,
					'tutor-file-uploader-disabled': isDisabled
				}"
				@click="openFileDialog()"
				@dragover.prevent="handleDragOver($event)"
				@dragleave.prevent="handleDragLeave($event)"
				@drop.prevent="handleDrop($event)"
				<?php echo self::IMAGE_UPLOADER === $variant ? 'data-image-uploader' : ''; ?>
			>
				<input 
					type="file" 
					class="tutor-file-uploader-input"
					:multiple="multiple"
					:accept="accept"
					:disabled="isDisabled"
					x-ref="fileInput"
					@change="handleFileSelect($event)"
					name="<?php echo esc_attr( $this->name ); ?>"
					id="<?php echo esc_attr( ! empty( $this->id ) ? $this->id : $this->name ); ?>"
					<?php echo $this->get_attributes_string(); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>
				>
				<div class="tutor-file-uploader-icon">
					<?php SvgIcon::make()->name( $icon )->size( $this->upload_icon_size )->render(); ?>
				</div>
				<div class="tutor-file-uploader-content">
					<p class="tutor-file-uploader-title"><?php echo esc_html( $title ); ?></p>
					<?php if ( ! empty( $subtitle ) ) : ?>
					<p class="tutor-file-uploader-subtitle"><?php echo esc_html( $subtitle ); ?></p>
					<?php endif; ?>
				</div>
				<button type="button" class="tutor-btn tutor-btn-primary-soft" :disabled="isDisabled">
					<?php echo esc_html( $button_text ); ?>
				</button>
			</div>
		</div>
		<?php
		$this->component_string = ob_get_clean();
		return $this->component_string;
	}
}
