<?php
/**
 * Email Open Tracking — inject 1x1 pixel into HTML emails.
 *
 * Tracks email opens by injecting a transparent tracking pixel into
 * outgoing HTML emails. Logs opens in the notification activity log.
 *
 * @package Mersal_Notif
 */

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

class Mersal_Notif_Email_Tracking {

	/**
	 * Initialize hooks.
	 */
	public function init() {
		if ( ! $this->is_enabled() ) {
			return;
		}

		// Intercept wp_mail to inject tracking pixel.
		add_filter( 'wp_mail', array( $this, 'intercept_mail' ) );

		// Serve the tracking pixel.
		add_action( 'template_redirect', array( $this, 'serve_pixel' ) );
	}

	/**
	 * Check if email tracking is enabled.
	 *
	 * @return bool
	 */
	private function is_enabled() {
		return (int) Mersal_Notif_Settings::get( 'email_tracking_enabled', 0 ) === 1;
	}

	/**
	 * Intercept wp_mail to inject tracking pixel.
	 *
	 * @param array $args Mail arguments.
	 * @return array Modified arguments.
	 */
	public function intercept_mail( $args ) {
		// Only track Mersal notification emails.
		if ( empty( $args['headers'] ) || ! is_array( $args['headers'] ) ) {
			return $args;
		}

		$has_mersal_header = false;
		foreach ( $args['headers'] as $header ) {
			if ( false !== strpos( $header, 'X-MNotif-Track' ) ) {
				$has_mersal_header = true;
				break;
			}
		}

		if ( ! $has_mersal_header ) {
			return $args;
		}

		// Generate tracking ID.
		$track_id = wp_generate_password( 16, false );
		$pixel_url = add_query_arg( array(
			'mnotif_track' => $track_id,
		), home_url( '/' ) );

		$pixel = '<img src="' . esc_url( $pixel_url ) . '" width="1" height="1" style="display:none;" alt="" />';

		// Inject pixel into HTML body.
		if ( is_string( $args['message'] ) && false !== strpos( $args['message'], '</body>' ) ) {
			$args['message'] = str_replace( '</body>', $pixel . '</body>', $args['message'] );
		} elseif ( is_string( $args['message'] ) ) {
			$args['message'] .= $pixel;
		}

		// Store tracking data.
		$recipient = is_array( $args['to'] ) ? reset( $args['to'] ) : $args['to'];
		set_transient( 'mnotif_track_' . $track_id, array(
			'recipient'  => $recipient,
			'subject'    => $args['subject'] ?? '',
			'sent_at'    => time(),
		), 30 * DAY_IN_SECONDS );

		// Remove the tracking header.
		$args['headers'] = array_filter( $args['headers'], function ( $h ) {
			return false === strpos( $h, 'X-MNotif-Track' );
		} );

		return $args;
	}

	/**
	 * Serve the tracking pixel and log the open.
	 */
	public function serve_pixel() {
		// phpcs:ignore WordPress.Security.NonceVerification.Recommended
		$track_id = isset( $_GET['mnotif_track'] ) ? sanitize_text_field( wp_unslash( $_GET['mnotif_track'] ) ) : '';
		if ( '' === $track_id ) {
			return;
		}

		$data = get_transient( 'mnotif_track_' . $track_id );
		if ( ! is_array( $data ) ) {
			$this->send_pixel();
			return;
		}

		// Log the open event.
		$log = get_option( Mersal_Notif_Core::LOG_OPTION, array() );
		if ( ! is_array( $log ) ) {
			$log = array();
		}

		$log[] = array(
			'channel'   => 'email',
			'to'        => $data['recipient'],
			'status'    => 'opened',
			'rule'      => $data['subject'] ?? '',
			'time'      => time(),
			'track_id'  => $track_id,
		);

		// Keep only last 200 entries (aligned with core log limit).
		if ( count( $log ) > 200 ) {
			$log = array_slice( $log, -200 );
		}

		update_option( Mersal_Notif_Core::LOG_OPTION, $log, false );

		// Delete the transient.
		delete_transient( 'mnotif_track_' . $track_id );

		// Send the pixel.
		$this->send_pixel();
	}

	/**
	 * Send a 1x1 transparent GIF pixel.
	 */
	private function send_pixel() {
		header( 'Content-Type: image/gif' );
		header( 'Content-Length: 43' );
		header( 'Cache-Control: no-cache, no-store, must-revalidate' );
		header( 'Pragma: no-cache' );
		header( 'Expires: 0' );
		// 1x1 transparent GIF.
		echo base64_decode( 'R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7' );
		exit;
	}

	/**
	 * Add tracking header to outgoing Mersal emails.
	 * Call this from the notification dispatch before wp_mail.
	 *
	 * @param array $headers Existing headers.
	 * @return array Modified headers.
	 */
	public static function add_tracking_header( $headers ) {
		$headers[] = 'X-MNotif-Track: ' . wp_generate_password( 8, false );
		return $headers;
	}
}
