<?php
/**
 * Cart recovery class.
 *
 * @package CartNinjaRecovery
 */

if ( ! defined( 'ABSPATH' ) ) {
	 exit;
}

class CARTNINJA_Cart_Recovery {

	public function maybe_restore_cart_from_token() {
		if ( ! isset( $_GET['cartninja_token'] ) ) {
			return;
		}

		if ( ! function_exists( 'WC' ) || ! WC() || ! WC()->cart || ! WC()->session ) {
			return;
		}

		$token = sanitize_text_field( wp_unslash( $_GET['cartninja_token'] ) );

		if ( ! preg_match( '/^[A-Za-z0-9]{32}$/', $token ) ) {
			$this->redirect_invalid_recovery_link();
		}

		global $wpdb;

		$table = $wpdb->prefix . 'cartninja_carts';
		$cart  = $wpdb->get_row(
			$wpdb->prepare(
				"SELECT * FROM {$table}
				WHERE recovery_token = %s
					AND recovery_expires_at IS NOT NULL
					AND recovery_expires_at >= %s
					AND tracking_status = 'tracked'
					AND status IN ('active','abandoned','recovering','lost')
					AND recovered_order_id IS NULL
				LIMIT 1",
				$token,
				current_time( 'mysql' )
			),
			ARRAY_A
		);

		if ( ! $cart ) {
			$this->redirect_invalid_recovery_link();
		}

		$contents = json_decode( $cart['cart_contents'], true );

		if ( empty( $contents ) || ! is_array( $contents ) ) {
			$this->redirect_invalid_recovery_link();
		}

		WC()->cart->empty_cart();

		foreach ( $contents as $item ) {
			$product_id   = isset( $item['product_id'] ) ? absint( $item['product_id'] ) : 0;
			$variation_id = isset( $item['variation_id'] ) ? absint( $item['variation_id'] ) : 0;
			$quantity     = isset( $item['quantity'] ) ? absint( $item['quantity'] ) : 1;
			$variation    = isset( $item['variation'] ) && is_array( $item['variation'] ) ? array_map( 'sanitize_text_field', $item['variation'] ) : array();

			if ( $product_id && $quantity ) {
				WC()->cart->add_to_cart( $product_id, $quantity, $variation_id, $variation );
			}
		}

		$wpdb->update(
			$table,
			array(
				'status' => 'recovering',
			),
			array( 'id' => absint( $cart['id'] ) ),
			array( '%s' ),
			array( '%d' )
		);

		WC()->session->set( 'cartninja_recovered_cart_id', absint( $cart['id'] ) );
		WC()->session->set( 'cartninja_recovery_token', $token );
		$this->mark_notification_clicked( absint( $cart['id'] ) );

		$settings     = get_option( 'cartninja_settings', array() );
		$general      = isset( $settings['general'] ) ? $settings['general'] : array();
		$recovery_url = ! empty( $general['recovery_url_base'] ) ? esc_url_raw( $general['recovery_url_base'] ) : ( function_exists( 'wc_get_cart_url' ) ? wc_get_cart_url() : home_url( '/cart/' ) );

		wp_safe_redirect( $recovery_url );
		exit;
	}

	public function mark_order_recovered( $order_id ) {
		global $wpdb;

		$order_id = absint( $order_id );

		if ( ! $order_id ) {
			return;
		}

		$cart_id = $this->locate_cart_for_order( $order_id );

		if ( ! $cart_id ) {
			return;
		}

		$cart = $wpdb->get_row(
			$wpdb->prepare(
				"SELECT * FROM {$wpdb->prefix}cartninja_carts WHERE id = %d",
				$cart_id
			),
			ARRAY_A
		);

		if ( ! $cart ) {
			return;
		}

		if ( 'active' === $cart['status'] ) {
			$wpdb->delete( $wpdb->prefix . 'cartninja_notifications', array( 'cart_id' => $cart_id ), array( '%d' ) );
			$wpdb->delete( $wpdb->prefix . 'cartninja_carts', array( 'id' => $cart_id ), array( '%d' ) );

			if ( function_exists( 'WC' ) && WC() && WC()->session ) {
				WC()->session->__unset( 'cartninja_recovered_cart_id' );
				WC()->session->__unset( 'cartninja_recovery_token' );
			}
			return;
		}

		$wpdb->update(
			$wpdb->prefix . 'cartninja_carts',
			array(
				'status'             => 'recovered',
				'recovered_order_id' => absint( $order_id ),
				'recovered_at'       => current_time( 'mysql' ),
				'recovery_expires_at' => current_time( 'mysql' ),
			),
			array( 'id' => $cart_id ),
			array( '%s', '%d', '%s', '%s' ),
			array( '%d' )
		);

		if ( function_exists( 'WC' ) && WC() && WC()->session ) {
			WC()->session->__unset( 'cartninja_recovered_cart_id' );
			WC()->session->__unset( 'cartninja_recovery_token' );
		}
	}

	private function redirect_invalid_recovery_link() {
		$settings     = get_option( 'cartninja_settings', array() );
		$general      = isset( $settings['general'] ) && is_array( $settings['general'] ) ? $settings['general'] : array();
		$recovery_url = ! empty( $general['recovery_url_base'] ) ? esc_url_raw( $general['recovery_url_base'] ) : ( function_exists( 'wc_get_cart_url' ) ? wc_get_cart_url() : home_url( '/cart/' ) );

		if ( function_exists( 'wc_add_notice' ) ) {
			wc_add_notice( __( 'This cart recovery link has expired or is no longer available.', 'cartninja-recovery-for-woocommerce' ), 'notice' );
		}

		wp_safe_redirect( remove_query_arg( 'cartninja_token', $recovery_url ) );
		exit;
	}

	private function locate_cart_for_order( $order_id ) {
		global $wpdb;

		$cart_id    = 0;
		$session_id = '';
		$email      = '';
		$phone      = '';
		$order      = function_exists( 'wc_get_order' ) ? wc_get_order( $order_id ) : false;

		if ( function_exists( 'WC' ) && WC() && WC()->session ) {
			$cart_id    = absint( WC()->session->get( 'cartninja_recovered_cart_id' ) );
			$session_id = sanitize_text_field( WC()->session->get_customer_id() );
		}

		if ( $cart_id ) {
			return $cart_id;
		}

		if ( $order ) {
			$email = sanitize_email( $order->get_billing_email() );
			$phone = preg_replace( '/[^0-9+\-]/', '', (string) $order->get_billing_phone() );
		}

		if ( ! empty( $session_id ) ) {
			$cart_id = (int) $wpdb->get_var(
				$wpdb->prepare(
					"SELECT id FROM {$wpdb->prefix}cartninja_carts WHERE session_id = %s AND status IN ('active','abandoned','recovering','lost') AND recovered_order_id IS NULL ORDER BY cart_updated_at DESC LIMIT 1",
					$session_id
				)
			);
		}

		if ( $cart_id ) {
			return $cart_id;
		}

		if ( ! empty( $email ) ) {
			$cart_id = (int) $wpdb->get_var(
				$wpdb->prepare(
					"SELECT id FROM {$wpdb->prefix}cartninja_carts WHERE email = %s AND status IN ('active','abandoned','recovering','lost') AND recovered_order_id IS NULL ORDER BY cart_updated_at DESC LIMIT 1",
					$email
				)
			);
		}

		if ( $cart_id ) {
			return $cart_id;
		}

		if ( ! empty( $phone ) ) {
			$cart_id = (int) $wpdb->get_var(
				$wpdb->prepare(
					"SELECT id FROM {$wpdb->prefix}cartninja_carts WHERE phone = %s AND status IN ('active','abandoned','recovering','lost') AND recovered_order_id IS NULL ORDER BY cart_updated_at DESC LIMIT 1",
					$phone
				)
			);
		}

		return $cart_id;
	}

	private function mark_notification_clicked( $cart_id ) {
		global $wpdb;

		$notifications_table = $wpdb->prefix . 'cartninja_notifications';
		$notification_id     = $wpdb->get_var(
			$wpdb->prepare(
				"SELECT id FROM {$notifications_table} WHERE cart_id = %d ORDER BY id DESC LIMIT 1",
				$cart_id
			)
		);

		if ( ! $notification_id ) {
			return;
		}

		$wpdb->update(
			$notifications_table,
			array(
				'status'     => 'clicked',
				'clicked_at' => current_time( 'mysql' ),
			),
			array( 'id' => absint( $notification_id ) ),
			array( '%s', '%s' ),
			array( '%d' )
		);
	}
}
