<?php
/**
 * Journey REST API Controller
 *
 * @package EDD\Pro\CartRecovery\REST\Controllers
 * @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\REST\Controllers;

use EDD\Pro\CartRecovery\Journey\Repository;
use WP_REST_Server;
use WP_REST_Request;
use WP_REST_Response;
use WP_Error;

// Exit if accessed directly.
defined( 'ABSPATH' ) || exit;

/**
 * Journey REST API Controller class.
 *
 * @since 3.6.5
 */
class Journey {

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

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

	/**
	 * Checks if a given request has access to read journey data.
	 *
	 * @since 3.6.5
	 * @param WP_REST_Request $request Full data about the request.
	 * @return true|WP_Error True if the request has read access, WP_Error object otherwise.
	 */
	public function get_items_permissions_check( $request ) {
		if ( ! current_user_can( 'manage_shop_settings' ) ) {
			return new WP_Error(
				'rest_forbidden',
				__( 'Sorry, you are not allowed to access journey data.', 'easy-digital-downloads' ),
				array( 'status' => 403 )
			);
		}

		return true;
	}

	/**
	 * Gets journey events for a specific cart.
	 *
	 * @since 3.6.5
	 * @param WP_REST_Request $request Full data about the request.
	 * @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure.
	 */
	public function get_cart_journey( $request ) {
		$cart_id = absint( $request['cart_id'] );

		if ( ! $cart_id ) {
			return new WP_Error(
				'invalid_cart_id',
				__( 'Invalid cart ID.', 'easy-digital-downloads' ),
				array( 'status' => 400 )
			);
		}

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

		if ( empty( $events ) ) {
			return new WP_REST_Response(
				array(
					'cart_id' => $cart_id,
					'events'  => array(),
					'message' => __( 'No journey events found for this cart.', 'easy-digital-downloads' ),
				),
				200
			);
		}

		// Format events for response.
		$formatted_events = array();
		foreach ( $events as $event ) {
			$formatted_events[] = $this->prepare_item_for_response( $event, $request );
		}

		return new WP_REST_Response(
			array(
				'cart_id' => $cart_id,
				'events'  => $formatted_events,
			),
			200
		);
	}

	/**
	 * Gets funnel metrics for a date range.
	 *
	 * @since 3.6.5
	 * @param WP_REST_Request $request Full data about the request.
	 * @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure.
	 */
	public function get_funnel_metrics( $request ) {
		$start_date = ! empty( $request['start_date'] ) ? sanitize_text_field( $request['start_date'] ) : '';
		$end_date   = ! empty( $request['end_date'] ) ? sanitize_text_field( $request['end_date'] ) : '';

		$metrics = $this->repository->get_funnel_metrics( $start_date, $end_date );

		return new WP_REST_Response( $metrics, 200 );
	}

	/**
	 * Gets average timing metrics between events.
	 *
	 * @since 3.6.5
	 * @param WP_REST_Request $request Full data about the request.
	 * @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure.
	 */
	public function get_timing_metrics( $request ) {
		$from_event = sanitize_text_field( $request['from_event'] );
		$to_event   = sanitize_text_field( $request['to_event'] );
		$start_date = ! empty( $request['start_date'] ) ? sanitize_text_field( $request['start_date'] ) : '';
		$end_date   = ! empty( $request['end_date'] ) ? sanitize_text_field( $request['end_date'] ) : '';

		$avg_seconds = $this->repository->get_average_time_between_events(
			$from_event,
			$to_event,
			$start_date,
			$end_date
		);

		// Convert seconds to human-readable format.
		$hours   = floor( $avg_seconds / 3600 );
		$minutes = floor( ( $avg_seconds % 3600 ) / 60 );
		$seconds = $avg_seconds % 60;

		return new WP_REST_Response(
			array(
				'from_event'       => $from_event,
				'to_event'         => $to_event,
				'average_seconds'  => $avg_seconds,
				'average_human'    => sprintf( '%dh %dm %ds', $hours, $minutes, $seconds ),
			),
			200
		);
	}

	/**
	 * Prepares a single journey event for response.
	 *
	 * @since 3.6.5
	 * @param object          $event   Journey event object.
	 * @param WP_REST_Request $request Request object.
	 * @return array Formatted event data.
	 */
	private function prepare_item_for_response( $event, $request ) {
		return array(
			'id'           => (int) $event->id,
			'cart_id'      => (int) $event->cart_id,
			'email_id'     => ! empty( $event->email_id ) ? (int) $event->email_id : null,
			'event_type'   => $event->event_type,
			'event_data'   => ! empty( $event->event_data ) ? json_decode( $event->event_data, true ) : null,
			'user_agent'   => $event->user_agent,
			'ip_address'   => $event->ip_address,
			'date_created' => $event->date_created,
			'time_ago'     => human_time_diff( strtotime( $event->date_created ) ),
		);
	}
}
