<?php
/**
 * The Privacy class.
 *
 * Used to define privacy related information
 *
 *
 * @since      7.0
 * @package    CartBounty Pro - Save and recover abandoned carts for WooCommerce
 * @subpackage CartBounty Pro - Save and recover abandoned carts for WooCommerce/includes
 * @author     Streamline.lv
 */
class CartBounty_Pro_Privacy{

	/**
	 * The admin handler that manages the plugin's settings, options, and backend functionality.
	 *
	 * @since    10.9
	 * @access   protected
	 * @var      CartBounty_Pro_Admin    $admin    Provides methods to control and extend the plugin's admin area.
	 */
	protected $admin = null;

	/**
	 * Get the admin handler (lazy-loaded).
	 * Creates the connector on first use and then reuses the same instance.
	 *
	 * @since 10.9
	 * @access protected
	 * @return CartBounty_Pro_Admin
	 */
	protected function admin(){
		
		if( $this->admin === null ){
			$this->admin = new CartBounty_Pro_Admin( CARTBOUNTY_PRO_PLUGIN_NAME_SLUG, CARTBOUNTY_PRO_VERSION_NUMBER );
		}

		return $this->admin;
	}

	/**
	 * The unique identifier of this plugin.
	 *
	 * @since    7.0
	 * @access   protected
	 * @var      string    $plugin_name    The string used to uniquely identify this plugin.
	 */
	protected $plugin_name;

	public function __construct(){
		$this->plugin_name = CARTBOUNTY_PRO_ABBREVIATION;
	}

	/**
	 * Safely add privacy suggestions on WordPress Privacy page
	 *
	 * @since    7.0
	 */
	public function add_privacy_message(){
		if ( function_exists( 'wp_add_privacy_policy_content' ) ) {
			$content = $this->get_privacy_message();

			if ( $content ) {
				wp_add_privacy_policy_content( $this->plugin_name, $this->get_privacy_message() );
			}
		}
	}

	/**
	 * Suggested content for WordPress Privacy policy
	 *
	 * @since    7.0
	 * @return   HTML
	 */
	public function get_privacy_message(){
		$content = '<div class="wp-suggested-text">' .
			'<p class="privacy-policy-tutorial">' .
				esc_html__( 'We have outlined the main sections you might want to include in your Privacy policy and provided suggestions that might be necessary. Please use our privacy policy suggestions to create a comprehensive privacy policy document and consult your legal team.', 'woo-save-abandoned-carts' ) .
			'</p>' .
			'<p>' . esc_html__( 'We collect information about your shopping cart during the checkout process on our store.', 'woo-save-abandoned-carts' ) . '</p>' .
			'<h2>' . esc_html__( 'What personal data we collect and why we collect it', 'woo-save-abandoned-carts' ) . '</h2>' .
			'<p>' . esc_html__( 'We will start tracking your shopping cart as soon as you add an item to your shopping cart and enter your email or phone number in the checkout form or popup. If you have signed into your account, we will start tracking your cart as soon as you add an item to your cart.', 'woo-save-abandoned-carts' ) . '</p>' .
			'<p>' . esc_html__( 'We store the contents of your shopping cart, your IP address, and the data you provide in the checkout form or popup to:', 'woo-save-abandoned-carts' ) . '</p>' .
			'<ul>' .
				'<li>' . esc_html__( 'Send you a transactional email or text message about your abandoned cart.', 'woo-save-abandoned-carts' ) . '</li>' .
				'<li>' . esc_html__( 'Improve customer experience by restoring data that has been entered in the checkout form in case you leave or accidentally refresh the page.', 'woo-save-abandoned-carts' ) . '</li>' .
				'<li>' . esc_html__( 'To help detect and prevent fraudulent activities, such as unauthorized access, account takeover, or suspicious transactions.', 'woo-save-abandoned-carts' ) . '</li>' .
			'</ul>' .
			'<h2>' . esc_html__( 'How long we retain your data', 'woo-save-abandoned-carts' ) . '</h2>' .
			'<p class="privacy-policy-tutorial">' .
				esc_html__( 'Personal data in abandoned carts is anonymized after a period of 180 days. You can change this by using "cartbounty_pro_anonymization_interval" filter in your functions.php file.', 'woo-save-abandoned-carts' ) .
			'</p>' .
			'<p>' . esc_html__( 'We will store abandoned cart information for 180 days for the purpose of restoring your abandoned cart and checkout form data. This includes your name, surname, billing address, shipping address, email address, phone number, location, IP address and additional information.', 'woo-save-abandoned-carts' ) . '</p>' .
			'<h2>' . esc_html__( 'Who has access', 'woo-save-abandoned-carts' ) . '</h2>' .
			'<p>' . esc_html__( 'Our store Administrators and Shop Managers have access to the abandoned cart data you have provided.', 'woo-save-abandoned-carts' ) . '</p>' .
			'<h2>' . esc_html__( 'Who we share your data with', 'woo-save-abandoned-carts' ) . '</h2>' .
			'<p class="privacy-policy-tutorial">' .
				esc_html__( 'In this section you should name and list all third-party providers with whom you share abandoned cart data and why.', 'woo-save-abandoned-carts' ) .
			'</p>' .
			'<p>' . wp_kses( __( 'We may share your abandoned cart data with third parties who help us send abandoned cart reminders; for example, <a href="https://www.activecampaign.com/legal/privacy-policy/?_r=5347LGDC">ActiveCampaign</a>, <a href="https://www.getresponse.com/legal/privacy?a=vPJGRchyVX">GetResponse</a>, <a href="https://mailchimp.com/legal/privacy/">MailChimp</a>, <a href="'. CARTBOUNTY_PRO_BULKGATE_TRIAL_LINK .'">BulkGate</a> or similar system.', 'woo-save-abandoned-carts' ), 'data' ) . '</p>' .
			'</div>';
		return $content;
	}

	/**
	 * Abandoned cart exporter method
	 * Abandoned carts are exported in batches of 20 to avoid timeouts
	 *
	 * @since 	 7.0
	 * @param    $email_address		Email
	 * @param    $page   			Page number
	 * @return   array
	 */
	function data_exporter( $email_address, $page ){
		global $wpdb;
		$items_per_page = 20;
		$page = (int) $page;
		$offset = ( $page * $items_per_page ) - $items_per_page;
		$export_items = array();
		$cart_table = $wpdb->prefix . CARTBOUNTY_PRO_TABLE_NAME;

		$abandoned_carts = $wpdb->get_results(
			$wpdb->prepare(
				"SELECT * FROM $cart_table
				WHERE email = %s
				ORDER BY id DESC
				LIMIT ". $offset.", ". $items_per_page,
				sanitize_email($email_address)
			)
		);

		foreach ( (array) $abandoned_carts as $cart ){ //Building data to export
			if (!empty($cart)){
				$export_items[] = array(
					'group_id' 			=> 'cartbounty-pro-abandoned-carts',
					'group_label' 		=> esc_html__( 'Abandoned carts', 'woo-save-abandoned-carts' ),
					'group_description' => esc_html__( 'WooCommerce abandoned carts', 'woo-save-abandoned-carts' ),
					'item_id' 			=> 'abandoned-cart-' . $cart->id,
					'data' 				=> self::get_exporter_cart_data($cart),
				);
			}
		}

		$done = count( $abandoned_carts ) < $items_per_page; //Determining if we still have some carts left to output due limits per page
		return array(
			'data' => $export_items,
			'done' => $done
		);
	}

	/**
	 * Get personal data (key/value pairs) for an abandoned cart
	 *
	 * @since 	 7.0
	 * @param    $cart    Cart object
	 * @return 	 array
	 */
	protected static function get_exporter_cart_data( $cart ){
		$admin = $this->admin();
		$cart_data   = array();

		$fields_to_export = apply_filters(
			'cartbounty_pro_export_abandoned_cart_fields',
			array(
				'id'			=> esc_html__( 'ID', 'woo-save-abandoned-carts' ),
				'name'			=> esc_html__( 'Name', 'woo-save-abandoned-carts' ),
				'surname'		=> esc_html__( 'Surname', 'woo-save-abandoned-carts' ),
				'email'			=> esc_html__( 'Email', 'woo-save-abandoned-carts' ),
				'phone'			=> esc_html__( 'Phone', 'woo-save-abandoned-carts' ),
				'location'		=> esc_html__( 'Location', 'woo-save-abandoned-carts' ),
				'cart_contents'	=> esc_html__( 'Cart contents', 'woo-save-abandoned-carts' ),
				'cart_total'	=> esc_html__( 'Cart total', 'woo-save-abandoned-carts' ),
				'time'			=> esc_html__( 'Time', 'woo-save-abandoned-carts' ),
				'other_fields'	=> esc_html__( 'Other fields', 'woo-save-abandoned-carts' ),
			),
			$cart
		);

		foreach ( $fields_to_export as $field => $name ){
			$value = '';

			switch ( $field ) {
				case 'location':

					$location_data = maybe_unserialize( $cart->$field );
					$country = $location_data['country'];
					$city = $location_data['city'];
					$postcode = $location_data['postcode'];
					$location = $country;

					if(!empty($city)){
						$location .= ', ' . $city;
					}

					if(!empty($postcode)){
						$location .= ', ' . $postcode;
					}

					$value = esc_html($location);
					break;

				case 'cart_contents':
					$item_names = array();
					$cart_contents = $admin->get_saved_cart_contents( $cart->$field );

					if( $cart_contents ){

						foreach( $cart_contents as $product ){
							
							if( is_array( $product ) ){

								if( isset( $product['product_title'] ) ){
									$product_title = esc_html($product['product_title']);
									$quantity = $product['quantity'];
									$item_names[] = $product_title . ' x ' . $quantity;
								}
							}
						}
						$value = implode( ', ', $item_names );
					}
					break;

				case 'other_fields':
					$field_names = array();
					
					if(!is_serialized($cart->$field)){
						break;
					}

					$field_array = maybe_unserialize( $cart->$field );

					if( is_array( $field_array ) ){

						foreach( $field_array as $key => $field ){

							if(!empty($field)){
								$field_names[] = $key . ': ' . $field;
							}
						}
						$value = implode( ', ', $field_names );
					}
					break;

				case 'cart_total':
					$value = $cart->$field . ' ' . $cart->currency; 
					break;

				default:
					$value = $cart->$field;
					break;
			}

			$value = apply_filters( 'cartbounty_pro_export_abandoned_cart_field', $value, $field, $cart );
			if ( $value ) {
				$cart_data[] = array(
					'name'  => $name,
					'value' => $value,
				);
			}
		}

		$cart_data = apply_filters( 'cartbounty_pro_export_abandoned_cart', $cart_data, $cart ); //allowing to register custom data for this order for the export
		return $cart_data;
	}

	/**
	 * Register abandoned cart data exporter method
	 *
	 * @since 	 7.0
	 * @param    $exporters    Exporter array
	 * @return 	 array
	 */
	function cartbounty_pro_exporter( $exporters ){
		$exporters['cartbounty-pro'] = array(
			'exporter_friendly_name' => CARTBOUNTY_PRO_ABBREVIATION,
			'callback' => array( $this, 'data_exporter' )
		);
		return $exporters;
	}

	/**
	 * Abandoned cart eraser method
	 * Abandoned carts are erased in batches of 20 to avoid timeouts
	 *
	 * @since 	 7.0
	 * @param    $email_address		Email
	 * @param    $page   			Page number
	 * @return   array
	 */
	function cart_eraser( $email_address, $page ){
		global $wpdb;
		$items_per_page = 20;
		$page = (int) $page;
		$offset = ( $page * $items_per_page ) - $items_per_page;
		$cart_table = $wpdb->prefix . CARTBOUNTY_PRO_TABLE_NAME;

		$abandoned_carts = $wpdb->get_results(
			$wpdb->prepare(
				"SELECT * FROM $cart_table
				WHERE email = %s
				ORDER BY id DESC
				LIMIT ". $offset.", ". $items_per_page,
				sanitize_email($email_address)
			)
		);

		$items_removed = false;
		$deleted_row_count = false;
		$messages = array();
		$affected_ids = array();

		foreach ( (array) $abandoned_carts as $cart ) {
			if (!empty($cart)){
				$this->remove_abandoned_cart_data( $cart );
				$affected_ids[] = $cart->id;
				$items_removed = true;
			}
		}

		$messages[] = sprintf(
			/* translators: %s - Abandoned cart ID */
			esc_html( _n( 'Removed abandoned cart %s.', 'Removed abandoned carts %s.', count($affected_ids), 'woo-save-abandoned-carts' ) ), implode( ', ', $affected_ids ) );

		$done = count( $abandoned_carts ) < $items_per_page; return array(
			'items_removed' => $items_removed,
			'items_retained' => false,
			'messages' => $messages,
			'done' => $done,
		);
	}

	/**
	 * Abandoned cart erasure / anonymization
	 *
	 * @since 	 7.0
	 * @param    $cart    Abandoned cart object
	 */
	private function remove_abandoned_cart_data( $cart ){
		$this->anonymize_cart( $cart );
		return;
	}

	/**
	 * Abandoned cart erasure / anonymization. Returns affected row count
	 *
	 * @since 	 7.0
	 */
	public function anonymize_abandoned_cart_data() {
		global $wpdb;
		$cart_table = $wpdb->prefix . CARTBOUNTY_PRO_TABLE_NAME;
		$admin = $this->admin();
		$time = $admin->get_time_intervals();

		$abandoned_carts = $wpdb->get_results( //Selecting all rows that are not empty and are not older than the Maximum sync period
			$wpdb->prepare(
				"SELECT id, name, surname, email, phone, ip_address FROM $cart_table
				WHERE (name != '' OR 
				surname != '' OR
				email != '' OR
				phone != '' OR
				ip_address != '' ) AND
				time < %s AND
				anonymized = %d",
				$time['anonymization_period'],
				0
			)
		);

		if( $abandoned_carts ){

			foreach( $abandoned_carts as $key => $cart ){
				$this->anonymize_cart( $cart );
			}
		}

		return;
	}

	/**
	 * Method that anonymizes abandoned cart personal data
	 *
	 * @since 	 7.0
	 * @param    $cart    Abandoned cart object
	 */
	private function anonymize_cart( $cart ){
		global $wpdb;
		$cart_table = $wpdb->prefix . CARTBOUNTY_PRO_TABLE_NAME;
		$admin = $this->admin();
		$name = '';
		$surname = '';
		$email = '';
		$phone = '';
		$ip_address = '';

		if( !empty( $cart->name ) ){
			$name = $admin->anonymize_string( $cart->name );
		}

		if( !empty( $cart->surname ) ){
			$surname = $admin->anonymize_string( $cart->surname );
		}

		if( !empty( $cart->email ) ){
			$email = $admin->anonymize_email( $cart->email );
		}

		if( !empty( $cart->phone ) ){
			$phone = $admin->anonymize_phone( $cart->phone );
		}

		if( !empty( $cart->ip_address ) ){
			$ip_address = $admin->anonymize_string( $cart->ip_address );
		}

		$wpdb->update(
			$cart_table,
			array(
				'name' 			=> $name,
				'surname' 		=> $surname,
				'email' 		=> $email,
				'phone' 		=> $phone,
				'session_id' 	=> '',
				'other_fields' 	=> '',
				'ip_address' 	=> $ip_address,
				'anonymized' 	=> true
			),
			array(
				'id' => $cart->id
			),
			array( '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s' ),
			array( '%d' )
		);
		return;
	}

	/**
	 * Register abandoned cart data eraser method
	 *
	 * @since 	 7.0
	 * @param    $erasers    Eraser array
	 * @return 	 array
	 */
	function cartbounty_pro_eraser( $erasers ) {
		$erasers['cartbounty-pro'] = array(
			'eraser_friendly_name' => CARTBOUNTY_PRO_ABBREVIATION,
			'callback'             => array( $this, 'cart_eraser' ),
		);
		return $erasers;
	}
}