<?php
/**
 * Review landing page submission handler.
 *
 * @package ProofWP
 */
declare(strict_types=1);

defined('ABSPATH') || exit;


function dsproofwp_get_form_settings(): array {
	global $wpdb;
	$settings_json = $wpdb->get_var("SELECT form_settings FROM {$wpdb->prefix}dsproofwp_form_settings WHERE id = 1");
	$settings = $settings_json ? json_decode($settings_json, true) : [];
	
	require_once __DIR__ . '/services/DSProofwp_Recaptcha_Service.php';
	$recaptcha_service = new DSProofwp_Recaptcha_Service();
	$recaptcha_secret_key_set = $recaptcha_service->has_secret_key();
	
	return [
		'image_max_size_mb'    => isset($settings['image_max_size_mb']) ? (int) $settings['image_max_size_mb'] : 5,
		'video_max_size_mb'    => isset($settings['video_max_size_mb']) ? (int) $settings['video_max_size_mb'] : 50,
		'image_max_count'      => isset($settings['image_max_count']) ? (int) $settings['image_max_count'] : 5,
		'video_max_count'      => isset($settings['video_max_count']) ? (int) $settings['video_max_count'] : 1,
		'image_upload_enabled' => isset($settings['image_upload_enabled']) ? (bool) $settings['image_upload_enabled'] : true,
		'video_upload_enabled' => isset($settings['video_upload_enabled']) ? (bool) $settings['video_upload_enabled'] : true,
		'allowed_image_types'  => !empty($settings['allowed_image_types']) ? array_map('trim', explode(',', $settings['allowed_image_types'])) : ['jpg', 'jpeg', 'png', 'webp'],
		'allowed_video_types'  => !empty($settings['allowed_video_types']) ? array_map('trim', explode(',', $settings['allowed_video_types'])) : ['mp4', 'mov', 'webm'],
		'consent_enabled'      => isset($settings['consent_enabled']) ? (bool) $settings['consent_enabled'] : false,
		'consent_text'         => isset($settings['consent_text']) ? (string) $settings['consent_text'] : __('I agree to the terms and conditions.', 'proofwp'),
		'recaptcha_enabled'    => isset($settings['recaptcha_enabled']) ? (bool) $settings['recaptcha_enabled'] : false,
		'recaptcha_site_key'   => isset($settings['recaptcha_site_key']) ? (string) $settings['recaptcha_site_key'] : '',
		'recaptcha_secret_key_set' => $recaptcha_secret_key_set,
	];
}

function dsproofwp_validate_and_filter_media(array $raw_files, array $settings): array {
	$valid_files_indices = [];
	$errors = [];
	$first_type = null;
	$type_count = 0;

	$image_max_size_bytes = $settings['image_max_size_mb'] * 1024 * 1024;
	$video_max_size_bytes = $settings['video_max_size_mb'] * 1024 * 1024;

	// Track error types to show clean, aggregated messages
	$has_unsupported_ext = false;
	$has_disabled_video = false;
	$has_disabled_image = false;
	$has_large_video = false;
	$has_large_image = false;
	$has_too_many_videos = false;
	$has_too_many_images = false;

	for ($i = 0, $count = count($raw_files['name']); $i < $count; $i++) {
		if (empty($raw_files['name'][$i]) || empty($raw_files['tmp_name'][$i]) || ($raw_files['error'][$i] ?? UPLOAD_ERR_NO_FILE) !== UPLOAD_ERR_OK) {
			continue;
		}

		$ext = strtolower(pathinfo($raw_files['name'][$i], PATHINFO_EXTENSION));
		
		$is_video = in_array($ext, $settings['allowed_video_types'], true);
		$is_image = in_array($ext, $settings['allowed_image_types'], true);
		
		if (!$is_video && !$is_image) {
			$has_unsupported_ext = true;
			continue;
		}
		
		$current_type = $is_video ? 'video' : 'image';
		
		if ($current_type === 'video' && !$settings['video_upload_enabled']) {
			$has_disabled_video = true;
			continue;
		}
		
		if ($current_type === 'image' && !$settings['image_upload_enabled']) {
			$has_disabled_image = true;
			continue;
		}

		// Set the primary type based on the first valid file
		if ($first_type === null) {
			$first_type = $current_type;
		}

		// Filter out files that don't match the primary type (only one type supported per review)
		if ($current_type !== $first_type) {
			continue;
		}

		// Validate sizes and counts dynamically based on form settings
		if ($is_video) {
			if ($raw_files['size'][$i] > $video_max_size_bytes) {
				$has_large_video = true;
				continue;
			}
			if ($type_count >= $settings['video_max_count']) {
				$has_too_many_videos = true;
				continue;
			}
		} else {
			if ($raw_files['size'][$i] > $image_max_size_bytes) {
				$has_large_image = true;
				continue;
			}
			if ($type_count >= $settings['image_max_count']) {
				$has_too_many_images = true;
				continue;
			}
		}

		$type_count++;
		$valid_files_indices[] = $i;
	}

	// Generate user-friendly error messages
	if ($has_unsupported_ext) {
		$errors[] = __('One or more files have an unsupported extension.', 'proofwp');
	}
	if ($has_disabled_video) {
		$errors[] = __('Video uploads are currently disabled.', 'proofwp');
	}
	if ($has_disabled_image) {
		$errors[] = __('Image uploads are currently disabled.', 'proofwp');
	}
	if ($has_large_video) {
		$errors[] = sprintf(__('One or more videos exceed the maximum upload size of %dMB.', 'proofwp'), $settings['video_max_size_mb']);
	}
	if ($has_large_image) {
		$errors[] = sprintf(__('One or more images exceed the maximum upload size of %dMB.', 'proofwp'), $settings['image_max_size_mb']);
	}
	if ($has_too_many_videos) {
		$errors[] = sprintf(__('You can only upload up to %d video(s) per review.', 'proofwp'), $settings['video_max_count']);
	}
	if ($has_too_many_images) {
		$errors[] = sprintf(__('You can only upload up to %d image(s) per review.', 'proofwp'), $settings['image_max_count']);
	}
	
	return [
		'indices' => $valid_files_indices,
		'errors'  => $errors,
	];
}

function dsproofwp_process_review_media(array $raw_files, array $valid_indices, int $product_id, int $review_id, DSProofwp_Review_Media_Repository $media_repo): array {
	$errors = [];
	$media_items = [];

	foreach ($valid_indices as $i) {
		$attachment_result = dsproofwp_handle_review_file_upload([
			'name'     => $raw_files['name'][$i],
			'tmp_name' => $raw_files['tmp_name'][$i],
			'size'     => $raw_files['size'][$i],
			'type'     => $raw_files['type'][$i],
			'error'    => $raw_files['error'][$i] ?? 0,
		], $product_id);

		if (is_wp_error($attachment_result)) {
			$errors[] = sprintf(
				/* translators: 1: file name, 2: error message */
				__('Unable to upload %1$s: %2$s', 'proofwp'),
				$raw_files['name'][$i],
				$attachment_result->get_error_message()
			);
			continue;
		}

		$attachment_id = (int) $attachment_result;
		$url = wp_get_attachment_url($attachment_id);
		$media_items[] = [
			'attachment_id' => $attachment_id,
			'media_type'    => dsproofwp_determine_media_type($raw_files['name'][$i]),
			'url'           => $url ?: '',
		];
	}

	if (!empty($media_items)) {
		$media_repo->store_for_review($review_id, $media_items);
	}
	
	return $errors;
}

function dsproofwp_handle_review_form_submission(WC_Order $order, array $order_items, DSProofwp_Review_Request_Repository $review_request_repo): array
{
	$page_data = [
		'errors' => [],
		'posted_rating' => [],
		'posted_review' => [],
		'success' => false,
	];

	if (!isset($_POST['proofwp_review_nonce']) || !wp_verify_nonce(sanitize_text_field(wp_unslash($_POST['proofwp_review_nonce'])), 'proofwp_review_form')) {
		$page_data['errors'][] = __('Security check failed. Please try again.', 'proofwp');
		return $page_data;
	}

	$ratings = isset($_POST['rating']) ? array_map('absint', (array) $_POST['rating']) : [];
	$review_texts = isset($_POST['review_text']) ? array_map(
		function ($value) { return sanitize_textarea_field(wp_unslash($value)); },
		(array) $_POST['review_text']
	) : [];

	$page_data['posted_rating'] = $ratings;
	$page_data['posted_review'] = $review_texts;

	$has_rating = false;
	foreach ($ratings as $rating) {
		if ($rating > 0) {
			$has_rating = true;
			break;
		}
	}

	if (!$has_rating) {
		$page_data['errors'][] = __('Please submit at least one review rating.', 'proofwp');
		return $page_data;
	}

	global $wpdb;
	$settings = dsproofwp_get_form_settings();

	if ($settings['consent_enabled'] && empty($_POST['proofwp_consent'])) {
		$page_data['errors'][] = __('You must agree to the terms and conditions to submit your review.', 'proofwp');
		return $page_data;
	}

	if ($settings['recaptcha_enabled'] && !empty($settings['recaptcha_site_key']) && $settings['recaptcha_secret_key_set']) {
		$recaptcha_token = isset($_POST['recaptcha_token']) ? trim(sanitize_text_field(wp_unslash($_POST['recaptcha_token']))) : '';
		if (empty($recaptcha_token)) {
			$page_data['errors'][] = __('reCAPTCHA verification is required.', 'proofwp');
			return $page_data;
		}

		require_once __DIR__ . '/services/DSProofwp_Recaptcha_Service.php';
		$recaptcha_service = new DSProofwp_Recaptcha_Service();
		if (!$recaptcha_service->verify_token($recaptcha_token)) {
			$page_data['errors'][] = __('reCAPTCHA verification failed. Please try again.', 'proofwp');
			return $page_data;
		}
	}
	
	$review_repo = new DSProofwp_Review_Repository($wpdb);
	$media_repo = new DSProofwp_Review_Media_Repository($wpdb);
	$review_count = 0;

	// ----------------------------------------------------
	// PASS 1: VALIDATE ALL INPUTS
	// ----------------------------------------------------
	$processed_items = [];

	foreach ($order_items as $item) {
		$product = $item->get_product();
		if (!$product) {
			continue;
		}

		$product_id = $product->get_id();
		$rating = $ratings[$product_id] ?? 0;
		if ($rating < 1 || $rating > 5) {
			continue;
		}

		$raw_files = [
			'name'     => $_FILES['media']['name'][$product_id] ?? [],
			'type'     => $_FILES['media']['type'][$product_id] ?? [],
			'tmp_name' => $_FILES['media']['tmp_name'][$product_id] ?? [],
			'error'    => $_FILES['media']['error'][$product_id] ?? [],
			'size'     => $_FILES['media']['size'][$product_id] ?? [],
		];

		$validation_result = dsproofwp_validate_and_filter_media($raw_files, $settings);
		if (!empty($validation_result['errors'])) {
			$page_data['errors'] = array_merge($page_data['errors'], $validation_result['errors']);
		}

		$processed_items[] = [
			'product_id'    => $product_id,
			'rating'        => $rating,
			'raw_files'     => $raw_files,
			'valid_indices' => $validation_result['indices'],
		];
	}

	// Abort if any file failed validation (e.g. wrong type, max size, disabled uploads)
	if (!empty($page_data['errors'])) {
		$page_data['errors'] = array_values(array_unique($page_data['errors']));
		return $page_data;
	}

	// ----------------------------------------------------
	// PASS 2: PROCESS & INSERT REVIEWS
	// ----------------------------------------------------
	foreach ($processed_items as $p_item) {
		$product_id    = $p_item['product_id'];
		$rating        = $p_item['rating'];
		$raw_files     = $p_item['raw_files'];
		$valid_indices = $p_item['valid_indices'];
		
		$has_media = count($valid_indices) > 0;

		$review_data = [
			'product_id'   => $product_id,
			'author_name'  => $order->get_billing_first_name() ?: $order->get_billing_full_name(),
			'author_email' => $order->get_billing_email(),
			'content'      => $review_texts[$product_id] ?? '',
			'rating'       => $rating,
			'status'       => '0',
			'source'       => 'review_landing_page',
			'verified'     => 1,
			'is_visual'    => $has_media ? 1 : 0, 
		];

		if ($has_media) {
			$review = $review_repo->create($review_data);
			if (!$review || empty($review['id'])) {
				continue;
			}

			$review_count++;
			
			$upload_errors = dsproofwp_process_review_media($raw_files, $valid_indices, $product_id, (int)$review['id'], $media_repo);
			if (!empty($upload_errors)) {
				// We append upload errors but don't abort, as the review is already created.
				$page_data['errors'] = array_merge($page_data['errors'], $upload_errors);
			}
		} else {
			// Queue for bulk insertion (no media attached)
			$bulk_no_media_reviews[] = $review_data;
		}
	}

	if (!empty($bulk_no_media_reviews)) {
		foreach ($bulk_no_media_reviews as $bulk_review) {
			$review = $review_repo->create($bulk_review);
			if ($review && !empty($review['id'])) {
				$review_count++;
			}
		}
	}

	if ($review_count < 1) {
		$page_data['errors'][] = __('No reviews were submitted. Please try again.', 'proofwp');
		return $page_data;
	}

	// Only clear the request if we didn't have any upload errors in pass 2, 
	// though typically we'd consider it successful enough if reviews were stored.
	if (empty($page_data['errors'])) {
		$review_request_repo->cancel_all_requests_by_order((int) $order->get_id());
		$page_data['success'] = true;
	}

	return $page_data;
}
