<?php
/**
 * Email Tracking Repository.
 *
 * Handles database operations for email tracking (opens, clicks, bounces).
 *
 * @package EDD\Pro\CartRecovery\Tracking
 * @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\Tracking;

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

use EDD\Pro\CartRecovery\Database\Queries\RecoveryEmail as EmailQuery;
use EDD\Pro\CartRecovery\Journey\EventLogger;

/**
 * Repository class for email tracking operations.
 *
 * @since 3.6.5
 */
final class Repository {

	/**
	 * Event logger instance.
	 *
	 * @var EventLogger
	 */
	private $event_logger;

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

	/**
	 * Records an email open event.
	 *
	 * Only records the first open event (idempotent).
	 *
	 * @since 3.6.5
	 * @param int $email_id The recovery email ID.
	 * @return bool True if recorded (or already recorded), false on error.
	 */
	public function record_open( int $email_id ): bool {
		if ( $email_id <= 0 ) {
			return false;
		}

		$email_query = new EmailQuery();
		$email       = $email_query->get_item( $email_id );

		if ( ! $email ) {
			edd_debug_log( sprintf( '[EDD ACR Tracking] Cannot record open: email %d not found', $email_id ) );
			return false;
		}

		// Only record if not already opened.
		if ( ! empty( $email->date_opened ) ) {
			return true; // Already recorded, return true (idempotent).
		}

		$updated = $email_query->update_item(
			$email_id,
			array(
				'date_opened'     => edd_get_utc_date_string(),
				'delivery_status' => 'opened',
			)
		);

		if ( $updated ) {
			edd_debug_log( sprintf( '[EDD ACR Tracking] Email %d opened', $email_id ) );
			do_action( 'edd_acr_email_opened', $email_id, $email );

			// Log email_opened journey event.
			if ( ! empty( $email->cart_id ) ) {
				$this->event_logger->log_email_event(
					'email_opened',
					(int) $email->cart_id,
					$email_id
				);
			}
		} else {
			edd_debug_log( sprintf( '[EDD ACR Tracking] Failed to record open for email %d', $email_id ), true );
		}

		return (bool) $updated;
	}

	/**
	 * Records an email click event.
	 *
	 * Only records the first click event (idempotent).
	 *
	 * @since 3.6.5
	 * @param int $email_id The recovery email ID.
	 * @return bool True if recorded (or already recorded), false on error.
	 */
	public function record_click( int $email_id ): bool {
		if ( $email_id <= 0 ) {
			return false;
		}

		$email_query = new EmailQuery();
		$email       = $email_query->get_item( $email_id );

		if ( ! $email ) {
			edd_debug_log( sprintf( '[EDD ACR Tracking] Cannot record click: email %d not found', $email_id ) );
			return false;
		}

		// Only record if not already clicked.
		if ( ! empty( $email->date_clicked ) ) {
			return true; // Already recorded, return true (idempotent).
		}

		$updates = array(
			'date_clicked' => edd_get_utc_date_string(),
		);

		// If email hasn't been opened yet, record this as an open too.
		if ( empty( $email->date_opened ) ) {
			$updates['date_opened'] = edd_get_utc_date_string();
		}

		$updated = $email_query->update_item( $email_id, $updates );

		if ( $updated ) {
			edd_debug_log( sprintf( '[EDD ACR Tracking] Email %d clicked', $email_id ) );
			do_action( 'edd_acr_email_clicked', $email_id, $email );

			// Log email_clicked journey event.
			if ( ! empty( $email->cart_id ) ) {
				$this->event_logger->log_email_event(
					'email_clicked',
					(int) $email->cart_id,
					$email_id
				);
			}
		} else {
			edd_debug_log( sprintf( '[EDD ACR Tracking] Failed to record click for email %d', $email_id ), true );
		}

		return (bool) $updated;
	}
}
