<?php
/**
 * Send abandoned cart email.
 *
 * @package woodmart
 */

if ( ! class_exists( 'XTS_Email_Abandoned_Cart' ) ) :

	/**
	 * Send abandoned cart email.
	 */
	class XTS_Email_Abandoned_Cart extends WC_Email {
		/**
		 * True when the email notification is sent to customers.
		 *
		 * @var bool
		 */
		protected $customer_email = true;

		/**
		 * WC_Product instance.
		 *
		 * @var WC_Product;
		 */
		public $object;

		/**
		 * WC_Coupon instance.
		 *
		 * @var WC_Coupon|false
		 */
		public $coupon;

		/**
		 * User name.
		 *
		 * @var string $user_name
		 */
		public $user_name;

		/**
		 * Constructor.
		 */
		public function __construct() {
			if ( ! woodmart_get_opt( 'cart_recovery_enabled' ) || ! woodmart_woocommerce_installed() ) {
				return;
			}

			$this->template_base = WOODMART_THEMEROOT . '/woocommerce/';

			$this->id          = 'woodmart_abandoned_cart_email';
			$this->title       = esc_html__( 'Abandoned cart', 'woodmart' );
			$this->description = esc_html__( 'This email reminds customers about their incomplete purchases, encouraging them to complete their orders.', 'woodmart' );

			$this->heading = wp_kses_post( __( 'Don\'t Forget to Complete Your Purchase!', 'woodmart' ) );
			$this->subject = wp_kses_post( __( 'Don\'t Forget to Complete Your Purchase!', 'woodmart' ) );

			$this->template_html  = 'emails/abandoned-cart.php';
			$this->template_plain = 'emails/plain/abandoned-cart.php';

			// Triggers for this email.
			add_action( 'woodmart_send_abandoned_cart_notification', array( $this, 'trigger' ) );

			add_filter( 'woodmart_emails_list', array( $this, 'register_woodmart_email' ) );

			// Call parent constructor.
			parent::__construct();
		}

		/**
		 * Register email in Woodmart emails list.
		 *
		 * @param array $email_class Email classes list.
		 *
		 * @return array
		 */
		public function register_woodmart_email( $email_class ) {
			$email_class[] = get_class( $this );

			return $email_class;
		}

		/**
		 * Method triggered to send email.
		 *
		 * @param array $cart_data Abandoned art data.
		 *
		 * @return void
		 */
		public function trigger( $cart_data ) {
			$this->object    = $cart_data;
			$this->recipient = $this->object->_user_email;

			if ( ! empty( $this->object->_language ) ) {
				do_action( 'wpml_switch_language', $this->object->_language );
			}

			$user = get_user_by( 'email', $this->recipient );

			if ( $user instanceof WP_User ) {
				$user_name = $user->display_name;
			} elseif ( ! empty( $this->object->_user_first_name ) || ! empty( $this->object->_user_last_name ) ) {
				$user_name = $this->object->_user_first_name . ' ' . $this->object->_user_last_name;
			} else {
				$user_name = esc_html__( 'Customer', 'woodmart' );
			}

			$this->user_name = $user_name;
			$this->coupon    = $this->create_and_get_coupon();

			if ( ! $this->is_enabled() || ! $this->get_recipient() || ! $this->object ) {
				return;
			}

			$this->send(
				$this->get_recipient(),
				$this->get_subject(),
				$this->get_content(),
				$this->get_headers(),
				$this->get_attachments()
			);

			do_action( 'wpml_switch_language', apply_filters( 'wpml_default_language', null ) );
		}

		/**
		 * Get content html.
		 *
		 * @return string
		 */
		public function get_content_html() {
			ob_start();

			wc_get_template(
				$this->template_html,
				array(
					'email'               => $this,
					'email_heading'       => $this->get_heading(),
					'unsubscribe_link'    => $this->get_unsubscribe_link(),
					'recover_button_link' => $this->get_recover_button_link(),
					'coupon'              => $this->coupon,
					'sent_to_admin'       => false,
					'plain_text'          => false,
				)
			);

			return ob_get_clean();
		}

		/**
		 * Get content plain.
		 *
		 * @return string
		 */
		public function get_content_plain() {
			ob_start();

			wc_get_template(
				$this->template_plain,
				array(
					'email'               => $this,
					'email_heading'       => $this->get_heading(),
					'unsubscribe_link'    => $this->get_unsubscribe_link(),
					'recover_button_link' => $this->get_recover_button_link(),
					'coupon'              => $this->coupon,
					'sent_to_admin'       => false,
					'plain_text'          => true,
				)
			);

			return ob_get_clean();
		}

		/**
		 * Get confirm subscription link.
		 * Create confirm token if not exists.
		 *
		 * @return string Confirm subscription url.
		 */
		public function get_recover_button_link() {
			$args = array( 'wd_rec_cart' => $this->object->ID );

			if ( $this->coupon ) {
				$args['coupon_code'] = $this->coupon->get_code();
			}

			return add_query_arg( $args, wc_get_cart_url() );
		}

		/**
		 * Get unsubscribe link.
		 * Create unsubscribe token if not exists and store it in cart metadata.
		 *
		 * @return string Unsubscribe url.
		 */
		public function get_unsubscribe_link() {
			$token_meta_key = '_unsubscribe_token';
			$stored_token   = get_post_meta( $this->object->ID, $token_meta_key, true );

			// Generate new token if not exists
			if ( ! $stored_token ) {
				$plain_token  = wp_generate_password( 32, false );
				$hashed_token = wp_hash_password( $plain_token );

				update_post_meta( $this->object->ID, $token_meta_key, $hashed_token );

				$stored_token = $plain_token;
			}

			return add_query_arg(
				array(
					'token'  => $stored_token,
					'email'  => $this->object->_user_email,
					'action' => 'woodmart_abandoned_cart_unsubscribe',
				),
				wc_get_page_permalink( 'shop' )
			);
		}

		/**
		 * Init fields that will store admin preferences.
		 *
		 * @return void
		 */
		public function init_form_fields() {
			parent::init_form_fields();

			unset( $this->form_fields['additional_content'] );
		}

		/**
		 * Create a new coupon to send with email and return WC_Coupon instance.
		 *
		 * @return WC_Coupon|false
		 */
		public function create_and_get_coupon() {
			$coupon_enabled = woodmart_get_opt( 'abandoned_cart_coupon_enabled' );
			$discount_type  = woodmart_get_opt( 'abandoned_cart_coupon_discount_type', 'percent' );
			$coupon_amount  = woodmart_get_opt( 'abandoned_cart_coupon_amount', 10 );

			if ( ! $coupon_enabled || ! $discount_type || ! $coupon_amount ) {
				return false;
			}

			$expiry_date = '';

			if ( woodmart_get_opt( 'abandoned_cart_delete_expired_coupons', true ) ) {
				$expiry_date = strtotime( current_time( 'mysql' ) ) + intval( woodmart_get_opt( 'abandoned_cart_coupon_timeframe', 1 ) ) * intval( woodmart_get_opt( 'abandoned_cart_coupon_timeframe_period', DAY_IN_SECONDS ) );
				$expiry_date = gmdate( 'Y-m-d H:i:s', $expiry_date );
			}

			if ( woodmart_is_email_preview_request() ) {
				$dummy_coupon = new class( $coupon_amount, $discount_type, $expiry_date ) {
					/**
					 * Dummy coupon class for email preview.
					 *
					 * @var string $coupon_amount Coupon amount.
					 */
					private $coupon_amount;

					/**
					 * The type of discount to be applied.
					 *
					 * @var string
					 */
					private $discount_type;

					/**
					 * The expiry date of the coupon.
					 *
					 * @var string
					 */
					private $expiry_date;

					/**
					 * Constructor.
					 *
					 * @param string $coupon_amount Coupon amount.
					 * @param string $discount_type Discount type.
					 * @param string $expiry_date Expiry date.
					 */
					public function __construct( $coupon_amount, $discount_type, $expiry_date ) {
						$this->coupon_amount = $coupon_amount;
						$this->discount_type = $discount_type;
						$this->expiry_date   = $expiry_date;
					}

					/**
					 * Get the coupon amount.
					 *
					 * @return string
					 */
					public function get_amount() {
						return $this->coupon_amount;
					}

					/**
					 * Get the discount type.
					 *
					 * @return string
					 */
					public function get_discount_type() {
						return $this->discount_type;
					}

					/**
					 * Get the expiry date.
					 *
					 * @return WC_DateTime|string
					 */
					public function get_date_expires() {
						return woodmart_get_opt( 'abandoned_cart_delete_expired_coupons', true ) ? new WC_DateTime( $this->expiry_date ) : '';
					}

					/**
					 * Get the coupon code.
					 *
					 * @return string
					 */
					public function get_code() {
						return 'DUMMY_COUPON';
					}
				};

				return $dummy_coupon;
			}

			$coupon_prefix = woodmart_get_opt( 'abandoned_cart_coupon_prefix', 'WD' );
			$code_length   = apply_filters( 'woodmart_abandoned_cart_coupon_code_length', 10 );
			$coupon_code   = '';

			for ( $attempt = 0; $attempt < 10; $attempt++ ) {
				$possible_coupon_code = strtoupper( $coupon_prefix . '_' . wp_generate_password( $code_length, false ) );

				if ( ! wc_get_coupon_id_by_code( $possible_coupon_code ) ) {
					$coupon_code = $possible_coupon_code;
					break;
				}
			}

			if ( ! $coupon_code ) {
				return false;
			}

			$new_coupon_id = wp_insert_post(
				array(
					'post_title'   => $coupon_code,
					'post_content' => '',
					'post_status'  => 'publish',
					'post_author'  => 1,
					'post_type'    => 'shop_coupon',
				)
			);

			$args = apply_filters(
				'woodmart_coupon_args',
				array(
					'discount_type'            => $discount_type,
					'coupon_amount'            => $coupon_amount,
					'individual_use'           => 'yes',
					'product_ids'              => '',
					'exclude_product_ids'      => '',
					'usage_limit'              => '1',
					'expiry_date'              => $expiry_date,
					'apply_before_tax'         => 'yes',
					'free_shipping'            => 'no',
					'wd_abandoned_cart_coupon' => 'yes',
				),
				$new_coupon_id,
				$this->object->ID // Abandoned cart id.
			);

			if ( $args ) {
				foreach ( $args as $key => $arg ) {
					update_post_meta( $new_coupon_id, $key, $arg );
				}
			}

			return new WC_Coupon( $new_coupon_id );
		}
	}

endif;

return new XTS_Email_Abandoned_Cart();
