<?php
/**
 * Tracking controller for referral and event tracking.
 *
 * @package Awesomemotive\Rewardswp\Controllers
 * @since 1.0.0
 */

namespace Awesomemotive\Rewardswp\Controllers;

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

use Awesomemotive\Rewardswp\Helpers\CookieHelper;
use Awesomemotive\Rewardswp\Helpers\OptionsHelper;
use Awesomemotive\Rewardswp\Services\AssetsService;
use Awesomemotive\Rewardswp\Services\TrackingService;
use Awesomemotive\Rewardswp\Settings\Options\Referrals\CookieExpirationOption;
use Awesomemotive\Rewardswp\Settings\Options\Referrals\ReferralVariableOption;
use Awesomemotive\Rewardswp\Interfaces\ControllerInterface;
use function Awesomemotive\Rewardswp\Helpers\frontend_ajax_url;
use function Awesomemotive\Rewardswp\Helpers\get_option_value;

class TrackingController implements ControllerInterface {

	/**
	 * AJAX nonce for tracking requests.
	 *
	 * @since 1.0.0
	 */
	const AJAX_NONCE = 'rewardswp_tracking_nonce';

	/**
	 * Frontend script handle for tracking.
	 *
	 * @since 1.0.0
	 */
	const SCRIPT_HANDLE = 'rewardswp-tracking';

	/**
	 * Tracking service instance.
	 *
	 * @since 1.0.0
	 *
	 * @var TrackingService
	 */
	private TrackingService $tracking_service;

	/**
	 * Assets service instance.
	 *
	 * @since 1.0.0
	 *
	 * @var AssetsService
	 */
	private AssetsService $assets_service;

	/**
	 * Cookie helper instance.
	 *
	 * @since 1.0.0
	 *
	 * @var CookieHelper
	 */
	private CookieHelper $cookie_helper;

	/**
	 * Constructor
	 *
	 * @since 1.0.0
	 *
	 * @param TrackingService $tracking_service
	 * @param AssetsService   $assets_service
	 * @param CookieHelper    $cookie_helper
	 */
	public function __construct(
		TrackingService $tracking_service,
		AssetsService $assets_service,
		CookieHelper $cookie_helper
	) {
		$this->tracking_service = $tracking_service;
		$this->assets_service   = $assets_service;
		$this->cookie_helper    = $cookie_helper;
	}

	/**
	 * Initialize tracking by adding the necessary scripts.
	 *
	 * @since 1.0.0
	 *
	 * @return void
	 */
	public function init(): void {
		add_action( 'wp_ajax_nopriv_rewardswp_track_visit', [ $this, 'ajax_track_visit' ] );
		add_action( 'wp_ajax_rewardswp_track_visit', [ $this, 'ajax_track_visit' ] );

		// Bail if the referral var is not present in the URL.
		if ( ! filter_input( INPUT_GET, get_option_value( ReferralVariableOption::class ) ) ) {
			return;
		}

		add_action( 'wp_enqueue_scripts', [ $this, 'enqueue_scripts' ] );
	}

	/**
	 * Enqueue necessary scripts.
	 *
	 * @since 1.0.0
	 *
	 * @return void
	 */
	public function enqueue_scripts(): void {
		$this->assets_service->enqueue_script( self::SCRIPT_HANDLE, 'tracking.js' );

		$data = wp_json_encode(
			[
				'ajaxUrl'              => frontend_ajax_url(),
				'nonce'                => wp_create_nonce( self::AJAX_NONCE ),
				'visitIdCookieName'    => $this->tracking_service::VISIT_ID_COOKIE_NAME,
				'advocateIdCookieName' => $this->tracking_service::ADVOCATE_ID_COOKIE_NAME,
				'cookieExpiration'     => get_option_value( CookieExpirationOption::class ),
				'cookiePath'           => $this->cookie_helper->get_cookie_path(),
				'cookieDomain'         => $this->cookie_helper->get_cookie_domain(),
				'referralSlug'         => get_option_value( ReferralVariableOption::class ),
			]
		);

		wp_add_inline_script(
			self::SCRIPT_HANDLE,
			"const rewardswpTrackingVars={$data}",
			'before'
		);
	}

	/**
	 * Tracking ajax handler.
	 *
	 * @since 1.0.0
	 *
	 * @return void
	 */
	public function ajax_track_visit(): void {
		check_ajax_referer( self::AJAX_NONCE );

		$referral_code = sanitize_text_field( filter_input( INPUT_POST, 'referral_code' ) );

		if ( empty( $referral_code ) ) {
			return; // Bail if there's nothing to track.
		}

		$event = $this->tracking_service->track_visit(
			$referral_code,
			sanitize_text_field( filter_input( INPUT_POST, 'referrer_url' ) ),
			sanitize_text_field( filter_input( INPUT_POST, 'landing_url' ) )
		);

		// Attempt to create the event and return with the ID or 0 in case nothing was tracked.
		wp_send_json_success(
			[
				'event_id'    => $event->id ?? 0,
				'advocate_id' => $event->advocate_id ?? 0,
			]
		);

		wp_die();
	}
}
