<?php
/**
 * Main Abandoned Cart Module File.
 *
 * @package automation-web-platform
 */

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


if ( ! class_exists( 'WAWP_Abandoned_Carts' ) ) {

	/**
	 * Class WAWP_Abandoned_Carts.
	 * Main controller for the Abandoned Cart module.
	 *
	 * @package automation-web-platform
	 */
	class WAWP_Abandoned_Carts {
		use WAWP_Security_Trait;
		use WAWP_Abandoned_Cart_Logic;
		use WAWP_Settings_Handler;
		use WAWP_Phone_Helper_Trait;
		use WAWP_Logging_Trait;
		use WAWP_Abandoned_Cart_Helper_Trait;
		use WAWP_Abandoned_Cart_Frontend;
		use WAWP_Abandoned_Cart_Backend;

		/**
		 * Option name.
		 *
		 * @var string
		 */
		private $option_name = WAWP_Settings_Registry::ABANDONED_CART_SETTINGS;

		/**
		 * Notifications instance.
		 *
		 * @var WAWP_Abandoned_Cart_Notifications
		 */
		public $notifications;

		/**
		 * Constructor.
		 */
		public function __construct() {
			if ( ! class_exists( 'WooCommerce' ) || ! $this->get_wawp_setting( WAWP_Settings_Registry::ABANDONED_CARTS_ENABLED, 1 ) ) {
				return;
			}

			// Initialize Notifications.
			require_once WAWP_PLUGIN_DIR . 'includes/abandoned-cart/class-wawp-abandoned-cart-notifications.php';
			$this->notifications = WAWP_Abandoned_Cart_Notifications::get_instance();

			// Hooks.
			add_action( 'init', array( $this, 'cleanup_empty_records' ) );
			add_action( 'init', array( $this, 'init_session' ) );
			add_action( 'wp', array( $this, 'capture_ip_user_agent' ) );
			add_action( 'woocommerce_cart_updated', array( $this, 'cart_updated' ) );
			add_action( 'woocommerce_checkout_update_order_review', array( $this, 'checkout_update_order_review' ), 10, 1 );
			add_action( 'woocommerce_thankyou', array( $this, 'order_thankyou' ) );
			add_action( 'woocommerce_add_to_cart', array( $this, 'woocommerce_add_to_cart_callback' ), 10, 4 );
			add_action( 'woocommerce_remove_cart_item', array( $this, 'track_removed_from_cart' ), 10, 2 );
			add_action( 'wp_enqueue_scripts', array( $this, 'enqueue_scripts' ) );
			add_filter( 'wawp_frontend_global_vars', array( $this, 'add_frontend_global_vars' ) );
			add_action( 'wp_footer', array( $this, 'add_popup' ) );
			add_filter( 'woocommerce_checkout_get_value', array( $this, 'prefill_checkout_fields' ), 10, 2 );
			add_action( 'wp_loaded', array( $this, 'restore_abandoned_cart' ) );
			add_action( 'wp_login', array( $this, 'handle_user_login' ), 10, 2 );
			add_action( 'user_register', array( $this, 'handle_user_register' ) );

			// Legacy AJAX Handlers (To be migrated).
			add_action( 'wp_ajax_nopriv_wawp_save_phone', array( $this, 'save_phone_number' ) );
			add_action( 'wp_ajax_wawp_save_phone', array( $this, 'save_phone_number' ) );
			add_action( 'wp_ajax_nopriv_wawp_reclaim_session', array( $this, 'reclaim_session' ) );
			add_action( 'wp_ajax_wawp_reclaim_session', array( $this, 'reclaim_session' ) );
			add_action( 'wp_ajax_nopriv_wawp_track_page', array( $this, 'track_page' ) );
			add_action( 'wp_ajax_wawp_track_page', array( $this, 'track_page' ) );
		}

		/**
		 * Alias for REST API compatibility.
		 *
		 * @param array $params Request parameters.
		 * @return array Result data.
		 */
		public function get_sessions( $params ) {
			return $this->get_sessions_return( $params );
		}

		/**
		 * Hooked to woocommerce_add_to_cart.
		 *
		 * @param string $cart_item_key  Cart item key.
		 * @param int    $product_id     Product ID.
		 * @param int    $quantity       Quantity.
		 * @param int    $variation_id  Variation ID.
		 */
		public function woocommerce_add_to_cart_callback( $cart_item_key, $product_id, $quantity, $variation_id ) {
			if ( empty( $_SESSION['wac_session'] ) ) {
				return;
			}

			$session_id = sanitize_text_field( wp_unslash( $_SESSION['wac_session'] ) );
			$product    = function_exists( 'wc_get_product' ) ? wc_get_product( $variation_id ? $variation_id : $product_id ) : null;
			if ( $product ) {
				global $wpdb;
				$table = $wpdb->prefix . 'wawp_abandoned_carts';

				$row = WAWP()->db->get_results_cached( $wpdb->prepare( 'SELECT id, cart_contents, cart_total, contact_details FROM %i WHERE session_id = %s ORDER BY id DESC LIMIT 1', $table, $session_id ), 'wac_session_' . md5( (string) $session_id ), 'wawp_abandoned_carts', 300 );
				$row = ! empty( $row ) ? (object) $row[0] : null;

				$cart_items = $row ? maybe_unserialize( $row->cart_contents ) : array();
				if ( ! is_array( $cart_items ) ) {
					$cart_items = array();
				}

				$contact_details = $row ? maybe_unserialize( $row->contact_details ) : array();
				if ( ! is_array( $contact_details ) ) {
					$contact_details = array();
				}

				$cart_total   = $row ? (float) $row->cart_total : 0.0;
				$cart_items[] = array(
					'product_id'   => $product_id,
					'variation_id' => $variation_id,
					'quantity'     => $quantity,
					'name'         => $product->get_name(),
					'price'        => $product->get_price(),
				);

				$cart_total += ( $product->get_price() * $quantity );

				$this->insert_or_update( $session_id, get_current_user_id(), maybe_serialize( $contact_details ), '', maybe_serialize( $cart_items ), $cart_total, 'shopping' );
				$this->add_history_event(
					'cart_add',
					array(
						'link'  => $product->get_permalink(),
						'name'  => $product->get_name(),
						'price' => $product->get_price(),
						'qty'   => $quantity,
					)
				);

				if ( $row ) {
					$this->notifications->schedule_notifications_for_cart( $row->id, 'abandoned_cart' );
					do_action( 'wawp_abandoned_cart_trigger', $row->id, 'abandoned_cart' );
					do_action( 'wawp_abandoned_cart_trigger', $row->id, 'shopping' );
				}
			}
		}

		/**
		 *  Track item removal from cart.
		 *
		 * @param string  $cart_item_key Cart item key.
		 * @param WC_Cart $cart          Cart object.
		 */
		public function track_removed_from_cart( $cart_item_key, $cart ) {
			if ( empty( $_SESSION['wac_session'] ) ) {
				return;
			}

			$item = $cart->removed_cart_contents[ $cart_item_key ] ?? null;
			if ( ! $item ) {
				return;
			}

			$product = function_exists( 'wc_get_product' ) ? wc_get_product( $item['variation_id'] ? $item['variation_id'] : $item['product_id'] ) : null;
			if ( ! $product ) {
				return;
			}

			$this->add_history_event(
				'cart_remove',
				array(
					'link'  => $product->get_permalink(),
					'name'  => $product->get_name(),
					'price' => function_exists( 'wc_price' ) ? wc_price( $product->get_price() ) : $product->get_price(),
					'qty'   => $item['quantity'] ?? 1,
				)
			);
		}

		/**
		 * Core method to insert or update cart records.
		 *
		 * @param string      $session_id   Session ID.
		 * @param int         $user_id      User ID.
		 * @param string      $contact      Contact details (serialized).
		 * @param string      $loc          Location.
		 * @param string      $contents     Cart contents (serialized).
		 * @param float       $total        Cart total.
		 * @param string      $status       Status.
		 * @param string      $browser      Browser info.
		 * @param string      $os           OS info.
		 * @param string      $device       Device info.
		 * @param string      $order_id     Order ID.
		 * @param string|null $page_history Page history.
		 * @param string      $screen_size  Screen size.
		 */
		public function insert_or_update( $session_id, $user_id = 0, $contact = '', $loc = '', $contents = '', $total = 0.0, $status = '', $browser = '', $os = '', $device = '', $order_id = '', $page_history = null, $screen_size = '' ) {
			if ( is_user_logged_in() && current_user_can( 'manage_options' ) ) {
				return false;
			}
			global $wpdb;
			$table = $wpdb->prefix . 'wawp_abandoned_carts';

			$row = WAWP()->db->get_results_cached( $wpdb->prepare( 'SELECT * FROM %i WHERE session_id = %s ORDER BY id DESC LIMIT 1', $table, $session_id ), 'wac_session_full_' . md5( (string) $session_id ), 'wawp_abandoned_carts', 300 );
			$row = ! empty( $row ) ? (object) $row[0] : null;

			if ( is_user_logged_in() ) {
				$user_id   = get_current_user_id();
				$user_meta = array(
					'billing_first_name' => get_user_meta( $user_id, 'billing_first_name', true ),
					'billing_last_name'  => get_user_meta( $user_id, 'billing_last_name', true ),
					'billing_email'      => get_user_meta( $user_id, 'billing_email', true ),
					'billing_phone'      => WAWP()->user_manager->get_user_phone( $user_id ),
					'billing_country'    => get_user_meta( $user_id, 'billing_country', true ),
					'billing_city'       => get_user_meta( $user_id, 'billing_city', true ),
					'billing_address_1'  => get_user_meta( $user_id, 'billing_address_1', true ),
					'billing_address_2'  => get_user_meta( $user_id, 'billing_address_2', true ),
					'billing_state'      => get_user_meta( $user_id, 'billing_state', true ),
					'billing_postcode'   => get_user_meta( $user_id, 'billing_postcode', true ),
				);

				$existing_cd = ( ! empty( $contact ) ) ? maybe_unserialize( $contact ) : ( ( $row && ! empty( $row->contact_details ) ) ? maybe_unserialize( $row->contact_details ) : array() );
				if ( ! is_array( $existing_cd ) ) {
					$existing_cd = array();
				}

				foreach ( $user_meta as $key => $value ) {
					if ( empty( $existing_cd[ $key ] ) && ! empty( $value ) ) {
						$existing_cd[ $key ] = $value;
					}
				}

				$contact = maybe_serialize( $existing_cd );
				if ( 'new' === strtolower( $status ) || empty( $status ) ) {
					$status = 'returning customer';
				}
			}

			$data = array(
				'session_id' => $session_id,
				'updated_at' => current_time( 'mysql', true ),
			);

			if ( $user_id ) {
				$data['user_id'] = $user_id;
			}
			if ( '' !== $contact ) {
				$data['contact_details'] = $contact;
			}
			if ( '' !== $loc ) {
				$data['location'] = $loc;
			}
			if ( '' !== $contents ) {
				$data['cart_contents'] = $contents;
			}
			if ( 0.0 !== $total ) {
				$data['cart_total'] = $total;
			}
			if ( '' !== $status ) {
				$data['status'] = $status;
			}
			if ( '' !== $order_id ) {
				$existing_orders = ( $row && ! empty( $row->order_id ) ) ? explode( ',', $row->order_id ) : array();
				if ( ! in_array( (string) $order_id, $existing_orders, true ) ) {
					$existing_orders[] = (string) $order_id;
				}
				$data['order_id'] = implode( ',', array_filter( $existing_orders ) );
			}
			if ( '' !== $browser ) {
				$data['browser'] = $browser;
			}
			if ( '' !== $os ) {
				$data['os'] = $os;
			}
			if ( '' !== $device ) {
				$data['device'] = $device;
			}
			if ( '' !== $screen_size ) {
				$data['screen_size'] = $screen_size;
			}
			if ( null !== $page_history ) {
				$data['page_history'] = $page_history;
			}

			if ( $row ) {
				WAWP()->db->update_row( 'abandoned_carts', $data, array( 'id' => $row->id ) );
			} else {
				if ( empty( $data['status'] ) ) {
					$data['status'] = 'new';
				}
				$data['created_at'] = current_time( 'mysql', true );

				WAWP()->db->insert( 'abandoned_carts', $data );
			}
			wp_cache_delete( 'wac_session_full_' . md5( (string) $session_id ), 'wawp_abandoned_carts' );
			wp_cache_delete( 'wac_session_' . md5( (string) $session_id ), 'wawp_abandoned_carts' );
		}

		/**
		 * Maintenance: Cleanup empty/bot records.
		 */
		public function cleanup_empty_records() {
			if ( ! $this->get_wawp_setting( WAWP_Settings_Registry::AC_ENABLE_DATA_CLEANER, 0 ) ) {
				return;
			}

			$counter                         = isset( $_SESSION['wac_cleanup_counter'] ) ? (int) $_SESSION['wac_cleanup_counter'] : 0;
			$_SESSION['wac_cleanup_counter'] = $counter + 1;
			if ( $counter < 3 ) {
				return;
			}

			global $wpdb;
			$table = $wpdb->prefix . 'wawp_abandoned_carts';

			WAWP()->db->query( $wpdb->prepare( "DELETE FROM %i WHERE (location IS NULL OR location = '') AND (contact_details IS NULL OR contact_details = '' OR contact_details = 'a:0:{}')", $table ) );
		}

		/**
		 * Handle phone number saving from popup.
		 */
		public function save_phone_number() {
			$nonce = isset( $_POST['nonce'] ) ? sanitize_text_field( wp_unslash( $_POST['nonce'] ) ) : '';
			if ( ! wp_verify_nonce( $nonce, 'wawp_nonce' ) ) {
				$this->send_error( esc_html__( 'Security check failed.', 'automation-web-platform' ), 403 );
			}
			$res = $this->save_phone_number_return( $_POST );

			if ( $res['success'] ) {
				$this->send_success( $res['message'], $res['data'] ?? array() );
			} else {
				$this->send_error( $res['message'] );
			}
		}

		/**
		 * Internal logic for saving phone number.
		 *
		 * @param array $data Input data.
		 * @return array Result data.
		 */
		public function save_phone_number_return( $data ) {
			if ( empty( $data['phone_number'] ) ) {
				return array(
					'success' => false,
					'message' => esc_html__( 'Phone number is required.', 'automation-web-platform' ),
				);
			}

			$phone_number = $this->get_digits_only( $data['phone_number'] );
			$user_id      = get_current_user_id();
			$contact      = array();
			global $wpdb;
			$table = $wpdb->prefix . 'wawp_abandoned_carts';

			if ( $user_id ) {
				WAWP()->connector->sync_user_phone( $user_id, $phone_number );
				$_SESSION['login_your_whatsapp'] = $phone_number;
			} else {
				setcookie( 'New_phone', $phone_number, time() + ( 30 * 24 * 60 * 60 ), '/' );
			}

			$session_id = $this->get_cart_session_id();
			if ( $session_id ) {
				$row     = WAWP()->db->get_results_cached( $wpdb->prepare( 'SELECT id, contact_details FROM %i WHERE session_id = %s ORDER BY id DESC LIMIT 1', $table, $session_id ), 'wac_session_contact_' . md5( (string) $session_id ), 'wawp_abandoned_carts', 300 );
				$row_arr = ! empty( $row ) ? (array) $row[0] : null;
				if ( $row_arr ) {
					$contact = maybe_unserialize( $row_arr['contact_details'] );
				}
				if ( ! is_array( $contact ) ) {
					$contact = array();
				}
				$contact['billing_phone'] = $phone_number;

				if ( method_exists( $this, 'lookup_phone_carrier' ) ) {
					$carrier = $this->lookup_phone_carrier( $phone_number );
					if ( $carrier ) {
						$contact['billing_carrier'] = $carrier;
					}
				}

				$this->insert_or_update( $session_id, $user_id, maybe_serialize( $contact ), '', '', 0.0, 'potential customer' );

				// Record history event for contact info submission.
				$this->add_history_event(
					'contact_info',
					array(
						'phone' => $phone_number,
						'email' => $contact['billing_email'] ?? '',
					)
				);

				// Re-fetch to get correct ID for notifications.
				$cart_row     = WAWP()->db->get_results_cached( $wpdb->prepare( 'SELECT id FROM %i WHERE session_id = %s ORDER BY id DESC LIMIT 1', $table, $session_id ), 'wac_session_id_only_' . md5( (string) $session_id ), 'wawp_abandoned_carts', 60 );
				$cart_row_arr = ! empty( $cart_row ) ? (array) $cart_row[0] : null;
				if ( $cart_row_arr ) {
					$this->notifications->schedule_notifications_for_cart( $cart_row_arr['id'], 'potential_customer' );
					do_action( 'wawp_abandoned_cart_trigger', $cart_row_arr['id'], 'potential_customer' );
				}
			}

			return array(
				'success' => true,
				'message' => esc_html__( 'Phone number saved successfully.', 'automation-web-platform' ),
			);
		}

		/**
		 * Handle user login session merge.
		 *
		 * @param string  $user_login User login.
		 * @param WP_User $user       User object.
		 */
		public function handle_user_login( $user_login, $user ) {
			if ( empty( $_SESSION['wac_session'] ) || ! $user ) {
				return;
			}
			$session_id = sanitize_text_field( wp_unslash( $_SESSION['wac_session'] ) );
			global $wpdb;
			$table     = $wpdb->prefix . 'wawp_abandoned_carts';
			$guest_row = WAWP()->db->get_results_cached( $wpdb->prepare( 'SELECT * FROM %i WHERE session_id = %s AND (user_id IS NULL OR user_id = 0) ORDER BY id DESC LIMIT 1', $table, $session_id ), 'wac_guest_row_' . md5( (string) $session_id ), 'wawp_abandoned_carts', 60 );
			$guest_row = ! empty( $guest_row ) ? (object) $guest_row[0] : null;

			if ( ! $guest_row ) {
				return;
			}

			$user_row = WAWP()->db->get_results_cached( $wpdb->prepare( "SELECT * FROM %i WHERE user_id = %d AND status <> 'purchased' ORDER BY id DESC LIMIT 1", $table, $user->ID ), 'wac_user_row_' . $user->ID, 'wawp_abandoned_carts', 60 );
			$user_row = ! empty( $user_row ) ? (object) $user_row[0] : null;
			if ( $user_row ) {
				// Simple merge for now.
				WAWP()->db->delete_row( 'abandoned_carts', array( 'id' => $guest_row->id ) );
			} else {
				WAWP()->db->update_row(
					'abandoned_carts',
					array(
						'user_id' => $user->ID,
						'status'  => 'returning customer',
					),
					array( 'id' => $guest_row->id )
				);
			}
			wp_cache_delete( 'wac_session_' . md5( (string) $session_id ), 'wawp_abandoned_carts' );

			$this->add_history_event( 'user_login', 'User logged in: ' . $user->user_login );
		}

		/**
		 * Handle user registration.
		 *
		 * @param int $user_id User ID.
		 */
		public function handle_user_register( $user_id ) {
			if ( empty( $_SESSION['wac_session'] ) ) {
				return;
			}
			$user = get_userdata( $user_id );
			$this->add_history_event( 'user_signup', 'User signed up: ' . $user->user_login );
		}
	}
}
