<?php
/**
 * ActiveTrail Event Handler
 *
 * @package ActiveTrail_WooCommerce
 * @since 1.0.0
 */

// Prevent direct access
if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

/**
 * ActiveTrail Event Handler Class
 *
 * Handles all ecommerce event tracking and sending to ActiveTrail
 */
class ActiveTrail_Event_Handler {

	/**
	 * API Client instance
	 *
	 * @var ActiveTrail_API_Client
	 */
	private $api_client;

	/**
	 * Plugin settings
	 *
	 * @var array
	 */
	private $settings;

	/**
	 * Event queue for batching
	 *
	 * @var array
	 */
	private $event_queue = array();

	/**
	 * Constructor
	 *
	 * @param ActiveTrail_API_Client $api_client API client instance
	 * @param array                  $settings Plugin settings
	 */
	public function __construct( $api_client, $settings ) {
		$this->api_client = $api_client;
		$this->settings   = $settings;

		$this->init_hooks();
		$this->create_events_table();
	}

	/**
	 * Initialize WordPress hooks
	 */
	private function init_hooks() {
		// Product view tracking
		add_action( 'woocommerce_single_product_summary', array( $this, 'track_product_view' ), 5 );

		// Cart event tracking
		add_action( 'woocommerce_add_to_cart', array( $this, 'track_add_to_cart' ), 10, 6 );
		add_action( 'woocommerce_cart_item_removed', array( $this, 'track_remove_from_cart' ), 10, 2 );
		add_action( 'woocommerce_after_cart_item_quantity_update', array( $this, 'track_cart_quantity_update' ), 10, 4 );

		// Checkout tracking
		add_action( 'woocommerce_checkout_init', array( $this, 'track_checkout_start' ) );
		add_action( 'woocommerce_checkout_order_processed', array( $this, 'track_purchase' ), 10, 3 );

		// AJAX hooks for frontend events
		add_action( 'wp_ajax_activetrail_track_event', array( $this, 'ajax_track_event' ) );
		add_action( 'wp_ajax_nopriv_activetrail_track_event', array( $this, 'ajax_track_event' ) );

		// Batch event processing
		add_action( 'activetrail_process_event_queue', array( $this, 'process_event_queue' ) );

		// Enqueue frontend scripts
		add_action( 'wp_enqueue_scripts', array( $this, 'enqueue_frontend_scripts' ) );
	}

	/**
	 * Create events tracking table
	 */
	private function create_events_table() {
		global $wpdb;

		$table_name = $wpdb->prefix . 'activetrail_events';

		$charset_collate = $wpdb->get_charset_collate();

		$sql = "CREATE TABLE $table_name (
            id bigint(20) NOT NULL AUTO_INCREMENT,
            event_type varchar(50) NOT NULL,
            customer_email varchar(100) DEFAULT NULL,
            customer_id bigint(20) DEFAULT NULL,
            session_id varchar(255) DEFAULT NULL,
            product_id bigint(20) DEFAULT NULL,
            order_id bigint(20) DEFAULT NULL,
            event_data longtext DEFAULT NULL,
            event_value decimal(10,2) DEFAULT NULL,
            currency varchar(3) DEFAULT NULL,
            created_at datetime DEFAULT CURRENT_TIMESTAMP,
            synced tinyint(1) DEFAULT 0,
            sync_attempts int(11) DEFAULT 0,
            last_sync_attempt datetime DEFAULT NULL,
            PRIMARY KEY (id),
            KEY event_type (event_type),
            KEY customer_email (customer_email),
            KEY customer_id (customer_id),
            KEY product_id (product_id),
            KEY synced (synced),
            KEY created_at (created_at)
        ) $charset_collate;";

		require_once ABSPATH . 'wp-admin/includes/upgrade.php';
		dbDelta( $sql );
	}

	/**
	 * Enqueue frontend scripts for event tracking
	 */
	public function enqueue_frontend_scripts() {
		if ( ! is_admin() ) {
			wp_enqueue_script(
				'activetrail-event-tracker',
				ACTIVETRAIL_WC_PLUGIN_URL . 'assets/js/event-tracker.js',
				array( 'jquery' ),
				ACTIVETRAIL_WC_VERSION,
				true
			);

			wp_localize_script(
				'activetrail-event-tracker',
				'activetrail_events',
				array(
					'ajax_url'       => admin_url( 'admin-ajax.php' ),
					'nonce'          => wp_create_nonce( 'activetrail_track_event' ),
					'customer_email' => $this->get_customer_email(),
					'session_id'     => $this->get_session_id(),
					'currency'       => get_woocommerce_currency(),
					'debug'          => defined( 'WP_DEBUG' ) && WP_DEBUG,
				)
			);
		}
	}

	/**
	 * Track product view event
	 */
	public function track_product_view() {
		global $product;

		if ( ! $product || ! is_product() ) {
			return;
		}

		$this->track_event(
			'product_view',
			array(
				'product_id'       => $product->get_id(),
				'product_name'     => $product->get_name(),
				'product_price'    => $product->get_price(),
				'product_category' => $this->get_product_categories( $product ),
				'product_sku'      => $product->get_sku(),
				'product_url'      => get_permalink( $product->get_id() ),
			)
		);
	}

	/**
	 * Track add to cart event
	 *
	 * @param string $cart_item_key Cart item key
	 * @param int    $product_id Product ID
	 * @param int    $quantity Quantity
	 * @param int    $variation_id Variation ID
	 * @param array  $variation Variation data
	 * @param array  $cart_item_data Cart item data
	 */
	public function track_add_to_cart( $cart_item_key, $product_id, $quantity, $variation_id, $variation, $cart_item_data ) {
		$product = wc_get_product( $product_id );
		if ( ! $product ) {
			return;
		}

		$this->track_event(
			'add_to_cart',
			array(
				'product_id'       => $product_id,
				'variation_id'     => $variation_id,
				'product_name'     => $product->get_name(),
				'product_price'    => $product->get_price(),
				'quantity'         => $quantity,
				'line_total'       => $product->get_price() * $quantity,
				'product_category' => $this->get_product_categories( $product ),
				'product_sku'      => $product->get_sku(),
				'cart_total'       => WC()->cart ? WC()->cart->get_total( 'edit' ) : 0,
			),
			$product->get_price() * $quantity
		);
	}

	/**
	 * Track remove from cart event
	 *
	 * @param string  $cart_item_key Cart item key
	 * @param WC_Cart $cart Cart object
	 */
	public function track_remove_from_cart( $cart_item_key, $cart ) {
		// Get the removed item from cart contents
		$removed_item = isset( $cart->removed_cart_contents[ $cart_item_key ] ) ? $cart->removed_cart_contents[ $cart_item_key ] : null;

		if ( ! $removed_item ) {
			$this->log( 'Failed to track remove from cart: removed item not found for key ' . $cart_item_key, 'warning' );
			return;
		}

		$product = isset( $removed_item['data'] ) && $removed_item['data'] ? $removed_item['data'] : null;
		// Fallback: WooCommerce may not always put the product object in removed_cart_contents (e.g. session storage).
		if ( ! $product && ! empty( $removed_item['product_id'] ) ) {
			$product = wc_get_product( ! empty( $removed_item['variation_id'] ) ? $removed_item['variation_id'] : $removed_item['product_id'] );
		}
		if ( ! $product || ! is_a( $product, 'WC_Product' ) ) {
			$this->log( 'Failed to track remove from cart: product data missing for key ' . $cart_item_key, 'warning' );
			return;
		}

		$this->track_event(
			'remove_from_cart',
			array(
				'product_id'       => isset( $removed_item['product_id'] ) ? $removed_item['product_id'] : 0,
				'variation_id'     => isset( $removed_item['variation_id'] ) ? $removed_item['variation_id'] : 0,
				'product_name'     => $product->get_name(),
				'product_price'    => $product->get_price(),
				'quantity'         => isset( $removed_item['quantity'] ) ? $removed_item['quantity'] : 1,
				'line_total'       => isset( $removed_item['line_total'] ) ? $removed_item['line_total'] : 0,
				'product_category' => $this->get_product_categories( $product ),
				'product_sku'      => $product->get_sku(),
				'cart_total'       => $cart->get_total( 'edit' ),
			),
			isset( $removed_item['line_total'] ) ? $removed_item['line_total'] : 0
		);
	}

	/**
	 * Track cart quantity update event
	 *
	 * @param string  $cart_item_key Cart item key
	 * @param int     $quantity New quantity
	 * @param int     $old_quantity Old quantity
	 * @param WC_Cart $cart Cart object
	 */
	public function track_cart_quantity_update( $cart_item_key, $quantity, $old_quantity, $cart ) {
		$cart_item = $cart->get_cart_item( $cart_item_key );
		if ( ! $cart_item ) {
			return;
		}

		$product = $cart_item['data'];
		if ( ! $product ) {
			return;
		}

		$this->track_event(
			'cart_update',
			array(
				'product_id'       => $cart_item['product_id'],
				'variation_id'     => $cart_item['variation_id'] ?? 0,
				'product_name'     => $product->get_name(),
				'product_price'    => $product->get_price(),
				'old_quantity'     => $old_quantity,
				'new_quantity'     => $quantity,
				'quantity_change'  => $quantity - $old_quantity,
				'line_total'       => $cart_item['line_total'],
				'product_category' => $this->get_product_categories( $product ),
				'product_sku'      => $product->get_sku(),
				'cart_total'       => $cart->get_total( 'edit' ),
			),
			$cart_item['line_total']
		);
	}

	/**
	 * Track checkout start event
	 */
	public function track_checkout_start() {
		if ( ! WC()->cart || WC()->cart->is_empty() ) {
			return;
		}

		$cart_items = array();
		foreach ( WC()->cart->get_cart() as $cart_item ) {
			$product = $cart_item['data'];
			if ( $product ) {
				$cart_items[] = array(
					'product_id'   => $cart_item['product_id'],
					'product_name' => $product->get_name(),
					'quantity'     => $cart_item['quantity'],
					'price'        => $product->get_price(),
					'line_total'   => $cart_item['line_total'],
				);
			}
		}

		$this->track_event(
			'checkout_start',
			array(
				'cart_total'       => WC()->cart->get_total( 'edit' ),
				'cart_items_count' => WC()->cart->get_cart_contents_count(),
				'cart_items'       => $cart_items,
				'currency'         => get_woocommerce_currency(),
			),
			WC()->cart->get_total( 'edit' )
		);
	}

	/**
	 * Track purchase event (enhanced)
	 *
	 * @param int      $order_id Order ID
	 * @param array    $posted_data Posted data
	 * @param WC_Order $order Order object
	 */
	public function track_purchase( $order_id, $posted_data, $order ) {
		$order_items = array();
		foreach ( $order->get_items() as $item ) {
			$product = $item->get_product();
			if ( $product ) {
				$order_items[] = array(
					'product_id'   => $product->get_id(),
					'product_name' => $product->get_name(),
					'quantity'     => $item->get_quantity(),
					'price'        => $item->get_total() / $item->get_quantity(),
					'line_total'   => $item->get_total(),
					'category'     => $this->get_product_categories( $product ),
				);
			}
		}

		$this->track_event(
			'purchase',
			array(
				'order_id'          => $order_id,
				'order_number'      => $order->get_order_number(),
				'order_total'       => $order->get_total(),
				'order_subtotal'    => $order->get_subtotal(),
				'order_tax'         => $order->get_total_tax(),
				'order_shipping'    => $order->get_shipping_total(),
				'order_items'       => $order_items,
				'order_items_count' => count( $order_items ),
				'currency'          => $order->get_currency(),
				'payment_method'    => $order->get_payment_method(),
				'coupons'           => $order->get_coupon_codes(),
			),
			$order->get_total(),
			$order_id
		);
	}

	/**
	 * AJAX handler for frontend event tracking
	 */
	public function ajax_track_event() {
		check_ajax_referer( 'activetrail_track_event', 'nonce' );

		$event_type = isset( $_POST['event_type'] ) ? sanitize_text_field( wp_unslash( $_POST['event_type'] ) ) : '';
        // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- event_data is an array that will be sanitized when used
		$event_data  = isset( $_POST['event_data'] ) ? wp_unslash( $_POST['event_data'] ) : array();
		$event_value = isset( $_POST['event_value'] ) ? floatval( wp_unslash( $_POST['event_value'] ) ) : 0;

		if ( empty( $event_type ) ) {
			wp_send_json_error( 'Event type is required' );
		}

		// Sanitize event data
		$event_data = $this->sanitize_event_data( $event_data );

		$result = $this->track_event( $event_type, $event_data, $event_value );

		if ( $result ) {
			wp_send_json_success( 'Event tracked successfully' );
		} else {
			wp_send_json_error( 'Failed to track event' );
		}
	}

	/**
	 * Track an event
	 *
	 * @param string $event_type Event type
	 * @param array  $event_data Event data
	 * @param float  $event_value Event value (optional)
	 * @param int    $order_id Order ID (optional)
	 * @return bool
	 */
	public function track_event( $event_type, $event_data = array(), $event_value = 0, $order_id = null ) {
		global $wpdb;

		// Check if event tracking is enabled for this event type
		if ( ! $this->is_event_tracking_enabled( $event_type ) ) {
			return false;
		}

		$table_name = $wpdb->prefix . 'activetrail_events';

		$data = array(
			'event_type'     => $event_type,
			'customer_email' => $this->get_customer_email(),
			'customer_id'    => get_current_user_id() ?: null,
			'session_id'     => $this->get_session_id(),
			'product_id'     => isset( $event_data['product_id'] ) ? intval( $event_data['product_id'] ) : null,
			'order_id'       => $order_id,
			'event_data'     => wp_json_encode( $event_data ),
			'event_value'    => $event_value,
			'currency'       => get_woocommerce_currency(),
			'created_at'     => current_time( 'mysql' ),
		);

        // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery -- Direct query needed for event tracking
		$result = $wpdb->insert( $table_name, $data );

		if ( $result ) {
			$this->log( 'Event tracked: ' . $event_type . ' (ID: ' . $wpdb->insert_id . ')' );

			// Add to immediate processing queue for high-priority events
			if ( in_array( $event_type, array( 'purchase', 'add_to_cart' ) ) ) {
				$this->queue_event_for_immediate_processing( $wpdb->insert_id );
			}

			return true;
		} else {
			$this->log( 'Failed to track event: ' . $event_type, 'error' );
			return false;
		}
	}

	/**
	 * Queue event for immediate processing
	 *
	 * @param int $event_id Event ID
	 */
	private function queue_event_for_immediate_processing( $event_id ) {
		// Process immediately for critical events
		wp_schedule_single_event( time() + 10, 'activetrail_process_single_event', array( $event_id ) );
	}

	/**
	 * Process event queue (scheduled task)
	 */
	public function process_event_queue() {
		global $wpdb;

		$table_name = $wpdb->prefix . 'activetrail_events';
		$table      = esc_sql( $table_name );

		// Get unsynced events (limit to 50 per batch)
        // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching,WordPress.DB.PreparedSQL.InterpolatedNotPrepared -- Direct query needed for event tracking, table name is escaped
        // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared -- Table name is escaped with esc_sql()
        // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching -- Direct query needed for event tracking
		$events = $wpdb->get_results(
            // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared -- Table name is escaped with esc_sql()
			"SELECT * FROM {$table} 
             WHERE synced = 0 
             AND (sync_attempts < 3 OR sync_attempts IS NULL)
             ORDER BY created_at ASC 
             LIMIT 50"
		);

		if ( empty( $events ) ) {
			return;
		}

		$this->log( 'Processing ' . count( $events ) . ' events from queue' );

		foreach ( $events as $event ) {
			$this->process_single_event( $event );
		}
	}

	/**
	 * Process a single event
	 *
	 * @param object $event Event object from database
	 */
	private function process_single_event( $event ) {
		global $wpdb;

		$table_name = $wpdb->prefix . 'activetrail_events';

		// Update sync attempt
        // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching -- Direct query needed for event tracking
		$wpdb->update(
			$table_name,
			array(
				'sync_attempts'     => intval( $event->sync_attempts ) + 1,
				'last_sync_attempt' => current_time( 'mysql' ),
			),
			array( 'id' => $event->id )
		);

		// Send event to ActiveTrail (this would be implemented based on their event API)
		$result = $this->send_event_to_activetrail( $event );

		if ( $result['success'] ) {
			// Mark as synced
            // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching -- Direct query needed for event tracking
			$wpdb->update(
				$table_name,
				array( 'synced' => 1 ),
				array( 'id' => $event->id )
			);

			$this->log( 'Event synced successfully: ' . $event->event_type . ' (ID: ' . $event->id . ')' );
		} else {
			$this->log( 'Failed to sync event: ' . $event->event_type . ' (ID: ' . $event->id . ') - ' . $result['message'], 'error' );
		}
	}

	/**
	 * Send event to ActiveTrail
	 * Note: This is a placeholder - ActiveTrail doesn't have a specific events API endpoint
	 * Events would typically be sent as part of customer data or custom fields
	 *
	 * @param object $event Event object
	 * @return array
	 */
	private function send_event_to_activetrail( $event ) {
		// For now, we'll log the event and mark as successful
		// In a real implementation, you might:
		// 1. Send as custom fields in customer updates
		// 2. Use ActiveTrail's webhook system
		// 3. Store in custom fields for campaign targeting

		$this->log( 'Event data prepared for ActiveTrail: ' . $event->event_type, 'info' );

		return array(
			'success' => true,
			'message' => 'Event logged locally (ActiveTrail integration pending)',
		);
	}

	/**
	 * Get customer email
	 *
	 * @return string
	 */
	private function get_customer_email() {
		$email = '';

		// Try to get from current user
		if ( is_user_logged_in() ) {
			$user  = wp_get_current_user();
			$email = $user->user_email;
		}

		// Try to get from WooCommerce customer
		if ( empty( $email ) && WC()->customer ) {
			$email = WC()->customer->get_billing_email();
		}

		return $email;
	}

	/**
	 * Get session ID
	 *
	 * @return string
	 */
	private function get_session_id() {
		if ( WC()->session ) {
			return WC()->session->get_customer_id();
		}

		return session_id() ?: uniqid( 'activetrail_' );
	}

	/**
	 * Get product categories
	 *
	 * @param WC_Product $product Product object
	 * @return string
	 */
	private function get_product_categories( $product ) {
		$categories = wp_get_post_terms( $product->get_id(), 'product_cat', array( 'fields' => 'names' ) );
		return is_array( $categories ) ? implode( ', ', $categories ) : '';
	}

	/**
	 * Check if event tracking is enabled for event type
	 *
	 * @param string $event_type Event type
	 * @return bool
	 */
	private function is_event_tracking_enabled( $event_type ) {
		$enabled_events = $this->settings['enabled_events'] ?? array(
			'product_view',
			'add_to_cart',
			'remove_from_cart',
			'cart_update',
			'checkout_start',
			'purchase',
		);

		return in_array( $event_type, $enabled_events );
	}

	/**
	 * Sanitize event data
	 *
	 * @param array $data Event data
	 * @return array
	 */
	private function sanitize_event_data( $data ) {
		if ( ! is_array( $data ) ) {
			return array();
		}

		$sanitized = array();
		foreach ( $data as $key => $value ) {
			$key = sanitize_key( $key );

			if ( is_string( $value ) ) {
				$sanitized[ $key ] = sanitize_text_field( $value );
			} elseif ( is_numeric( $value ) ) {
				$sanitized[ $key ] = floatval( $value );
			} elseif ( is_array( $value ) ) {
				$sanitized[ $key ] = $this->sanitize_event_data( $value );
			} else {
				$sanitized[ $key ] = sanitize_text_field( strval( $value ) );
			}
		}

		return $sanitized;
	}

	/**
	 * Get event statistics
	 *
	 * @param int $days Number of days to look back
	 * @return array
	 */
	public function get_event_statistics( $days = 30 ) {
		global $wpdb;

		$table_name = $wpdb->prefix . 'activetrail_events';
		$table      = esc_sql( $table_name );

        // phpcs:disable WordPress.DB.PreparedSQL.InterpolatedNotPrepared
        // phpcs:disable WordPress.DB.DirectDatabaseQuery.DirectQuery
        // phpcs:disable WordPress.DB.DirectDatabaseQuery.NoCaching

		$stats = $wpdb->get_results(
			$wpdb->prepare(
				"
                SELECT
                    event_type,
                    COUNT(*) AS count,
                    SUM(event_value) AS total_value,
                    AVG(event_value) AS avg_value
                FROM {$table}
                WHERE created_at >= DATE_SUB(NOW(), INTERVAL %d DAY)
                GROUP BY event_type
                ORDER BY count DESC
                ",
				$days
			)
		);

        // phpcs:enable WordPress.DB.PreparedSQL.InterpolatedNotPrepared
        // phpcs:enable WordPress.DB.DirectDatabaseQuery.DirectQuery
        // phpcs:enable WordPress.DB.DirectDatabaseQuery.NoCaching

		return $stats;
	}

	/**
	 * Clean old events
	 *
	 * @param int $days Days to keep
	 * @return int Number of deleted events
	 */
	public function clean_old_events( $days = 90 ) {
		global $wpdb;

		$table_name = $wpdb->prefix . 'activetrail_events';
		$table      = esc_sql( $table_name );

        // phpcs:disable WordPress.DB.PreparedSQL.InterpolatedNotPrepared
        // phpcs:disable WordPress.DB.DirectDatabaseQuery.DirectQuery
        // phpcs:disable WordPress.DB.DirectDatabaseQuery.NoCaching

		$deleted = $wpdb->query(
			$wpdb->prepare(
				"
                DELETE FROM {$table}
                WHERE created_at < DATE_SUB(NOW(), INTERVAL %d DAY)
                ",
				$days
			)
		);

        // phpcs:enable WordPress.DB.PreparedSQL.InterpolatedNotPrepared
        // phpcs:enable WordPress.DB.DirectDatabaseQuery.DirectQuery
        // phpcs:enable WordPress.DB.DirectDatabaseQuery.NoCaching

		$this->log( "Cleaned {$deleted} old events" );

		return $deleted;
	}

	/**
	 * Log message
	 *
	 * @param string $message Log message
	 * @param string $level Log level
	 */
	private function log( $message, $level = 'info' ) {
		if ( function_exists( 'activetrail_logger' ) ) {
			$level_map    = array(
				'info'    => 'INFO',
				'debug'   => 'DEBUG',
				'warning' => 'WARNING',
				'error'   => 'ERROR',
			);
			$mapped_level = isset( $level_map[ $level ] ) ? $level_map[ $level ] : 'INFO';
			activetrail_logger()->log( $message, $mapped_level, 'GENERAL' );
		}
	}
}
