<?php
/**
 * Rental order: persists rental dates on the order line item using HPOS-safe
 * WC_Order_Item methods, and displays them in admin order detail, order emails,
 * and the customer "thank you" / account views.
 *
 * @package WooEquipmentRental
 */

declare( strict_types=1 );

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

/**
 * Class WCRent_Rental_Order
 */
class WCRent_Rental_Order {

	// -----------------------------------------------------------------------
	// Initialisation
	// -----------------------------------------------------------------------

	/**
	 * Registers all hooks.
	 */
	public static function init(): void {
		add_action(
			'woocommerce_checkout_create_order_line_item',
			array( self::class, 'save_line_item_meta' ),
			10,
			4
		);

		add_action(
			'woocommerce_after_order_itemmeta',
			array( self::class, 'display_in_admin_order' ),
			10,
			3
		);

		add_filter(
			'woocommerce_hidden_order_itemmeta',
			array( self::class, 'hide_raw_admin_item_meta' )
		);

		add_action(
			'woocommerce_order_item_meta_end',
			array( self::class, 'display_in_order_meta' ),
			10,
			3
		);
	}

	// -----------------------------------------------------------------------
	// Line item persistence
	// -----------------------------------------------------------------------

	/**
	 * Copies rental start, end, and duration from the cart item into the
	 * order line item using HPOS-safe $item->add_meta_data().
	 *
	 * @param WC_Order_Item_Product $item          Line item.
	 * @param string                $cart_item_key Cart item hash.
	 * @param array<string, mixed>  $cart_item     Cart item data.
	 * @param WC_Order              $order         Parent order.
	 */
	public static function save_line_item_meta(
		WC_Order_Item_Product $item,
		string $cart_item_key,
		array $cart_item,
		WC_Order $order
	): void {
		if ( empty( $cart_item['rental_start'] ) ) {
			return;
		}

		$start = sanitize_text_field( $cart_item['rental_start'] );
		$end   = sanitize_text_field( $cart_item['rental_end'] ?? '' );
		$days  = absint( $cart_item['rental_days'] ?? 0 );

		// Using add_meta_data() is the HPOS-safe equivalent of add_order_item_meta().
		$item->add_meta_data( '_rental_start', $start, true );
		$item->add_meta_data( '_rental_end', $end, true );
		$item->add_meta_data( '_rental_days', $days, true );

		if ( ! empty( $cart_item['rental_start_time'] ) ) {
			$item->add_meta_data( '_rental_start_time', sanitize_text_field( $cart_item['rental_start_time'] ), true );
			$item->add_meta_data( '_rental_end_time', sanitize_text_field( $cart_item['rental_end_time'] ?? '' ), true );
		}
		if ( isset( $cart_item['rental_hours'] ) ) {
			$item->add_meta_data( '_rental_hours', (float) $cart_item['rental_hours'], true );
		}
	}

	// -----------------------------------------------------------------------
	// Admin display
	// -----------------------------------------------------------------------

	/**
	 * Hides the raw `_rental_*` line-item meta from the admin order screen.
	 *
	 * The admin item template renders meta with an empty hide-prefix, so it
	 * lists underscore-prefixed keys verbatim. {@see display_in_admin_order()}
	 * already prints them with readable labels, so without this the merchant
	 * sees each value twice.
	 *
	 * @param array<int, string> $hidden Meta keys WooCommerce should not display.
	 * @return array<int, string>
	 */
	public static function hide_raw_admin_item_meta( array $hidden ): array {
		return array_merge(
			$hidden,
			array(
				'_rental_start',
				'_rental_end',
				'_rental_days',
				'_rental_start_time',
				'_rental_end_time',
				'_rental_hours',
			)
		);
	}

	/**
	 * Renders rental dates below the line item inside the WP Admin order
	 * detail screen.
	 *
	 * Hooked to `woocommerce_after_order_itemmeta`, which is the admin
	 * item template's own extension point. (`woocommerce_after_order_item_name`
	 * is a front-end hook and never fires here.)
	 *
	 * @param int           $item_id Order line item ID.
	 * @param WC_Order_Item $item    Order line item.
	 * @param mixed         $product Product for the line item, or false.
	 */
	public static function display_in_admin_order(
		int $item_id,
		$item,
		$product = null
	): void {
		unset( $item_id, $product );

		if ( ! $item instanceof WC_Order_Item ) {
			return;
		}

		$start = $item->get_meta( '_rental_start' );
		$end   = $item->get_meta( '_rental_end' );
		$days  = $item->get_meta( '_rental_days' );

		if ( ! $start || ! $end ) {
			return;
		}

		echo '<div class="wcrent-rental-meta-wrap wc-order-item-rental">';
		echo '<dl class="wcrent-rental-meta">';
		printf( '<dt>%s</dt><dd>%s</dd>', esc_html__( 'Rental start', 'harbor-equipment-rental-for-woocommerce' ), esc_html( WCRent_Utils::format_date( $start ) ) );
		printf( '<dt>%s</dt><dd>%s</dd>', esc_html__( 'Return by', 'harbor-equipment-rental-for-woocommerce' ), esc_html( WCRent_Utils::format_date( $end ) ) );
		printf( '<dt>%s</dt><dd>%s</dd>', esc_html__( 'Rental days', 'harbor-equipment-rental-for-woocommerce' ), esc_html( (string) $days ) );

		$start_time = $item->get_meta( '_rental_start_time' );
		$end_time   = $item->get_meta( '_rental_end_time' );
		$hours      = $item->get_meta( '_rental_hours' );
		if ( $start_time && $end_time ) {
			printf(
				'<dt>%s</dt><dd>%s</dd>',
				esc_html__( 'Rental time', 'harbor-equipment-rental-for-woocommerce' ),
				esc_html( $start_time . ' – ' . $end_time . ( $hours ? ' (' . (float) $hours . ' ' . _n( 'hour', 'hours', (float) $hours, 'harbor-equipment-rental-for-woocommerce' ) . ')' : '' ) )
			);
		}

		echo '</dl>';
		echo '</div>';
	}

	// -----------------------------------------------------------------------
	// Email / frontend display
	// -----------------------------------------------------------------------

	/**
	 * Appends rental dates to line item meta on the order confirmation page,
	 * customer account "view order" screen, and order emails.
	 *
	 * Hooks into `woocommerce_order_item_meta_end` which fires for both
	 * frontend order views and transactional emails.
	 *
	 * @param int           $item_id Order item ID.
	 * @param WC_Order_Item $item    Order line item.
	 * @param WC_Order      $order   Parent order.
	 */
	public static function display_in_order_meta(
		int $item_id,
		WC_Order_Item $item,
		WC_Order $order
	): void {
		// Only act on product line items.
		if ( ! ( $item instanceof WC_Order_Item_Product ) ) {
			return;
		}

		$start = $item->get_meta( '_rental_start' );
		$end   = $item->get_meta( '_rental_end' );
		$days  = $item->get_meta( '_rental_days' );

		if ( ! $start || ! $end ) {
			return;
		}

		$is_email = doing_action( 'woocommerce_email_order_details' );

		$start_formatted = esc_html( WCRent_Utils::format_date( $start ) );
		$end_formatted   = esc_html( WCRent_Utils::format_date( $end ) );

		if ( $is_email ) {
			printf(
				'<p class="wcrent-rental-dates">
					<strong>%1$s:</strong> %2$s &ndash; %3$s (%4$s)
				</p>',
				esc_html__( 'Rental period', 'harbor-equipment-rental-for-woocommerce' ),
				$start_formatted, // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- pre-escaped via esc_html()
				$end_formatted,   // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- pre-escaped via esc_html()
				sprintf(
					esc_html(
						/* translators: %d: number of days */
						_n( '%d day', '%d days', (int) $days, 'harbor-equipment-rental-for-woocommerce' )
					),
					(int) $days
				)
			);

			$start_time_meta = $item->get_meta( '_rental_start_time' );
			$end_time_meta   = $item->get_meta( '_rental_end_time' );
			if ( $start_time_meta && $end_time_meta ) {
				printf(
					'<p class="wcrent-rental-time">
						<strong>%1$s:</strong> %2$s &ndash; %3$s
					</p>',
					esc_html__( 'Rental time', 'harbor-equipment-rental-for-woocommerce' ),
					esc_html( $start_time_meta ),
					esc_html( $end_time_meta )
				);
			}
		} else {
			$start_time_meta = $item->get_meta( '_rental_start_time' );
			$end_time_meta   = $item->get_meta( '_rental_end_time' );

			echo '<dl class="wcrent-rental-dates">';
			printf(
				'<dt>%1$s</dt>
				<dd>%2$s</dd>
				<dt>%3$s</dt>
				<dd>%4$s</dd>
				<dt>%5$s</dt>
				<dd>%6$s</dd>',
				esc_html__( 'Rental start', 'harbor-equipment-rental-for-woocommerce' ),
				$start_formatted, // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- pre-escaped via esc_html()
				esc_html__( 'Rental end', 'harbor-equipment-rental-for-woocommerce' ),
				$end_formatted,   // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- pre-escaped via esc_html()
				esc_html__( 'Rental days', 'harbor-equipment-rental-for-woocommerce' ),
				esc_html( (string) $days )
			);

			if ( $start_time_meta && $end_time_meta ) {
				printf(
					'<dt>%1$s</dt>
					<dd>%2$s &ndash; %3$s</dd>',
					esc_html__( 'Rental time', 'harbor-equipment-rental-for-woocommerce' ),
					esc_html( $start_time_meta ),
					esc_html( $end_time_meta )
				);
			}
			echo '</dl>';
		}
	}
}
