<?php
/**
 *
 * Usage Tracking for CRM insights
 * is only included if the setting
 * is enabled
 *
 * @since 4.3.0
 */

class jpcrm_usage_tracking {

	protected $setting_key = 'teammember_usage';

	public function __construct() {

		$this->init_hooks();
	}

	public function init_hooks() {

		#} Usage tracking (pageviews) sent via AJAX
		add_action( 'admin_footer', array( $this, 'tracking_footer' ) );
		add_action( 'wp_ajax_jpcrm_send_page_view', array( $this, 'send_page_view' ) );
	}

	/**
	 * AJAX function to send the pageview
	 */
	public function send_page_view() {

		global $zbs;

		$res = array();

		// check nonce
		check_ajax_referer( 'jpcrm_usage_tracking_nonce', 'security' );

		// retrieve page_name
		$page_name = sanitize_text_field( $_POST['page_name'] );

		// pool data
		$data = array(
			'action'     => 'jpcrm_track_usage',
			'event_name' => $page_name,
			'event_type' => 'page_view',
			'site_url'   => home_url(),
		);

		// call
		$response = wp_remote_post(
			$zbs->urls['usage'],
			array(
				'method'      => 'POST',
				'timeout'     => 45,
				'redirection' => 5,
				'httpversion' => '1.0',
				'blocking'    => true,
				'headers'     => array(),
				'body'        => $data,
				'cookies'     => array(),
			)
		);

		$res['pageview'] = 'sent';

		// send summary snapshot based on a transient
		if ( ! get_transient( 'jpcrm_crm_snapshot' ) ) {

			$this->send_snapshot();
			$res['snapshot'] = 'sent';
			set_transient( 'jpcrm_crm_snapshot', true, DAY_IN_SECONDS );

		}

		wp_send_json( $res, 200, JSON_UNESCAPED_SLASHES );
	}

	/**
	 * send summary snapshot
	 */
	public function send_snapshot() {

		global $zbs, $wp_version;

		// build data
		$contacts_count     = $zbs->DAL->contacts->getFullCount();
		$contacts_woo_count = $zbs->DAL->contacts->getContacts(
			array(

				'externalSource' => 'woo',
				'count'          => true,

			)
		);
		$contacts_with_extsource = $zbs->DAL->contacts->getTotalExtSourceCount();
		$companies_count         = $zbs->DAL->companies->getFullCount();
		$transactions_count      = $zbs->DAL->transactions->getFullCount();
		$quotes_count            = $zbs->DAL->quotes->getFullCount();
		$invoices_count          = $zbs->DAL->invoices->getFullCount();
		$forms_count             = $zbs->DAL->forms->getFullCount();
		$tasks_count             = $zbs->DAL->events->getFullCount();
		$crm_users               = $this->get_teammates_count( true );
		$extensions_count        = zeroBSCRM_extensionsInstalledCount();
		$modules_count           = jpcrm_core_modules_installed_count();
		$wp_version              = $wp_version;
			$crm_version         = $zbs::VERSION;
		$dal_version             = $zbs->dal_version;
		$php_version             = PHP_VERSION;
		$mysql_version           = zeroBSCRM_database_getVersion();

		$data = array(
			'action'                  => 'jpcrm_track_stats',
			'site_url'                => home_url(),
			'contacts_count'          => $contacts_count,
			'contacts_woo_count'      => $contacts_woo_count,
			'contacts_with_extsource' => $contacts_with_extsource,
			'companies_count'         => $companies_count,
			'transactions_count'      => $transactions_count,
			'quotes_count'            => $quotes_count,
			'invoices_count'          => $invoices_count,
			'forms_count'             => $forms_count,
			'events_count'            => $tasks_count,
			'users_count'             => $crm_users,
			'extensions_count'        => $extensions_count,
			'modules_count'           => $modules_count,
			'wp_version'              => $wp_version,
			'crm_version'             => $crm_version,
			'dal_version'             => $dal_version,
			'php_version'             => $php_version,
			'mysql_version'           => $mysql_version,
		);

		// call
		return wp_remote_post(
			$zbs->urls['usage'],
			array(
				'method'      => 'POST',
				'timeout'     => 45,
				'redirection' => 5,
				'httpversion' => '1.0',
				'blocking'    => true,
				'headers'     => array(),
				'body'        => $data,
				'cookies'     => array(),
			)
		);
	}

	/**
	 * Package admin page as string which can be passed to usage tracking API
	 */
	public function get_jpcrm_admin_page() {

		// retrieve uri
		$uri = isset( $_SERVER['REQUEST_URI'] ) ? esc_url_raw( wp_unslash( $_SERVER['REQUEST_URI'] ) ) : '';
		$uri = preg_replace( '|^.*/wp-admin/|i', '', $uri );

		// if somehow failed, return
		if ( ! $uri ) {
			return '';
		}

		// hard remove any unwanted get parameters here
		$uri = remove_query_arg( array( '_wpnonce' ), admin_url( $uri ) );

		// get _GET Parameters
		$parameters = jpcrm_url_get_params( $uri );

		// cycle through some key parameters and tokenise for anonymity / cleanliness
		if ( is_array( $parameters ) ) {

			$return_string = '';

			// required: page
			if ( isset( $parameters['page'] ) && ! empty( $parameters['page'] ) ) {

				$return_string = $parameters['page'];

			} else {

				// missing $page, skip
				return '';

			}

			// Overrides:

			// action: by default it's add, unless zbsid is set, then it's edit, make so:
			if ( isset( $parameters['action'] ) && ! empty( $parameters['action'] ) ) {

				// if action is set and no zbsid is present, it's an add
				if ( $parameters['action'] == 'edit' && (
					! isset( $parameters['zbsid'] ) || empty( $parameters['zbsid'] )
				) ) {

					$parameters['action'] = 'add';
				}

				// note if there's an action present and zbsid, we can go ahead and remove zbsid from the return :)
				if ( isset( $parameters['zbsid'] ) ) {

					unset( $parameters['zbsid'] );

				}
			}

			// generic out any non-helpful data
			$parameters_to_blank = array( 'zbsid', 'zbsprefillcust', 'zbsprefill', 'zbs_tag', 'quickfilters', 'sort', 'zbsowner', 'zbs_template_id' );

			foreach ( $parameters_to_blank as $parameter_key ) {

				if ( isset( $parameters[ $parameter_key ] ) ) {

					// set generic value
					$parameters[ $parameter_key ] = 'present';

				}
			}

			// finally rebuild into a useful string
			foreach ( $parameters as $parameter_key => $parameter_value ) {

				// skip page as is always added above
				if ( $parameter_key == 'page' ) {

					continue;

				}

				if ( ! empty( $return_string ) ) {

					$return_string .= '|';

				}

				// here we check if $parameter_value might be an email
				// ... designed as future-proofing and to catch any potential leaks of user data to our system
				if ( zeroBSCRM_validateEmail( $parameter_value ) ) {
					$parameter_value = '{email}';
				}

				// append return string
				$return_string .= $parameter_key . ':' . $parameter_value;

			}

			return $return_string;

		}

		// fallback: retrieve page via explode
		$split = explode( '?page=', $uri );
		$page  = $split[0];
		if ( count( $split ) == 2 ) {
			$page = $split[1];
		}

		// returns everything after the ?page= part of the URL
		return $page;
	}

	/**
	 * JS to track usage
	 */
	public function tracking_footer() {

		global $zbs;

		if ( zeroBSCRM_isAdminPage() ) {

			// retrieve page info
			$page = $this->get_jpcrm_admin_page();

			if ( ! empty( $page ) ) {

				$this->track_specific_pageview( $page );

			}
		}
	}

	/**
	 * JS to track usage for a specific key
	 * is used by `tracking_footer()` and can be used inline throughout
	 * core to track extra view events
	 */
	public function track_specific_pageview( $page_key = '' ) {

		global $zbs;

		if ( zeroBSCRM_isAdminPage() ) {

			// Where usage tracking enabled, clock that this user is a CRM team member
			// noting that this never sends team-member data out of the install, only the count
			$this->track_crm_teammember_usage();

			if ( ! empty( $page_key ) ) {

				?>
				<script>
					data = {
						action: 'jpcrm_send_page_view',
						page_name: '<?php echo esc_html( $page_key ); ?>',
						security: '<?php echo esc_html( wp_create_nonce( 'jpcrm_usage_tracking_nonce' ) ); ?>'
					};
					jQuery.post(ajaxurl, data, function (response) {
						//nothing to see here.
					});
				</script>
				<?php

			}
		}
	}

	/**
	 * Adds user id to an option of "WP users who use the CRM" which is totalled for usage statistics
	 * (No specific user usage data is ever sent)
	 */
	private function track_crm_teammember_usage() {

		global $zbs;

		// retrieve existing array
		$existing_teammembers = $zbs->settings->get( $this->setting_key );

		// catch first call
		if ( ! is_array( $existing_teammembers ) ) {
			$existing_teammembers = array();
		}

		$current_user_id = get_current_user_id();

		// append
		if ( isset( $existing_teammembers[ $current_user_id ] ) ) {

			// increment
			++$existing_teammembers[ $current_user_id ]['count'];

			// update
			$existing_teammembers[ $current_user_id ]['last_seen'] = time();

		} else {

			// add
			$existing_teammembers[ $current_user_id ] = array(
				'count'     => 1,
				'last_seen' => time(),
			);

		}

		// update setting
		$zbs->settings->update( $this->setting_key, $existing_teammembers );
	}

	/**
	 * Retrieves a count of teammates who have accessed a crm page (optionally checking wp user status)
	 *
	 * @param $check_is_current_wp_user - bool; if true check that the user_id is a current wp user
	 */
	public function get_teammates_count( $check_is_current_wp_crm_user = false ) {

		global $zbs;

		// retrieve teammembers
		$seen_teammembers = $zbs->settings->get( $this->setting_key );

		// catch first call
		if ( ! is_array( $seen_teammembers ) ) {
			return 0;
		}

		// if validating current status, do that, else return count
		if ( $check_is_current_wp_crm_user ) {

			// filter user_ids who are current wp_users
			$current_wp_teammembers = array_filter( array_keys( $seen_teammembers ), 'get_userdata' );

			// filter user_ids who do not have a CRM backend role (and are not admins)
			// e.g. CRM admins who are now Subscribers
			$current_wp_teammembers = array_filter( $current_wp_teammembers, 'zeroBSCRM_permsIsZBSUserOrAdmin' );

			return count( $current_wp_teammembers );

		} else {

			return count( $seen_teammembers );

		}
	}
}
