<?php
/**
 * Telemetry integration for UGC Commerce.
 *
 * Uses the linno/telemetry SDK (PostHog-backed) to track plugin lifecycle
 * events, onboarding completion, and key feature usage.
 *
 * All tracking is failure-safe: any SDK exception is caught so telemetry
 * never interrupts normal plugin operation.
 *
 * @package Ugcify\Tracking
 * @since   1.0.0
 */

namespace Ugcify\Tracking;

use LinnoSDK\Telemetry\Client;

// Exit if accessed directly.
if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

/**
 * Class Telemetry
 */
class Telemetry {

	/**
	 * PostHog API key for UGC Commerce.
	 *
	 * @var string
	 */
	private const POSTHOG_API_KEY = 'phc_c1PKf0NEqy1gSDdX7OlQQDRtfn9QAHhmcOAyRPAl1zY';

	/**
	 * PostHog host URL.
	 *
	 * @var string
	 */
	private const POSTHOG_HOST = 'https://eu.i.posthog.com';

	/**
	 * Approved feature identifiers for usage tracking.
	 *
	 * @var string[]
	 */
	private const APPROVED_FEATURES = [
		'review_submitted',
		'social_import',
		'ab_testing',
		'reward_coupon',
	];

	/**
	 * Singleton instance.
	 *
	 * @var Telemetry|null
	 */
	private static $instance;

	/**
	 * Linno telemetry client.
	 *
	 * @var Client|null
	 */
	private $client;

	/**
	 * Initialize telemetry singleton.
	 *
	 * @return Telemetry|null
	 */
	public static function init() {
		if ( ! self::$instance ) {
			self::$instance = new self();
		}

		return self::$instance;
	}

	/**
	 * Boot the PostHog-backed telemetry client and register triggers.
	 *
	 * Failure-safe: any SDK exception is caught so telemetry never interrupts
	 * plugin activation or other core flows.
	 */
	private function __construct() {
		if ( ! class_exists( '\\LinnoSDK\\Telemetry\\Client' ) ) {
			return;
		}

		try {
			$this->client = new Client(
				[
					'pluginFile'    => UGCIFY_FILE,
					'slug'          => 'ugcify',
					'pluginName'    => 'UGCify',
					'version'       => UGCIFY_VERSION,
					'driver'        => 'posthog',
					'driver_config' => [
						'api_key' => self::POSTHOG_API_KEY,
						'host'    => self::POSTHOG_HOST,
					],
					'review_prompt' => [
						'webhook'             => 'https://rextheme.com/wp-json/mrm/v1/form/1/webhook/receive',
						'min_feedback_length' => 50,
						'snooze_schedule'     => [ 7, 30, 90 ],
						'nps_question'        => 'How likely are you to recommend UGCify to your friends or colleagues?',
						'low_score_threshold' => 7,
						'review_url'          => 'https://wordpress.org/support/plugin/ugcify/reviews/#new-post',
						'support_url'         => 'https://rextheme.com/support/',
						'privacy_url'         => 'https://rextheme.com/privacy-policy/',
						'installed_option_key' => 'ugcify_installed_time',
						'position'            => 'bottom-right',
						'allowed_screens'     => [
							'ugcify',
						],
					],
				]
			);
		} catch ( \Exception $e ) {
			return;
		}

		$this->register_triggers();
	}

	/**
	 * Register all telemetry triggers: onboarding lifecycle and feature usage.
	 *
	 * Activation and deactivation lifecycle events are handled automatically by
	 * the Linno SDK through register_activation_hook / register_deactivation_hook.
	 * Onboarding completion is single-fire; the SDK guards repeat emissions via
	 * has_sent_event( 'onboarding_completed' ).
	 *
	 * @return void
	 */
	private function register_triggers(): void {
		if ( ! $this->client ) {
			return;
		}

		try {
			$this->client->define_triggers(
				[
					'onboarding'   => [
						'hook'     => 'ugcify_setup_wizard_complete',
						'callback' => [ $this, 'setup_payload' ],
					],
					'feature_used' => [
						'review_submitted' => [
							'hook'     => 'ugcify_review_submitted',
							'callback' => [ $this, 'feature_usage_payload' ],
						],
						'social_import'    => [
							'hook'     => 'ugcify_social_import_completed',
							'callback' => [ $this, 'feature_usage_payload' ],
						],
						'ab_testing'       => [
							'hook'     => 'ugcify_ab_test_created',
							'callback' => [ $this, 'feature_usage_payload' ],
						],
						'reward_coupon'    => [
							'hook'     => 'ugcify_reward_coupon_issued',
							'callback' => [ $this, 'feature_usage_payload' ],
						],
					],
				]
			);
		} catch ( \Exception $e ) {
			// Failure-safe: trigger registration errors must not surface to callers.
		}

		// First review approved — Aha milestone wired directly.
		add_action( 'ugcify_review_approved', [ $this, 'handle_aha_milestone' ], 10, 1 );

		// PostHog JS session recording — admin pages only, consent-gated.
		add_action( 'admin_head', [ $this, 'output_posthog_js' ] );
	}

	// -------------------------------------------------------------------------
	// Payload callbacks
	// -------------------------------------------------------------------------

	/**
	 * Onboarding completion payload.
	 *
	 * @param string $action Setup action label passed by the wizard hook.
	 *
	 * @return array<string,mixed>
	 */
	public function setup_payload( string $action = '' ): array {
		return [
			'action'      => sanitize_text_field( $action ),
			'__timestamp' => $this->current_timestamp(),
		];
	}

	/**
	 * Feature usage payload.
	 *
	 * Accepts the arguments supplied by whichever product-action hook fired.
	 * No customer PII is included.
	 *
	 * @param mixed ...$_args Hook arguments (silently ignored beyond timestamp).
	 *
	 * @return array<string,mixed>
	 */
	public function feature_usage_payload( ...$_args ): array {
		return [
			'__timestamp' => $this->current_timestamp(),
		];
	}

	// -------------------------------------------------------------------------
	// Aha milestone (first review approved)
	// -------------------------------------------------------------------------

	/**
	 * Handle the first-review-approved Aha milestone.
	 *
	 * Fires the Aha event exactly once per site. Subsequent calls are silently
	 * skipped once the milestone has been recorded.
	 *
	 * @param int|string $review_id Review post/row ID.
	 *
	 * @return void
	 */
	public function handle_aha_milestone( $review_id ): void {
		if ( $this->has_aha_completed() ) {
			return;
		}

		try {
			if ( $this->client ) {
				$this->client->track_kui( 'first_review_approved', $this->aha_payload( $review_id ) );
			}
		} catch ( \Exception $e ) {
			// Failure-safe: telemetry errors must never block review processing.
		}

		$this->mark_aha_completed( $review_id );
	}

	/**
	 * Check whether the first-review-approved Aha milestone has been recorded.
	 *
	 * @return bool
	 */
	public function has_aha_completed(): bool {
		return (bool) get_option( 'ugcify_first_review_approved', false );
	}

	/**
	 * Persist the Aha milestone state.
	 *
	 * @param int|string $review_id Review that triggered the milestone.
	 *
	 * @return void
	 */
	public function mark_aha_completed( $review_id ): void {
		update_option( 'ugcify_first_review_approved', '1' );
		update_option( 'ugcify_first_review_approved_at', $this->current_timestamp() );
		update_option( 'ugcify_first_review_approved_id', absint( $review_id ) );
	}

	/**
	 * Build the Aha milestone payload.
	 *
	 * Excludes all customer PII.
	 *
	 * @param int|string $review_id Review id.
	 *
	 * @return array<string,mixed>
	 */
	public function aha_payload( $review_id ): array {
		return [
			'__timestamp' => $this->current_timestamp(),
		];
	}

	// -------------------------------------------------------------------------
	// PostHog JS session recording
	// -------------------------------------------------------------------------

	/**
	 * Output the PostHog JavaScript snippet for session recording on ugcify admin pages.
	 *
	 * Runs on admin_head. Skipped when:
	 *   - Not on an ugcify admin page.
	 *   - User has not opted in to telemetry.
	 *
	 * The snippet identifies the site via the same unique_id used by the PHP SDK
	 * so server-side events and browser sessions are linked in PostHog.
	 *
	 * @return void
	 */
	public function output_posthog_js(): void {
		if ( ! $this->client ) {
			return;
		}

		if ( 'yes' !== $this->client->get_optin_state() ) {
			return;
		}

		// phpcs:ignore WordPress.Security.NonceVerification.Recommended
		$page = isset( $_GET['page'] ) ? sanitize_key( wp_unslash( $_GET['page'] ) ) : '';
		if ( ! $page || ! str_starts_with( $page, 'ugcify' ) ) {
			return;
		}

		$api_key = self::POSTHOG_API_KEY;
		$host    = self::POSTHOG_HOST;
		$site_id = esc_js( $this->client->get_unique_id() );

		?>
		<script>
		!function(t,e){var o,n,p,r;e.__SV||(window.posthog=e,e._i=[],e.init=function(i,s,a){function g(t,e){var o=e.split(".");2==o.length&&(t=t[o[0]],e=o[1]),t[e]=function(){t.push([e].concat(Array.prototype.slice.call(arguments,0)))}}(p=t.createElement("script")).type="text/javascript",p.crossOrigin="anonymous",p.async=!0,p.src=s.api_host.replace(".i.posthog.com","")+"/"+(s.asset_host||s.api_host).replace(".i.posthog.com","").replace("http://","").replace("https://","")+"/static/array.js",(r=t.getElementsByTagName("script")[0]).parentNode.insertBefore(p,r);var u=e;for(void 0!==a?u=e[a]=[]:a="posthog",u.people=u.people||[],u.toString=function(t){var e="posthog";return"posthog"!==a&&(e+="."+a),t||(e+=" (stub)"),e},u.people.toString=function(){return u.people.toString()+" (stub)"},o="init capture register register_once register_for_session unregister unregister_for_session getFeatureFlag getFeatureFlagPayload isFeatureEnabled reloadFeatureFlags updateEarlyAccessFeatureEnrollment getEarlyAccessFeatures getActiveMatchingSurveys getSurveys getNextSurveyStep onFeatureFlags posthog.init identify reset people.set people.set_once set_config startSessionRecording stopSessionRecording sessionRecordingStarted captureException loadToolbar get_distinct_id getGroups group resetGroups setPersonPropertiesForFlags resetPersonPropertiesForFlags setGroupPropertiesForFlags resetGroupPropertiesForFlags createPersonProfile opt_in_capturing opt_out_capturing has_opted_in_capturing has_opted_out_capturing clear_opt_in_out_capturing debug".split(" "),n=0;n<o.length;n++)g(u,o[n]);e._i.push([i,s,a])},e.__SV=1)}(document,window.posthog||[]);

		posthog.init(
			<?php echo wp_json_encode( $api_key ); ?>,
			{
				api_host: <?php echo wp_json_encode( $host ); ?>,
				session_recording: {
					recordCrossOriginIframes: false
				},
				capture_pageview: false,
				capture_pageleave: false,
				loaded: function( ph ) {
					ph.identify( <?php echo wp_json_encode( $site_id ); ?> );
				}
			}
		);
		</script>
		<?php
	}

	// -------------------------------------------------------------------------
	// Helpers
	// -------------------------------------------------------------------------

	/**
	 * Return current UTC timestamp for analytics ingestion.
	 *
	 * @return string ISO-8601 UTC timestamp.
	 */
	private function current_timestamp(): string {
		return gmdate( 'c' );
	}
}