<?php
/**
 * Email Handler for Kurs Booking
 *
 * Manages all email notifications for bookings.
 *
 * @package KursBooking
 * @since   1.0.0
 */

declare(strict_types=1);

// Prevent direct access.
if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

/**
 * Class Kurs_Booking_Email
 *
 * Handles email sending for booking notifications.
 */
class Kurs_Booking_Email {

	/**
	 * Initialize email functionality.
	 */
	public static function init(): void {
		// Set HTML content type for emails.
		add_filter( 'wp_mail_content_type', array( __CLASS__, 'set_html_content_type' ) );

		// Custom from name and email.
		add_filter( 'wp_mail_from', array( __CLASS__, 'custom_mail_from' ) );
		add_filter( 'wp_mail_from_name', array( __CLASS__, 'custom_mail_from_name' ) );

		// Send confirmation emails when booking is confirmed.
		add_action( 'kurs_booking_confirmed', array( __CLASS__, 'on_booking_confirmed' ), 5, 1 );
	}

	/**
	 * Handle booking confirmed action.
	 *
	 * Sends confirmation emails to customer and admin when a booking is confirmed.
	 *
	 * @since 1.6.0
	 * @param int $buchung_id The booking post ID.
	 */
	public static function on_booking_confirmed( int $buchung_id ): void {
		// Send confirmation email to customer.
		self::send_booking_confirmed( $buchung_id );

		// Send notification to admin.
		self::send_admin_notification( $buchung_id );
	}

	/**
	 * Set content type to HTML.
	 *
	 * @return string Content type.
	 */
	public static function set_html_content_type(): string {
		return 'text/html';
	}

	/**
	 * Custom from email address.
	 *
	 * @param string $from_email Default from email.
	 * @return string Custom from email.
	 */
	public static function custom_mail_from( string $from_email ): string {
		// Sprint 2.6: Use correct option key from Settings.
		$custom = get_option( 'kurs_booking_email_from_address', '' );
		return ! empty( $custom ) ? sanitize_email( $custom ) : $from_email;
	}

	/**
	 * Custom from name.
	 *
	 * @param string $from_name Default from name.
	 * @return string Custom from name.
	 */
	public static function custom_mail_from_name( string $from_name ): string {
		$custom = get_option( 'kurs_booking_company_name', '' );
		return ! empty( $custom ) ? sanitize_text_field( $custom ) : $from_name;
	}

	/**
	 * Get customer email from booking with fallback for legacy meta keys.
	 *
	 * Supports both new format (_buchung_email) and legacy format (_buchung_customer_email).
	 *
	 * @param int $buchung_id Booking post ID.
	 * @return string Customer email or empty string.
	 */
	private static function get_customer_email( int $buchung_id ): string {
		// Try new format first (Sprint 8+).
		$email = Kurs_Booking_Buchung::get_meta( $buchung_id, 'email', '' );

		// Fallback to legacy format.
		if ( empty( $email ) ) {
			$email = self::get_customer_email( $buchung_id );
		}

		return $email;
	}

	/**
	 * Send booking received email (Double-Opt-In).
	 *
	 * §312i BGB - Eingangsbestätigung PFLICHT.
	 *
	 * @param int $buchung_id Booking post ID.
	 * @return bool True if sent successfully.
	 */
	public static function send_booking_received( int $buchung_id ): bool {
		$buchung = get_post( $buchung_id );

		if ( ! $buchung || 'kurs-buchung' !== $buchung->post_type ) {
			return false;
		}

		$email = self::get_customer_email( $buchung_id );

		if ( empty( $email ) || ! is_email( $email ) ) {
			return false;
		}

		$kurs_id = (int) Kurs_Booking_Buchung::get_meta( $buchung_id, 'kurs_id', 0 );
		$token   = Kurs_Booking_Buchung::get_meta( $buchung_id, 'confirm_token', '' );

		// Build confirmation URL (clean URL format).
		$confirm_url = home_url( '/buchung-bestaetigen/' . $token . '/' );

		// Prepare template data.
		$data = self::get_booking_data( $buchung_id, $kurs_id );
		$data['confirm_url'] = $confirm_url;

		// Build default subject.
		$default_subject = sprintf(
			/* translators: %s: Booking number */
			__( 'Buchungsanfrage eingegangen - Bitte bestätigen Sie Ihre Email [%s]', 'kurs-booking' ),
			$buchung->post_title
		);

		// Get subject (custom or default).
		$subject = self::get_email_subject( 'booking_received', $default_subject, $data );

		// Render body.
		$body = self::render_template( 'email-booking-received', $data );

		// Allow customization via filters.
		$subject = apply_filters( 'kurs_booking_email_received_subject', $subject, $buchung_id );
		$body    = apply_filters( 'kurs_booking_email_received_body', $body, $buchung_id, $data );

		return self::send( $email, $subject, $body );
	}

	/**
	 * Send booking confirmed email.
	 *
	 * @param int $buchung_id Booking post ID.
	 * @return bool True if sent successfully.
	 */
	public static function send_booking_confirmed( int $buchung_id ): bool {
		$buchung = get_post( $buchung_id );

		if ( ! $buchung || 'kurs-buchung' !== $buchung->post_type ) {
			return false;
		}

		$email = self::get_customer_email( $buchung_id );

		if ( empty( $email ) || ! is_email( $email ) ) {
			return false;
		}

		$kurs_id = (int) Kurs_Booking_Buchung::get_meta( $buchung_id, 'kurs_id', 0 );

		// Generate cancellation token if not exists.
		$cancel_token = get_post_meta( $buchung_id, '_cancel_token', true );
		if ( empty( $cancel_token ) ) {
			$cancel_token = Kurs_Booking_Buchung::generate_cancel_token( $buchung_id );
		}

		// Prepare template data.
		$data = self::get_booking_data( $buchung_id, $kurs_id );

		// Sprint 4.6: Check if digital product.
		$is_digital_product = Kurs_Booking_Kurs::is_digital_product( $kurs_id );
		$data['is_digital_product'] = $is_digital_product;

		// Add cancellation link (only for non-digital products).
		if ( ! $is_digital_product ) {
			$data['cancel_url'] = add_query_arg( 'kurs_cancel', $cancel_token, home_url() );
		}

		// Sprint 4.6: For digital products, add withdrawal consent confirmation (§312f BGB).
		if ( $is_digital_product ) {
			$withdrawal_consent = get_post_meta( $buchung_id, '_withdrawal_consent', true );
			$company_name       = get_option( 'kurs_booking_company_name', get_bloginfo( 'name' ) );

			$data['withdrawal_consent']      = ! empty( $withdrawal_consent );
			$data['withdrawal_consent_text'] = sprintf(
				/* translators: %s: Company name */
				__( 'Ich stimme der Vertragsausfuehrung durch %s vor Ablauf der Widerrufsfrist zu und weiss, dass dadurch mein Widerrufsrecht erlischt.', 'kurs-booking' ),
				esc_html( $company_name )
			);
			$data['video_access_days'] = Kurs_Booking_Kurs::get_video_access_days( $kurs_id );
		}

		// Include Zoom data only for online/hybrid courses.
		$kurs_type = Kurs_Booking_Kurs::get_meta( $kurs_id, 'type', 'vor_ort' );

		if ( in_array( $kurs_type, array( 'online', 'hybrid' ), true ) ) {
			$data['zoom_link']     = Kurs_Booking_Kurs::get_meta( $kurs_id, 'zoom_link', '' );
			$data['zoom_password'] = Kurs_Booking_Kurs::get_meta( $kurs_id, 'zoom_password', '' );
		}

		// Build default subject.
		$default_subject = sprintf(
			/* translators: 1: Booking number, 2: Course name */
			__( 'Buchungsbestätigung Nr. %1$s – %2$s', 'kurs-booking' ),
			$buchung->post_title,
			get_the_title( $kurs_id )
		);

		// Get subject (custom or default).
		$subject = self::get_email_subject( 'booking_confirmed', $default_subject, $data );

		// Render body.
		$body = self::render_template( 'email-booking-confirmed', $data );

		// Allow customization.
		$subject = apply_filters( 'kurs_booking_email_confirmed_subject', $subject, $buchung_id );
		$body    = apply_filters( 'kurs_booking_email_confirmed_body', $body, $buchung_id, $data );

		$sent = self::send( $email, $subject, $body );

		// For Video-Kurs (digital products), automatically send video access email.
		if ( $sent && Kurs_Booking_Kurs::is_digital_product( $kurs_id ) ) {
			$token     = get_post_meta( $buchung_id, '_buchung_token', true );
			$video_url = add_query_arg( 'buchung', $token, home_url( '/mein-videokurs/' ) );
			self::send_video_access( $buchung_id, $video_url );
		}

		return $sent;
	}

	/**
	 * Send cancellation confirmation email to customer.
	 *
	 * @param int $buchung_id Booking post ID.
	 * @return bool True if sent successfully.
	 */
	public static function send_cancellation_confirmation( int $buchung_id ): bool {
		$buchung = get_post( $buchung_id );

		if ( ! $buchung || 'kurs-buchung' !== $buchung->post_type ) {
			return false;
		}

		$email = self::get_customer_email( $buchung_id );

		if ( empty( $email ) || ! is_email( $email ) ) {
			return false;
		}

		$kurs_id = (int) Kurs_Booking_Buchung::get_meta( $buchung_id, 'kurs_id', 0 );

		// Prepare template data.
		$data = self::get_booking_data( $buchung_id, $kurs_id );

		// Add cancellation details.
		$cancel_data = Kurs_Booking_Buchung::get_cancellation_data( $buchung_id );
		if ( $cancel_data ) {
			$data['cancel_fee_percent']   = $cancel_data['fee_percent'];
			$data['cancel_fee_amount']    = $cancel_data['fee_amount'];
			$data['cancel_refund_amount'] = $cancel_data['refund_amount'];
			$data['cancel_reason']        = $cancel_data['fee_reason'];
			$data['cancel_date']          = $cancel_data['confirmed_at']
				? date_i18n( 'd.m.Y, H:i', strtotime( $cancel_data['confirmed_at'] ) )
				: date_i18n( 'd.m.Y, H:i' );
		}

		// Build default subject.
		$default_subject = sprintf(
			/* translators: 1: Booking number */
			__( 'Stornierungsbestätigung – Buchung %1$s', 'kurs-booking' ),
			$buchung->post_title
		);

		// Get subject (custom or default).
		$subject = self::get_email_subject( 'cancellation_confirmation', $default_subject, $data );

		// Render body.
		$body = self::render_template( 'email-cancellation-confirmation', $data );

		// Allow customization.
		$subject = apply_filters( 'kurs_booking_email_cancellation_subject', $subject, $buchung_id );
		$body    = apply_filters( 'kurs_booking_email_cancellation_body', $body, $buchung_id, $data );

		return self::send( $email, $subject, $body );
	}

	/**
	 * Send cancellation notification to admin.
	 *
	 * @param int $buchung_id Booking post ID.
	 * @return bool True if sent successfully.
	 */
	public static function send_admin_cancellation_notification( int $buchung_id ): bool {
		$admin_email = get_option( 'kurs_booking_admin_email', get_option( 'admin_email' ) );

		if ( empty( $admin_email ) || ! is_email( $admin_email ) ) {
			return false;
		}

		$buchung = get_post( $buchung_id );

		if ( ! $buchung || 'kurs-buchung' !== $buchung->post_type ) {
			return false;
		}

		$kurs_id = (int) Kurs_Booking_Buchung::get_meta( $buchung_id, 'kurs_id', 0 );

		// Prepare template data.
		$data                  = self::get_booking_data( $buchung_id, $kurs_id );
		$data['edit_url']      = admin_url( 'post.php?post=' . $buchung_id . '&action=edit' );
		$data['kurs_edit_url'] = admin_url( 'post.php?post=' . $kurs_id . '&action=edit' );

		// Add cancellation details.
		$cancel_data = Kurs_Booking_Buchung::get_cancellation_data( $buchung_id );
		if ( $cancel_data ) {
			$data['cancel_fee_percent']   = $cancel_data['fee_percent'];
			$data['cancel_fee_amount']    = $cancel_data['fee_amount'];
			$data['cancel_refund_amount'] = $cancel_data['refund_amount'];
			$data['cancel_reason']        = $cancel_data['reason'];
			$data['cancel_fee_reason']    = $cancel_data['fee_reason'];
			$data['cancel_notes']         = $cancel_data['notes'];
			$data['cancel_date']          = $cancel_data['confirmed_at']
				? date_i18n( 'd.m.Y, H:i', strtotime( $cancel_data['confirmed_at'] ) )
				: date_i18n( 'd.m.Y, H:i' );
		}

		// Build default subject.
		$default_subject = sprintf(
			/* translators: 1: Booking number, 2: Course name */
			__( 'Stornierung: %1$s – %2$s', 'kurs-booking' ),
			$buchung->post_title,
			get_the_title( $kurs_id )
		);

		// Get subject (custom or default).
		$subject = self::get_email_subject( 'admin_cancellation', $default_subject, $data );

		// Render body.
		$body = self::render_template( 'email-admin-cancellation', $data );

		return self::send( $admin_email, $subject, $body );
	}

	/**
	 * Send immediate admin notification for inquiries (D1 Einzelcoaching).
	 *
	 * This is sent immediately when a D1/Anfrage type request is submitted,
	 * before the customer confirms their email (Double-Opt-In).
	 *
	 * @param int $buchung_id Booking post ID.
	 * @return bool True if sent successfully.
	 */
	public static function send_admin_inquiry_notification( int $buchung_id ): bool {
		$admin_email = get_option( 'kurs_booking_admin_email', get_option( 'admin_email' ) );

		if ( empty( $admin_email ) || ! is_email( $admin_email ) ) {
			return false;
		}

		$buchung = get_post( $buchung_id );

		if ( ! $buchung || 'kurs-buchung' !== $buchung->post_type ) {
			return false;
		}

		$kurs_id = (int) Kurs_Booking_Buchung::get_meta( $buchung_id, 'kurs_id', 0 );

		// Prepare template data.
		$data                  = self::get_booking_data( $buchung_id, $kurs_id );
		$data['edit_url']      = admin_url( 'post.php?post=' . $buchung_id . '&action=edit' );
		$data['kurs_edit_url'] = admin_url( 'post.php?post=' . $kurs_id . '&action=edit' );

		// Build subject for inquiry.
		$subject = sprintf(
			/* translators: 1: Course name, 2: Customer name */
			__( 'Neue Anfrage: %1$s – von %2$s', 'kurs-booking' ),
			get_the_title( $kurs_id ),
			esc_html( $data['customer_name'] )
		);

		// Build body.
		$body = '<div style="font-family: Arial, sans-serif; max-width: 600px; margin: 0 auto;">';
		$body .= '<h2 style="color: #0073aa;">' . esc_html__( 'Neue Kontaktanfrage eingegangen', 'kurs-booking' ) . '</h2>';
		$body .= '<div style="background: #f0f7fc; border-left: 4px solid #0073aa; padding: 15px; margin: 20px 0;">';
		$body .= '<p style="margin: 0;"><strong>' . esc_html__( 'Achtung:', 'kurs-booking' ) . '</strong> ';
		$body .= esc_html__( 'Dies ist eine Kontaktanfrage (keine bestätigte Buchung). Der Interessent hat seine E-Mail-Adresse noch nicht bestätigt.', 'kurs-booking' ) . '</p>';
		$body .= '</div>';

		$body .= '<table style="width: 100%; border-collapse: collapse; margin: 20px 0;">';
		$body .= '<tr><td style="padding: 10px; border-bottom: 1px solid #eee; font-weight: bold;">' . esc_html__( 'Anfrage für:', 'kurs-booking' ) . '</td>';
		$body .= '<td style="padding: 10px; border-bottom: 1px solid #eee;">' . esc_html( $data['kurs_title'] ) . '</td></tr>';
		$body .= '<tr><td style="padding: 10px; border-bottom: 1px solid #eee; font-weight: bold;">' . esc_html__( 'Name:', 'kurs-booking' ) . '</td>';
		$body .= '<td style="padding: 10px; border-bottom: 1px solid #eee;">' . esc_html( $data['customer_name'] ) . '</td></tr>';
		$body .= '<tr><td style="padding: 10px; border-bottom: 1px solid #eee; font-weight: bold;">' . esc_html__( 'E-Mail:', 'kurs-booking' ) . '</td>';
		$body .= '<td style="padding: 10px; border-bottom: 1px solid #eee;"><a href="mailto:' . esc_attr( $data['customer_email'] ) . '">' . esc_html( $data['customer_email'] ) . '</a></td></tr>';

		if ( ! empty( $data['customer_phone'] ) ) {
			$body .= '<tr><td style="padding: 10px; border-bottom: 1px solid #eee; font-weight: bold;">' . esc_html__( 'Telefon:', 'kurs-booking' ) . '</td>';
			$body .= '<td style="padding: 10px; border-bottom: 1px solid #eee;"><a href="tel:' . esc_attr( $data['customer_phone'] ) . '">' . esc_html( $data['customer_phone'] ) . '</a></td></tr>';
		}

		$body .= '<tr><td style="padding: 10px; border-bottom: 1px solid #eee; font-weight: bold;">' . esc_html__( 'Anfrage-Nr.:', 'kurs-booking' ) . '</td>';
		$body .= '<td style="padding: 10px; border-bottom: 1px solid #eee;">' . esc_html( $data['buchung_nummer'] ) . '</td></tr>';
		$body .= '<tr><td style="padding: 10px; border-bottom: 1px solid #eee; font-weight: bold;">' . esc_html__( 'Eingegangen am:', 'kurs-booking' ) . '</td>';
		$body .= '<td style="padding: 10px; border-bottom: 1px solid #eee;">' . esc_html( $data['buchung_date'] ) . ' ' . wp_date( 'H:i' ) . '</td></tr>';
		$body .= '</table>';

		// Action button.
		$body .= '<p style="margin: 30px 0; text-align: center;">';
		$body .= '<a href="' . esc_url( $data['edit_url'] ) . '" style="background: #0073aa; color: #fff; padding: 12px 30px; text-decoration: none; border-radius: 4px; display: inline-block;">' . esc_html__( 'Anfrage ansehen', 'kurs-booking' ) . '</a>';
		$body .= '</p>';

		$body .= '<hr style="margin: 30px 0; border: none; border-top: 1px solid #ddd;">';
		$body .= '<p style="font-size: 12px; color: #666; text-align: center;">';
		$body .= esc_html__( 'Diese E-Mail wurde automatisch versendet.', 'kurs-booking' ) . '</p>';
		$body .= '</div>';

		return self::send( $admin_email, $subject, $body );
	}

	/**
	 * Send admin notification email.
	 *
	 * @param int $buchung_id Booking post ID.
	 * @return bool True if sent successfully.
	 */
	public static function send_admin_notification( int $buchung_id ): bool {
		$admin_email = get_option( 'kurs_booking_admin_email', get_option( 'admin_email' ) );

		if ( empty( $admin_email ) || ! is_email( $admin_email ) ) {
			return false;
		}

		$buchung = get_post( $buchung_id );

		if ( ! $buchung || 'kurs-buchung' !== $buchung->post_type ) {
			return false;
		}

		$kurs_id = (int) Kurs_Booking_Buchung::get_meta( $buchung_id, 'kurs_id', 0 );

		// Prepare template data.
		$data                  = self::get_booking_data( $buchung_id, $kurs_id );
		$data['edit_url']      = admin_url( 'post.php?post=' . $buchung_id . '&action=edit' );
		$data['kurs_edit_url'] = admin_url( 'post.php?post=' . $kurs_id . '&action=edit' );

		// Build default subject.
		$default_subject = sprintf(
			/* translators: 1: Booking number, 2: Course name */
			__( 'Neue Buchung: %1$s – %2$s', 'kurs-booking' ),
			$buchung->post_title,
			get_the_title( $kurs_id )
		);

		// Get subject (custom or default).
		$subject = self::get_email_subject( 'admin_notification', $default_subject, $data );

		// Render body.
		$body = self::render_template( 'email-admin-notification', $data );

		return self::send( $admin_email, $subject, $body );
	}

	/**
	 * Send video access email.
	 *
	 * @param int    $buchung_id Booking post ID.
	 * @param string $video_url  Video access URL.
	 * @return bool True if sent successfully.
	 */
	public static function send_video_access( int $buchung_id, string $video_url ): bool {
		$email = self::get_customer_email( $buchung_id );

		if ( empty( $email ) || ! is_email( $email ) ) {
			return false;
		}

		$kurs_id = (int) Kurs_Booking_Buchung::get_meta( $buchung_id, 'kurs_id', 0 );

		$data              = self::get_booking_data( $buchung_id, $kurs_id );
		$data['video_url'] = esc_url( $video_url );

		// Build default subject.
		$default_subject = sprintf(
			/* translators: %s: Course name */
			__( 'Ihr Video-Zugang – %s', 'kurs-booking' ),
			get_the_title( $kurs_id )
		);

		// Get subject (custom or default).
		$subject = self::get_email_subject( 'video_access', $default_subject, $data );

		// Render body.
		$body = self::render_template( 'email-video-access', $data );

		return self::send( $email, $subject, $body );
	}

	/**
	 * Get booking data for email templates.
	 *
	 * @param int $buchung_id Booking post ID.
	 * @param int $kurs_id    Kurs post ID.
	 * @return array<string, mixed> Template data.
	 */
	private static function get_booking_data( int $buchung_id, int $kurs_id ): array {
		$buchung = get_post( $buchung_id );
		$kurs    = get_post( $kurs_id );

		// Booking data.
		$tickets      = Kurs_Booking_Buchung::get_meta( $buchung_id, 'tickets', array() );
		$tickets      = is_array( $tickets ) ? $tickets : array();
		$ticket_days  = Kurs_Booking_Buchung::get_meta( $buchung_id, 'ticket_days', array() );
		$ticket_days  = is_array( $ticket_days ) ? $ticket_days : array();
		$total_price  = (float) Kurs_Booking_Buchung::get_meta( $buchung_id, 'total_price', 0 );

		// Kurs data.
		$varianten = Kurs_Booking_Kurs::get_varianten( $kurs_id );

		// Sprint 4.10: Get course days for per_day calculation (max/default value).
		$kurs_days   = Kurs_Booking_Kurs::get_course_days( $kurs_id );
		$global_hint = get_option( 'kurs_booking_manual_payment_hint', 'Wird vor Ort verrechnet' );

		// Build ticket details.
		$ticket_details    = array();
		$auto_invoice_total = 0;
		$manual_total       = 0;
		$has_manual_items   = false;

		foreach ( $tickets as $variant_id => $quantity ) {
			if ( $quantity < 1 ) {
				continue;
			}

			$variant_name  = '';
			$variant_price = 0;
			$per_day       = false;
			$auto_invoice  = true;
			$hinweis       = '';

			foreach ( $varianten as $index => $v ) {
				$v_id = $v['id'] ?? ( $index + 1 );
				if ( (int) $v_id === (int) $variant_id ) {
					$variant_name  = $v['name'] ?? '';
					$variant_price = (float) ( $v['preis'] ?? 0 );
					// Sprint 4.10: Get per_day, auto_invoice, hinweis.
					$per_day      = ! empty( $v['per_day'] );
					$auto_invoice = $v['auto_invoice'] ?? true;
					$hinweis      = $v['hinweis'] ?? '';
					if ( empty( $hinweis ) && ! $auto_invoice ) {
						$hinweis = $global_hint;
					}
					break;
				}
			}

			// Sprint 4.10: Calculate effective price with per_day and user-selected days.
			$effective_price = $variant_price;
			$price_label     = '';
			$selected_days   = $kurs_days; // Default to full course days.

			if ( $per_day ) {
				// Get user-selected days for this variant, default to full course days.
				$selected_days = isset( $ticket_days[ $variant_id ] ) && $ticket_days[ $variant_id ] > 0
					? min( absint( $ticket_days[ $variant_id ] ), $kurs_days )
					: $kurs_days;
				$effective_price = $variant_price * $selected_days;
				$price_label = sprintf(
					/* translators: 1: Price per day, 2: Number of days */
					__( '(%1$s/Tag × %2$d Tage)', 'kurs-booking' ),
					Kurs_Booking_Settings::format_price( $variant_price ),
					$selected_days
				);
			}

			$subtotal = $effective_price * $quantity;

			// Track totals for invoice vs manual payment.
			if ( $auto_invoice ) {
				$auto_invoice_total += $subtotal;
			} else {
				$manual_total    += $subtotal;
				$has_manual_items = true;
			}

			$ticket_details[] = array(
				'name'         => $variant_name,
				'quantity'     => $quantity,
				'unit_price'   => $variant_price,
				'subtotal'     => $subtotal,
				// Sprint 4.10: New fields.
				'per_day'       => $per_day,
				'auto_invoice'  => $auto_invoice,
				'hinweis'       => $hinweis,
				'price_label'   => $price_label,
				'kurs_days'     => $kurs_days,
				'selected_days' => $selected_days, // User-selected days for this variant.
			);
		}

		// Deposit calculation - only on auto_invoice items.
		$deposit_enabled = (bool) Kurs_Booking_Kurs::get_meta( $kurs_id, 'deposit_enabled', false );
		$deposit_percent = (int) Kurs_Booking_Kurs::get_meta( $kurs_id, 'deposit_percent', 30 );
		$invoice_total   = $has_manual_items ? $auto_invoice_total : $total_price;
		$deposit_amount  = $deposit_enabled ? ( $invoice_total * $deposit_percent / 100 ) : 0;
		$rest_amount     = $invoice_total - $deposit_amount;

		// MwSt calculation.
		$is_small_business = (bool) get_option( 'kurs_booking_small_business', false );
		$vat_rate          = $is_small_business ? 0 : (float) get_option( 'kurs_booking_vat_rate', 19 );
		// Prices are stored as gross (brutto), calculate net from gross.
		$net_price  = $vat_rate > 0 ? round( $total_price / ( 1 + $vat_rate / 100 ), 2 ) : $total_price;
		$vat_amount = round( $total_price - $net_price, 2 );

		// Payment due date.
		$payment_due_days = (int) get_option( 'kurs_booking_payment_due_days', 14 );
		$booking_timestamp = $buchung ? strtotime( $buchung->post_date ) : time();
		$payment_due_date  = $payment_due_days > 0
			? gmdate( 'd.m.Y', strtotime( "+{$payment_due_days} days", $booking_timestamp ) )
			: __( 'Sofort', 'kurs-booking' );

		// Kurs-specific data.
		$kurs_instructor = Kurs_Booking_Kurs::get_meta( $kurs_id, 'instructor', '' );
		$kurs_horse      = Kurs_Booking_Kurs::get_meta( $kurs_id, 'horse', '' );
		$kurs_notes      = Kurs_Booking_Kurs::get_meta( $kurs_id, 'notes', '' );
		$default_notes   = get_option( 'kurs_booking_default_notes', '' );

		// Company data.
		$company = self::get_company_data();

		// Cancellation policy.
		$cancellation = self::get_cancellation_text();

		return array(
			// Booking.
			'buchung_nummer' => $buchung ? $buchung->post_title : '',
			'buchung_id'     => $buchung_id,
			'buchung_date'   => $buchung ? get_the_date( 'd.m.Y', $buchung ) : '',
			'status'         => Kurs_Booking_Buchung::get_meta( $buchung_id, 'status', 'pending' ),

			// Customer (with fallback for legacy meta keys).
			'customer_name'  => Kurs_Booking_Buchung::get_meta( $buchung_id, 'name', '' )
				?: Kurs_Booking_Buchung::get_meta( $buchung_id, 'customer_name', '' ),
			'customer_email' => self::get_customer_email( $buchung_id ),
			'customer_phone' => Kurs_Booking_Buchung::get_meta( $buchung_id, 'phone', '' )
				?: Kurs_Booking_Buchung::get_meta( $buchung_id, 'customer_phone', '' ),

			// Kurs.
			'kurs_id'         => $kurs_id,
			'kurs_title'      => $kurs ? $kurs->post_title : '',
			'kurs_type'       => Kurs_Booking_Kurs::get_meta( $kurs_id, 'type', 'vor_ort' ),
			'kurs_date'       => self::format_date( Kurs_Booking_Kurs::get_meta( $kurs_id, 'start_date', '' ) ),
			'kurs_start'      => Kurs_Booking_Kurs::get_meta( $kurs_id, 'start_time', '' ),
			'kurs_end'        => Kurs_Booking_Kurs::get_meta( $kurs_id, 'end_time', '' ),
			'kurs_location'   => Kurs_Booking_Kurs::get_meta( $kurs_id, 'location', '' ),
			'kurs_address'    => Kurs_Booking_Kurs::get_meta( $kurs_id, 'address', '' ),
			'kurs_instructor' => $kurs_instructor,
			'kurs_horse'      => $kurs_horse,
			'kurs_notes'      => $kurs_notes,

			// Tickets & Prices.
			'tickets'          => $ticket_details,
			'total_price'      => $total_price,
			'net_price'        => $net_price,
			'vat_amount'       => $vat_amount,
			'vat_rate'         => $vat_rate,
			'is_small_business' => $is_small_business,
			'deposit_enabled'  => $deposit_enabled,
			'deposit_percent'  => $deposit_percent,
			'deposit_amount'   => $deposit_amount,
			// Sprint 4.10: Invoice vs manual payment breakdown.
			'has_manual_items'   => $has_manual_items,
			'auto_invoice_total' => $auto_invoice_total,
			'manual_total'       => $manual_total,
			'invoice_total'      => $invoice_total,
			'kurs_days'          => $kurs_days,
			'rest_amount'      => $rest_amount,
			'currency'         => 'EUR',
			'payment_due_date' => $payment_due_date,
			'default_notes'    => $default_notes,

			// Company.
			'company'        => $company,

			// Legal.
			'cancellation'   => $cancellation,
			'agb_url'        => get_option( 'kurs_booking_agb_url', '' ),
			'privacy_url'    => get_privacy_policy_url(),
		);
	}

	/**
	 * Get company data from settings.
	 *
	 * Sprint 2.6: Uses Settings helper methods for consistent data.
	 *
	 * @return array<string, string> Company data.
	 */
	private static function get_company_data(): array {
		// Get base company data from Settings.
		$company = Kurs_Booking_Settings::get_company_data();
		$bank    = Kurs_Booking_Settings::get_bank_data();

		return array(
			'name'       => $company['name'],
			'address'    => $company['street'],
			'city'       => $company['city'],
			'phone'      => $company['phone'],
			'email'      => $company['email'] ?: get_option( 'admin_email' ),
			'website'    => $company['website'] ?: home_url(),
			'ceo'        => $company['ceo'],
			'tax_number' => $company['tax'],
			'vat_id'     => $company['vat'],
			'iban'       => $bank['iban'],
			'bic'        => $bank['bic'],
			'bank_name'  => $bank['bank_name'],
		);
	}

	/**
	 * Get formatted cancellation policy text.
	 *
	 * Sprint 2.6: Uses Settings helper for consistent cancellation text.
	 *
	 * @return string Cancellation policy HTML.
	 */
	private static function get_cancellation_text(): string {
		// Use Settings class for consistent cancellation text generation.
		$text = Kurs_Booking_Settings::get_cancellation_text();

		// Convert plain text to HTML list format for emails.
		$lines = array_filter( explode( "\n", $text ) );
		$items = array();

		foreach ( $lines as $line ) {
			$line = trim( $line, "• \t" );
			if ( ! empty( $line ) ) {
				$items[] = '<li>' . esc_html( $line ) . '</li>';
			}
		}

		if ( ! empty( $items ) ) {
			return '<ul>' . implode( '', $items ) . '</ul>';
		}

		return wp_kses_post( $text );
	}

	/**
	 * Format date string.
	 *
	 * @param string $date Date string (Y-m-d format).
	 * @return string Formatted date.
	 */
	private static function format_date( string $date ): string {
		if ( empty( $date ) ) {
			return '';
		}

		$timestamp = strtotime( $date );

		if ( false === $timestamp ) {
			return $date;
		}

		return wp_date( 'd.m.Y', $timestamp );
	}

	/**
	 * Format price with currency.
	 *
	 * Sprint 2.6: Uses Settings helper for consistent price formatting.
	 *
	 * @param float $amount Amount.
	 * @return string Formatted price.
	 */
	public static function format_price( float $amount ): string {
		return Kurs_Booking_Settings::format_price( $amount );
	}

	/**
	 * Get email subject (custom or default).
	 *
	 * @param string               $template_key Template key (e.g., 'booking_received').
	 * @param string               $default      Default subject.
	 * @param array<string, mixed> $data         Template data for variable replacement.
	 * @return string Processed subject.
	 */
	private static function get_email_subject( string $template_key, string $default, array $data ): string {
		$custom = Kurs_Booking_Settings::get_custom_email_template( $template_key );

		if ( $custom && ! empty( $custom['subject'] ) ) {
			return Kurs_Booking_Settings::process_email_template_variables( $custom['subject'], $data );
		}

		return $default;
	}

	/**
	 * Render email template.
	 *
	 * @param string               $template Template name (without .php).
	 * @param array<string, mixed> $data     Template data.
	 * @return string Rendered HTML.
	 */
	private static function render_template( string $template, array $data ): string {
		// Check for custom template from database first.
		// Convert template name: 'email-booking-received' -> 'booking_received'.
		$template_key = str_replace( array( 'email-', '-' ), array( '', '_' ), $template );
		$custom       = Kurs_Booking_Settings::get_custom_email_template( $template_key );

		if ( $custom && ! empty( $custom['body'] ) ) {
			// Use custom template from database.
			return Kurs_Booking_Settings::process_email_template_variables( $custom['body'], $data );
		}

		// Standard template lookup.
		$template_path = KURS_BOOKING_PATH . 'templates/' . $template . '.php';

		// Allow theme override.
		$theme_template = locate_template( 'kurs-booking/' . $template . '.php' );

		if ( $theme_template ) {
			$template_path = $theme_template;
		}

		// Allow filter for custom template path.
		$template_path = apply_filters( 'kurs_booking_email_template_path', $template_path, $template );

		if ( ! file_exists( $template_path ) ) {
			// Fallback to plain text.
			return self::render_fallback_template( $template, $data );
		}

		// Extract data for template.
        // phpcs:ignore WordPress.PHP.DontExtract.extract_extract -- Safe, controlled data.
		extract( $data, EXTR_SKIP );

		ob_start();
		include $template_path;
		return ob_get_clean() ?: '';
	}

	/**
	 * Render fallback template when file is missing.
	 *
	 * @param string               $template Template name.
	 * @param array<string, mixed> $data     Template data.
	 * @return string Basic HTML email.
	 */
	private static function render_fallback_template( string $template, array $data ): string {
		$output = '<div style="font-family: Arial, sans-serif; max-width: 600px; margin: 0 auto;">';

		switch ( $template ) {
			case 'email-booking-received':
				$output .= '<h2>' . esc_html__( 'Buchungsanfrage eingegangen', 'kurs-booking' ) . '</h2>';
				$output .= '<p>' . sprintf(
					/* translators: %s: Customer name */
					esc_html__( 'Guten Tag %s,', 'kurs-booking' ),
					esc_html( $data['customer_name'] ?? '' )
				) . '</p>';
				$output .= '<p>' . esc_html__( 'Vielen Dank für Ihre Buchungsanfrage!', 'kurs-booking' ) . '</p>';
				$output .= '<p><strong>' . esc_html__( 'Buchungsnummer:', 'kurs-booking' ) . '</strong> ' . esc_html( $data['buchung_nummer'] ?? '' ) . '</p>';
				$output .= '<p><strong>' . esc_html__( 'Kurs:', 'kurs-booking' ) . '</strong> ' . esc_html( $data['kurs_title'] ?? '' ) . '</p>';

				if ( ! empty( $data['confirm_url'] ) ) {
					$output .= '<p style="margin: 20px 0;"><a href="' . esc_url( $data['confirm_url'] ) . '" style="background: #0073aa; color: #fff; padding: 12px 24px; text-decoration: none; border-radius: 4px;">' . esc_html__( 'E-Mail-Adresse bestätigen', 'kurs-booking' ) . '</a></p>';
				}
				break;

			case 'email-booking-confirmed':
				$output .= '<h2>' . esc_html__( 'Buchungsbestätigung', 'kurs-booking' ) . '</h2>';
				$output .= '<p>' . esc_html__( 'Ihre Buchung wurde erfolgreich bestätigt!', 'kurs-booking' ) . '</p>';
				$output .= '<p><strong>' . esc_html__( 'Buchungsnummer:', 'kurs-booking' ) . '</strong> ' . esc_html( $data['buchung_nummer'] ?? '' ) . '</p>';
				$output .= '<p><strong>' . esc_html__( 'Kurs:', 'kurs-booking' ) . '</strong> ' . esc_html( $data['kurs_title'] ?? '' ) . '</p>';
				$output .= '<p><strong>' . esc_html__( 'Datum:', 'kurs-booking' ) . '</strong> ' . esc_html( $data['kurs_date'] ?? '' ) . '</p>';
				$output .= '<p><strong>' . esc_html__( 'Gesamtpreis:', 'kurs-booking' ) . '</strong> ' . self::format_price( $data['total_price'] ?? 0 ) . '</p>';

				// Add cancellation link.
				if ( ! empty( $data['cancel_url'] ) ) {
					$output .= '<hr style="margin: 20px 0; border: none; border-top: 1px solid #ddd;">';
					$output .= '<p style="font-size: 12px; color: #666;">' . esc_html__( 'Stornierung:', 'kurs-booking' ) . ' ';
					$output .= '<a href="' . esc_url( $data['cancel_url'] ) . '">' . esc_html__( 'Buchung stornieren', 'kurs-booking' ) . '</a></p>';
				}
				break;

			case 'email-cancellation-confirmation':
				$output .= '<h2>' . esc_html__( 'Stornierungsbestätigung', 'kurs-booking' ) . '</h2>';
				$output .= '<p>' . sprintf(
					/* translators: %s: Customer name */
					esc_html__( 'Guten Tag %s,', 'kurs-booking' ),
					esc_html( $data['customer_name'] ?? '' )
				) . '</p>';
				$output .= '<p>' . esc_html__( 'Ihre Buchung wurde erfolgreich storniert.', 'kurs-booking' ) . '</p>';
				$output .= '<p><strong>' . esc_html__( 'Buchungsnummer:', 'kurs-booking' ) . '</strong> ' . esc_html( $data['buchung_nummer'] ?? '' ) . '</p>';
				$output .= '<p><strong>' . esc_html__( 'Kurs:', 'kurs-booking' ) . '</strong> ' . esc_html( $data['kurs_title'] ?? '' ) . '</p>';
				$output .= '<p><strong>' . esc_html__( 'Storniert am:', 'kurs-booking' ) . '</strong> ' . esc_html( $data['cancel_date'] ?? '' ) . '</p>';

				// Show refund info.
				if ( isset( $data['cancel_refund_amount'] ) ) {
					$output .= '<div style="background: #f8f9fa; padding: 15px; border-radius: 4px; margin: 20px 0;">';
					$output .= '<p style="margin: 5px 0;"><strong>' . esc_html__( 'Ursprünglicher Betrag:', 'kurs-booking' ) . '</strong> ' . self::format_price( $data['total_price'] ?? 0 ) . '</p>';
					$output .= '<p style="margin: 5px 0;"><strong>' . esc_html__( 'Stornogebühr:', 'kurs-booking' ) . '</strong> ' . self::format_price( $data['cancel_fee_amount'] ?? 0 ) . ' (' . esc_html( $data['cancel_fee_percent'] ?? 0 ) . '%)</p>';
					$output .= '<p style="margin: 5px 0; font-size: 1.1em;"><strong>' . esc_html__( 'Rückerstattung:', 'kurs-booking' ) . '</strong> ' . self::format_price( $data['cancel_refund_amount'] ?? 0 ) . '</p>';
					$output .= '</div>';

					if ( ( $data['cancel_refund_amount'] ?? 0 ) > 0 ) {
						$output .= '<p>' . esc_html__( 'Die Rückerstattung wird auf das bei der Buchung verwendete Zahlungsmittel erfolgen.', 'kurs-booking' ) . '</p>';
					}
				}
				break;

			case 'email-admin-cancellation':
				$output .= '<h2 style="color: #dc3545;">' . esc_html__( 'Buchung storniert', 'kurs-booking' ) . '</h2>';
				$output .= '<p><strong>' . esc_html__( 'Buchungsnummer:', 'kurs-booking' ) . '</strong> ' . esc_html( $data['buchung_nummer'] ?? '' ) . '</p>';
				$output .= '<p><strong>' . esc_html__( 'Kurs:', 'kurs-booking' ) . '</strong> ' . esc_html( $data['kurs_title'] ?? '' ) . '</p>';
				$output .= '<p><strong>' . esc_html__( 'Kunde:', 'kurs-booking' ) . '</strong> ' . esc_html( $data['customer_name'] ?? '' ) . ' (' . esc_html( $data['customer_email'] ?? '' ) . ')</p>';
				$output .= '<p><strong>' . esc_html__( 'Storniert am:', 'kurs-booking' ) . '</strong> ' . esc_html( $data['cancel_date'] ?? '' ) . '</p>';

				// Show financial details.
				$output .= '<div style="background: #fff3cd; padding: 15px; border-radius: 4px; margin: 20px 0;">';
				$output .= '<p style="margin: 5px 0;"><strong>' . esc_html__( 'Buchungsbetrag:', 'kurs-booking' ) . '</strong> ' . self::format_price( $data['total_price'] ?? 0 ) . '</p>';
				$output .= '<p style="margin: 5px 0;"><strong>' . esc_html__( 'Stornogebühr:', 'kurs-booking' ) . '</strong> ' . self::format_price( $data['cancel_fee_amount'] ?? 0 ) . ' (' . esc_html( $data['cancel_fee_percent'] ?? 0 ) . '%)</p>';
				$output .= '<p style="margin: 5px 0;"><strong>' . esc_html__( 'Zu erstatten:', 'kurs-booking' ) . '</strong> ' . self::format_price( $data['cancel_refund_amount'] ?? 0 ) . '</p>';
				$output .= '<p style="margin: 5px 0;"><strong>' . esc_html__( 'Grund:', 'kurs-booking' ) . '</strong> ' . esc_html( $data['cancel_fee_reason'] ?? '' ) . '</p>';
				if ( ! empty( $data['cancel_notes'] ) ) {
					$output .= '<p style="margin: 5px 0;"><strong>' . esc_html__( 'Notizen:', 'kurs-booking' ) . '</strong> ' . esc_html( $data['cancel_notes'] ) . '</p>';
				}
				$output .= '</div>';

				if ( ! empty( $data['edit_url'] ) ) {
					$output .= '<p><a href="' . esc_url( $data['edit_url'] ) . '" style="background: #0073aa; color: #fff; padding: 10px 20px; text-decoration: none; border-radius: 4px; display: inline-block;">' . esc_html__( 'Buchung anzeigen', 'kurs-booking' ) . '</a></p>';
				}
				break;

			default:
				$output .= '<p>' . esc_html__( 'Buchungsinformation', 'kurs-booking' ) . '</p>';
		}

		// Add footer.
		if ( ! empty( $data['company'] ) ) {
			$company = $data['company'];
			$output .= '<hr style="margin: 30px 0; border: none; border-top: 1px solid #ddd;">';
			$output .= '<p style="font-size: 12px; color: #666;">';
			$output .= esc_html( $company['name'] ?? '' ) . '<br>';
			$output .= esc_html( $company['address'] ?? '' ) . '<br>';
			$output .= esc_html( $company['zip'] ?? '' ) . ' ' . esc_html( $company['city'] ?? '' ) . '<br>';
			$output .= '</p>';
		}

		$output .= '</div>';

		return $output;
	}

	/**
	 * Get the email logo URL.
	 *
	 * Checks for custom logo in settings, falls back to site logo.
	 *
	 * @return string Logo URL or empty string.
	 */
	private static function get_email_logo_url(): string {
		// 1. Check for custom email logo in plugin settings.
		$custom_logo_id = get_option( 'kurs_booking_email_logo', 0 );
		if ( $custom_logo_id ) {
			$logo_url = wp_get_attachment_image_url( (int) $custom_logo_id, 'medium' );
			if ( $logo_url ) {
				return $logo_url;
			}
		}

		// 2. Check for company logo in plugin settings.
		$company_logo_id = get_option( 'kurs_booking_company_logo', 0 );
		if ( $company_logo_id ) {
			$logo_url = wp_get_attachment_image_url( (int) $company_logo_id, 'medium' );
			if ( $logo_url ) {
				return $logo_url;
			}
		}

		// 3. Fall back to site custom logo.
		$custom_logo_id = get_theme_mod( 'custom_logo' );
		if ( $custom_logo_id ) {
			$logo_url = wp_get_attachment_image_url( (int) $custom_logo_id, 'medium' );
			if ( $logo_url ) {
				return $logo_url;
			}
		}

		return '';
	}

	/**
	 * Send email using wp_mail.
	 *
	 * @param string $to      Recipient email.
	 * @param string $subject Email subject.
	 * @param string $body    Email body (HTML).
	 * @return bool True if sent.
	 */
	private static function send( string $to, string $subject, string $body ): bool {
		// Get company info for header.
		$company_name = get_option( 'kurs_booking_company_name', '' );
		$logo_url     = self::get_email_logo_url();
		$primary_color = '#00868b'; // Teal - matches theme.

		// Build logo/header section.
		$header_html = '';
		if ( $logo_url ) {
			$header_html = '
			<div style="text-align: center; padding: 30px 20px; background-color: ' . esc_attr( $primary_color ) . ';">
				<img src="' . esc_url( $logo_url ) . '" alt="' . esc_attr( $company_name ) . '" style="max-width: 200px; max-height: 80px; height: auto;">
			</div>';
		} elseif ( $company_name ) {
			$header_html = '
			<div style="text-align: center; padding: 30px 20px; background-color: ' . esc_attr( $primary_color ) . ';">
				<h1 style="margin: 0; color: #ffffff; font-size: 28px; font-weight: 600;">' . esc_html( $company_name ) . '</h1>
			</div>';
		}

		// Build footer.
		$company_website = get_option( 'kurs_booking_company_website', '' );
		$company_email   = get_option( 'kurs_booking_email_from_address', '' );
		$company_phone   = get_option( 'kurs_booking_company_phone', '' );

		$footer_parts = array();
		if ( $company_name ) {
			$footer_parts[] = esc_html( $company_name );
		}
		if ( $company_email ) {
			$footer_parts[] = '<a href="mailto:' . esc_attr( $company_email ) . '" style="color: #666666;">' . esc_html( $company_email ) . '</a>';
		}
		if ( $company_phone ) {
			$footer_parts[] = esc_html( $company_phone );
		}
		if ( $company_website ) {
			$footer_parts[] = '<a href="' . esc_url( $company_website ) . '" style="color: #666666;">' . esc_html( preg_replace( '#^https?://#', '', $company_website ) ) . '</a>';
		}

		$footer_html = '';
		if ( ! empty( $footer_parts ) ) {
			$footer_html = '
			<div style="text-align: center; padding: 20px; border-top: 1px solid #e0e0e0; margin-top: 30px;">
				<p style="margin: 0; font-size: 13px; color: #666666;">' . implode( ' | ', $footer_parts ) . '</p>
			</div>';
		}

		// Wrap body in HTML structure with email-safe styling.
		$html = '<!DOCTYPE html>
<html lang="de">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <title>' . esc_html( $subject ) . '</title>
    <!--[if mso]>
    <style type="text/css">
        body, table, td {font-family: Arial, sans-serif !important;}
    </style>
    <![endif]-->
</head>
<body style="margin: 0; padding: 0; background-color: #f5f5f5; font-family: Arial, sans-serif; -webkit-font-smoothing: antialiased;">
    <table role="presentation" width="100%" cellpadding="0" cellspacing="0" style="background-color: #f5f5f5;">
        <tr>
            <td align="center" style="padding: 20px 10px;">
                <table role="presentation" width="600" cellpadding="0" cellspacing="0" style="max-width: 600px; width: 100%; background-color: #ffffff; border-radius: 8px; overflow: hidden; box-shadow: 0 2px 8px rgba(0,0,0,0.1);">
                    <!-- Header with Logo -->
                    <tr>
                        <td>' . $header_html . '</td>
                    </tr>
                    <!-- Email Body -->
                    <tr>
                        <td style="padding: 30px 40px; font-size: 16px; line-height: 1.6; color: #333333;">
                            ' . $body . '
                        </td>
                    </tr>
                    <!-- Footer -->
                    <tr>
                        <td>' . $footer_html . '</td>
                    </tr>
                </table>
            </td>
        </tr>
    </table>
</body>
</html>';

		$headers = array(
			'Content-Type: text/html; charset=UTF-8',
		);

		// Sprint 2.6: Add reply-to header using correct option key.
		$reply_to = get_option( 'kurs_booking_email_from_address', '' );

		if ( ! empty( $reply_to ) ) {
			$headers[] = 'Reply-To: ' . sanitize_email( $reply_to );
		}

		// Sprint 2.6: Add BCC to admin if enabled.
		$booking_settings = Kurs_Booking_Settings::get_booking_settings();
		if ( $booking_settings['bcc_admin'] && ! empty( $booking_settings['admin_email'] ) ) {
			$headers[] = 'Bcc: ' . sanitize_email( $booking_settings['admin_email'] );
		}

		// Allow filtering.
		$headers = apply_filters( 'kurs_booking_email_headers', $headers, $to, $subject );

		// Log email in debug mode.
		if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) {
			error_log( sprintf( 'Kurs Booking Email: To=%s, Subject=%s', $to, $subject ) );
		}

		return wp_mail( $to, $subject, $html, $headers );
	}
}
