<?php
/**
 * Telemetry Module
 * Sends anonymous usage data to improve the plugin
 *
 * @package WP Switchboard Pro
 */

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

class WPSB_Telemetry_Module {

    private static $instance = null;
    private $webhook_url;
    private $activation_id;
    private $install_id; // Persists from free version for conversion tracking

    public static function instance() {
        if (is_null(self::$instance)) {
            self::$instance = new self();
        }
        return self::$instance;
    }

    private function __construct() {
        // Only initialize on admin pages, AJAX requests, or WP-Cron
        // This prevents any overhead on front-end page loads
        if (!is_admin() && !wp_doing_ajax() && !wp_doing_cron()) {
            return;
        }

        // Get webhook URL (base64 encoded with signature)
        $encoded_data = defined('WPSB_TELEMETRY_WEBHOOK_URL')
            ? WPSB_TELEMETRY_WEBHOOK_URL
            : get_option('wpsb_telemetry_webhook_url');

        // Decode and verify webhook URL
        $this->webhook_url = $this->decode_and_verify_webhook_url($encoded_data);

        // Get activation ID from SureCart license
        $this->activation_id = $this->get_activation_id();

        // Get install_id (persists from free version, or generate new if fresh pro install)
        $this->install_id = $this->get_install_id();

        // Only initialize if telemetry is enabled and configured
        if ($this->is_enabled() && $this->is_configured()) {
            $this->init_hooks();
        }
    }

    /**
     * Initialize hooks
     */
    private function init_hooks() {
        // Send first activation
        add_action('switchboard_plugin_activated', [$this, 'send_first_activation']);

        // Send license validated event (Pro only)
        add_action('switchboard_license_validated', [$this, 'send_license_validated']);

        // Send module enable/disable events
        add_action('switchboard_module_enabled', [$this, 'send_module_enabled'], 10, 1);
        add_action('switchboard_module_disabled', [$this, 'send_module_disabled'], 10, 3);

        // Schedule weekly ping
        if (!wp_next_scheduled('wpsb_weekly_telemetry_ping')) {
            wp_schedule_event(time(), 'weekly', 'wpsb_weekly_telemetry_ping');
        }
        add_action('wpsb_weekly_telemetry_ping', [$this, 'send_weekly_ping']);

        // Add settings page
        add_action('admin_init', [$this, 'register_settings']);

        // Enqueue assets for disable reason popover
        add_action('admin_enqueue_scripts', [$this, 'enqueue_assets']);

        // AJAX handler for module disable
        add_action('wp_ajax_wpsb_disable_module', [$this, 'ajax_disable_module']);
    }

    /**
     * Check if telemetry is enabled
     */
    private function is_enabled() {
        // Check if user opted out (check both option names for compatibility)
        $opted_out = get_option('switchboard_opt_out_telemetry', false);

        // Skip localhost/dev environments (unless explicitly allowed via flag)
        $is_localhost = $this->is_localhost();
        $allow_localhost = defined('SWITCHBOARD_ALLOW_LOCALHOST_TELEMETRY') && SWITCHBOARD_ALLOW_LOCALHOST_TELEMETRY;

        // If localhost and not allowed, disable telemetry
        if ($is_localhost && !$allow_localhost) {
            return false;
        }

        if ($opted_out) {
            return false;
        }

        return true;
    }

    /**
     * Check if telemetry is configured
     */
    private function is_configured() {
        return !empty($this->webhook_url) && !empty($this->activation_id) && !empty($this->install_id);
    }

    /**
     * Get activation ID from SureCart license
     */
    private function get_activation_id() {
        // Get from wpswitchboard_license_options
        $license_options = get_option('wpswitchboard_license_options');

        if ($license_options && isset($license_options['sc_activation_id'])) {
            return $license_options['sc_activation_id'];
        }

        // Fallback: check old option
        $activation_id = get_option('wpsb_activation_id');

        if (!$activation_id) {
            // Generate a unique ID if none exists (fallback)
            $activation_id = 'wpsb_' . substr(md5(get_site_url()), 0, 16);
            update_option('wpsb_activation_id', $activation_id);
        }

        return $activation_id;
    }

    /**
     * Get or generate install ID (persists from free version for conversion tracking)
     * This ID stays the same when upgrading from free to pro
     */
    private function get_install_id() {
        // Check if install_id already exists (from free version or previous pro install)
        $install_id = get_option('wpsb_install_id');

        if (!$install_id) {
            // Generate new install_id if this is a fresh pro installation
            // Use same format as free version for consistency
            $random_component = function_exists('wp_generate_password')
                ? wp_generate_password(20, false)
                : bin2hex(random_bytes(10));

            $install_id = 'wpsb_pro_' . substr(md5(get_site_url() . $random_component), 0, 20);
            update_option('wpsb_install_id', $install_id, false); // Don't autoload
        }

        return $install_id;
    }

    /**
     * Get license key from stored options (used as HMAC secret)
     */
    private function get_license_key() {
        // Get from wpswitchboard_license_options (already stored locally!)
        $license_options = get_option('wpswitchboard_license_options');

        if ($license_options && isset($license_options['sc_license_key'])) {
            // Return the license key directly - no API call needed!
            return $license_options['sc_license_key'];
        }

        // Fallback: Try to fetch from SureCart API if not stored locally
        return $this->fetch_license_key_from_api();
    }

    /**
     * Fetch license key from SureCart API (fallback method)
     */
    private function fetch_license_key_from_api() {
        // Check cache first
        $cache_key = 'wpsb_license_key_' . $this->activation_id;
        $cached = get_transient($cache_key);

        if ($cached !== false) {
            return $cached;
        }

        // Fetch from SureCart API
        $api_key = 'sk_test_tDhJ2juajF6QTQQDVW3EpAcw';

        // Get activation to find license ID
        $activation_response = wp_remote_get(
            'https://api.surecart.com/v1/activations/' . $this->activation_id,
            [
                'headers' => [
                    'Authorization' => 'Bearer ' . $api_key,
                    'Content-Type' => 'application/json',
                ],
                'timeout' => 15,
            ]
        );

        if (is_wp_error($activation_response)) {
            return null;
        }

        $activation_data = json_decode(wp_remote_retrieve_body($activation_response));
        if (!$activation_data || !isset($activation_data->license)) {
            return null;
        }

        // Get license to retrieve the key
        $license_response = wp_remote_get(
            'https://api.surecart.com/v1/licenses/' . $activation_data->license,
            [
                'headers' => [
                    'Authorization' => 'Bearer ' . $api_key,
                    'Content-Type' => 'application/json',
                ],
                'timeout' => 15,
            ]
        );

        if (is_wp_error($license_response)) {
            return null;
        }

        $license_data = json_decode(wp_remote_retrieve_body($license_response));
        if (!$license_data || !isset($license_data->key)) {
            return null;
        }

        // Cache for 1 hour
        set_transient($cache_key, $license_data->key, 3600);

        return $license_data->key;
    }

    /**
     * Check if site is localhost
     */
    private function is_localhost() {
        $url = get_site_url();
        $localhost_patterns = [
            'localhost',
            '127.0.0.1',
            '::1',
            '.local',
            '.test',
            '.dev',
            'staging.',
            'dev.',
        ];

        foreach ($localhost_patterns as $pattern) {
            if (strpos($url, $pattern) !== false) {
                return true;
            }
        }

        return false;
    }

    /**
     * Decode and verify webhook URL integrity
     */
    private function decode_and_verify_webhook_url($encoded_data) {
        if (empty($encoded_data)) {
            return '';
        }

        // Try to decode as JSON
        $data = json_decode(base64_decode($encoded_data), true);

        if ($data && isset($data['v'])) {
            // Version 2: Encrypted + authenticated (AES-256-GCM)
            if ($data['v'] === 2 && isset($data['c']) && isset($data['i']) && isset($data['t'])) {
                return $this->decrypt_webhook_url_v2($data);
            }

            // Version 1: Signed only
            if ($data['v'] === 1 && isset($data['url']) && isset($data['signature'])) {
                return $this->verify_webhook_url_v1($data);
            }
        }

        // Legacy format detection
        if ($data && isset($data['url']) && isset($data['signature'])) {
            // Old signed format (v1 without version field)
            return $this->verify_webhook_url_v1($data);
        }

        // Fallback: plain base64 URL (legacy)
        $url = base64_decode($encoded_data);

        // Basic validation - must be HTTPS and contain expected endpoint pattern
        if (strpos($url, 'https://') === 0 && strpos($url, '/wp-json/wpsb-telemetry/v1/webhook') !== false) {
            return $url;
        }

        return '';
    }

    /**
     * Decrypt webhook URL (Version 2 - AES-256-GCM)
     */
    private function decrypt_webhook_url_v2($data) {
        try {
            $ciphertext = base64_decode($data['c']);
            $iv = base64_decode($data['i']);
            $tag = base64_decode($data['t']);

            $key = $this->get_encryption_key();

            // Decrypt with authenticated decryption
            $url = openssl_decrypt(
                $ciphertext,
                'aes-256-gcm',
                $key,
                OPENSSL_RAW_DATA,
                $iv,
                $tag
            );

            if ($url === false) {
                return '';
            }

            // Additional validation
            if (strpos($url, 'https://') === 0 && strpos($url, '/wp-json/wpsb-telemetry/v1/webhook') !== false) {
                return $url;
            }

            return '';

        } catch (Exception $e) {
            return '';
        }
    }

    /**
     * Verify webhook URL (Version 1 - HMAC signature)
     */
    private function verify_webhook_url_v1($data) {
        $url = $data['url'];
        $signature = $data['signature'];

        // Verify signature using embedded secret
        $expected_signature = $this->generate_url_signature($url);

        if (hash_equals($expected_signature, $signature)) {
            // Signature valid - URL hasn't been tampered with
            return $url;
        }

        return '';
    }

    /**
     * Get encryption key (shared secret between receiver and all senders)
     *
     * IMPORTANT: This must be the SAME constant as in the receiver plugin.
     * Do not modify this value - it must match the receiver's secret exactly.
     */
    private function get_encryption_key() {
        // Use the same hardcoded shared secret as receiver (not WordPress salts!)
        // This MUST be identical to the receiver's secret
        $shared_secret = 'a8f5e2d1c9b4a7f3e8d2c5b9a4f7e3d8c2b5a9f4e7d3c8b2a5f9e4d7c3b8a2f5';

        return hash('sha256', 'wpsb_telemetry_v2_' . $shared_secret, true); // 32 bytes for AES-256
    }

    /**
     * Generate signature for webhook URL verification (v1 compatibility)
     */
    private function generate_url_signature($url) {
        $secret = 'wpsb_telemetry_url_verification_v1_' . wp_salt('nonce');
        return hash_hmac('sha256', $url, $secret);
    }

    /**
     * Get decoded webhook URL
     */
    private function get_webhook_url() {
        return $this->webhook_url;
    }

    /**
     * Send telemetry data
     */
    private function send($data) {
        if (!$this->is_configured()) {
            return false;
        }

        // Get license key (HMAC secret)
        $license_key = $this->get_license_key();

        if (!$license_key) {
            return false;
        }

        // No site URL or fingerprint needed - server will fetch site details from SureCart using activation_id
        // Authentication handled by X-Signature HMAC verification

        // Prepare payload
        $payload = wp_json_encode($data);

        // Generate signature using license key
        $signature = hash_hmac('sha256', $payload, $license_key);

        // Get decoded webhook URL
        $webhook_url = $this->get_webhook_url();

        if (empty($webhook_url)) {
            return false;
        }

        // Send request
        $response = wp_remote_post($webhook_url, [
            'headers' => [
                'Content-Type' => 'application/json',
                'X-Signature' => $signature,
                'X-Timestamp' => time(),
            ],
            'body' => $payload,
            'timeout' => 10,
            'blocking' => false, // Non-blocking for better performance
        ]);

        if (is_wp_error($response)) {
        }

        return !is_wp_error($response);
    }

    /**
     * Send first activation event
     */
    public function send_first_activation() {
        // Check if already sent
        if (get_option('wpsb_telemetry_first_activation_sent')) {
            return;
        }

        $data = [
            'activation_id' => $this->activation_id,
            'install_id' => $this->install_id, // For conversion tracking
            'is_free' => false, // Explicit pro flag
            'event_type' => 'first_activation',
            'plugin_version' => defined('SWITCHBOARD_VERSION') ? SWITCHBOARD_VERSION : '0.0.0',
            'wp_version' => get_bloginfo('version'),
            'php_version' => PHP_VERSION,
            'site_name' => get_bloginfo('name'),
            'site_url' => get_site_url(),
            'install_date' => current_time('mysql'),
            'is_localhost' => $this->is_localhost(),
            'is_multisite' => is_multisite(),
            'locale' => get_locale(),
            'timestamp' => time(), // Unix timestamp
        ];

        if ($this->send($data)) {
            update_option('wpsb_telemetry_first_activation_sent', true);
        }
    }

    /**
     * Send license validated event
     * This is called when a Pro license is successfully activated
     */
    public function send_license_validated() {
        $data = [
            'activation_id' => $this->activation_id,
            'install_id' => $this->install_id, // For conversion tracking!
            'is_free' => false, // Explicit pro flag
            'event_type' => 'license_validated',
            'plugin_version' => defined('SWITCHBOARD_VERSION') ? SWITCHBOARD_VERSION : '0.0.0',
            'wp_version' => get_bloginfo('version'),
            'php_version' => PHP_VERSION,
            'site_name' => get_bloginfo('name'),
            'site_url' => get_site_url(),
            'is_localhost' => $this->is_localhost(),
            'is_multisite' => is_multisite(),
            'locale' => get_locale(),
            'timestamp' => time(), // Unix timestamp
        ];

        $this->send($data);
    }

    /**
     * Send module enabled event
     */
    public function send_module_enabled($module_slug) {
        $module_info = $this->get_module_info($module_slug);

        $data = [
            'activation_id' => $this->activation_id,
            'install_id' => $this->install_id, // For conversion tracking
            'is_free' => false, // Explicit pro flag
            'event_type' => 'module_enabled',
            'module' => (object) [
                'slug' => $module_info['slug'],  // Full slug with category (e.g., "content/auto-featured-image")
                'name' => $module_info['name'],
            ],
            'timestamp' => time(), // Unix timestamp
        ];

        $this->send($data);
    }

    /**
     * Send module disabled event
     */
    public function send_module_disabled($module_slug, $reason = null, $reason_details = null) {
        // Debug logging
        if (defined('WP_DEBUG') && WP_DEBUG) {
            error_log('[WP Switchboard Telemetry] send_module_disabled called: module=' . $module_slug .
                     ', reason=' . ($reason ?: 'none') .
                     ', details=' . ($reason_details ? 'yes' : 'no'));
        }

        $module_info = $this->get_module_info($module_slug);

        // Check if feedback is disabled - if so, don't send reason/details
        $disable_feedback = filter_var(get_option('switchboard_disable_feedback', true), FILTER_VALIDATE_BOOLEAN);

        if (defined('WP_DEBUG') && WP_DEBUG) {
            error_log('[WP Switchboard Telemetry] disable_feedback option: ' . ($disable_feedback ? 'YES' : 'NO'));
        }

        if ($disable_feedback) {
            $reason = null;
            $reason_details = null;
            if (defined('WP_DEBUG') && WP_DEBUG) {
                error_log('[WP Switchboard Telemetry] Feedback disabled, clearing reason and details');
            }
        }

        $data = [
            'activation_id' => $this->activation_id,
            'install_id' => $this->install_id, // For conversion tracking
            'is_free' => false, // Explicit pro flag
            'event_type' => 'module_disabled',
            'module' => (object) [
                'slug' => $module_info['slug'],  // Full slug with category (e.g., "content/auto-featured-image")
                'name' => $module_info['name'],
            ],
            'reason' => $reason,
            'reason_details' => $reason_details,
            'timestamp' => time(), // Unix timestamp
        ];

        $this->send($data);
    }

    /**
     * Get module info (category and name) from filename slug
     * Returns array with 'category', 'name', and 'slug' (category/filename)
     */
    private function get_module_info($module_slug) {
        // Try to load the module file and extract the name and category
        $categories = ['admin', 'content', 'media', 'security', 'optimization', 'user-management', 'utilities'];

        foreach ($categories as $category) {
            $file_path = (defined('SWITCHBOARD_PATH') ? SWITCHBOARD_PATH : plugin_dir_path(dirname(dirname(dirname(dirname(__FILE__))))))
                . 'modules/' . $category . '/' . $module_slug . '.php';

            if (file_exists($file_path)) {
                // Try to extract module name from PHP doc comment
                $file_contents = file_get_contents($file_path);
                $module_name = null;

                if (preg_match('/@module\s+(.+)/i', $file_contents, $matches)) {
                    $module_name = trim($matches[1]);
                } elseif (preg_match('/\*\s*Module:\s*(.+)/i', $file_contents, $matches)) {
                    $module_name = trim($matches[1]);
                } elseif (preg_match('/\*\s*Name:\s*(.+)/i', $file_contents, $matches)) {
                    $module_name = trim($matches[1]);
                } else {
                    // Fallback: Generate readable name from slug
                    $module_name = ucwords(str_replace(['-', '_'], ' ', $module_slug));
                }

                return [
                    'category' => $category,
                    'name' => $module_name,
                    'slug' => $category . '/' . $module_slug,  // Full slug with category prefix
                ];
            }
        }

        // Fallback if file not found
        return [
            'category' => 'unknown',
            'name' => ucwords(str_replace(['-', '_'], ' ', $module_slug)),
            'slug' => 'unknown/' . $module_slug,
        ];
    }

    /**
     * Send weekly ping
     */
    public function send_weekly_ping() {
        // Get all enabled modules with names
        $enabled_modules = $this->get_enabled_modules();

        $data = [
            'activation_id' => $this->activation_id,
            'install_id' => $this->install_id, // For conversion tracking
            'is_free' => false, // Explicit pro flag
            'event_type' => 'weekly_ping',
            'plugin_version' => defined('SWITCHBOARD_VERSION') ? SWITCHBOARD_VERSION : '0.0.0',
            'wp_version' => get_bloginfo('version'),
            'php_version' => PHP_VERSION,
            'site_url' => get_site_url(),
            'site_name' => get_bloginfo('name'),
            'is_localhost' => $this->is_localhost(),
            'is_multisite' => is_multisite(),
            'enabled_modules' => $enabled_modules,
            'timestamp' => time(), // Unix timestamp
        ];

        $this->send($data);
    }

    /**
     * Get all enabled modules with their names
     */
    private function get_enabled_modules() {
        $enabled = [];

        // Get active modules from WordPress option
        $active_modules = get_option('switchboard_active_modules', []);

        foreach ($active_modules as $module_slug) {
            $module_info = $this->get_module_info($module_slug);
            $enabled[] = [
                'slug' => $module_info['slug'],  // Full slug with category
                'name' => $module_info['name'],
            ];
        }

        return $enabled;
    }


    /**
     * Register settings
     */
    public function register_settings() {
        register_setting('wpsb_telemetry', 'switchboard_opt_out_telemetry');

        add_settings_section(
            'wpsb_telemetry_section',
            __('Usage Data Sharing', 'wpswitchboard'),
            [$this, 'render_settings_section'],
            'wpsb_settings'
        );

        add_settings_field(
            'switchboard_opt_out_telemetry',
            __('Share Usage Data', 'wpswitchboard'),
            [$this, 'render_opt_out_field'],
            'wpsb_settings',
            'wpsb_telemetry_section'
        );
    }

    /**
     * Render settings section description
     */
    public function render_settings_section() {
        echo '<p>' . __('Help us improve WP Switchboard by sharing anonymous usage data.', 'wpswitchboard') . '</p>';
    }

    /**
     * Render opt-out field
     */
    public function render_opt_out_field() {
        $opted_out = get_option('switchboard_opt_out_telemetry', false);
        ?>
        <label>
            <input type="checkbox" name="switchboard_opt_out_telemetry" value="1" <?php checked($opted_out, true); ?>>
            <?php _e('Disable usage data sharing', 'wpswitchboard'); ?>
        </label>
        <p class="description">
            <?php _e('We collect anonymous data about which modules are used to help prioritize development. No personal information or site content is collected.', 'wpswitchboard'); ?>
            <a href="#" target="_blank"><?php _e('Learn more about what we collect', 'wpswitchboard'); ?></a>
        </p>
        <?php
    }

    /**
     * Enqueue assets
     */
    public function enqueue_assets($hook) {
        // Only load on module management pages (WP Switchboard and Telemetry pages)
        // Check for: toplevel_page_wpswitchboard, settings_page_wpswitchboard, wpsb-telemetry, etc.
        if (strpos($hook, 'switchboard') === false && strpos($hook, 'wpsb') === false) {
            return;
        }

        // Check if feedback is disabled
        $disable_feedback = filter_var(get_option('switchboard_disable_feedback', true), FILTER_VALIDATE_BOOLEAN);

        // Only load feedback modal assets if feedback is NOT disabled
        if ($disable_feedback) {
            return;
        }

        wp_enqueue_style(
            'wpsb-telemetry-disable-reason',
            plugin_dir_url(__FILE__) . 'assets/disable-reason.css',
            [],
            defined('SWITCHBOARD_VERSION') ? SWITCHBOARD_VERSION : '1.0.0'
        );

        wp_enqueue_script(
            'wpsb-telemetry-disable-reason',
            plugin_dir_url(__FILE__) . 'assets/disable-reason.js',
            ['jquery'],
            defined('SWITCHBOARD_VERSION') ? SWITCHBOARD_VERSION : '1.0.0',
            true
        );

        wp_localize_script('wpsb-telemetry-disable-reason', 'wpsbTelemetry', [
            'ajaxUrl' => admin_url('admin-ajax.php'),
            'nonce' => wp_create_nonce('wpsb_disable_module'),
            'i18n' => [
                'title' => __('Why are you disabling this module?', 'wpswitchboard'),
                'not_needed' => __('Not needed for my site', 'wpswitchboard'),
                'has_issues' => __('Causing issues/conflicts', 'wpswitchboard'),
                'performance' => __('Performance concerns', 'wpswitchboard'),
                'missing_features' => __('Missing features I need', 'wpswitchboard'),
                'just_testing' => __('Just testing', 'wpswitchboard'),
                'skip' => __('Skip', 'wpswitchboard'),
            ],
        ]);
    }

    /**
     * AJAX handler for module disable
     */
    public function ajax_disable_module() {
        check_ajax_referer('wpsb_disable_module', 'nonce');

        if (!current_user_can('manage_options')) {
            wp_send_json_error('Insufficient permissions');
        }

        $module = isset($_POST['module']) ? sanitize_text_field($_POST['module']) : '';
        $reason = isset($_POST['reason']) ? sanitize_text_field($_POST['reason']) : null;

        if (empty($module)) {
            wp_send_json_error('Module not specified');
        }

        // Actually disable the module by removing it from active modules
        $active_modules = get_option('switchboard_active_modules', []);

        // Remove this module from active modules array
        $active_modules = array_diff($active_modules, [$module]);

        // Update option
        update_option('switchboard_active_modules', $active_modules);

        // Trigger telemetry event with reason
        do_action('switchboard_module_disabled', $module, $reason);

        wp_send_json_success([
            'message' => __('Module disabled successfully', 'wpswitchboard'),
            'module' => $module,
            'reason' => $reason,
        ]);
    }
}

// Initialize telemetry
WPSB_Telemetry_Module::instance();
