<?php
/**
 * AJAX handlers — quote request (no WooCommerce required).
 */

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

add_action( 'wp_ajax_tilvora_quote_request',        'tilvora_ajax_quote_request' );
add_action( 'wp_ajax_nopriv_tilvora_quote_request', 'tilvora_ajax_quote_request' );

/**
 * Save a base64 JPEG data URL captured from the Three.js canvas to the uploads folder.
 *
 * @param string $base64_data Full data URL (data:image/jpeg;base64,...).
 * @param int    $project_id  Project ID used in the filename.
 * @return string Public URL of the saved image, or '' on failure.
 */
function tilvora_save_quote_design_image( $base64_data, $project_id ) {
	if ( empty( $base64_data ) ) {
		return '';
	}

	$prefix = 'data:image/jpeg;base64,';
	if ( 0 !== strpos( $base64_data, $prefix ) ) {
		return '';
	}

	// phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions.obfuscation_base64_decode -- Decoding a JPEG data URL captured from the Three.js canvas, not obfuscating code.
	$raw = base64_decode( substr( $base64_data, strlen( $prefix ) ) );

	// Minimum sanity checks: must be at least 5 KB and start with JPEG magic bytes.
	if ( ! $raw || strlen( $raw ) < 5000 || "\xFF\xD8" !== substr( $raw, 0, 2 ) ) {
		return '';
	}

	$upload    = wp_upload_dir();
	$dir       = trailingslashit( $upload['basedir'] ) . 'tilvora-quotes/';
	$file_name = 'design-' . absint( $project_id ) . '-' . wp_generate_password( 12, false ) . '.jpg';
	$file_path = $dir . $file_name;

	if ( ! wp_mkdir_p( $dir ) ) {
		return '';
	}

	// Use WP_Filesystem for writing binary files.
	global $wp_filesystem;
	if ( empty( $wp_filesystem ) ) {
		if ( ! function_exists( 'WP_Filesystem' ) ) {
			require_once ABSPATH . 'wp-admin/includes/file.php';
		}
		WP_Filesystem();
	}

	if ( ! $wp_filesystem || ! $wp_filesystem->put_contents( $file_path, $raw, 0644 ) ) {
		return '';
	}

	return trailingslashit( $upload['baseurl'] ) . 'tilvora-quotes/' . $file_name;
}

function tilvora_ajax_quote_request() {
	check_ajax_referer( 'tilvora_quote_request', 'nonce' );

	$name       = sanitize_text_field( wp_unslash( $_POST['name']        ?? '' ) );
	$email      = sanitize_email(      wp_unslash( $_POST['email']       ?? '' ) );
	$phone      = sanitize_text_field( wp_unslash( $_POST['phone']       ?? '' ) );
	$postcode   = sanitize_text_field( wp_unslash( $_POST['postcode']    ?? '' ) );
	$tile_name  = sanitize_text_field( wp_unslash( $_POST['tile_name']   ?? '' ) );
	$notes      = sanitize_textarea_field( wp_unslash( $_POST['notes']   ?? '' ) );
	$project_id = absint( $_POST['project_id'] ?? 0 );
	$price_total = sanitize_text_field( wp_unslash( $_POST['price_total'] ?? '' ) );
	$currency    = sanitize_text_field( wp_unslash( $_POST['currency']    ?? '' ) );

	// fields_json is window.Configurator.buildOrder().fields — a generic
	// [{id, label, value}, ...] list covering whatever controls the product's
	// own config.json defines (material-grid today, anything else tomorrow),
	// so this never needs updating again when a product's customization
	// options change. Each entry is re-sanitized here; never trust client JSON.
	// The raw string itself is sanitized before decoding (contains only plain
	// label/value text, never HTML/SVG, so sanitize_text_field() is safe here).
	$fields_json_raw = sanitize_text_field( wp_unslash( $_POST['fields_json'] ?? '[]' ) );
	$fields_raw       = json_decode( $fields_json_raw, true );
	$fields     = array();
	if ( is_array( $fields_raw ) ) {
		foreach ( $fields_raw as $f ) {
			if ( empty( $f['label'] ) || ! isset( $f['value'] ) || ! is_scalar( $f['value'] ) ) {
				continue;
			}
			$fields[] = array(
				'label' => sanitize_text_field( $f['label'] ),
				'value' => sanitize_text_field( (string) $f['value'] ),
			);
		}
	}

	$selection_summary = '';
	foreach ( $fields as $f ) {
		$selection_summary .= $f['label'] . ': ' . $f['value'] . "\n";
	}
	$selection_summary = trim( $selection_summary );

	if ( ! $name || ! is_email( $email ) ) {
		wp_send_json_error( [ 'message' => __( 'Please enter your name and a valid email address.', 'tilvora-3d-flooring-visualizer' ) ] );
		return;
	}

	// ── Persist to Quote Inbox ───────────────────────────────────────────────
	// Save the design snapshot (base64 JPEG from the Three.js canvas) to disk.
	// phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- Base64 JPEG data URL; sanitize_text_field() strips base64 characters. Content is validated (JPEG magic bytes, minimum size) inside tilvora_save_quote_design_image().
	$design_image_b64 = isset( $_POST['design_image'] ) ? wp_unslash( $_POST['design_image'] ) : '';
	$design_image_url = tilvora_save_quote_design_image( $design_image_b64, $project_id );

	$quote_id = tilvora_insert_quote(
		array(
			'project_id'       => $project_id,
			'name'             => $name,
			'email'            => $email,
			'phone'            => $phone,
			'postcode'         => $postcode,
			'tile_name'         => $tile_name,
			'selection_summary' => $selection_summary,
			'price_total'       => $price_total,
			'currency'          => $currency,
			'notes'             => $notes,
			'design_image_url'  => $design_image_url,
		)
	);

	// ── Emails happen out-of-band ────────────────────────────────────────────
	// wp_mail() blocks on a live SMTP connection (often 20s+ per call on hosts
	// without a fast local mail transport) — sending two of them synchronously
	// here means the customer stares at "Sending…" for 40s+ before seeing
	// success, even though the quote itself was already saved instantly.
	// Scheduling both emails as a WP-Cron event and immediately spawning it
	// (a non-blocking loopback request) lets the AJAX response return the
	// moment the DB row is saved; the emails go out a moment later in a
	// separate request the customer never waits on.
	if ( $quote_id ) {
		wp_schedule_single_event( time(), 'tilvora_send_quote_emails_event', array( $quote_id ) );
		spawn_cron();
	}

	wp_send_json_success( [ 'message' => __( 'Quote request sent successfully.', 'tilvora-3d-flooring-visualizer' ) ] );
}

add_action( 'tilvora_send_quote_emails_event', 'tilvora_send_quote_emails' );

/**
 * Sends the business-owner notification + customer confirmation emails for
 * a saved quote. Runs out-of-band via WP-Cron (see tilvora_ajax_quote_request()
 * above) so a slow mail transport never delays the customer's success message.
 * Reads everything from the already-saved DB row rather than $_POST, since
 * this executes in a separate request that has no access to the original one.
 *
 * @param int $quote_id Row ID from tilvora_insert_quote().
 */
function tilvora_send_quote_emails( $quote_id ) {
	$quote = tilvora_get_quote( $quote_id );
	if ( ! $quote ) {
		return;
	}

	$project_title = $quote->project_id ? get_the_title( $quote->project_id ) : '';
	$site_name     = get_bloginfo( 'name' );
	$admin_email   = get_option( 'admin_email' );
	$lines         = $quote->selection_summary ? explode( "\n", trim( $quote->selection_summary ) ) : array();

	// ── Email to business owner ──────────────────────────────────────────────
	$subject = sprintf(
		/* translators: 1: tile name 2: customer name */
		__( 'New Quote Request — %1$s — %2$s', 'tilvora-3d-flooring-visualizer' ),
		$quote->tile_name ?: 'No tile selected',
		$quote->customer_name
	);

	/* translators: %s: site name */
	$body  = sprintf( __( 'New quote request via the Tilvora 3D Visualizer on %s.', 'tilvora-3d-flooring-visualizer' ), $site_name );
	if ( $project_title ) {
		/* translators: %s: project title */
		$body .= ' ' . sprintf( __( 'Project: %s', 'tilvora-3d-flooring-visualizer' ), $project_title );
	}
	$body .= "\n\n";
	$body .= "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n";
	/* translators: %s: customer name */
	$body .= sprintf( __( 'Customer:  %s', 'tilvora-3d-flooring-visualizer' ), $quote->customer_name )  . "\n";
	/* translators: %s: customer email address */
	$body .= sprintf( __( 'Email:     %s', 'tilvora-3d-flooring-visualizer' ), $quote->customer_email ) . "\n";
	/* translators: %s: customer phone number */
	if ( $quote->customer_phone )    $body .= sprintf( __( 'Phone:     %s', 'tilvora-3d-flooring-visualizer' ), $quote->customer_phone )    . "\n";
	/* translators: %s: customer postcode */
	if ( $quote->customer_postcode ) $body .= sprintf( __( 'Postcode:  %s', 'tilvora-3d-flooring-visualizer' ), $quote->customer_postcode ) . "\n";
	$body .= "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n";
	if ( $lines ) {
		foreach ( $lines as $line ) {
			$body .= $line . "\n";
		}
	} else {
		/* translators: %s: tile name */
		$body .= sprintf( __( 'Selection: %s', 'tilvora-3d-flooring-visualizer' ), $quote->tile_name ?: '—' ) . "\n";
	}
	if ( $quote->price_total ) {
		/* translators: %s: quoted price total */
		$body .= sprintf( __( 'Price:     %s', 'tilvora-3d-flooring-visualizer' ), $quote->currency . $quote->price_total ) . "\n";
	}
	if ( $quote->notes ) {
		$body .= "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n";
		/* translators: %s: customer notes */
		$body .= sprintf( __( 'Notes:     %s', 'tilvora-3d-flooring-visualizer' ), $quote->notes ) . "\n";
	}

	wp_mail( $admin_email, $subject, $body, [ 'Reply-To: ' . $quote->customer_name . ' <' . $quote->customer_email . '>' ] );

	// ── Confirmation to customer ─────────────────────────────────────────────
	$confirm_subject = sprintf(
		/* translators: %s: site name */
		__( 'Your quote request — %s', 'tilvora-3d-flooring-visualizer' ),
		$site_name
	);

	/* translators: %s: customer name */
	$confirm_body  = sprintf( __( 'Hi %s,', 'tilvora-3d-flooring-visualizer' ), $quote->customer_name ) . "\n\n";
	$confirm_body .= __( "Thank you for your quote request. We've received your design and will be in touch shortly.\n\n", 'tilvora-3d-flooring-visualizer' );
	$confirm_body .= "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n";
	if ( $lines ) {
		foreach ( $lines as $line ) {
			$confirm_body .= $line . "\n";
		}
	} else {
		/* translators: %s: tile name */
		$confirm_body .= sprintf( __( 'Selection: %s', 'tilvora-3d-flooring-visualizer' ), $quote->tile_name ?: '—' ) . "\n";
	}
	if ( $quote->price_total ) {
		/* translators: %s: quoted price total */
		$confirm_body .= sprintf( __( 'Price:     %s', 'tilvora-3d-flooring-visualizer' ), $quote->currency . $quote->price_total ) . "\n";
	}
	$confirm_body .= "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n\n";
	$confirm_body .= __( "Best regards,\n", 'tilvora-3d-flooring-visualizer' ) . $site_name;

	wp_mail( $quote->customer_email, $confirm_subject, $confirm_body, [ 'Reply-To: ' . $admin_email ] );
}
