<?php
/**
 * Unified Log Handler for WAWP.
 *
 * @package automation-web-platform
 */

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


/**
 * Class WAWP_Unified_Log
 *
 * @package automation-web-platform
 */
class WAWP_Unified_Log extends WAWP_Log_Base {


	/**
	 * Current login method hint.
	 *
	 * @var string
	 */
	public static $current_login_method = 'standard_login';

	/**
	 * Whether to skip the next automatic login log.
	 *
	 * @var bool
	 */
	public static $skip_next_login_log = false;

	/**
	 * Constructor.
	 */
	public function __construct() {
		parent::__construct();
		$this->init_ajax_handlers();

		// Register global activity hooks.
		add_action( 'wp_login', array( $this, 'log_user_login' ), 10, 2 );
		add_action( 'user_register', array( $this, 'log_user_registration' ) );
	}

	/**
	 * Setup class properties.
	 */
	protected function setup_properties() {
		$this->table_name   = WAWP()->db->get_unified_table_name();
		$this->nonce_action = 'wawp_unified_logs_nonce';
		$this->section      = 'activity_hub';
	}

	/**
	 * Get recipient column name.
	 *
	 * @return string
	 */
	protected function get_recipient_column_name() {
		return 'phone';
	}

	/**
	 * Get type column name.
	 *
	 * @return string
	 */
	protected function get_type_column_name() {
		return 'event_type';
	}

	/**
	 * Initialize AJAX handlers.
	 */
	public function init_ajax_handlers() {
		// All log operations are now served via REST API: /wp-json/wawp/v1/logs/{op}.
	}

	/**
	 * Log Types Constants.
	 */
	const TYPE_MESSAGE = 'message';
	const TYPE_AUTH    = 'auth';
	const TYPE_SYSTEM  = 'system';
	const TYPE_EVENT   = 'event';

	/**
	 * Log a generic activity to the unified logs.
	 *
	 * @param array $args Activity arguments.
	 * @return int|bool
	 */
	public function add_activity_log( $args = array() ) {
		global $wpdb;
		$table    = $this->table_name;
		$defaults = array(
			'user_id'    => null,
			'order_id'   => null,
			'phone'      => null,
			'email'      => null,
			'message'    => null,
			'event_type' => self::TYPE_SYSTEM,
			'gateway'    => 'system',
			'log_status' => 'success',
			'details'    => array(),
			'created_at' => current_time( 'mysql' ),
		);
		$data     = wp_parse_args( $args, $defaults );

		// Handle 'status' to 'log_status' mapping.
		if ( isset( $args['status'] ) && ! isset( $args['log_status'] ) ) {
			$data['log_status'] = $args['status'];
		}

		// Ensure phone/email is extracted from details if missing.
		if ( empty( $data['phone'] ) && empty( $data['email'] ) ) {
			$raw_contact = $data['details']['phone'] ?? $data['details']['recipient'] ?? $data['details']['whatsapp_number'] ?? $data['details']['email'] ?? null;
			if ( $raw_contact ) {
				if ( is_email( $raw_contact ) ) {
					$data['email'] = $raw_contact;
				} else {
					$data['phone'] = $raw_contact;
				}
			}
		} elseif ( ! empty( $data['phone'] ) && is_email( $data['phone'] ) && empty( $data['email'] ) ) {
			$data['email'] = $data['phone'];
			$data['phone'] = null;
		}

		// Ensure event_type is meaningful (avoid General if better info exists).
		if ( 'General' === $data['event_type'] || 'system' === $data['event_type'] ) {
			if ( ! empty( $data['details']['context'] ) ) {
				$data['event_type'] = $data['details']['context'];
			} elseif ( ! empty( $data['details']['type'] ) ) {
				$data['event_type'] = ucfirst( $data['details']['type'] );
			}
		}

		// Auto-Resolve User ID if missing but phone/email is present.
		if ( empty( $data['user_id'] ) ) {
			if ( ! empty( $data['email'] ) ) {
				$user = get_user_by( 'email', $data['email'] );
				if ( $user ) {
					$data['user_id'] = $user->ID;
				}
			}
			if ( empty( $data['user_id'] ) && ! empty( $data['phone'] ) ) {
				$data['user_id'] = WAWP()->user_manager->is_phone_taken( $data['phone'] );
			}
		}

		// Ensure message is extracted if possible.
		if ( empty( $data['message'] ) ) {
			if ( isset( $data['details']['message'] ) ) {
				$data['message'] = $data['details']['message'];
			} elseif ( isset( $data['details']['text'] ) ) {
				$data['message'] = $data['details']['text'];
			} elseif ( isset( $data['details']['subject'] ) ) {
				$data['message'] = $data['details']['subject'];
			}
		}

		// Final check for event_type fallback.
		if ( empty( $data['event_type'] ) ) {
			$data['event_type'] = 'System';
		}

		// Ensure details is JSON encoded.
		if ( is_array( $data['details'] ) ) {
			$data['details'] = wp_json_encode( $data['details'] );
		}

		$result = WAWP()->db->insert(
			'unified_activity_logs',
			array(
				'user_id'    => $data['user_id'],
				'order_id'   => $data['order_id'],
				'phone'      => $data['phone'],
				'email'      => $data['email'],
				'message'    => $data['message'],
				'event_type' => $data['event_type'],
				'gateway'    => $data['gateway'],
				'log_status' => $data['log_status'],
				'details'    => $data['details'],
				'created_at' => $data['created_at'],
			)
		);

		if ( $result ) {
			wp_cache_delete( 'wawp_log_total_' . md5( $table . $data['gateway'] ), 'wawp_database' );
			wp_cache_flush_group( 'wawp_logs' ); // Invalidate stats.
		}

		return $result ? $wpdb->insert_id : false;
	}

	/**
	 * Update an existing log entry status and details.
	 *
	 * @param int    $log_id   Log entry ID.
	 * @param string $status   New status.
	 * @param mixed  $response Optional response data.
	 * @return int|bool
	 */
	public function update_activity_log( $log_id, $status, $response = null ) {
		global $wpdb;
		$table = $this->table_name;
		$row   = WAWP()->db->get_results_cached( $wpdb->prepare( 'SELECT details FROM %i WHERE id = %d', $table, $log_id ), 'wawp_log_details_' . $log_id, 'wawp_database', 60 );
		$row   = ! empty( $row ) ? (object) $row[0] : null;
		if ( ! $row ) {
			return false;
		}
		$details = json_decode( $row->details, true );
		$details = $details ? $details : array();
		if ( null !== $response ) {
			if ( is_array( $response ) ) {
				$details = array_merge( $details, $response );
			} else {
				$details['response'] = $response;
			}
		}

		$updated = WAWP()->db->update_row(
			'unified_activity_logs',
			array(
				'log_status' => $status,
				'details'    => wp_json_encode( $details ),
			),
			array( 'id' => $log_id )
		);
		wp_cache_flush_group( 'wawp_logs' );
		return $updated;
	}

	/**
	 * Log a message event.
	 *
	 * @param array $args Message arguments.
	 * @return int|bool
	 */
	public function log_message( $args ) {
		// Auto-extract response and status.
		$response   = isset( $args['wawp_status'] ) ? $args['wawp_status'] : ( isset( $args['response'] ) ? $args['response'] : '' );
		$log_status = isset( $args['log_status'] ) ? $args['log_status'] : '';
		if ( empty( $log_status ) ) {
			if ( is_array( $response ) ) {
				$status     = isset( $response['status'] ) ? $response['status'] : '';
				$log_status = in_array( $status, array( 'delivered', 'read', 'sent' ), true )
					? 'success'
					: ( 'failed' === $status ? 'failed' : 'success' );
			} elseif ( 'failed' === ( isset( $args['status'] ) ? $args['status'] : '' ) ) {
				$log_status = 'failed';
			} else {
				$log_status = 'success';
			}
		}

		$details = array(
			'phone'        => $args['whatsapp_number'] ?? $args['phone'] ?? '',
			'message'      => $args['message'] ?? '',
			'message_type' => $args['message_type'] ?? 'General',
			'response'     => $response,
			'instance'     => $args['instance_id'] ?? '',
			'rule_id'      => $args['rule_id'] ?? null,
		);

		return $this->add_activity_log(
			array(
				'user_id'    => isset( $args['user_id'] ) ? $args['user_id'] : null,
				'order_id'   => isset( $args['order_id'] ) ? $args['order_id'] : null,
				'phone'      => $details['phone'],
				'event_type' => 'message',
				'gateway'    => isset( $args['gateway'] ) ? $args['gateway'] : 'whatsapp',
				'log_status' => $log_status,
				'details'    => $details,
			)
		);
	}

	/**
	 * Log an authentication event (login/signup).
	 *
	 * @param int    $user_id User ID.
	 * @param string $type    Event type.
	 * @param string $method  Auth method.
	 * @param string $status  Status.
	 * @param array  $meta    Additional meta data.
	 * @return int|bool
	 */
	public function log_auth( $user_id, $type = 'login', $method = 'otp', $status = 'success', $meta = array() ) {
		$details = array_merge(
			array(
				'method' => $method,
				'ua'     => isset( $_SERVER['HTTP_USER_AGENT'] ) ? sanitize_text_field( wp_unslash( $_SERVER['HTTP_USER_AGENT'] ) ) : '',
				'ip'     => WAWP()->get_client_ip(),
			),
			$meta
		);

		return $this->add_activity_log(
			array(
				'user_id'    => $user_id,
				'event_type' => $type,
				'gateway'    => 'system',
				'log_status' => $status,
				'details'    => $details,
			)
		);
	}

	/**
	 * Log a generic event.
	 *
	 * @param string $type     Event type.
	 * @param string $gateway  Gateway.
	 * @param string $status   Status.
	 * @param array  $details  Details.
	 * @param int    $user_id  User ID.
	 * @param int    $order_id Order ID.
	 * @return int|bool
	 */
	public function log_event( $type, $gateway, $status, $details = array(), $user_id = null, $order_id = null ) {
		return $this->add_activity_log(
			array(
				'user_id'    => $user_id,
				'order_id'   => $order_id,
				'event_type' => $type,
				'gateway'    => $gateway,
				'log_status' => $status,
				'details'    => $details,
			)
		);
	}

	/**
	 * Main AJAX handler for the activity hub.
	 *
	 * @param array $params Request parameters.
	 * @return array
	 */
	public function get_logs( $params ) {
		$draw    = isset( $params['draw'] ) ? intval( $params['draw'] ) : 1;
		$start   = isset( $params['start'] ) ? intval( $params['start'] ) : 0;
		$length  = isset( $params['length'] ) ? intval( $params['length'] ) : 20;
		$search  = isset( $params['search']['value'] ) ? sanitize_text_field( $params['search']['value'] ) : ( isset( $params['search'] ) ? sanitize_text_field( $params['search'] ) : '' );
		$gateway = isset( $params['gateway'] ) ? sanitize_text_field( $params['gateway'] ) : '';

		global $wpdb;
		$table_name  = $this->table_name;
		$users_table = $wpdb->users;
		$where       = array( '1=1' );
		// Exclude completely anonymous records.
		$where[]     = "(l.user_id > 0 OR (l.phone IS NOT NULL AND l.phone != '' AND l.phone != 'N/A' AND l.phone != 'system') OR (l.email IS NOT NULL AND l.email != ''))";
		$gateway_val = ! empty( $gateway ) ? $gateway : '';
		$search_val  = ! empty( $search ) ? '%' . $wpdb->esc_like( $search ) . '%' : '';

		$cache_key = 'wawp_hub_logs_' . md5( $table_name . $gateway_val . $search_val . $start . $length );
		$results   = WAWP()->db->get_results_cached(
			$wpdb->prepare(
				"SELECT l.user_id, l.phone, l.email as log_email, u.display_name, u.user_email, MAX(l.created_at) as last_activity, COUNT(l.id) as total_actions, SUM(CASE WHEN l.log_status = 'success' THEN 1 ELSE 0 END) as success_messages, SUM(CASE WHEN l.log_status = 'failed' THEN 1 ELSE 0 END) as failed_messages 
				 FROM %i l 
				 LEFT JOIN %i u ON l.user_id = u.ID 
				 WHERE (l.user_id > 0 OR (l.phone IS NOT NULL AND l.phone != '' AND l.phone != 'N/A' AND l.phone != 'system') OR (l.email IS NOT NULL AND l.email != ''))
				 AND (%s = '' OR l.gateway = %s)
				 AND (%s = '' OR (u.display_name LIKE %s OR u.user_email LIKE %s OR l.phone LIKE %s OR l.email LIKE %s OR l.user_id LIKE %s))
				 GROUP BY COALESCE(l.user_id, l.email, l.phone) 
				 ORDER BY last_activity DESC 
				 LIMIT %d OFFSET %d",
				$table_name,
				$users_table,
				$gateway_val,
				$gateway_val,
				$search_val,
				$search_val,
				$search_val,
				$search_val,
				$search_val,
				$search_val,
				$length,
				$start
			),
			$cache_key,
			'wawp_logs',
			60
		);

		$count_cache_key = 'wawp_hub_logs_total_' . md5( $table_name . $gateway_val . $search_val );
		$total_records   = WAWP()->db->get_var_cached(
			$wpdb->prepare(
				"SELECT COUNT(DISTINCT COALESCE(l.user_id, l.email, l.phone)) FROM %i l WHERE (l.user_id > 0 OR (l.phone IS NOT NULL AND l.phone != '' AND l.phone != 'N/A' AND l.phone != 'system') OR (l.email IS NOT NULL AND l.email != '')) AND (%s = '' OR l.gateway = %s) AND (%s = '' OR (l.phone LIKE %s OR l.email LIKE %s OR l.user_id LIKE %s))",
				$table_name,
				$gateway_val,
				$gateway_val,
				$search_val,
				$search_val,
				$search_val,
				$search_val
			),
			$count_cache_key,
			'wawp_logs',
			60
		);
		$data            = array();

		if ( $results ) {
			foreach ( $results as $row ) {
				$name  = $row['display_name'];
				$email = ! empty( $row['user_email'] ) ? $row['user_email'] : $row['log_email'];
				$phone = $row['phone'];
				$uid   = $row['user_id'];

				// Fix cross-placed values: email in phone field.
				if ( ! empty( $phone ) && is_email( $phone ) ) {
					if ( empty( $email ) ) {
						$email = $phone;
					}
					$phone = '';
				}

				// Fix cross-placed values: phone in email field (rare but requested).
				if ( ! empty( $email ) && ! is_email( $email ) && empty( $phone ) ) {
					$phone = $email;
					$email = '';
				}

				// 1. If we have an email but NO user_id, let's try to find the user via email.
				if ( ! $uid && ! empty( $email ) ) {
					$user_by_email = get_user_by( 'email', $email );
					if ( $user_by_email ) {
						$uid = $user_by_email->ID;
					}
				}

				// 2. If we have a phone but NO user_id, let's try to find the user via WAWP User Manager or Usermeta.
				if ( ! $uid && ! empty( $phone ) ) {
					if ( class_exists( 'WAWP' ) && isset( WAWP()->user_manager ) ) {
						$uid = WAWP()->user_manager->is_phone_taken( $phone );
					}

					// Fallback to usermeta if user_info table didn't have it.
					if ( ! $uid ) {
						$phone_like     = '%' . $wpdb->esc_like( $phone ) . '%';
						$users_by_phone = WAWP()->db->get_col_cached(
							$wpdb->prepare(
								"SELECT user_id FROM %i WHERE (meta_key = %s OR meta_key = 'billing_phone') AND meta_value LIKE %s LIMIT 1",
								$wpdb->usermeta,
								WAWP_Settings_Registry::USER_PHONE_META_KEY,
								$phone_like
							),
							'user_meta_phone_like_' . md5( $phone ),
							'wawp_users',
							300
						);
						if ( ! empty( $users_by_phone ) ) {
							$uid = $users_by_phone[0];
						}
					}
				}

				// If found, populate name and email/phone from DB.
				if ( $uid ) {
					$user_obj = get_userdata( $uid );
					if ( $user_obj ) {
						$name = $user_obj->display_name;
						if ( empty( $email ) ) {
							$email = $user_obj->user_email;
						}
					}
				}

				// 3. If we have a user_id but NO phone, use the WAWP User Manager (which checks custom table and usermeta).
				if ( $uid && empty( $phone ) ) {
					if ( class_exists( 'WAWP' ) && isset( WAWP()->user_manager ) ) {
						$phone = WAWP()->user_manager->get_user_phone( $uid );
					} else {
						$phone = get_user_meta( $uid, WAWP_Settings_Registry::USER_PHONE_META_KEY, true );
						if ( empty( $phone ) ) {
							$phone = get_user_meta( $uid, 'billing_phone', true );
						}
					}
				}

				if ( empty( $name ) ) {
					$name  = $phone ? $phone : ( $email ? $email : esc_html__( 'Guest', 'automation-web-platform' ) );
					$email = empty( $email ) ? esc_html__( 'N/A', 'automation-web-platform' ) : $email;
				}

				$id = $uid ? $uid : 'guest:' . ( $phone ? $phone : $email );

				$first_name     = '';
				$last_name      = '';
				$avatar_url     = '';
				$email_verified = false;
				$phone_verified = false;

				if ( $uid ) {
					$user_obj = get_userdata( $uid );
					if ( $user_obj ) {
						$first_name = get_user_meta( $uid, 'first_name', true );
						$last_name  = get_user_meta( $uid, 'last_name', true );
						$avatar_url = get_avatar_url( $uid );

						$email_verified = WAWP()->user_manager->get_verification_status( $uid, 'email' );
						$phone_verified = WAWP()->user_manager->get_verification_status( $uid, 'whatsapp' );
					}
				} elseif ( ! empty( $email ) && is_email( $email ) ) {
						$avatar_url = get_avatar_url( $email );
				}

				$last_login_time = '';
				if ( $uid ) {
					$cache_key       = 'wawp_last_login_' . $uid;
					$cache_group     = 'wawp_users';
					$last_login_time = wp_cache_get( $cache_key, $cache_group );
					if ( false === $last_login_time ) {
						$last_login_ts = get_user_meta( $uid, 'wawp_last_login_timestamp', true );
						if ( $last_login_ts ) {
							$last_login_time = date_i18n( get_option( 'date_format' ) . ' ' . get_option( 'time_format' ), intval( $last_login_ts ) );
						} else {
							// Fallback: Query unified logs table for the last login event.
							$last_login_row = call_user_func_array(
								array( $wpdb, 'get_var' ),
								array(
									$wpdb->prepare(
										"SELECT created_at FROM %i WHERE user_id = %d AND event_type = 'login' ORDER BY created_at DESC LIMIT 1",
										$table_name,
										$uid
									),
								)
							);
							if ( $last_login_row ) {
								$last_login_time = mysql2date( get_option( 'date_format' ) . ' ' . get_option( 'time_format' ), $last_login_row );
							} else {
								$last_login_time = '';
							}
						}
						wp_cache_set( $cache_key, $last_login_time, $cache_group, 3600 );
					}
				}

				if ( ! isset( $data[ $id ] ) ) {
					$data[ $id ] = array(
						'id'             => $id,
						'name'           => $name,
						'first_name'     => $first_name,
						'last_name'      => $last_name,
						'avatar_url'     => $avatar_url,
						'email_verified' => $email_verified,
						'phone_verified' => $phone_verified,
						'email'          => empty( $email ) ? esc_html__( 'N/A', 'automation-web-platform' ) : $email,
						'phone'          => empty( $phone ) ? esc_html__( 'N/A', 'automation-web-platform' ) : $phone,
						'last_activity'  => $row['last_activity'],
						'last_login'     => $last_login_time,
						'success_count'  => 0,
						'failed_count'   => 0,
						'total_actions'  => 0,
					);
				}

				// If we resolved email or phone in a subsequent row, update the original row if it was missing.
				if ( esc_html__( 'N/A', 'automation-web-platform' ) === $data[ $id ]['email'] && ! empty( $email ) ) {
					$data[ $id ]['email'] = $email;
					if ( empty( $data[ $id ]['avatar_url'] ) && is_email( $email ) ) {
						$data[ $id ]['avatar_url'] = get_avatar_url( $email );
					}
				}
				if ( esc_html__( 'N/A', 'automation-web-platform' ) === $data[ $id ]['phone'] && ! empty( $phone ) ) {
					$data[ $id ]['phone'] = $phone;
				}
				if ( esc_html__( 'Guest', 'automation-web-platform' ) === $data[ $id ]['name'] || $data[ $id ]['name'] === $data[ $id ]['phone'] ) {
					if ( ! empty( $name ) && $name !== $phone ) {
						$data[ $id ]['name'] = $name;
					}
				}

				// Merge stats.
				$data[ $id ]['success_count'] += (int) $row['success_messages'];
				$data[ $id ]['failed_count']  += (int) $row['failed_messages'];
				$data[ $id ]['total_actions'] += (int) $row['total_actions'];

				// Update last activity if newer.
				if ( strtotime( $row['last_activity'] ) > strtotime( $data[ $id ]['last_activity'] ) ) {
					$data[ $id ]['last_activity'] = $row['last_activity'];
				}
			}
		}

		return array(
			'draw'            => $draw,
			'recordsTotal'    => (int) $total_records,
			'recordsFiltered' => (int) $total_records,
			'data'            => array_values( $data ),
		);
	}

	/**
	 * Fetch full timeline for a specific user.
	 *
	 * @param array $params Request parameters.
	 * @return array
	 */
	public function get_user_timeline( $params ) {
		$user_id_raw = isset( $params['user_id'] ) ? sanitize_text_field( $params['user_id'] ) : '';
		if ( empty( $user_id_raw ) ) {
			return array(
				'success' => false,
				'message' => 'Invalid identifier',
			);
		}

		global $wpdb;
		$table_name = $this->table_name;
		if ( strpos( $user_id_raw, 'guest:' ) === 0 ) {
			$contact = str_replace( 'guest:', '', $user_id_raw );
			if ( empty( $contact ) || 'N/A' === $contact ) {
				$results = WAWP()->db->get_results_cached( $wpdb->prepare( 'SELECT * FROM %i WHERE (phone IS NULL OR phone = "") AND (email IS NULL OR email = "") AND user_id IS NULL ORDER BY created_at DESC LIMIT 100', $table_name ), 'wawp_timeline_guest_na', 'wawp_logs', 60 );
			} else {
				$results = WAWP()->db->get_results_cached( $wpdb->prepare( 'SELECT * FROM %i WHERE (phone = %s OR email = %s) AND user_id IS NULL ORDER BY created_at DESC LIMIT 100', $table_name, $contact, $contact ), 'wawp_timeline_guest_' . md5( $contact ), 'wawp_logs', 60 );
			}
		} else {
			$uid   = intval( $user_id_raw );
			$phone = '';
			$email = '';
			if ( class_exists( 'WAWP' ) && isset( WAWP()->user_manager ) ) {
				$phone = WAWP()->user_manager->get_user_phone( $uid );
			} else {
				$phone = get_user_meta( $uid, WAWP_Settings_Registry::USER_PHONE_META_KEY, true );
				if ( empty( $phone ) ) {
					$phone = get_user_meta( $uid, 'billing_phone', true );
				}
			}
			$user_obj = get_userdata( $uid );
			if ( $user_obj ) {
				$email = $user_obj->user_email;
			}

			if ( ! empty( $phone ) || ! empty( $email ) ) {
				$results = WAWP()->db->get_results_cached( $wpdb->prepare( 'SELECT * FROM %i WHERE (user_id = %d OR phone = %s OR email = %s) ORDER BY created_at DESC LIMIT 100', $table_name, $uid, $phone, $email ), 'wawp_timeline_user_' . $uid, 'wawp_logs', 60 );
			} else {
				$results = WAWP()->db->get_results_cached( $wpdb->prepare( 'SELECT * FROM %i WHERE user_id = %d ORDER BY created_at DESC LIMIT 100', $table_name, $uid ), 'wawp_timeline_user_' . $uid, 'wawp_logs', 60 );
			}
		}

		$timeline = array();
		if ( $results ) {
			foreach ( $results as $row ) {
				$details    = json_decode( $row['details'], true );
				$timeline[] = array(
					'id'         => $row['id'],
					'event_type' => $row['event_type'],
					'gateway'    => $row['gateway'],
					'status'     => $row['log_status'],
					'message'    => $row['message'],
					'created_at' => $row['created_at'],
					'details'    => $details,
				);
			}
		}

		$final_timeline = array();
		$removed_ids    = array();

		foreach ( $timeline as $event ) {
			if ( in_array( $event['id'], $removed_ids, true ) ) {
				continue;
			}

			if ( 'login' === $event['event_type'] && 'system' === $event['gateway'] ) {
				$login_time = strtotime( $event['created_at'] );
				foreach ( $timeline as $other_event ) {
					if ( $other_event['id'] === $event['id'] ) {
						continue;
					}
					if ( in_array( $other_event['id'], $removed_ids, true ) ) {
						continue;
					}

					$is_login_notif = (
						( isset( $other_event['details']['trigger_key'] ) && 'user_login' === $other_event['details']['trigger_key'] ) ||
						'user_login' === $other_event['event_type'] ||
						'User Login' === $other_event['event_type']
					);

					if ( $is_login_notif ) {
						$other_time = strtotime( $other_event['created_at'] );
						if ( abs( $login_time - $other_time ) <= 30 ) {
							if ( ! empty( $other_event['message'] ) ) {
								$event['message'] = $other_event['message'];
							}
							$removed_ids[] = $other_event['id'];
							break;
						}
					}
				}
			}

			$final_timeline[] = $event;
		}

		// Filter out any newly removed events that were added before they were scanned as 'other_event'.
		$filtered_timeline = array();
		foreach ( $final_timeline as $event ) {
			if ( ! in_array( $event['id'], $removed_ids, true ) ) {
				$filtered_timeline[] = $event;
			}
		}

		return array(
			'success' => true,
			'data'    => $filtered_timeline,
		);
	}

	/**
	 * Delete logs handler.
	 *
	 * @param array $params Request parameters.
	 * @return array
	 */
	public function delete_logs( $params ) {
		$log_id    = isset( $params['log_id'] ) ? intval( $params['log_id'] ) : ( isset( $params['id'] ) ? intval( $params['id'] ) : 0 );
		$user_id   = isset( $params['user_id'] ) ? intval( $params['user_id'] ) : 0;
		$phone     = isset( $params['phone'] ) ? sanitize_text_field( $params['phone'] ) : '';
		$clear_all = ! empty( $params['clear_all'] );
		global $wpdb;
		$table_name = $this->table_name;

		if ( $clear_all ) {

			WAWP()->db->execute_query( $wpdb->prepare( 'TRUNCATE TABLE %i', $table_name ) );
			wp_cache_flush_group( 'wawp_logs' );

			return array(
				'success' => true,
				'message' => esc_html__( 'All logs have been cleared successfully.', 'automation-web-platform' ),
			);
		}

		if ( $log_id ) {
			WAWP()->db->delete_row( 'unified_activity_logs', array( 'id' => $log_id ) );
			wp_cache_flush_group( 'wawp_logs' );

			return array(
				'success' => true,
				'message' => esc_html__( 'Log entry deleted successfully.', 'automation-web-platform' ),
			);
		} elseif ( $user_id || $phone || ! empty( $params['email'] ) ) {
			$email = isset( $params['email'] ) ? sanitize_email( $params['email'] ) : '';
			$phone = ! empty( $phone ) && 'N/A' !== $phone ? $phone : '';

			// If we have a user_id, fetch registered email and phone to fully clear all traces.
			if ( $user_id ) {
				$user_obj = get_userdata( $user_id );
				if ( $user_obj ) {
					if ( empty( $email ) ) {
						$email = $user_obj->user_email;
					}
				}
				if ( empty( $phone ) ) {
					if ( class_exists( 'WAWP' ) && isset( WAWP()->user_manager ) ) {
						$phone = WAWP()->user_manager->get_user_phone( $user_id );
					} else {
						$phone = get_user_meta( $user_id, 'wawp_user_phone', true );
						if ( empty( $phone ) ) {
							$phone = get_user_meta( $user_id, 'billing_phone', true );
						}
					}
				}
			}

			// Sanitize and normalize phone/email values.
			$email = is_email( $email ) ? sanitize_email( $email ) : '';
			$phone = sanitize_text_field( $phone );

			$where_clauses = array();
			if ( $user_id ) {
				$where_clauses[] = $wpdb->prepare( 'user_id = %d', $user_id );
			}
			if ( ! empty( $phone ) && 'N/A' !== $phone ) {
				$where_clauses[] = $wpdb->prepare( 'phone = %s', $phone );
				$where_clauses[] = $wpdb->prepare( 'email = %s', $phone );
				$digits          = preg_replace( '/\D/', '', $phone );
				if ( ! empty( $digits ) ) {
					$where_clauses[] = $wpdb->prepare( 'phone = %s', $digits );
					$where_clauses[] = $wpdb->prepare( 'phone = %s', '+' . $digits );
				}
			}
			if ( ! empty( $email ) && 'N/A' !== $email ) {
				$where_clauses[] = $wpdb->prepare( 'email = %s', $email );
				$where_clauses[] = $wpdb->prepare( 'phone = %s', $email );
			}

			if ( ! empty( $where_clauses ) ) {
				$query = "DELETE FROM $table_name WHERE " . implode( ' OR ', $where_clauses );
				WAWP()->db->execute_query( $query );
			}

			wp_cache_flush_group( 'wawp_logs' );

			return array(
				'success' => true,
				'message' => esc_html__( 'All logs for this customer have been deleted.', 'automation-web-platform' ),
			);
		}

		return array(
			'success' => false,
			'message' => 'Missing parameters for deletion',
		);
	}

	/**
	 * Get hub data for React dashboard.
	 *
	 * @return array
	 */
	public function get_hub_data() {
		$stats    = $this->get_base_stats();
		$statuses = $this->get_distinct_statuses();
		$m_types  = $this->get_distinct_types();

		return array(
			'iconBaseUrl'       => WAWP_PLUGIN_URL . 'assets/icons/',
			'saveSettingsNonce' => wp_create_nonce( 'wawp_save_log_settings_nonce' ),
			'logStatuses'       => $statuses,
			'messageTypes'      => $m_types,
			'logStats'          => $stats,
			'msgs'              => array(
				'logsTitle'                => esc_html__( 'Activity Hub', 'automation-web-platform' ),
				'logsSubtitle'             => esc_html__( 'Standardized unified activity logging for all platform events.', 'automation-web-platform' ),
				'clearAllLogsBtn'          => esc_html__( 'Clear All Logs', 'automation-web-platform' ),
				'sendMessageBtn'           => esc_html__( 'Send Message', 'automation-web-platform' ),
				'overviewTitle'            => esc_html__( 'Activity Overview', 'automation-web-platform' ),
				'overviewSubtitle'         => esc_html__( 'High-level metrics of your unified interaction engine.', 'automation-web-platform' ),
				'trackedUsersLabel'        => esc_html__( 'Tracked Users', 'automation-web-platform' ),
				'trackedUsersSub'          => esc_html__( 'Total unique users logged', 'automation-web-platform' ),
				'badgeNetwork'             => esc_html__( 'Network', 'automation-web-platform' ),
				'badgeSuccess'             => esc_html__( 'Success', 'automation-web-platform' ),
				'badgeFailed'              => esc_html__( 'Failed', 'automation-web-platform' ),
				'badgeLive'                => esc_html__( 'Live', 'automation-web-platform' ),
				'successHubLabel'          => esc_html__( 'Successful Hub', 'automation-web-platform' ),
				'successHubSub'            => esc_html__( 'Delivered communications', 'automation-web-platform' ),
				'failedEventsLabel'        => esc_html__( 'Failed Events', 'automation-web-platform' ),
				'failedEventsSub'          => esc_html__( 'Communications with errors', 'automation-web-platform' ),
				'globalActionsLabel'       => esc_html__( 'Global Actions', 'automation-web-platform' ),
				'globalActionsSub'         => esc_html__( 'Total actions & events', 'automation-web-platform' ),
				'directoryTitle'           => esc_html__( 'Engagement Directory', 'automation-web-platform' ),
				'directorySubtitle'        => esc_html__( 'Click on any user to view their complete interaction timeline.', 'automation-web-platform' ),
				'searchPlaceholder'        => esc_html__( 'Search by name, email or ID...', 'automation-web-platform' ),
				'colUserIdentity'          => esc_html__( 'User Identity', 'automation-web-platform' ),
				'colContactDetails'        => esc_html__( 'Contact Details', 'automation-web-platform' ),
				'colCommStats'             => esc_html__( 'Communication Stats', 'automation-web-platform' ),
				'colTotalActivity'         => esc_html__( 'Total Activity', 'automation-web-platform' ),
				'colLastPulse'             => esc_html__( 'Last Pulse', 'automation-web-platform' ),
				'lastLoginLabel'           => esc_html__( 'Last login:', 'automation-web-platform' ),
				'neverLabel'               => esc_html__( 'Never', 'automation-web-platform' ),
				'deliveredLabel'           => esc_html__( 'Delivered', 'automation-web-platform' ),
				'failedStatusLabel'        => esc_html__( 'Failed', 'automation-web-platform' ),
				'eventsBadge'              => esc_html__( 'EVENTS', 'automation-web-platform' ),
				'viewTimelineBtn'          => esc_html__( 'View Timeline', 'automation-web-platform' ),
				'pageWord'                 => esc_html__( 'Page', 'automation-web-platform' ),
				'ofWord'                   => esc_html__( 'of', 'automation-web-platform' ),
				'prevBtn'                  => esc_html__( 'Previous', 'automation-web-platform' ),
				'nextBtn'                  => esc_html__( 'Next', 'automation-web-platform' ),
				'timelineDesc'             => esc_html__( 'Complete history of events and communication lifecycle for this customer.', 'automation-web-platform' ),
				'wpProfileBtn'             => esc_html__( 'WP Profile', 'automation-web-platform' ),
				'clearHistoryBtn'          => esc_html__( 'Clear History', 'automation-web-platform' ),
				'emailAddressLabel'        => esc_html__( 'Email Address', 'automation-web-platform' ),
				'verifiedLabel'            => esc_html__( 'Verified', 'automation-web-platform' ),
				'notVerifiedLabel'         => esc_html__( 'Not Verified', 'automation-web-platform' ),
				'recipientPhone'           => esc_html__( 'Recipient Phone', 'automation-web-platform' ),
				'recipientEmail'           => esc_html__( 'Recipient Email', 'automation-web-platform' ),
				'orderIdLabel'             => esc_html__( 'Order ID', 'automation-web-platform' ),
				'contextLabel'             => esc_html__( 'Trigger Context', 'automation-web-platform' ),
				'templateNameLabel'        => esc_html__( 'Template Name', 'automation-web-platform' ),
				'messageContentLabel'      => esc_html__( 'Message Content', 'automation-web-platform' ),
				'errorMessageLabel'        => esc_html__( 'Error Message', 'automation-web-platform' ),
				'statusRead'               => esc_html__( 'Read', 'automation-web-platform' ),
				'statusSent'               => esc_html__( 'Sent', 'automation-web-platform' ),
				'statusSentSmtp'           => esc_html__( 'Sent (SMTP)', 'automation-web-platform' ),
				'noRecords'                => esc_html__( 'No activity records found.', 'automation-web-platform' ),
				'snapshotTitle'            => esc_html__( 'Snapshot', 'automation-web-platform' ),
				'snapshotSubtitle'         => esc_html__( 'Overview of delivery and performance metrics across all channels.', 'automation-web-platform' ),
				'totalLabel'               => esc_html__( 'Total Events', 'automation-web-platform' ),
				'sentLabel'                => esc_html__( 'Success', 'automation-web-platform' ),
				'failedLabel'              => esc_html__( 'Failures', 'automation-web-platform' ),
				'uniqueLabel'              => esc_html__( 'Users', 'automation-web-platform' ),
				'phoneNumberLabel'         => esc_html__( 'Phone Number', 'automation-web-platform' ),
				'lastLoginTitle'           => esc_html__( 'Last Login', 'automation-web-platform' ),
				'loggedInStatus'           => esc_html__( 'Logged In', 'automation-web-platform' ),
				'neverLoggedInStatus'      => esc_html__( 'Never Logged In', 'automation-web-platform' ),
				'closeAuditTrailBtn'       => esc_html__( 'Close Audit Trail', 'automation-web-platform' ),
				'detailedEventTraceTitle'  => esc_html__( 'Detailed Event Trace', 'automation-web-platform' ),
				'detailedEventTraceDesc'   => esc_html__( 'In-depth technical breakdown and payload analysis of this specific event.', 'automation-web-platform' ),
				'gatewaySignalLabel'       => esc_html__( 'Gateway Signal', 'automation-web-platform' ),
				'successStatusLabel'       => esc_html__( 'Success Status', 'automation-web-platform' ),
				'dismissDetailsBtn'        => esc_html__( 'Dismiss Details', 'automation-web-platform' ),
				'clearCustHistoryTitle'    => esc_html__( 'Clear Customer History?', 'automation-web-platform' ),
				'clearCustHistoryDesc'     => esc_html__( 'Permanently delete all activity logs for this specific user.', 'automation-web-platform' ),
				'clearCustHistoryConfirm1' => esc_html__( 'This will permanently delete all activity logs for', 'automation-web-platform' ),
				'clearCustHistoryConfirm2' => esc_html__( '. This action cannot be undone.', 'automation-web-platform' ),
				'cancelBtn'                => esc_html__( 'Cancel', 'automation-web-platform' ),
				'deletingLabel'            => esc_html__( 'Deleting...', 'automation-web-platform' ),
				'yesClearAllBtn'           => esc_html__( 'Yes, Clear All', 'automation-web-platform' ),
				'wipeEntireHubTitle'       => esc_html__( 'Wipe Entire Activity Hub?', 'automation-web-platform' ),
				'wipeEntireHubDesc'        => esc_html__( 'Permanently delete ALL activity logs from the system.', 'automation-web-platform' ),
				'wipeEntireHubConfirm1'    => esc_html__( 'You are about to', 'automation-web-platform' ),
				'wipeEntireHubConfirm2'    => esc_html__( 'permanently delete ALL activity logs', 'automation-web-platform' ),
				'wipeEntireHubConfirm3'    => esc_html__( 'from the entire system. This action is irreversible.', 'automation-web-platform' ),
				'clearingLabel'            => esc_html__( 'Clearing...', 'automation-web-platform' ),
				'yesClearEverythingBtn'    => esc_html__( 'Yes, Clear Everything', 'automation-web-platform' ),
				'evtCustomerLoggedIn'      => esc_html__( 'Customer Logged In', 'automation-web-platform' ),
				'evtNewCustomerRegistered' => esc_html__( 'New Customer Registered', 'automation-web-platform' ),
				'evtPhoneNumberVerified'   => esc_html__( 'Phone Number Verified', 'automation-web-platform' ),
				'evtMetaWAMessage'         => esc_html__( 'Meta WhatsApp Message', 'automation-web-platform' ),
				'evtWAMessage'             => esc_html__( 'WhatsApp Message', 'automation-web-platform' ),
				'evtSentEmail'             => esc_html__( 'Sent Email', 'automation-web-platform' ),
				'evtAddedToCart'           => esc_html__( 'Added Items to Cart', 'automation-web-platform' ),
				'evtPlacedOrder'           => esc_html__( 'Placed an Order', 'automation-web-platform' ),
				'evtWAActivity'            => esc_html__( 'WhatsApp Activity', 'automation-web-platform' ),
				'evtEmailActivity'         => esc_html__( 'Email Activity', 'automation-web-platform' ),
				'evtFirebaseSMSActivity'   => esc_html__( 'Firebase SMS Activity', 'automation-web-platform' ),
				'evtSystemActivity'        => esc_html__( 'System Activity', 'automation-web-platform' ),
				'evtEmailMessage'          => esc_html__( 'Email Message', 'automation-web-platform' ),
				'drawerSendManualMsg'      => esc_html__( 'Send Manual Message', 'automation-web-platform' ),
				'drawerChooseUserDesc'     => esc_html__( 'Choose a user, gateway, and send your message', 'automation-web-platform' ),
				'drawerSendMessage'        => esc_html__( 'Send Message', 'automation-web-platform' ),
				'drawerSendMsgDesc'        => esc_html__( 'Dispatch an instant manual notification directly to any WordPress customer and log the interaction in the Activity Hub.', 'automation-web-platform' ),
				'drawerRecipientUser'      => esc_html__( 'Recipient User', 'automation-web-platform' ),
				'drawerSearchSelect'       => esc_html__( 'Search and select a user...', 'automation-web-platform' ),
				'drawerSearchType'         => esc_html__( 'Type username, email, or display name...', 'automation-web-platform' ),
				'drawerCommChannel'        => esc_html__( 'Communication Channel', 'automation-web-platform' ),
				'drawerWawpInstance'       => esc_html__( 'Wawp Instance', 'automation-web-platform' ),
				'drawerOnline'             => esc_html__( 'online', 'automation-web-platform' ),
				'drawerInstances'          => esc_html__( 'instances', 'automation-web-platform' ),
				'drawerNoInstances'        => esc_html__( 'No Wawp instances are currently online.', 'automation-web-platform' ),
				'drawerMetaCloud'          => esc_html__( 'Meta Cloud API', 'automation-web-platform' ),
				'drawerMetaDesc'           => esc_html__( 'Official WhatsApp Business API', 'automation-web-platform' ),
				'drawerEmailSmtp'          => esc_html__( 'Email SMTP (Site)', 'automation-web-platform' ),
				'drawerEmailDesc'          => esc_html__( 'Delivered via site SMTP server', 'automation-web-platform' ),
				'drawerSmtpActive'         => esc_html__( 'SMTP Active — Ready to send', 'automation-web-platform' ),
				'drawerSmtpNotConfig'      => esc_html__( 'SMTP not configured —', 'automation-web-platform' ),
				'drawerConfigureNow'       => esc_html__( 'Configure now', 'automation-web-platform' ),
				'drawerMessageBody'        => esc_html__( 'Message Body', 'automation-web-platform' ),
				'drawerCustomerEmail'      => esc_html__( 'Customer Email', 'automation-web-platform' ),
				'drawerSubject'            => esc_html__( 'Subject', 'automation-web-platform' ),
				'drawerEnterSubject'       => esc_html__( 'Enter email subject...', 'automation-web-platform' ),
				'drawerTypeBody'           => esc_html__( 'Type email body here...', 'automation-web-platform' ),
				'errSelectRecipient'       => esc_html__( 'Please select a recipient user.', 'automation-web-platform' ),
				'errEnterMessage'          => esc_html__( 'Please enter a message body.', 'automation-web-platform' ),
				'msgSendSuccess'           => esc_html__( 'Message sent successfully.', 'automation-web-platform' ),
				'msgSendFailed'            => esc_html__( 'Failed to send message.', 'automation-web-platform' ),
				'msgSendError'             => esc_html__( 'An error occurred while sending the message.', 'automation-web-platform' ),
				'defaultSubject'           => esc_html__( 'Manual Message', 'automation-web-platform' ),
				'ctxMessagingService'      => esc_html__( 'Messaging Service', 'automation-web-platform' ),
				'ctxManualMessage'         => esc_html__( 'Manual Message', 'automation-web-platform' ),
				'ctxManualMessageSend'     => esc_html__( 'Manual Message Send', 'automation-web-platform' ),
				'ctxAdminTestMessage'      => esc_html__( 'Admin Test Message', 'automation-web-platform' ),
				'ctxFirebaseLogin'         => esc_html__( 'Firebase Login', 'automation-web-platform' ),
				'msgFailedRecipientEmpty'  => esc_html__( 'Failed to send: Recipient is empty', 'automation-web-platform' ),
				'msgFirebaseSMSSent'       => esc_html__( 'Firebase SMS sent.', 'automation-web-platform' ),
				'columns'                  => array(
					'id'        => esc_html__( 'ID', 'automation-web-platform' ),
					'user'      => esc_html__( 'User', 'automation-web-platform' ),
					'order'     => esc_html__( 'Order', 'automation-web-platform' ),
					'name'      => esc_html__( 'Name', 'automation-web-platform' ),
					'date'      => esc_html__( 'Date', 'automation-web-platform' ),
					'recipient' => esc_html__( 'Recipient', 'automation-web-platform' ),
					'subject'   => esc_html__( 'Activity', 'automation-web-platform' ),
					'attach'    => esc_html__( 'Attach', 'automation-web-platform' ),
					'extra'     => esc_html__( 'Gateway', 'automation-web-platform' ),
					'status'    => esc_html__( 'Status', 'automation-web-platform' ),
					'action'    => esc_html__( 'Action', 'automation-web-platform' ),
					'ref'       => esc_html__( 'Ref ID', 'automation-web-platform' ),
				),
			),
		);
	}

	/**
	 * Log user login event.
	 *
	 * @param string  $user_login User login.
	 * @param WP_User $user       User object.
	 */
	public function log_user_login( $user_login, $user ) {
		if ( self::$skip_next_login_log ) {
			self::$skip_next_login_log = false; // Reset for potential next login in same request (rare but safe).
			return;
		}

		// Prevent double logging if we already logged this in the same request.
		static $logged_uids = array();
		if ( in_array( $user->ID, $logged_uids, true ) ) {
			return;
		}
		$logged_uids[] = $user->ID;

		update_user_meta( $user->ID, 'wawp_last_login_timestamp', time() );

		$this->log_auth( $user->ID, 'login', self::$current_login_method );
	}

	/**
	 * Log user registration event.
	 *
	 * @param int $user_id User ID.
	 */
	public function log_user_registration( $user_id ) {
		$this->log_event(
			'signup',
			'system',
			'success',
			array(
				'ip' => isset( $_SERVER['REMOTE_ADDR'] ) ? sanitize_text_field( wp_unslash( filter_var( wp_unslash( $_SERVER['REMOTE_ADDR'] ), FILTER_VALIDATE_IP ) ) ) : 'unknown',
			),
			$user_id
		);
	}

	/**
	 * Format a single log row for DataTables output.
	 *
	 * @param array $log Raw log data.
	 * @return array
	 */
	protected function format_log_row( $log ) {
		return $log;
	}

	/**
	 * Get page-specific strings.
	 *
	 * @return array
	 */
	protected function get_page_strings() {
		return array();
	}
}
