<?php
/**
 * DESCRIPTION: Telemetry manager for Nemtly Booking — wraps the bitapps/wp-telemetry
 * library to send opt-in weekly usage reports and a deactivation feedback survey to feedio.
 *
 * Handles telemetry initialization and configuration.
 *
 * @since   PBOOKING_SINCE
 * @package Nemtly_Booking
 */

namespace NemtlyBooking\Core;

use BitApps\WPTelemetry\Telemetry\Telemetry;
use BitApps\WPTelemetry\Telemetry\TelemetryConfig;

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

/**
 * Telemetry class for initializing and managing telemetry tracking.
 *
 * This class configures the wp-telemetry library for Nemtly Booking. It sends weekly
 * reports about plugin usage to the configured feedio server (opt-in only) and provides
 * a deactivation feedback survey.
 *
 * Available filter hooks for customization:
 * - `nemtly_booking_telemetry_additional_data` - Add additional data to tracking reports
 * - `nemtly_booking_telemetry_data` - Modify telemetry data before sending
 * - `nemtly_booking_deactivate_reasons` - Add custom deactivation reasons to feedback survey
 * - `nemtly_booking_telemetry_server_url` - Override the telemetry server URL
 * - `nemtly_booking_telemetry_terms_url` - Set terms of service URL
 * - `nemtly_booking_telemetry_policy_url` - Set privacy policy URL
 *
 * @since PBOOKING_SINCE
 */
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 once the user
     * has opted in.
     *
     * @since PBOOKING_SINCE
     *
     * @return void
     */
    public static function init() {
        // Only initialize if the telemetry library is available.
        if ( ! class_exists( 'BitApps\\WPTelemetry\\Telemetry\\Telemetry' ) ) {
            return;
        }

        // Configure telemetry settings.
        TelemetryConfig::setTitle( __( 'Nemtly Booking', 'nemtly-booking' ) );
        TelemetryConfig::setSlug( 'nemtly-booking' );
        TelemetryConfig::setPrefix( 'nemtly_booking_' );
        TelemetryConfig::setVersion( defined( 'NEMTLY_BOOKING_VERSION' ) ? NEMTLY_BOOKING_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( 'NEMTLY_BOOKING_TELEMETRY_TOKEN' ) ? NEMTLY_BOOKING_TELEMETRY_TOKEN : '';
        $server_url = apply_filters( 'nemtly_booking_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( 'nemtly_booking_telemetry_terms_url', '' );
        if ( ! empty( $terms_url ) ) {
            TelemetryConfig::setTermsUrl( $terms_url );
        }
        $policy_url = apply_filters( 'nemtly_booking_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( 'nemtly_booking_telemetry_data', [ __CLASS__, 'add_plugin_name_to_data' ], 10, 1 );
        // Add inactive plugins list to telemetry data.
        add_filter( 'nemtly_booking_telemetry_data', [ __CLASS__, 'add_inactive_plugins_to_data' ], 10, 1 );
        // Remove plugin counts (redundant since we send full lists).
        add_filter( 'nemtly_booking_telemetry_data', [ __CLASS__, 'remove_plugin_counts' ], 10, 1 );
        // Add additional system data (MySQL, language, themes).
        add_filter( 'nemtly_booking_telemetry_data', [ __CLASS__, 'add_additional_system_data' ], 10, 1 );
        // Remove the "I have Pro" deactivation reason since Nemtly Booking has no Pro version.
        add_filter( 'nemtly_booking_deactivate_reasons', [ __CLASS__, 'remove_pro_deactivate_reason' ], 10, 1 );

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

        // Override the default opt-in admin notice with a custom "what we collect" one.
        // admin_init priority 20 ensures the telemetry library registered its notice 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.
     *
     * Ensures the telemetry data includes plugin_name which is preferred by the feedio
     * API. The plugin_name is set to the plugin slug for readability.
     *
     * @since PBOOKING_SINCE
     *
     * @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::getSlug();
        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 PBOOKING_SINCE
     *
     * @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 ) {
            // Skip if this plugin is active.
            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 and inactive plugins lists, counts are redundant and can
     * be derived from the lists.
     *
     * @since PBOOKING_SINCE
     *
     * @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 PBOOKING_SINCE
     *
     * @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;

        // MySQL/MariaDB version.
        if ( method_exists( $wpdb, 'db_version' ) ) {
            $data['mysql_version'] = $wpdb->db_version();
        } else {
            // Fallback: try to get version from query.
            $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;
            }
        }

        // Site language.
        $data['site_language'] = get_locale();

        // All themes list (not just active).
        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;
    }

    /**
     * Remove the "I have Nemtly Booking Pro" deactivation reason.
     *
     * Nemtly Booking does not have a Pro version, so this reason is not applicable.
     *
     * @since PBOOKING_SINCE
     *
     * @param array $reasons The deactivation reasons array.
     *
     * @return array Modified reasons array without the Pro option.
     */
    public static function remove_pro_deactivate_reason( $reasons ) {
        unset( $reasons[ TelemetryConfig::getPrefix() . 'pro' ] );
        return $reasons;
    }

    /**
     * Opt in to telemetry tracking.
     *
     * Allows code to opt in to telemetry tracking programmatically and forces an
     * immediate report send (bypassing the weekly schedule).
     *
     * @since PBOOKING_SINCE
     *
     * @return void
     */
    public static function opt_in() {
        if ( file_exists( NEMTLY_BOOKING_PATH . 'vendor/autoload.php' ) ) {
            require_once NEMTLY_BOOKING_PATH . 'vendor/autoload.php';
        }

        $telemetry_class = 'BitApps\\WPTelemetry\\Telemetry\\Telemetry';
        if ( ! class_exists( $telemetry_class ) ) {
            return;
        }

        // Clear last sent timestamp to force immediate send (bypass weekly check).
        delete_option( 'nemtly_booking_tracking_last_sended_at' );
        Telemetry::report()->trackingOptIn();

        // Use reflection to call sendTrackingReport directly to bypass the 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.
     *
     * @since PBOOKING_SINCE
     *
     * @return void
     */
    public static function opt_out() {
        if ( class_exists( 'BitApps\\WPTelemetry\\Telemetry\\Telemetry' ) ) {
            Telemetry::report()->trackingOptOut();
        }
    }

    /**
     * Check if telemetry tracking is allowed.
     *
     * @since PBOOKING_SINCE
     *
     * @return bool True if tracking is enabled, false otherwise.
     */
    public static function is_tracking_allowed() {
        if ( class_exists( 'BitApps\\WPTelemetry\\Telemetry\\Telemetry' ) ) {
            return Telemetry::report()->isTrackingAllowed();
        }
        return false;
    }

    /**
     * Remove the default wp-telemetry admin notice.
     *
     * Called on admin_init with priority 20 to ensure the telemetry library has already
     * registered its admin_notices action.
     *
     * @since PBOOKING_SINCE
     *
     * @return void
     */
    public static function remove_default_telemetry_notice() {
        if ( class_exists( 'BitApps\\WPTelemetry\\Telemetry\\Telemetry' ) ) {
            remove_action( 'admin_notices', [ Telemetry::report(), 'adminNotice' ] );
        }
    }

    /**
     * Custom telemetry admin notice with an expandable "what we collect" section.
     *
     * Overrides the default wp-telemetry notice to show an expandable list of the data
     * collected when the user clicks "what we collect".
     *
     * @since PBOOKING_SINCE
     *
     * @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();

        // Define what data we collect (comma-separated list).
        $collected_data        = [
            __( 'WordPress version', 'nemtly-booking' ),
            __( 'PHP version', 'nemtly-booking' ),
            __( 'MySQL version', 'nemtly-booking' ),
            __( 'Plugin version', 'nemtly-booking' ),
            __( 'Active plugins list', 'nemtly-booking' ),
            __( 'Inactive plugins list', 'nemtly-booking' ),
            __( 'Active theme name', 'nemtly-booking' ),
            __( 'Themes list', 'nemtly-booking' ),
            __( 'Site language', 'nemtly-booking' ),
            __( 'Site URL', 'nemtly-booking' ),
            __( 'Plugin name', 'nemtly-booking' ),
            __( 'Activation milestones (dates of first event, first booking, first payment)', 'nemtly-booking' ),
        ];
        $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)', 'nemtly-booking' ),
            '<strong>' . esc_html( $plugin_name ) . '</strong>',
            '<a href="#" class="nemtly-booking-what-we-collect-toggle" style="cursor: pointer; text-decoration: underline;">' . esc_html__( 'what we collect', 'nemtly-booking' ) . '</a>'
        );
        ?>
        <div class="updated nemtly-booking-telemetry-notice">
            <p><?php echo wp_kses_post( $notice_text ); ?></p>
            <div class="nemtly-booking-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', 'nemtly-booking' ); ?></a>&nbsp;
                <a href="<?php echo esc_url( $opt_out_url ); ?>"
                    class="button-secondary button-large"><?php esc_html_e( 'No thanks', 'nemtly-booking' ); ?></a>
            </p>
        </div>
        <script>
        (function() {
            document.addEventListener('DOMContentLoaded', function() {
                var toggle = document.querySelector('.nemtly-booking-what-we-collect-toggle');
                var dataSection = document.querySelector('.nemtly-booking-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
    }
}
