<?php
/**
 * Admin Muxer-Uploader logic.
 *
 * @package TheStudioPlayer
 */

if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

/**
 * Render Muxer-Uploader page.
 */
function thespl_render_muxer_page() {
	if ( ! thespl_current_user_can_policy( 'plugin_access' ) ) {
		return;
	}

	$ver           = thespl_get_readme_stable_tag_version();
	$plugin_name   = __( 'The Studio Player', 'the-studio-player' );
	$page_label    = __( 'Muxer-Uploader', 'the-studio-player' );
	$page_title    = $plugin_name;
	$muxer_engine  = thespl_get_muxer_engine();
	$has_pro_build = thespl_has_pro_assets();
	if ( '' !== $ver ) {
		$page_title .= ' - ' . $ver;
		if ( $has_pro_build ) {
			$page_title .= ' Pro';
		}
	}
	$page_title .= ' - ' . $page_label;

	// Protect the directory immediately if it exists and option is enabled.
	$player_settings  = thespl_get_player_settings();
	$htaccess_enabled = ! empty( $player_settings['streaming_htaccess_enabled'] );

	$muxer_settings = thespl_get_muxer_settings();
	$default_subdir = $muxer_settings['subdir'] ?? '';
	$upload_dir     = wp_upload_dir();

	$supports_slots_4      = $muxer_engine->get_operational_slot_count() > 2;
	$supports_hi_res_muxer = $muxer_engine->supports_high_resolution_input();
	$max_operational_slots = $muxer_engine->get_operational_slot_count();

	if ( $htaccess_enabled && ! empty( $upload_dir['basedir'] ) && is_string( $upload_dir['basedir'] ) ) {
		$audio_dir  = trailingslashit( trailingslashit( $upload_dir['basedir'] ) . 'the-studio-player/audio' );
		$target_dir = $audio_dir;
		if ( '' !== $default_subdir ) {
			$target_dir .= $default_subdir;
		}
		if ( thespl_init_filesystem() ) {
			global $wp_filesystem;
			if ( $wp_filesystem->is_dir( $target_dir ) ) {
				thespl_ensure_directory_protection( $target_dir );
			}
		}
	}
	?>
	<div class="wrap thespl-admin-wrapper">
		<h1><?php echo esc_html( $page_title ); ?></h1>

		<?php thespl_render_remote_admin_banners(); ?>

		<?php thespl_render_admin_top_nav( 'thespl-muxer' ); ?>

		<div class="thespl-muxer-app">
			<div class="section-box">
				<span class="section-title"><?php esc_html_e( 'Audio Files (Drag & Drop or Click)', 'the-studio-player' ); ?></span>
				<div id="file-slots" class="file-slots-grid">
					<div class="file-slot" data-slot="0">
						<div class="slot-header">
							<span class="slot-number">A</span>
							<span><?php esc_html_e( 'Variant 1 (Main)', 'the-studio-player' ); ?></span>
						</div>
						<div class="drop-zone">
							<span><?php esc_html_e( 'Drop WAV here or click to browse', 'the-studio-player' ); ?></span>
						</div>
						<div class="file-info">
							<div class="file-badge">
								<div class="file-name"></div>
								<div class="file-size"></div>
								<span class="remove-file">&times;</span>
							</div>
						</div>
						<input type="file" id="in1" accept=".wav,.WAV" multiple />
					</div>
					<div class="file-slot" data-slot="1">
						<div class="slot-header">
							<span class="slot-number">B</span>
							<span><?php esc_html_e( 'Variant 2', 'the-studio-player' ); ?></span>
						</div>
						<div class="drop-zone">
							<span><?php esc_html_e( 'Drop WAV here or click to browse', 'the-studio-player' ); ?></span>
						</div>
						<div class="file-info">
							<div class="file-badge">
								<div class="file-name"></div>
								<div class="file-size"></div>
								<span class="remove-file">&times;</span>
							</div>
						</div>
						<input type="file" id="in2" accept=".wav,.WAV" multiple />
					</div>
					<div class="file-slot <?php echo ! $supports_slots_4 ? 'pro-locked' : ''; ?>" data-slot="2">
						<div class="slot-header">
							<span class="slot-number">C</span>
							<span><?php esc_html_e( 'Variant 3', 'the-studio-player' ); ?></span>
							<?php
							if ( ! $supports_slots_4 ) {
								echo '<span class="thespl-pro-badge thespl-pro-badge--right">' . esc_html__( '(Pro Feature)', 'the-studio-player' ) . '</span>';
							}
							?>
						</div>
						<div class="drop-zone">
							<span><?php esc_html_e( 'Drop WAV here or click to browse', 'the-studio-player' ); ?></span>
						</div>
						<div class="file-info">
							<div class="file-badge">
								<div class="file-name"></div>
								<div class="file-size"></div>
								<span class="remove-file">&times;</span>
							</div>
						</div>
						<?php if ( $supports_slots_4 ) : ?>
						<input type="file" id="in3" accept=".wav,.WAV" multiple />
						<?php endif; ?>
					</div>
					<div class="file-slot <?php echo ! $supports_slots_4 ? 'pro-locked' : ''; ?>" data-slot="3">
						<div class="slot-header">
							<span class="slot-number">D</span>
							<span><?php esc_html_e( 'Variant 4', 'the-studio-player' ); ?></span>
							<?php
							if ( ! $supports_slots_4 ) {
								echo '<span class="thespl-pro-badge thespl-pro-badge--right">' . esc_html__( '(Pro Feature)', 'the-studio-player' ) . '</span>';
							}
							?>
						</div>
						<div class="drop-zone">
							<span><?php esc_html_e( 'Drop WAV here or click to browse', 'the-studio-player' ); ?></span>
						</div>
						<div class="file-info">
							<div class="file-badge">
								<div class="file-name"></div>
								<div class="file-size"></div>
								<span class="remove-file">&times;</span>
							</div>
						</div>
						<?php if ( $supports_slots_4 ) : ?>
						<input type="file" id="in4" accept=".wav,.WAV" multiple />
						<?php endif; ?>
					</div>
				</div>
			</div>

			<div class="status-display status-idle">
				<strong><?php esc_html_e( 'Status:', 'the-studio-player' ); ?></strong> <span id="status"><?php echo esc_html( sprintf( /* translators: %d: Maximum number of operational stereo WAV files. */ __( 'No files loaded - load up to %d stereo WAV files.', 'the-studio-player' ), (int) $max_operational_slots ) ); ?></span>
			</div>

			<div class="section-box">
				<span class="section-title"><?php esc_html_e( 'Configuration', 'the-studio-player' ); ?></span>
				
				<div class="control-row">
					<label class="control-label"><?php esc_html_e( 'Compression Level (0–8) *', 'the-studio-player' ); ?>
						<input id="comp" type="range" min="0" max="8" step="1" value="8" />
						<span id="comp-val">8</span>
						<span class="muted-label"><?php esc_html_e( 'Estimated size:', 'the-studio-player' ); ?></span>
						<span id="size-estimate">—</span>
					</label>
					<div id="config-limit-warning"></div>
				</div>
				<div class="config-note"><?php esc_html_e( 'FLAC is lossless — compression only affects file size.', 'the-studio-player' ); ?></div>
				
				<div class="radio-group" id="sr-group" style="margin-top:15px;">
					<label class="group-label"><strong><?php esc_html_e( 'Sample Rate:', 'the-studio-player' ); ?></strong></label>
					<label class="radio-option <?php echo ! $supports_hi_res_muxer ? 'disabled-option-soft' : ''; ?>">
						<input type="radio" name="sample-rate" value="44100" checked id="sr-44100"> 44.1 kHz
					</label>
					<label class="radio-option <?php echo ! $supports_hi_res_muxer ? 'disabled-option muted' : ''; ?>">
						<input type="radio" name="sample-rate" value="48000" id="sr-48000" <?php echo ! $supports_hi_res_muxer ? 'disabled' : ''; ?>> 
						48 kHz 
						<?php
						if ( ! $supports_hi_res_muxer ) {
							echo esc_html__( '(Pro)', 'the-studio-player' );}
						?>
					</label>
				</div>
				<div id="sr-note" class="config-note" style="margin-top:5px;"></div>
				
				<div class="radio-group" id="bd-group" style="margin-top:10px;">
					<label class="group-label"><strong><?php esc_html_e( 'Bit Depth:', 'the-studio-player' ); ?></strong></label>
					<label class="radio-option <?php echo ! $supports_hi_res_muxer ? 'disabled-option-soft' : ''; ?>">
						<input type="radio" name="bit-depth" value="16" checked id="bd-16"> 16-bit
					</label>
					<label class="radio-option <?php echo ! $supports_hi_res_muxer ? 'disabled-option muted' : ''; ?>">
						<input type="radio" name="bit-depth" value="24" id="bd-24" <?php echo ! $supports_hi_res_muxer ? 'disabled' : ''; ?>> 
						24-bit 
						<?php
						if ( ! $supports_hi_res_muxer ) {
							echo esc_html__( '(Pro)', 'the-studio-player' );}
						?>
					</label>
				</div>
				<div id="bd-note" class="config-note" style="margin-top:5px;"></div>

				<div class="control-row" style="margin-top:15px;">
					<label class="control-label" for="upload-chunk-size">
						<strong><?php esc_html_e( 'Upload chunk size:', 'the-studio-player' ); ?></strong>
					</label>
					<select id="upload-chunk-size"></select>
					<div id="upload-chunk-size-note" class="config-note"></div>
				</div>
			</div>

			<div class="section-box">
				<span class="section-title"><?php esc_html_e( 'Output Files', 'the-studio-player' ); ?></span>
				<div class="thespl-admin-inline-row">
					<div class="flex-1">
						<label for="flac-filename"><strong><?php esc_html_e( 'Final FLAC Filename:', 'the-studio-player' ); ?></strong></label><br>
						<input type="text" id="flac-filename" class="regular-text" placeholder="<?php esc_attr_e( 'e.g., songtitel-8ch.flac', 'the-studio-player' ); ?>" />
						<div class="config-note"><?php esc_html_e( 'Auto-generated from loaded files; editable before upload.', 'the-studio-player' ); ?></div>
					</div>
					<div class="flex-1" id="thespl-waveform-output-box">
						<label><strong><?php esc_html_e( 'Waveform JSON:', 'the-studio-player' ); ?></strong></label><br>
						<div id="thespl-waveform-output-text" class="config-note"><?php esc_html_e( 'Waveform JSON is available in Pro. Existing files are shown automatically in the player.', 'the-studio-player' ); ?></div>
					</div>
				</div>
			</div>

			<div class="button-group">
				<button id="reset"><?php esc_html_e( 'Reset All', 'the-studio-player' ); ?></button>
				<button id="run" disabled>🚀 <?php esc_html_e( 'Start Encoding & Upload', 'the-studio-player' ); ?></button>
			</div>

			<div id="progress">
				<div id="progress-bar">
					<div id="progress-fill"></div>
					<div id="progress-text">0%</div>
				</div>
			</div>

			<div id="result"></div>

			<?php
			$show_verification    = ! empty( $player_settings['show_security_verification'] );
			$all_security_enabled = ! empty( $player_settings['streaming_security_enabled'] ) && ! empty( $player_settings['streaming_htaccess_enabled'] );
			if ( $show_verification && $all_security_enabled && current_user_can( 'manage_options' ) ) :
				?>
			<div id="thespl-security-verification-box" class="section-box">
				<span class="section-title"><?php esc_html_e( 'Security Verification', 'the-studio-player' ); ?></span>
				<p><?php esc_html_e( 'Test direct access to your media files. These links should return 403 Forbidden if protection is active.', 'the-studio-player' ); ?></p>
				<div class="thespl-admin-inline-row">
					<?php
					$audio_url = '';
					if ( ! empty( $upload_dir['baseurl'] ) && is_string( $upload_dir['baseurl'] ) ) {
						$audio_url = trailingslashit( trailingslashit( $upload_dir['baseurl'] ) . 'the-studio-player/audio' );
					}
					$upload_url = $audio_url;
					if ( '' !== $default_subdir ) {
						$upload_url .= $default_subdir . '/';
					}
					$test_file   = $upload_url . 'test-access.flac';
					$latest_flac = get_posts(
						array(
							'post_type'      => 'attachment',
							'post_mime_type' => 'audio/flac',
							'posts_per_page' => 1,
							'orderby'        => 'date',
							'order'          => 'DESC',
							'fields'         => 'ids',
						)
					);

					$attachment_id = ! empty( $latest_flac ) ? $latest_flac[0] : 0;
					$stream_url    = add_query_arg( 'thespl_stream', ( $attachment_id ? (string) $attachment_id : '999999' ), home_url( '/' ) );
					?>
					<div class="flex-1">
						<strong><?php esc_html_e( 'Direct File Link:', 'the-studio-player' ); ?></strong><br>
						<code id="thespl-test-link-direct"><?php echo esc_url( $test_file ); ?></code>
						<p class="config-note">
							<a href="<?php echo esc_url( $test_file ); ?>" target="_blank" id="thespl-test-link-direct-btn" class="thespl-test-link"><?php esc_html_e( 'Open in new tab', 'the-studio-player' ); ?></a><br>
							<?php esc_html_e( 'Access to physical .flac files in this folder is blocked via .htaccess.', 'the-studio-player' ); ?>
						</p>
					</div>
					<div class="flex-1">
						<strong><?php esc_html_e( 'Streaming Endpoint (No Token):', 'the-studio-player' ); ?></strong><br>
						<code id="thespl-test-link-stream"><?php echo esc_url( $stream_url ); ?></code>
						<p class="config-note">
							<a href="<?php echo esc_url( $stream_url ); ?>" target="_blank" id="thespl-test-link-stream-btn" class="thespl-test-link"><?php esc_html_e( 'Open in new tab', 'the-studio-player' ); ?></a><br>
							<?php esc_html_e( 'Streaming without a valid, non-expired token is blocked via PHP security logic.', 'the-studio-player' ); ?>
						</p>
					</div>
				</div>
				<div style="margin-top: 15px; padding-top: 10px; border-top: 1px solid rgba(255,255,255,0.1); display: flex; justify-content: flex-end;">
					<label style="cursor: pointer; display: flex; align-items: center; gap: 8px;">
						<input type="checkbox" id="thespl-hide-security-verification" style="margin: 0;" />
						<span><?php esc_html_e( "Don't show this message again", 'the-studio-player' ); ?></span>
					</label>
				</div>
			</div>
			<?php endif; ?>

			<div class="section-box">
				<span class="section-title"><?php esc_html_e( 'Console Log', 'the-studio-player' ); ?></span>
				<div id="log"><?php esc_html_e( 'Initializing…', 'the-studio-player' ); ?></div>
			</div>

			<div class="thespl-muxer-metafoot">
				<span class="thespl-muxer-metafoot-prefix"><?php echo esc_html__( 'The Muxer-App', 'the-studio-player' ); ?></span>
				<span class="thespl-muxer-metafoot-sep"> | </span>
				<span class="thespl-muxer-metafoot-version">
					<?php
					if ( '' !== $ver ) {
						echo esc_html( 'v' . $ver );
					}
					?>
				</span>
				<span class="thespl-muxer-metafoot-sep"> | </span>
				<span class="thespl-muxer-metafoot-copy"><?php echo esc_html__( '© Peter Rahe', 'the-studio-player' ); ?> <?php echo esc_html( date_i18n( 'Y' ) ); ?></span>
			</div>
		</div>
	</div>
	<?php
}

/**
 * Hook into settings update to ensure directory protection.
 */
function thespl_maybe_apply_directory_protection() {
	$player = thespl_get_player_settings();
	if ( empty( $player['streaming_htaccess_enabled'] ) ) {
		return;
	}

	$muxer      = thespl_get_muxer_settings();
	$subdir     = $muxer['subdir'] ?? '';
	$upload_dir = wp_upload_dir();
	if ( empty( $upload_dir['basedir'] ) || ! is_string( $upload_dir['basedir'] ) ) {
		return;
	}
	$audio_dir  = trailingslashit( trailingslashit( $upload_dir['basedir'] ) . 'the-studio-player/audio' );
	$target_dir = $audio_dir;
	if ( '' !== $subdir ) {
		$target_dir .= $subdir;
	}
	if ( thespl_init_filesystem() ) {
		global $wp_filesystem;
		if ( $wp_filesystem->is_dir( $target_dir ) ) {
			thespl_ensure_directory_protection( $target_dir );
		}
	}
}
add_action( 'update_option_thespl_player_settings', 'thespl_maybe_apply_directory_protection' );
add_action( 'update_option_thespl_muxer_settings', 'thespl_maybe_apply_directory_protection' );

/**
 * Handle AJAX upload.
 */
function thespl_handle_upload() {
	check_ajax_referer( 'thespl_muxer_nonce', 'nonce' );
	if ( ! thespl_current_user_can_policy( 'plugin_access' ) ) {
		wp_send_json_error( array( 'message' => __( 'Permission denied', 'the-studio-player' ) ) );
	}

	if ( ! thespl_init_filesystem() ) {
		wp_send_json_error( array( 'message' => __( 'Filesystem initialization failed. Please check server permissions.', 'the-studio-player' ) ) );
	}
	global $wp_filesystem;

	if ( ! function_exists( 'wp_handle_upload' ) ) {
		/*
		 * Load the core upload helpers only when needed so we can call wp_handle_upload().
		 * This follows the WordPress.org guidance for allowed core includes: the helper
		 * file is required from within a function and immediately used, and is not exposed
		 * as a separate entry point or loader script.
		 */
		require_once ABSPATH . 'wp-admin/includes/file.php';
	}

	$forced_subdir = thespl_get_forced_upload_subdir();
	if ( '' !== $forced_subdir ) {
		$subdir = $forced_subdir;
	} else {
		$subdir_raw = isset( $_POST['subdir'] ) ? sanitize_text_field( wp_unslash( $_POST['subdir'] ) ) : '';
		$subdir     = thespl_sanitize_subdir_path( $subdir_raw );
	}

	$upload_dir = wp_upload_dir();
	if ( empty( $upload_dir['basedir'] ) || empty( $upload_dir['baseurl'] ) || ! is_string( $upload_dir['basedir'] ) || ! is_string( $upload_dir['baseurl'] ) ) {
		wp_send_json_error( array( 'message' => __( 'Upload directory is not properly configured', 'the-studio-player' ) ) );
	}

	$audio_dir = trailingslashit( trailingslashit( $upload_dir['basedir'] ) . 'the-studio-player/audio' );
	$audio_url = trailingslashit( trailingslashit( $upload_dir['baseurl'] ) . 'the-studio-player/audio' );

	$target_dir = $audio_dir;
	$target_url = $audio_url;
	if ( '' !== $subdir ) {
		$target_dir .= $subdir;
		$target_url .= $subdir;
	}

	if ( ! $wp_filesystem->exists( $target_dir ) ) {
		if ( ! $wp_filesystem->mkdir( $target_dir, 0755 ) ) {
			wp_send_json_error( array( 'message' => __( 'Failed to create directory', 'the-studio-player' ) ) );
		}
	}

	if ( ! $wp_filesystem->is_writable( $target_dir ) ) {
		wp_send_json_error( array( 'message' => __( 'Directory is not writable', 'the-studio-player' ) ) );
	}

	thespl_ensure_directory_protection( $target_dir );

	if ( false === get_option( 'thespl_muxer_settings' ) ) {
		$auto_settings = array(
			'subdir'     => $subdir,
			'chunk_size' => isset( $_POST['chunk_size'] ) ? intval( $_POST['chunk_size'] ) : 524288,
		);
		update_option( 'thespl_muxer_settings', $auto_settings );
	}

	if ( isset( $_POST['chunk_index'] ) ) {
		$limit      = wp_max_upload_size();
		$chunk_size = isset( $_POST['chunk_size'] ) ? (int) $_POST['chunk_size'] : 0;
		if ( $limit > 0 && $chunk_size > $limit ) {
			$human_chunk = size_format( $chunk_size );
			$human_limit = size_format( $limit );
			/* translators: 1: selected chunk size, 2: server upload limit */
			$message = sprintf( __( 'The selected upload chunk size (%1$s) is larger than your server\'s upload limit per request (%2$s). Please choose a smaller chunk size or increase the server limit.', 'the-studio-player' ), $human_chunk, $human_limit );
			wp_send_json_error(
				array(
					'message' => $message,
				)
			);
		}

		$chunk_index   = isset( $_POST['chunk_index'] ) ? intval( $_POST['chunk_index'] ) : 0;
		$total_chunks  = isset( $_POST['total_chunks'] ) ? intval( $_POST['total_chunks'] ) : 1;
		$file_key      = isset( $_POST['file_key'] ) ? sanitize_text_field( wp_unslash( $_POST['file_key'] ) ) : 'chunk_data';
		$original_name = isset( $_POST['file_name'] ) ? sanitize_file_name( wp_unslash( $_POST['file_name'] ) ) : 'unknown.bin';

		if ( ! isset( $_FILES[ $file_key ] ) ) {
			wp_send_json_error( array( 'message' => __( 'No chunk data received', 'the-studio-player' ) ) );
		}

		$file_data = array(
			'name'     => $original_name,
			'type'     => isset( $_FILES[ $file_key ]['type'] ) ? sanitize_mime_type( wp_unslash( $_FILES[ $file_key ]['type'] ) ) : '',
			'tmp_name' => isset( $_FILES[ $file_key ]['tmp_name'] ) ? sanitize_text_field( wp_unslash( $_FILES[ $file_key ]['tmp_name'] ) ) : '',
			'error'    => isset( $_FILES[ $file_key ]['error'] ) ? (int) $_FILES[ $file_key ]['error'] : 0,
			'size'     => isset( $_FILES[ $file_key ]['size'] ) ? (int) $_FILES[ $file_key ]['size'] : 0,
		);

		if ( 0 !== $file_data['error'] || '' === $file_data['tmp_name'] ) {
			wp_send_json_error( array( 'message' => __( 'No chunk data received', 'the-studio-player' ) ) );
		}

		thespl_handle_chunk_upload_core( $target_dir, $target_url, $subdir, $chunk_index, $total_chunks, $file_data, $original_name );
		return;
	}

	$files            = array( 'flac_file', 'json_file' );
	$uploaded_urls    = array();
	$upload_overrides = array(
		'test_form' => false,
		'mimes'     => thespl_get_upload_mime_types(),
	);

	$upload_dir_filter = static function ( $uploads ) use ( $subdir ) {
		$base_subdir = '/the-studio-player/audio';
		if ( '' !== $subdir ) {
			$base_subdir .= '/' . ltrim( $subdir, '/' );
		}
		$uploads['subdir'] = $base_subdir;
		$uploads['path']   = trailingslashit( $uploads['basedir'] ) . ltrim( $base_subdir, '/' );
		$uploads['url']    = trailingslashit( $uploads['baseurl'] ) . ltrim( $base_subdir, '/' );
		return $uploads;
	};

	add_filter( 'upload_dir', $upload_dir_filter );

	foreach ( $files as $key ) {
		if ( ! isset( $_FILES[ $key ] ) || ! isset( $_FILES[ $key ]['error'] ) || UPLOAD_ERR_OK !== (int) $_FILES[ $key ]['error'] ) {
			continue;
		}

		$handled = wp_handle_upload( $_FILES[ $key ], $upload_overrides );
		if ( isset( $handled['error'] ) ) {
			wp_send_json_error( array( 'message' => $handled['error'] ) );
		}

		if ( empty( $handled['file'] ) ) {
			continue;
		}

		$destination = $handled['file'];
		$filename    = sanitize_file_name( wp_basename( $destination ) );

		if ( ! thespl_validate_file_content( $destination ) ) {
			$wp_filesystem->delete( $destination );
			wp_send_json_error( array( 'message' => __( 'File validation failed (invalid content).', 'the-studio-player' ) ) );
		}

		$uploaded_urls[ $key ] = isset( $handled['url'] ) ? $handled['url'] : $target_url . '/' . $filename;
		thespl_register_media_attachment( $destination, $uploaded_urls[ $key ] );
	}

	remove_filter( 'upload_dir', $upload_dir_filter );

	if ( empty( $uploaded_urls ) ) {
		wp_send_json_error( array( 'message' => __( 'No files uploaded', 'the-studio-player' ) ) );
	}

	wp_send_json_success(
		array(
			'message'  => __( 'Files uploaded successfully', 'the-studio-player' ),
			'path'     => $target_dir,
			'flac_url' => $uploaded_urls['flac_file'] ?? '#',
			'json_url' => $uploaded_urls['json_file'] ?? '#',
		)
	);
}
add_action( 'wp_ajax_thespl_upload_muxed_files', 'thespl_handle_upload' );

/**
 * Handle Cancel Upload (Cleanup).
 */
function thespl_handle_cancel_upload() {
	check_ajax_referer( 'thespl_muxer_nonce', 'nonce' );
	if ( ! thespl_current_user_can_policy( 'plugin_access' ) ) {
		wp_send_json_error( array( 'message' => __( 'Permission denied', 'the-studio-player' ) ) );
	}

	if ( ! thespl_init_filesystem() ) {
		wp_send_json_error( array( 'message' => __( 'Filesystem error', 'the-studio-player' ) ) );
	}
	global $wp_filesystem;

	$subdir_raw = isset( $_POST['subdir'] ) ? sanitize_text_field( wp_unslash( $_POST['subdir'] ) ) : '';
	$filename   = isset( $_POST['filename'] ) ? sanitize_file_name( wp_unslash( $_POST['filename'] ) ) : '';

	if ( empty( $filename ) ) {
		wp_send_json_error( array( 'message' => __( 'Missing parameters', 'the-studio-player' ) ) );
	}

	$forced_subdir = thespl_get_forced_upload_subdir();
	$subdir        = '' !== $forced_subdir ? $forced_subdir : thespl_sanitize_subdir_path( $subdir_raw );

	$upload_dir = wp_upload_dir();
	if ( empty( $upload_dir['basedir'] ) || ! is_string( $upload_dir['basedir'] ) ) {
		wp_send_json_error( array( 'message' => __( 'Upload directory not found.', 'the-studio-player' ) ) );
	}
	$audio_dir  = trailingslashit( trailingslashit( $upload_dir['basedir'] ) . 'the-studio-player/audio' );
	$target_dir = $audio_dir;
	if ( '' !== $subdir ) {
		$target_dir .= $subdir;
	}

	$temp_filename = md5( $filename . $subdir ) . '.part';
	$temp_path     = $target_dir . '/' . $temp_filename;

	if ( $wp_filesystem->exists( $temp_path ) ) {
		if ( $wp_filesystem->delete( $temp_path ) ) {
			wp_send_json_success( array( 'message' => __( 'Temp file cleaned up', 'the-studio-player' ) ) );
		} else {
			wp_send_json_error( array( 'message' => __( 'Failed to delete temp file', 'the-studio-player' ) ) );
		}
	} else {
		wp_send_json_success( array( 'message' => __( 'No temp file found', 'the-studio-player' ) ) );
	}
}
add_action( 'wp_ajax_thespl_cancel_upload', 'thespl_handle_cancel_upload' );

/**
 * Register a file in WordPress Media Library.
 */
// Function moved to thespl-admin-helpers.php.

/**
 * Handle chunked upload (core implementation).
 *
 * @param string $target_dir    Target directory path for the assembled file.
 * @param string $target_url    Target base URL for the assembled file.
 * @param string $subdir        Relative upload subdirectory.
 * @param int    $chunk_index   Zero-based index of the current chunk.
 * @param int    $total_chunks  Total number of chunks expected.
 * @param array  $file_data     File data array similar to a $_FILES entry.
 * @param string $original_name Original file name provided by the client.
 */
function thespl_handle_chunk_upload_core( $target_dir, $target_url, $subdir, $chunk_index, $total_chunks, $file_data, $original_name ) {
	global $wp_filesystem;

	if ( ! isset( $file_data ) || ! isset( $file_data['tmp_name'] ) ) {
		wp_send_json_error( array( 'message' => __( 'No chunk data received', 'the-studio-player' ) ) );
	}

	$temp_filename = md5( $original_name . $subdir ) . '.part';
	$temp_path     = $target_dir . '/' . $temp_filename;

	$chunk_content = $wp_filesystem->get_contents( $file_data['tmp_name'] );
	if ( false === $chunk_content ) {
		wp_send_json_error( array( 'message' => __( 'Failed to read chunk content', 'the-studio-player' ) ) );
	}

	if ( 0 === $chunk_index ) {
		if ( false === $wp_filesystem->put_contents( $temp_path, $chunk_content, FS_CHMOD_FILE ) ) {
			wp_send_json_error( array( 'message' => __( 'Failed to write first chunk', 'the-studio-player' ) ) );
		}
	} else {
		$existing = $wp_filesystem->exists( $temp_path ) ? $wp_filesystem->get_contents( $temp_path ) : '';
		if ( false === $existing ) {
			$existing = '';
		}
		if ( false === $wp_filesystem->put_contents( $temp_path, $existing . $chunk_content, FS_CHMOD_FILE ) ) {
			/* translators: %d: Chunk index */
			wp_send_json_error( array( 'message' => sprintf( __( 'Failed to append chunk %d', 'the-studio-player' ), $chunk_index ) ) );
		}
	}

	if ( ( $total_chunks - 1 ) === $chunk_index ) {
		$final_path = $target_dir . '/' . $original_name;

		if ( $wp_filesystem->move( $temp_path, $final_path, true ) ) {
			if ( ! thespl_validate_file_content( $final_path ) ) {
				$wp_filesystem->delete( $final_path );
				wp_send_json_error( array( 'message' => __( 'File validation failed (invalid content).', 'the-studio-player' ) ) );
			}

			$attach_id = thespl_register_media_attachment( $final_path, $target_url . '/' . $original_name );

			wp_send_json_success(
				array(
					'message'  => __( 'Chunked upload complete', 'the-studio-player' ),
					'path'     => $final_path,
					'url'      => $target_url . '/' . $original_name,
					'media_id' => $attach_id,
				)
			);
		} else {
			wp_send_json_error( array( 'message' => __( 'Failed to finalize merged file', 'the-studio-player' ) ) );
		}
	} else {
		wp_send_json_success(
			array(
				/* translators: 1: Current chunk index, 2: Total chunks */
				'message'    => sprintf( __( 'Chunk %1$d/%2$d received', 'the-studio-player' ), $chunk_index + 1, $total_chunks ),
				'chunk_next' => $chunk_index + 1,
			)
		);
	}
}
