<?php

if ( ! defined( 'ABSPATH' ) ) {
	exit; // Exit if accessed directly
}

require_once plugin_dir_path( dirname( __FILE__ ) ) . 'includes/trait-verfacto-plugin-helper.php';

/**
 * Class responsible for initializing Verfacto tracker and controlls all track events
 */
class Verfacto_Plugin_Event_Tracker {

	use Verfacto_Plugin_Helper;

	/**
	 * The Verfacto tracker id
	 *
	 * @since  1.0.0
	 * @access private
	 * @var $tracker_id Keeps tracker id.
	 */
	private $tracker_id;

	/**
	 * Events tracker constructor register necessary hooks, return void if tracker is not enabled.
	 *
	 * @return void
	 */
	public function __construct() {
		if ( ! $this->is_tracker_enabled() ) {
			return;
		}

		$this->add_hooks();
	}

	/**
	 * Register nessesary hooks, to track variuos events
	 *
	 * @return void
	 */
	private function add_hooks() {

		// Inject Verfacto tracker.
		add_action( 'wp_head', array( $this, 'inject_verfacto_tracker' ) );

		// AddToBasket events.
		add_action( 'woocommerce_add_to_cart', array( $this, 'track_add_to_basket' ), 40, 4 );

		// AddToBasket events then AJAX is enabled
		add_action( 'woocommerce_ajax_added_to_cart', array( $this, 'track_add_to_basket_ajax' ) );

		// GoToCheckoutEvent events.
		add_action( 'woocommerce_after_checkout_form', array( $this, 'track_go_to_checkout' ) );

		// IdentifyUserOnLogin events.
		add_action( 'wp_login', array( $this, 'track_user_login' ) );

		// IdentifyUserOnOrder.
		add_action( 'woocommerce_thankyou', array( $this, 'track_identify' ), 40 );

		add_action( 'wp_footer', array( $this, 'execute_verfacto_tracker' ) );
	}

	/**
	 * Track user log-in event
	 *
	 * @param object $user_login WP user object.
	 * @return void
	 */
	public function track_user_login( $user_login ) {
		set_transient( $user_login, '1', 0 );
	}

	/**
	 * Fire verfacto tracker on user log-in
	 *
	 * @return void
	 */
	public function execute_verfacto_tracker() {
		global $current_user;

		if ( ! is_user_logged_in() ) {
			return;
		}

		if ( ! get_transient( $current_user->user_login ) ) {
			return;
		}
		// phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
		echo '<script> 
		window.onload = function() {
			if (document.readyState !== "loading") {
				window.VerfactoTracker.identify("' . esc_js( $this->tracker_id ) . '", "' . esc_js( sanitize_email( $current_user->user_email ) ) . '");
			}; 
		};
		</script>';

		delete_transient( $current_user->user_login );
	}

	/**
	 * Prints Verfacto tracker code
	 *
	 * @return void
	 */
	public function inject_verfacto_tracker() {
		echo wp_kses(
			$this->get_verfacto_tracker( $this->tracker_id ),
			array(
				'script' => array(
					'src'    => array(),
					'onload' => array(),
					'defer'  => array(),
				),
				'div'    => array(
					'class' => array(),
				),
			)
		);
	}

	/**
	 * Gets the Verfacto tracker snippet.
	 *
	 * @param string $tracker_id the tracker id.
	 * @return string HTML scripts
	 */
	public function get_verfacto_tracker( $tracker_id ) {

		if ( empty( $tracker_id ) ) {
			return '';
		}

		$attributes = array(
			'src'    => esc_html( Verfacto_Plugin::TRACKER_URL ),
			'defer'  => '',
			'onload' => 'window.VerfactoTracker.init("' . esc_js( $tracker_id ) . '")',
		);

		ob_start();

		?>
		<!-- WooCommerce Verfacto Tracker Begin -->
		<script <?php echo self::get_script_attributes( $attributes ); ?> ></script>

		<script>
			document.addEventListener( 'DOMContentLoaded', function() {
				const wc_fragment_holder = document.createElement('div');
				wc_fragment_holder.classList.add('verfacto-tracker-event-placeholder');
				document.body.appendChild(wc_fragment_holder);
			}, false );
		</script>
		<!-- Verfacto Tracker Integration End -->
		<?php

		return ob_get_clean();
	}

	/**
	 * Track add_to_basket event
	 *
	 * @param string $cart_item_key keep cart item key.
	 * @param int    $product_id keep product id.
	 * @param int    $quantity keep item quantity.
	 * @param int    $variation_id keep item variation id.
	 * @return void
	 */
	public function track_add_to_basket( $cart_item_key, $product_id, $quantity, $variation_id ) {
		if ( ! wp_doing_ajax() ) {
			// phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
			echo $this->track_event(
				'add_to_basket',
				$this->get_product(
					sanitize_text_field( wp_unslash( $product_id ) ),
					sanitize_text_field( wp_unslash( $quantity ) ),
					sanitize_text_field( wp_unslash( $variation_id ) )
				)
			);
		}
	}

	/**
	 * Track add_to_basket event on ajax
	 *
	 * @return void
	 */
	public function track_add_to_basket_ajax() {
		if ( 'no' === get_option( 'woocommerce_cart_redirect_after_add' ) && wp_doing_ajax() ) {
			add_filter( 'woocommerce_add_to_cart_fragments', array( $this, 'add_add_to_basket_event_fragment' ) );
		}
	}

	/**
	 * Track go_to_checkout event
	 *
	 * @return void
	 */
	public function track_go_to_checkout() {
		// phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
		echo $this->track_event( 'go_to_checkout' );
	}

	/**
	 * Track identify and place order event on successful order
	 *
	 * @return void
	 */
	public function track_identify() {
		$order_id = absint( get_query_var( 'order-received' ) );

		if ( get_post_type( $order_id ) === 'shop_order' ) {
			$order = wc_get_order( $order_id );

			$customer_email = strtolower( $order->get_billing_email() );

			if ( ! empty( $customer_email ) ) {
				echo '<script> 
				window.onload = function() {
					if (document.readyState !== "loading") { 
						window.VerfactoTracker.identify("' . esc_js( $this->tracker_id ) . '", "' . esc_js( sanitize_email( $customer_email ) ) . '");
						window.VerfactoTracker.track("' . esc_js( $this->tracker_id ) . '", "place_order");
					}; 
				};
				</script>';
			} else {
				echo '<script> 
				window.onload = function() {
					if (document.readyState !== "loading") {
						window.VerfactoTracker.track("' . esc_js( $this->tracker_id ) . '", "place_order");
					}; 
				};
				</script>';
			}
		}
	}

	/**
	 * General events tracking method
	 *
	 * @param string $event_name event to track.
	 * @param array  $data event data.
	 * @param bool   $track_ajax is event ajax or not.
	 *
	 * @return string of HTML
	 */
	public function track_event( $event_name, $data = null, $track_ajax = false ) {
		$script = '<script> %s
			window.VerfactoTracker.track("%s", "%s", %s);
        %s</script>';

		if ( ! empty( $data ) ) {
			if ( is_array( $data ) ) {
				$data = wp_json_encode( $data );
			} else {
				$data = "'" . esc_js( wp_unslash( $data ) ) . "'";
			}
		} else {
			$data = '{}';
		}

		return sprintf(
			$script,
			( ! $track_ajax ) ? 'window.onload = function() { if (document.readyState !== "loading") { ' : '',
			esc_js( $this->tracker_id ),
			esc_js( $event_name ),
			$data,
			( ! $track_ajax ) ? '} };' : ''
		);

	}

	/**
	 * Insert fragment to Woocommerce add to basket response
	 *
	 * @param string $fragments fragments of response.
	 * @return array of fragments
	 */
	public function add_add_to_basket_event_fragment( $fragments ) {
		$product_id  = isset( $_POST['product_id'] ) ? sanitize_text_field( wp_unslash( $_POST['product_id'] ) ) : null;
		$product_qty = isset( $_POST['quantity'] ) ? sanitize_text_field( wp_unslash( $_POST['quantity'] ) ) : null;

		$script = $this->track_event( 'add_to_basket', $this->get_product( $product_id, $product_qty ), true );
		$fragments['div.verfacto-tracker-event-placeholder'] = '<div class="verfacto-tracker-event-placeholder">' . $script . '</div>';
		return $fragments;
	}

	/**
	 * Get product data
	 *
	 * @param int $product_id product id.
	 * @param int $quantity product quantity.
	 * @param int $variation_id product variation id.
	 * @return void|object of product
	 */
	private function get_product( $product_id, $quantity = 1, $variation_id = null ) {
		$product = wc_get_product( $variation_id ?: $product_id );

		if ( ! $product instanceof \WC_Product ) {
			return;
		}

		$product = array(
			'name'       => $product->get_name(),
			'price'      => $product->get_regular_price(),
			'sale_price' => $product->get_sale_price(),
			'quantity'   => $quantity,
			'sku'        => $product->get_sku(),
		);

		return $product;
	}

	/**
	 * Check if tracker can be enabled
	 *
	 * @return bool
	 */
	private function is_tracker_enabled() {
		$tracker_id = $this->get_setting_by_name( 'verfacto_tracker_id' );

		if ( ! empty( $tracker_id ) ) {
			$this->tracker_id = $tracker_id;
			return true;
		}

		return false;
	}

	/**
	 * Construct HTML attributes line
	 *
	 * @param array $attributes attributes array of attributes.
	 * @return string of attributes
	 */
	private static function get_script_attributes( $attributes ) {
		$script_attributes = '';

		foreach ( $attributes as $tag => $value ) {
			$script_attributes .= ' ' . $tag . '="' . esc_attr( $value ) . '"';
		}

		return $script_attributes;
	}
}
