<?php
/**
 * Journey Timeline UI
 *
 * @package EDD\Pro\CartRecovery\Admin\Carts
 * @copyright   Copyright (c) 2026 Sandhills Development, LLC
 * @license     https://opensource.org/licenses/gpl-2.0.php GNU Public License
 * @since   3.6.5
 */

namespace EDD\Pro\CartRecovery\Admin\Carts;

// Exit if accessed directly.
defined( 'ABSPATH' ) || exit;
use EDD\Pro\CartRecovery\Journey\Repository;
use EDD\Pro\CartRecovery\Carts\Cart;

/**
 * Displays a chronological timeline of events for a cart.
 *
 * @since 3.6.5
 */
final class Timeline {

	/**
	 * Cart object.
	 *
	 * @var Cart
	 */
	private $cart;

	/**
	 * Journey repository.
	 *
	 * @var Repository
	 */
	private $repository;

	/**
	 * Constructor.
	 *
	 * @since 3.6.5
	 */
	public function __construct( Cart $cart ) {
		$this->cart       = $cart;
		$this->repository = new Repository();
	}

	/**
	 * Renders the journey timeline for a cart.
	 *
	 * @since 3.6.5
	 * @param int $cart_id The cart ID.
	 * @return void
	 */
	public function render( $cart_id ) {
		$cart_id = absint( $cart_id );
		if ( ! $cart_id ) {
			echo '<p class="edd-acr-empty-message"><em>' . esc_html__( 'Invalid cart ID.', 'easy-digital-downloads' ) . '</em></p>';
			return;
		}

		$events = $this->repository->get_cart_journey( $cart_id );

		if ( empty( $events ) ) {
			echo '<p class="edd-acr-empty-message"><em>' . esc_html__( 'No journey events found for this cart.', 'easy-digital-downloads' ) . '</em></p>';
			return;
		}

		?>
		<div class="edd-acr-journey-timeline">
			<?php foreach ( $events as $event ) : ?>
				<?php $this->render_event( $event ); ?>
			<?php endforeach; ?>
		</div>
		<?php
	}

	/**
	 * Renders a single event in the timeline.
	 *
	 * @since 3.6.5
	 * @param object $event The event object.
	 * @return void
	 */
	private function render_event( $event ) {
		$icon       = $this->get_event_icon( $event->event_type );
		$label      = $this->get_event_label( $event->event_type );
		$time_ago   = human_time_diff( strtotime( $event->date_created ) );
		$event_data = $this->parse_event_data( $event );
		$full_date  = edd_date_i18n( strtotime( $event->date_created ), get_option( 'date_format' ) . ' ' . get_option( 'time_format' ) );

		?>
		<div class="edd-acr-journey-event" data-event-type="<?php echo esc_attr( $event->event_type ); ?>">
			<div class="edd-acr-info-grid">
				<div class="edd-acr-info-row">
					<span class="edd-acr-info-label">
						<span class="dashicons dashicons-<?php echo esc_attr( $icon ); ?>"></span>
						<?php echo esc_html( $label ); ?>
					</span>
					<span class="edd-acr-info-value">
						<abbr title="<?php echo esc_attr( $full_date ); ?>">
							<?php
							/* translators: %s: time ago */
							echo esc_html( sprintf( __( '%s ago', 'easy-digital-downloads' ), $time_ago ) );
							?>
						</abbr>
					</span>
				</div>
				<?php if ( ! empty( $event_data ) || ! empty( $event->user_agent ) || ! empty( $event->ip_address ) ) : ?>
					<?php $this->render_event_details( $event_data, $event ); ?>
				<?php endif; ?>
			</div>
		</div>
		<?php
	}

	/**
	 * Gets the icon for an event type.
	 *
	 * @since 3.6.5
	 * @param string $event_type The event type.
	 * @return string Dashicon name.
	 */
	private function get_event_icon( $event_type ) {
		$icons = array(
			'cart_created'          => 'cart',
			'cart_updated'          => 'update',
			'cart_abandoned'        => 'clock',
			'cart_restored'         => 'backup',
			'cart_expired'          => 'dismiss',
			'cart_converted'        => 'yes-alt',
			'email_scheduled'       => 'calendar-alt',
			'email_sent'            => 'email',
			'email_failed'          => 'warning',
			'email_bounced'         => 'no-alt',
			'email_opened'          => 'visibility',
			'email_clicked'         => 'external',
			'email_converted'       => 'thumbs-up',
			'customer_unsubscribed' => 'no',
			'customer_resubscribed' => 'yes',
			'duplicate_cart_merged' => 'admin-links',
		);

		return $icons[ $event_type ] ?? 'marker';
	}

	/**
	 * Gets the human-readable label for an event type.
	 *
	 * @since 3.6.5
	 * @param string $event_type The event type.
	 * @return string Event label.
	 */
	private function get_event_label( $event_type ) {
		$labels = array(
			'cart_created'          => __( 'Cart Created', 'easy-digital-downloads' ),
			'cart_updated'          => __( 'Cart Updated', 'easy-digital-downloads' ),
			'cart_abandoned'        => __( 'Cart Abandoned', 'easy-digital-downloads' ),
			'cart_restored'         => __( 'Cart Restored', 'easy-digital-downloads' ),
			'cart_expired'          => __( 'Cart Expired', 'easy-digital-downloads' ),
			'cart_converted'        => __( 'Purchase Completed', 'easy-digital-downloads' ),
			'email_scheduled'       => __( 'Recovery Email Scheduled', 'easy-digital-downloads' ),
			'email_sent'            => __( 'Recovery Email Sent', 'easy-digital-downloads' ),
			'email_failed'          => __( 'Email Send Failed', 'easy-digital-downloads' ),
			'email_bounced'         => __( 'Email Bounced', 'easy-digital-downloads' ),
			'email_opened'          => __( 'Email Opened', 'easy-digital-downloads' ),
			'email_clicked'         => __( 'Email Link Clicked', 'easy-digital-downloads' ),
			'email_converted'       => __( 'Converted from Email', 'easy-digital-downloads' ),
			'customer_unsubscribed' => __( 'Customer Unsubscribed', 'easy-digital-downloads' ),
			'customer_resubscribed' => __( 'Customer Resubscribed', 'easy-digital-downloads' ),
			'duplicate_cart_merged' => __( 'Duplicate Cart Merged', 'easy-digital-downloads' ),
		);

		return $labels[ $event_type ] ?? $event_type;
	}

	/**
	 * Parses event data from JSON.
	 *
	 * @since 3.6.5
	 * @param object $event The event object.
	 * @return array Parsed event data.
	 */
	private function parse_event_data( $event ) {
		if ( empty( $event->event_data ) ) {
			return array();
		}

		$data = json_decode( $event->event_data, true );

		return is_array( $data ) ? $data : array();
	}

	/**
	 * Renders event details based on event type and data.
	 *
	 * @since 3.6.5
	 * @param array  $data  Event data.
	 * @param object $event Event object.
	 * @return void
	 */
	private function render_event_details( $data, $event ) {
		$this->render_event_data( $data );

		if ( ! empty( $event->ip_address ) ) {
			?>
			<div class="edd-acr-info-row">
				<span class="edd-acr-info-label"><?php esc_html_e( 'IP Address', 'easy-digital-downloads' ); ?></span>
				<span class="edd-acr-info-value"><?php echo esc_html( $event->ip_address ); ?></span>
			</div>
			<?php
		}

		if ( ! empty( $event->user_agent ) ) {
			?>
			<div class="edd-acr-info-row">
				<span class="edd-acr-info-label"><?php esc_html_e( 'User Agent', 'easy-digital-downloads' ); ?></span>
				<span class="edd-acr-info-value"><code><?php echo esc_html( substr( $event->user_agent, 0, 100 ) ); ?></code></span>
			</div>
			<?php
		}
	}

	/**
	 * Renders event data in a grid.
	 *
	 * @since 3.6.5
	 * @param array $data Event data.
	 * @return void
	 */
	private function render_event_data( array $data ): void {
		if ( empty( array_filter( $data ) ) ) {
			return;
		}
		?>
		<div class="edd-acr-info-row">
			<?php
			foreach ( $data as $key => $value ) {
				if ( empty( $value ) ) {
					continue;
				}
				?>
				<span class="edd-acr-info-label"><?php echo esc_html( $this->format_data_key( $key ) ); ?></span>
				<span class="edd-acr-info-value"><?php echo wp_kses_post( $this->format_data_value( $key, $value ) ); ?></span>
				<?php
			}
			?>
		</div>
		<?php
	}

	/**
	 * Formats a data key for display.
	 *
	 * @since 3.6.5
	 * @param string $key The data key.
	 * @return string Formatted key.
	 */
	private function format_data_key( $key ): string {

		$label = $this->get_labels()[ $key ] ?? '';
		if ( $label ) {
			return $label;
		}

		// Convert snake_case to Title Case.
		$key = str_replace( '_', ' ', $key );

		return ucwords( $key );
	}

	/**
	 * Formats a data value for display.
	 *
	 * @since 3.6.5
	 * @param string $key   The data key.
	 * @param mixed  $value The data value.
	 * @return string Formatted value.
	 */
	private function format_data_value( $key, $value ) {
		// Handle specific keys.
		if ( in_array( $key, array( 'cart_total', 'order_total' ), true ) ) {
			return edd_currency_filter( edd_format_amount( $value ), $this->cart->currency );
		}

		if ( 'order_id' === $key ) {
			$order = edd_get_order( $value );
			if ( $order ) {
				return sprintf(
					'<a href="%s">#%s</a>',
					esc_url(
						edd_get_admin_url(
							array(
								'page' => 'edd-payment-history',
								'view' => 'view-order-details',
								'id'   => $value,
							)
						)
					),
					$order->get_number()
				);
			}
		}

		if ( 'email_id' === $key ) {
			return sprintf( '#%d', $value );
		}

		if ( 'template_id' === $key ) {
			$email = edd_get_email( $value );
			if ( $email ) {
				return $email->get_template()->get_name();
			}

			return esc_html( $value );
		}

		// Default: return as string.
		if ( is_array( $value ) ) {
			return implode( ', ', $value );
		}

		return (string) $value;
	}

	/**
	 * Gets the labels for the event data.
	 *
	 * @since 3.6.5
	 * @return array Labels.
	 */
	private function get_labels(): array {
		return array(
			'email_id'            => __( 'Email ID', 'easy-digital-downloads' ),
			'order_id'            => __( 'Order ID', 'easy-digital-downloads' ),
			'cart_total'          => __( 'Cart Total', 'easy-digital-downloads' ),
			'order_total'         => __( 'Order Total', 'easy-digital-downloads' ),
			'discount_code'       => __( 'Discount Code', 'easy-digital-downloads' ),
			'recovery_token'      => __( 'Recovery Token', 'easy-digital-downloads' ),
			'email_subject'       => __( 'Email Subject', 'easy-digital-downloads' ),
			'email_body'          => __( 'Email Body', 'easy-digital-downloads' ),
			'email_headers'       => __( 'Email Headers', 'easy-digital-downloads' ),
			'email_attachments'   => __( 'Email Attachments', 'easy-digital-downloads' ),
			'email_status'        => __( 'Email Status', 'easy-digital-downloads' ),
			'email_error'         => __( 'Email Error', 'easy-digital-downloads' ),
			'email_error_message' => __( 'Email Error Message', 'easy-digital-downloads' ),
			'template_id'         => __( 'Email', 'easy-digital-downloads' ),
		);
	}
}
