<?php
/**
 * Handles WooCommerce related Activities
 *
 * @link       https://personalizewp.com/
 * @since      3.2.0 Merged into PWP
 * @since      1.0.0
 *
 * @package    PersonalizeWP
 * @subpackage PersonalizeWP/Tracking
 */

namespace PersonalizeWP\Tracking;

use PersonalizeWP\Tracking\Base;
use PersonalizeWP\Model\Activity;
use PersonalizeWP\Model\Contact;

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

/**
 * Defines WooCommerce functionality
 *
 * This class defines all code to track purchase activities
 */
class Woocommerce extends Base {

	/**
	 * Execute hooks
	 */
	public function setup() {

		// Sanity check for WooCommerce
		if ( ! function_exists( 'wc' ) ) {
			return;
		}

		add_action( 'wp_footer', array( $this, 'add_cart_update_tracking_js' ) );
		add_action( 'wp_footer', array( $this, 'add_checkout_tracking_js' ) );

		// Stores the UID against the users session data.
		add_action( 'personalizewp_pre_record_activity', array( $this, 'store_uid_in_wc_session' ), 10, 2 );

		// Block based, or using the WC Store API.
		add_action( 'woocommerce_store_api_checkout_update_order_meta', array( $this, 'api_checkout_order_created' ) );

		// For legacy situations i.e. using checkout shortcode, or 3rd party plugin.
		add_action( 'woocommerce_checkout_order_created', array( $this, 'legacy_checkout_order_created' ) );

		// Once the order has completed (which can be a manual process) use the stored UID to record the activity.
		add_action( 'woocommerce_order_status_completed', array( $this, 'track_purchase_activity' ), 10, 2 );
	}

	/**
	 * Returns the known UID that was stored in the users WC Session.
	 *
	 * @since 2.3.0
	 *
	 * @return string|null
	 */
	protected function get_uid_from_session() {

		$uid     = null;
		$session = wc()->session;
		if ( is_a( $session, 'WC_Session' ) ) {
			$uid = $session->get( '_pwp_id' );
		}

		return $uid;
	}

	/**
	 * During any activity request, detects a WC Session and stores the incoming UID.
	 *
	 * @since 2.3.0
	 *
	 * @param null|bool $check     Whether to allow recording the Activity entry.
	 * @param string    $unique_id Browser unique ID
	 */
	public function store_uid_in_wc_session( $check, $unique_id ) {

		// Ensure session exists
		if ( ! wc()->session ) {
			wc()->initialize_session();
		}

		// Checks for non-empty session
		if ( ! wc()->session->has_session() ) {
			// Return to ensure activity creation.
			return $check;
		}

		$uid = $this->get_uid_from_session();
		// Check UID isn't empty, and not already matching.
		if ( empty( $uid ) || $uid !== $unique_id ) {
			wc()->session->set( '_pwp_id', $unique_id );
		}

		// Simply return to allow activity creation
		return $check;
	}

	/**
	 * Transfers the UID stored within the Session to WC Order meta.
	 *
	 * @uses woocommerce_store_api_checkout_update_order_meta Action added in WC 7.2.0
	 *
	 * @param \WC_Order $order WC_Order object
	 *
	 * @since 2.3.0
	 */
	public function api_checkout_order_created( $order ) {

		if ( ! is_a( $order, 'WC_Order' ) ) {
			return;
		}

		$uid = $this->get_uid_from_session();
		// Sanity check.
		if ( empty( $uid ) ) {
			return;
		}

		$order->update_meta_data( '_pwp_id', $uid );
		$order->save();
	}

	/**
	 * Transfers the UID stored within the Session to WC Order meta.
	 *
	 * @uses woocommerce_checkout_order_created Action added in WC 4.3.0
	 *
	 * @param \WC_Order $order WC_Order object
	 *
	 * @since 2.3.0
	 */
	public function legacy_checkout_order_created( $order ) {

		if ( ! is_a( $order, 'WC_Order' ) ) {
			return;
		}

		$uid = $this->get_uid_from_session();
		// Sanity check.
		if ( empty( $uid ) ) {
			return;
		}

		$order->update_meta_data( '_pwp_id', $uid );
		$order->save();
	}

	/**
	 * Track successful purchase, pickup UID from WC Order meta.
	 *
	 * @param int       $order_id ID of the order
	 * @param \WC_Order $order    WC_Order object
	 *
	 * @return void
	 */
	public function track_purchase_activity( $order_id, $order ) {
		// Sanity check.
		$uid = $order->get_meta( '_pwp_id' );
		if ( empty( $uid ) ) {
			return;
		}

		$user      = false;
		$user_data = [];
		$user_meta = [
			'_has-completed-purchase' => true, // Store extra meta for easier rule validation.
		];

		// Prioritise using the order to find the WP User and use that.
		$order = wc_get_order( $order_id );
		if ( $order->get_customer_id() ) {
			$user = get_user_by( 'id', $order->get_customer_id() );
			if ( $user instanceof \WP_User ) {
				$user_data = array(
					// We know exactly who the user is, so mark it as such.
					'is_verified' => true, // This forces an update to the Visitor profile.
					'first_name'  => $user->first_name,
					'last_name'   => $user->last_name,
					'email'       => $user->user_email,
				);

				// Pre-set meta for visitor creation.
				$user_meta['wp_user_id']   = $user->ID;
				$user_meta['wp_user_role'] = $user->roles;
			}
		} elseif ( $order->get_billing_first_name() || $order->get_billing_last_name() ) {
			$user_data = array(
				'first_name' => $order->get_billing_first_name(),
				'last_name'  => $order->get_billing_last_name(),
				'email'      => $order->get_billing_email(),
			);
		}

		// Get the Contact record, creating it if we have user data to set, or we are tracking anon users.
		$contact = Contact::find_by_uid( $uid, $user_data );

		// Either we don't have a known user, or we are not tracking Anon users.
		if ( ! $contact ) {
			return;
		}

		// add activity record for purchase
		Activity::record(
			$contact->uid,
			array(
				'activity_type' => 'purchase',
				'object_id'     => $order_id,
				'object_type'   => 'woocommerce',
			)
		);
	}

	/**
	 * Outputs JS to detect Cart updating and trigger the next tracking activity submission.
	 *
	 * @since 3.0.0
	 *
	 * @return void
	 */
	public function add_cart_update_tracking_js() {

		// Only output if known WooCommerce template.
		if ( ! is_woocommerce() ) {
			return;
		}
		?>
<script>
(function(){
const trackPWPUserViaCart=()=>{
	const maybeKnown = window?.PersonalizeWP?.tracking?.maybeUserKnown || null;
	if(typeof maybeKnown === "function"){maybeKnown();}
}
document.addEventListener('wc-blocks_adding_to_cart',trackPWPUserViaCart);
document.addEventListener('wc-blocks_added_to_cart',trackPWPUserViaCart);
})();
</script>
		<?php
	}

	/**
	 * Outputs JS to detect display of a Cart or Checkout block page and immediately trigger the next tracking activity submission.
	 *
	 * @since 3.0.0
	 *
	 * @return void
	 */
	public function add_checkout_tracking_js() {

		// Only output if within the payment workflow.
		if ( ! is_cart() && ! is_checkout() && ! is_order_received_page() ) {
			return;
		}
		?>
<script>
(function(){
const trackPWPUserViaCheckout=()=>{
	const maybeKnown = window?.PersonalizeWP?.tracking?.maybeUserKnown || null;
	if(typeof maybeKnown === "function"){maybeKnown();}
}
document.addEventListener('DOMContentLoaded',trackPWPUserViaCheckout);
})();
</script>
		<?php
	}
}
