<?php
/**
 * DESCRIPTION: Handles telemetry initialization, configuration, and admin opt-in notice
 * for the Sheet Wise plugin using the wp-telemetry library.
 *
 * @package SheetWise
 * @since   2.0.0
 */

namespace SheetWise;

use SheetWise\Vendor\BitApps\WPTelemetry\Telemetry\Telemetry;
use SheetWise\Vendor\BitApps\WPTelemetry\Telemetry\TelemetryConfig;

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

/**
 * Telemetry class for initializing and managing telemetry tracking.
 *
 * This class handles the initialization and configuration of the wp-telemetry library
 * for the Sheet Wise plugin. It sends weekly reports about plugin usage to a
 * configured server and provides deactivation feedback surveys.
 *
 * Available filter hooks for customization:
 * - `swise_telemetry_additional_data` - Add additional data to tracking reports
 * - `swise_telemetry_data` - Modify telemetry data before sending
 * - `swise_deactivate_reasons` - Add custom deactivation reasons to feedback survey
 * - `swise_telemetry_server_url` - Override the telemetry server URL
 * - `swise_telemetry_terms_url` - Set terms of service URL
 * - `swise_telemetry_policy_url` - Set privacy policy URL
 *
 * @since 2.0.0
 */
class Telemetry_Manager {

	/**
	 * Initialize telemetry client.
	 *
	 * Configures and initializes the wp-telemetry library with plugin-specific settings.
	 * The telemetry will send weekly reports to the configured server URL.
	 *
	 * @since 2.0.0
	 *
	 * @return void
	 */
	public static function init() {
		// Only initialize if the telemetry library is available.
		if ( ! class_exists( 'SheetWise\\Vendor\\BitApps\\WPTelemetry\\Telemetry\\Telemetry' ) ) {
			return;
		}

		// Configure telemetry settings.
		TelemetryConfig::setTitle( 'Sheet Wise' );
		TelemetryConfig::setSlug( 'sheet-wise' );
		TelemetryConfig::setPrefix( 'swise_' );
		TelemetryConfig::setVersion( SWISE_VERSION );

		// Set server base URL for telemetry with plugin token for authentication.
		// The token is embedded in the URL path so wp-telemetry can authenticate
		// without needing custom HTTP headers.
		$token      = defined( 'SWISE_TELEMETRY_TOKEN' ) ? SWISE_TELEMETRY_TOKEN : '';
		$server_url = apply_filters( 'swise_telemetry_server_url', 'https://feedio.sapayth.com/api/t/' . $token . '/' );

		if ( ! empty( $server_url ) ) {
			TelemetryConfig::setServerBaseUrl( $server_url );
		}

		// Set optional terms and policy URLs.
		$terms_url = apply_filters( 'swise_telemetry_terms_url', '' );

		if ( ! empty( $terms_url ) ) {
			TelemetryConfig::setTermsUrl( $terms_url );
		}

		$policy_url = apply_filters( 'swise_telemetry_policy_url', 'https://feedio.sapayth.com/policy' );

		if ( ! empty( $policy_url ) ) {
			TelemetryConfig::setPolicyUrl( $policy_url );
		}

		// Add plugin_name to telemetry data to match feedio API requirements.
		add_filter( 'swise_telemetry_data', [ __CLASS__, 'add_plugin_name_to_data' ], 10, 1 );

		// Add inactive plugins list to telemetry data.
		add_filter( 'swise_telemetry_data', [ __CLASS__, 'add_inactive_plugins_to_data' ], 10, 1 );

		// Remove plugin counts (redundant since we send full lists).
		add_filter( 'swise_telemetry_data', [ __CLASS__, 'remove_plugin_counts' ], 10, 1 );

		// Add additional system data (MySQL, language, themes).
		add_filter( 'swise_telemetry_data', [ __CLASS__, 'add_additional_system_data' ], 10, 1 );

		// Initialize telemetry tracking.
		Telemetry::report()->addPluginData()->init();

		// Initialize deactivation feedback survey.
		Telemetry::feedback()->init();

		// Override the default admin notice and add our custom one.
		// Use admin_init hook with later priority to ensure telemetry is initialized first.
		add_action( 'admin_init', [ __CLASS__, 'remove_default_telemetry_notice' ], 20 );
		add_action( 'admin_notices', [ __CLASS__, 'custom_telemetry_notice' ], 10 );
	}

	/**
	 * Add plugin_name to telemetry data.
	 *
	 * This ensures the telemetry data includes plugin_name which is preferred
	 * by the feedio API. The plugin_name is set to the plugin slug for consistency.
	 * The API will also accept plugin_slug as a fallback.
	 *
	 * @since 2.0.0
	 *
	 * @param array $data The telemetry data array.
	 *
	 * @return array Modified data array with plugin_name added.
	 */
	public static function add_plugin_name_to_data( $data ) {
		$data['plugin_name'] = TelemetryConfig::getTitle();

		return $data;
	}

	/**
	 * Add inactive plugins list to telemetry data.
	 *
	 * The wp-telemetry library only sends active plugins by default.
	 * This filter adds inactive plugins to the data for complete plugin tracking.
	 *
	 * @since 2.0.0
	 *
	 * @param array $data The telemetry data array.
	 *
	 * @return array Modified data array with inactive_plugins_list added.
	 */
	public static function add_inactive_plugins_to_data( $data ) {
		if ( ! function_exists( 'get_plugins' ) ) {
			require_once ABSPATH . '/wp-admin/includes/plugin.php';
		}

		$all_plugins         = get_plugins();
		$active_plugins_keys = get_option( 'active_plugins', [] );
		$inactive_plugins    = [];

		foreach ( $all_plugins as $plugin_key => $plugin_data ) {
			if ( in_array( $plugin_key, $active_plugins_keys, true ) ) {
				continue;
			}

			$inactive_plugins[ $plugin_key ] = [
				'name'    => wp_strip_all_tags( $plugin_data['Name'] ?? '' ),
				'version' => wp_strip_all_tags( $plugin_data['Version'] ?? '' ),
				'author'  => wp_strip_all_tags( $plugin_data['Author'] ?? '' ),
			];
		}

		if ( ! empty( $inactive_plugins ) ) {
			$data['inactive_plugins_list'] = $inactive_plugins;
		}

		return $data;
	}

	/**
	 * Remove plugin counts from telemetry data.
	 *
	 * Since we send full active plugins list and inactive_plugins_list,
	 * counts are redundant and can be calculated from the lists.
	 *
	 * @since 2.0.0
	 *
	 * @param array $data The telemetry data array.
	 *
	 * @return array Modified data array with plugin counts removed.
	 */
	public static function remove_plugin_counts( $data ) {
		unset( $data['active_plugins_count'] );
		unset( $data['inactive_plugins_count'] );
		unset( $data['plugins_count'] );
		unset( $data['total_plugins_count'] );

		return $data;
	}

	/**
	 * Add additional system data to telemetry.
	 *
	 * Adds MySQL version, site language, and all themes list.
	 *
	 * @since 2.0.0
	 *
	 * @param array $data The telemetry data array.
	 *
	 * @return array Modified data array with additional system data.
	 */
	public static function add_additional_system_data( $data ) {
		global $wpdb;

		if ( method_exists( $wpdb, 'db_version' ) ) {
			$data['mysql_version'] = $wpdb->db_version();
		} else {
			$mysql_version = $wpdb->get_var( 'SELECT VERSION()' ); // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching

			if ( $mysql_version ) {
				$data['mysql_version'] = $mysql_version;
			}
		}

		$data['site_language'] = get_locale();

		if ( ! function_exists( 'wp_get_themes' ) ) {
			require_once ABSPATH . '/wp-includes/theme.php';
		}

		$themes_list = [];

		if ( function_exists( 'wp_get_themes' ) ) {
			$all_themes = wp_get_themes();

			foreach ( $all_themes as $theme_slug => $theme ) {
				$themes_list[ $theme_slug ] = [
					'name'    => $theme->get( 'Name' ),
					'version' => $theme->get( 'Version' ),
					'author'  => $theme->get( 'Author' ),
				];
			}
		}

		if ( ! empty( $themes_list ) ) {
			$data['themes_list'] = $themes_list;
		}

		return $data;
	}

	/**
	 * Opt in to telemetry tracking.
	 *
	 * Allows users to opt in to telemetry tracking programmatically.
	 *
	 * @since 2.0.0
	 *
	 * @return void
	 */
	public static function opt_in() {
		if ( ! class_exists( 'SheetWise\\Vendor\\BitApps\\WPTelemetry\\Telemetry\\Telemetry' ) ) {
			return;
		}

		// Clear last sent timestamp to force immediate send (bypass weekly check).
		delete_option( 'swise_tracking_last_sended_at' );

		Telemetry::report()->trackingOptIn();

		// Use reflection to call sendTrackingReport directly to bypass weekly check.
		try {
			$reflection = new \ReflectionClass( Telemetry::report() );
			$method     = $reflection->getMethod( 'sendTrackingReport' );
			$method->setAccessible( true );
			$method->invoke( Telemetry::report() );
		} catch ( \Exception $e ) { // phpcs:ignore Generic.CodeAnalysis.EmptyStatement.DetectedCatch
			// Error calling sendTrackingReport.
		}
	}

	/**
	 * Opt out of telemetry tracking.
	 *
	 * Allows users to opt out of telemetry tracking programmatically.
	 *
	 * @since 2.0.0
	 *
	 * @return void
	 */
	public static function opt_out() {
		if ( ! class_exists( 'SheetWise\\Vendor\\BitApps\\WPTelemetry\\Telemetry\\Telemetry' ) ) {
			return;
		}

		Telemetry::report()->trackingOptOut();
	}

	/**
	 * Check if telemetry tracking is allowed.
	 *
	 * @since 2.0.0
	 *
	 * @return bool True if tracking is enabled, false otherwise.
	 */
	public static function is_tracking_allowed() {
		if ( ! class_exists( 'SheetWise\\Vendor\\BitApps\\WPTelemetry\\Telemetry\\Telemetry' ) ) {
			return false;
		}

		return Telemetry::report()->isTrackingAllowed();
	}

	/**
	 * Remove the default wp-telemetry admin notice.
	 *
	 * This is called on admin_init with priority 20 to ensure the telemetry
	 * library has already added its admin_notices action.
	 *
	 * @since 2.0.0
	 *
	 * @return void
	 */
	public static function remove_default_telemetry_notice() {
		if ( ! class_exists( 'SheetWise\\Vendor\\BitApps\\WPTelemetry\\Telemetry\\Telemetry' ) ) {
			return;
		}

		remove_action( 'admin_notices', [ Telemetry::report(), 'adminNotice' ] );
	}

	/**
	 * Custom telemetry admin notice with expandable "Data We Collect" section.
	 *
	 * This overrides the default wp-telemetry notice to show an expandable section
	 * that displays what data is collected when "what we collect" is clicked.
	 *
	 * @since 2.0.0
	 *
	 * @return void
	 */
	public static function custom_telemetry_notice() {
		if ( ! current_user_can( 'manage_options' ) ) {
			return;
		}

		// Check if notice should be shown (same logic as wp-telemetry).
		$notice_dismissed = get_option( TelemetryConfig::getPrefix() . 'tracking_notice_dismissed' );
		$tracking_allowed = get_option( TelemetryConfig::getPrefix() . 'allow_tracking' );

		if ( $notice_dismissed || $tracking_allowed ) {
			return;
		}

		$opt_in_url  = wp_nonce_url( add_query_arg( TelemetryConfig::getPrefix() . 'tracking_opt_in', 'true' ), '_wpnonce' );
		$opt_out_url = wp_nonce_url( add_query_arg( TelemetryConfig::getPrefix() . 'tracking_opt_out', 'true' ), '_wpnonce' );
		$plugin_name = TelemetryConfig::getTitle();

		$collected_data = [
			__( 'WordPress version', 'sheet-wise' ),
			__( 'PHP version', 'sheet-wise' ),
			__( 'MySQL version', 'sheet-wise' ),
			__( 'Plugin version', 'sheet-wise' ),
			__( 'Active plugins list', 'sheet-wise' ),
			__( 'Inactive plugins list', 'sheet-wise' ),
			__( 'Active theme name', 'sheet-wise' ),
			__( 'Themes list', 'sheet-wise' ),
			__( 'Site language', 'sheet-wise' ),
			__( 'Site URL', 'sheet-wise' ),
			__( 'Plugin name', 'sheet-wise' ),
		];

		$collected_data_string = implode( ', ', $collected_data );

		$notice_text = sprintf(
			// Translators: %1$s is the plugin name, %2$s is the "what we collect" clickable text.
			__( 'Want to help make %1$s even more awesome? Allow %1$s to collect diagnostic data and usage information. (%2$s)', 'sheet-wise' ),
			'<strong>' . esc_html( $plugin_name ) . '</strong>',
			'<a href="#" class="swise-what-we-collect-toggle" style="cursor: pointer; text-decoration: underline;">' . esc_html__( 'what we collect', 'sheet-wise' ) . '</a>'
		);
		?>
		<div class="updated swise-telemetry-notice">
			<p><?php echo wp_kses_post( $notice_text ); ?></p>
			<div class="swise-collected-data" style="display: none;">
				<p style="margin: 5px 0 0 0;"><?php echo esc_html( $collected_data_string ); ?></p>
			</div>
			<p class="submit">
				&nbsp;<a href="<?php echo esc_url( $opt_in_url ); ?>"
					class="button-primary button-large"><?php esc_html_e( 'Allow', 'sheet-wise' ); ?></a>&nbsp;
				<a href="<?php echo esc_url( $opt_out_url ); ?>"
					class="button-secondary button-large"><?php esc_html_e( 'No thanks', 'sheet-wise' ); ?></a>
			</p>
		</div>
		<script>
		(function() {
			document.addEventListener('DOMContentLoaded', function() {
				var toggle = document.querySelector('.swise-what-we-collect-toggle');
				var dataSection = document.querySelector('.swise-collected-data');

				if (toggle && dataSection) {
					toggle.addEventListener('click', function(e) {
						e.preventDefault();
						if (dataSection.style.display === 'none') {
							dataSection.style.display = 'block';
						} else {
							dataSection.style.display = 'none';
						}
					});
				}
			});
		})();
		</script>
		<?php
	}
}
