<?php
/**
 * AuctionForge Auto Updater Class
 * Handles automatic updates from WP Plugin Deployer server
 */

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

class AuctionForge_Auto_Updater {
    
    private $plugin_slug;
    private $plugin_file;
    private $server_url;
    private $api_key;
    private $current_version;
    
    public function __construct($plugin_file, $current_version) {
        $this->plugin_file = $plugin_file;
        $this->current_version = $current_version;
        $this->plugin_slug = defined('AUCTIONFORGE_PLUGIN_SLUG') ? AUCTIONFORGE_PLUGIN_SLUG : basename(dirname(dirname(__FILE__)));
        
        // Get settings from options
        $this->server_url = get_option('auctionforge_update_server_url', 'https://wpdeploy.smoothbyteit.dev');
        $this->api_key = get_option('auctionforge_update_api_key', '');
        
        // Only register hooks if configured
        if ($this->is_configured()) {
            $this->init_hooks();
        }
        
        // Always add settings hooks for admin
        if (is_admin()) {
            add_action('admin_init', array($this, 'register_settings'));
            add_action('admin_notices', array($this, 'admin_notices'));
        }
    }
    
    /**
     * Check if updater is configured
     */
    private function is_configured() {
        return !empty($this->server_url) && !empty($this->api_key);
    }
    
    /**
     * Initialize hooks
     */
    private function init_hooks() {
        // Hook into WordPress update checks
        add_filter('pre_set_site_transient_update_plugins', array($this, 'check_for_updates'));
        add_filter('plugins_api', array($this, 'plugin_info'), 10, 3);
        
        // Add authorization header for downloads
        add_filter('http_request_args', array($this, 'add_download_auth'), 10, 2);
        
        // Check for pending updates hourly
        add_action('auctionforge_check_updates', array($this, 'check_pending_updates'));
        if (!wp_next_scheduled('auctionforge_check_updates')) {
            wp_schedule_event(time(), 'hourly', 'auctionforge_check_updates');
        }
        
        // Register REST API endpoint for remote trigger
        add_action('rest_api_init', array($this, 'register_rest_routes'));
        
        // Report health status
        add_action('auctionforge_report_health', array($this, 'report_health'));
        if (!wp_next_scheduled('auctionforge_report_health')) {
            wp_schedule_event(time(), 'twicedaily', 'auctionforge_report_health');
        }
        
        // Sync WP Defender vulnerabilities
        add_action('auctionforge_sync_vulnerabilities', array($this, 'sync_vulnerabilities'));
        if (!wp_next_scheduled('auctionforge_sync_vulnerabilities')) {
            wp_schedule_event(time(), 'twicedaily', 'auctionforge_sync_vulnerabilities');
        }
        
        // Sync user tracking data to central server
        add_action('auctionforge_sync_user_tracking', array($this, 'sync_user_tracking'));
        if (!wp_next_scheduled('auctionforge_sync_user_tracking')) {
            wp_schedule_event(time(), 'hourly', 'auctionforge_sync_user_tracking');
        }
        
        // Poll fraud enforcement setting from central server
        add_action('auctionforge_sync_fraud_enforcement', array($this, 'sync_fraud_enforcement'));
        if (!wp_next_scheduled('auctionforge_sync_fraud_enforcement')) {
            wp_schedule_event(time(), 'bp_ten_minutely', 'auctionforge_sync_fraud_enforcement');
        }
    }
    
    /**
     * Register settings
     */
    public function register_settings() {
        register_setting('auctionforge_updater', 'auctionforge_update_server_url');
        register_setting('auctionforge_updater', 'auctionforge_update_api_key');
        register_setting('auctionforge_updater', 'auctionforge_auto_update', array('default' => true));
        register_setting('auctionforge_updater', 'auctionforge_fraud_enforcement', array('default' => false));
    }
    
    /**
     * Admin notices
     */
    public function admin_notices() {
        if (!$this->is_configured()) {
            $settings_url = admin_url('edit.php?post_type=lot&page=auctionforge-updates');
            echo '<div class="notice notice-warning is-dismissible">';
            echo '<p><strong>AuctionForge:</strong> Configure the update server to receive automatic updates. ';
            echo '<a href="' . esc_url($settings_url) . '">Configure Now</a></p>';
            echo '</div>';
        }
    }
    
    /**
     * Make API request to deployment server
     */
    private function api_request($endpoint, $data = array(), $method = 'POST') {
        $url = rtrim($this->server_url, '/') . '/api.php/' . ltrim($endpoint, '/');
        
        $args = array(
            'method' => $method,
            'timeout' => 30,
            'headers' => array(
                'X-API-Key' => $this->api_key,
                'Content-Type' => 'application/json',
            ),
        );
        
        if ($method === 'POST' && !empty($data)) {
            $args['body'] = json_encode($data);
        }
        
        $response = wp_remote_request($url, $args);
        
        if (is_wp_error($response)) {
            return array('error' => $response->get_error_message());
        }
        
        $body = wp_remote_retrieve_body($response);
        return json_decode($body, true);
    }
    
    /**
     * Check for updates
     */
    public function check_for_updates($transient) {
        if (empty($transient->checked) || !$this->is_configured()) {
            return $transient;
        }
        
        // Prepare plugin data
        $plugins = array(
            $this->plugin_slug => array(
                'version' => $this->current_version
            )
        );
        
        $result = $this->api_request('check-updates', array('plugins' => $plugins));
        
        if (!empty($result['updates'][$this->plugin_slug])) {
            $update = $result['updates'][$this->plugin_slug];
            
            $transient->response[$this->plugin_file] = (object) array(
                'slug' => $this->plugin_slug,
                'plugin' => $this->plugin_file,
                'new_version' => $update['version'],
                'url' => !empty($update['homepage']) ? $update['homepage'] : '',
                'package' => $update['download_url'],
                'tested' => $update['tested_up_to'],
                'requires_php' => $update['requires_php'],
            );
        }
        
        return $transient;
    }
    
    /**
     * Check for pending updates from deployment server
     */
    public function check_pending_updates() {
        if (!$this->is_configured()) {
            return;
        }
        
        $result = $this->api_request('pending-updates', array(), 'GET');
        
        if (!empty($result['updates'])) {
            $auto_update = get_option('auctionforge_auto_update', true);
            
            foreach ($result['updates'] as $update) {
                if ($update['plugin_slug'] === $this->plugin_slug) {
                    if ($auto_update) {
                        $this->install_update($update);
                    } else {
                        // Trigger WordPress to show update notification
                        delete_site_transient('update_plugins');
                    }
                }
            }
        }
    }
    
    /**
     * Install update
     */
    private function install_update($update) {
        require_once ABSPATH . 'wp-admin/includes/class-wp-upgrader.php';
        
        $skin = new Automatic_Upgrader_Skin();
        $upgrader = new Plugin_Upgrader($skin);
        
        $result = $upgrader->upgrade($this->plugin_file);
        
        $status = $result ? 'completed' : 'failed';
        $error = $result ? '' : 'Installation failed';
        
        // Report back to server
        $this->api_request('update-deployed/' . $update['queue_id'], array(
            'status' => $status,
            'error_message' => $error,
        ));
    }
    
    /**
     * Plugin info for update screen
     */
    public function plugin_info($false, $action, $args) {
        if ($action !== 'plugin_information') {
            return $false;
        }
        
        if (!isset($args->slug) || $args->slug !== $this->plugin_slug) {
            return $false;
        }
        
        if (!$this->is_configured()) {
            return $false;
        }
        
        // Get plugin info from server
        $plugins = array($this->plugin_slug => array('version' => $this->current_version));
        $result = $this->api_request('check-updates', array('plugins' => $plugins));
        
        if (!empty($result['updates'][$this->plugin_slug])) {
            $update = $result['updates'][$this->plugin_slug];
            
            return (object) array(
                'name' => $update['name'],
                'slug' => $this->plugin_slug,
                'version' => $update['version'],
                'author' => '<a href="https://smoothbyteit.dev">SmoothByte IT</a>',
                'homepage' => 'https://smoothbyteit.dev',
                'requires' => $update['requires_wp'],
                'tested' => $update['tested_up_to'],
                'requires_php' => $update['requires_php'],
                'download_link' => $update['download_url'],
                'sections' => array(
                    'description' => 'AuctionForge - BidSpirit Auction Integration for WordPress.',
                ),
            );
        }
        
        return $false;
    }
    
    /**
     * Register REST API routes
     */
    public function register_rest_routes() {
        register_rest_route('auctionforge/v1', '/trigger-install', array(
            'methods' => 'POST',
            'callback' => array($this, 'rest_trigger_install'),
            'permission_callback' => array($this, 'verify_api_key'),
        ));
        
        register_rest_route('auctionforge/v1', '/defender-vulnerabilities', array(
            'methods' => 'GET',
            'callback' => array($this, 'rest_get_defender_vulnerabilities'),
            'permission_callback' => array($this, 'verify_api_key'),
        ));
    }
    
    /**
     * Verify API key for REST requests
     */
    public function verify_api_key($request) {
        $apiKey = $request->get_header('X-API-Key');
        return $apiKey === $this->api_key;
    }
    
    /**
     * REST API callback to trigger immediate installation
     */
    public function rest_trigger_install($request) {
        $params = $request->get_json_params();
        $pluginSlug = $params['plugin_slug'] ?? '';
        $version = $params['version'] ?? '';
        
        if (!$this->is_configured()) {
            return new WP_Error('not_configured', 'Update server not configured', array('status' => 400));
        }
        
        // Force check for updates
        delete_site_transient('update_plugins');
        $this->check_pending_updates();
        
        // Get the update info
        $updates = get_site_transient('update_plugins');
        
        if (!isset($updates->response[$this->plugin_file])) {
            return new WP_Error('no_update', 'No update available for this plugin', array('status' => 404));
        }
        
        // Trigger the installation
        require_once ABSPATH . 'wp-admin/includes/class-wp-upgrader.php';
        $skin = new Automatic_Upgrader_Skin();
        $upgrader = new Plugin_Upgrader($skin);
        
        $result = $upgrader->upgrade($this->plugin_file);
        
        if (is_wp_error($result)) {
            return new WP_Error('install_failed', $result->get_error_message(), array('status' => 500));
        }
        
        if ($result === false) {
            return new WP_Error('install_failed', 'Installation failed', array('status' => 500));
        }
        
        return rest_ensure_response(array(
            'success' => true,
            'message' => "Plugin updated to version $version",
            'plugin' => $pluginSlug,
            'version' => $version
        ));
    }
    
    /**
     * REST API callback to get WP Defender vulnerabilities
     */
    public function rest_get_defender_vulnerabilities($request) {
        global $wpdb;
        
        // Check if WP Defender is installed
        $table_name = $wpdb->prefix . 'defender_scan_item';
        
        if ($wpdb->get_var("SHOW TABLES LIKE '{$table_name}'") != $table_name) {
            return new WP_Error('no_defender', 'WP Defender is not installed', array('status' => 404));
        }
        
        // Get vulnerability records
        $vulnerabilities = $wpdb->get_results(
            $wpdb->prepare(
                "SELECT * FROM {$table_name} WHERE type = %s AND status = %s ORDER BY id DESC LIMIT 100",
                'vulnerability',
                'active'
            ),
            ARRAY_A
        );
        
        $results = array();
        
        foreach ($vulnerabilities as $vuln) {
            $raw_data = maybe_unserialize($vuln['raw_data']);
            
            if (!is_array($raw_data) || empty($raw_data['slug'])) {
                continue;
            }
            
            $results[] = array(
                'id' => $vuln['id'],
                'slug' => $raw_data['slug'] ?? '',
                'base_slug' => $raw_data['base_slug'] ?? '',
                'name' => $raw_data['name'] ?? '',
                'version' => $raw_data['version'] ?? '',
                'type' => $raw_data['type'] ?? 'plugin',
                'bugs' => $raw_data['bugs'] ?? array(),
                'scan_date' => current_time('mysql')
            );
        }
        
        return rest_ensure_response(array(
            'success' => true,
            'count' => count($results),
            'site_url' => home_url(),
            'site_name' => get_bloginfo('name'),
            'vulnerabilities' => $results,
            'defender_installed' => true,
            'wp_version' => get_bloginfo('version'),
            'php_version' => PHP_VERSION
        ));
    }
    
    /**
     * Report site health status to deployment server
     */
    public function report_health() {
        if (!$this->is_configured()) {
            return;
        }

        $health_data = array(
            'wp_version' => get_bloginfo('version'),
            'php_version' => PHP_VERSION,
            'plugin_slug' => $this->plugin_slug,
            'plugin_version' => $this->current_version,
            'plugin_file' => $this->plugin_file,
            'health_status' => 'healthy',
            'plugins' => array(),
            'errors' => array()
        );

        // Get all active plugins
        $active_plugins = get_option('active_plugins', array());
        foreach ($active_plugins as $plugin) {
            $plugin_data = get_plugin_data(WP_PLUGIN_DIR . '/' . $plugin);
            $health_data['plugins'][] = array(
                'slug' => dirname($plugin),
                'name' => $plugin_data['Name'],
                'version' => $plugin_data['Version'],
                'active' => true
            );
        }

        // Detect errors
        $errors = array();
        if (defined('WP_DEBUG_LOG') && WP_DEBUG_LOG) {
            $log_file = WP_CONTENT_DIR . '/debug.log';
            if (file_exists($log_file) && filesize($log_file) > 0) {
                $errors[] = array(
                    'message' => 'Debug log has entries',
                    'plugin' => $this->plugin_slug,
                );
            }
        }

        $health_data['health_status'] = count($errors) > 0 ? 'warning' : 'healthy';
        $health_data['errors'] = $errors;

        // Report to server
        $this->api_request('report-health', $health_data);
    }
    
    /**
     * Sync WP Defender vulnerabilities to deployment server
     */
    public function sync_vulnerabilities() {
        if (!$this->is_configured()) {
            return false;
        }
        
        global $wpdb;
        
        $table_name = $wpdb->prefix . 'defender_scan_item';
        
        if ($wpdb->get_var("SHOW TABLES LIKE '{$table_name}'") != $table_name) {
            update_option('auctionforge_last_vuln_sync_status', 'defender_not_installed');
            return false;
        }
        
        $vulnerabilities = $wpdb->get_results(
            $wpdb->prepare(
                "SELECT * FROM {$table_name} WHERE type = %s AND status = %s ORDER BY id DESC LIMIT 100",
                'vulnerability',
                'active'
            ),
            ARRAY_A
        );
        
        if (empty($vulnerabilities)) {
            update_option('auctionforge_last_vuln_sync_status', 'no_vulnerabilities_found');
            update_option('auctionforge_last_vuln_sync', current_time('mysql'));
            return false;
        }
        
        $results = array();
        
        foreach ($vulnerabilities as $vuln) {
            $raw_data = maybe_unserialize($vuln['raw_data']);
            
            if (!is_array($raw_data) || empty($raw_data['slug'])) {
                continue;
            }
            
            $bugs = $raw_data['bugs'] ?? array();
            if (empty($bugs)) {
                continue;
            }
            
            $results[] = array(
                'slug' => $raw_data['base_slug'] ?? dirname($raw_data['slug']),
                'version' => $raw_data['version'] ?? '',
                'name' => $raw_data['name'] ?? '',
                'type' => $raw_data['type'] ?? 'plugin',
                'bugs' => $bugs
            );
        }
        
        if (empty($results)) {
            update_option('auctionforge_last_vuln_sync_status', 'no_valid_vulnerabilities');
            update_option('auctionforge_last_vuln_sync', current_time('mysql'));
            return false;
        }
        
        $response = $this->api_request('sync-defender-vulnerabilities', array(
            'vulnerabilities' => $results,
            'site_url' => home_url(),
            'site_name' => get_bloginfo('name'),
            'scan_time' => current_time('mysql'),
            'defender_installed' => true
        ));
        
        if ($response && !is_wp_error($response)) {
            update_option('auctionforge_last_vuln_sync', current_time('mysql'));
            update_option('auctionforge_last_vuln_sync_status', 'success');
            update_option('auctionforge_last_vuln_count', count($results));
            
            if (isset($response['synced'])) {
                update_option('auctionforge_last_vuln_synced', $response['synced']);
                update_option('auctionforge_last_vuln_updated', $response['updated'] ?? 0);
                update_option('auctionforge_last_vuln_skipped', $response['skipped'] ?? 0);
            }
            
            return true;
        }
        
        update_option('auctionforge_last_vuln_sync_status', 'api_error');
        return false;
    }
    
    /**
     * Poll fraud enforcement setting from central server and update local option
     * This is the single source of truth — the wpdeploy server controls enforcement.
     */
    public function sync_fraud_enforcement() {
        if (!$this->is_configured()) {
            return;
        }
        
        $result = $this->api_request('fraud-enforcement-status', array(), 'GET');
        
        if ($result && isset($result['fraud_enforcement'])) {
            $enforcement = (bool) $result['fraud_enforcement'];
            update_option('auctionforge_fraud_enforcement', $enforcement);
            update_option('auctionforge_fraud_enforcement_synced_at', current_time('mysql'));
            
            // Report back to confirm
            $this->api_request('report-enforcement-status', array(
                'enforcement_enabled' => $enforcement,
                'site_url' => home_url(),
            ));
        }
    }
    
    /**
     * Sync user tracking data to central deployment server
     * Pushes all records modified since last sync
     */
    public function sync_user_tracking() {
        if (!$this->is_configured()) {
            return false;
        }
        
        global $wpdb;
        $table_name = $wpdb->prefix . 'auctionforge_user_tracking';
        
        // Check if table exists
        if ($wpdb->get_var("SHOW TABLES LIKE '$table_name'") != $table_name) {
            update_option('auctionforge_last_tracking_sync_status', 'table_not_found');
            return false;
        }
        
        // Get last sync time
        $lastSync = get_option('auctionforge_last_tracking_sync', '2000-01-01 00:00:00');
        
        // Get records modified since last sync (batch of 200)
        $records = $wpdb->get_results($wpdb->prepare(
            "SELECT * FROM $table_name WHERE last_seen >= %s ORDER BY last_seen ASC LIMIT 200",
            $lastSync
        ), ARRAY_A);
        
        if (empty($records)) {
            update_option('auctionforge_last_tracking_sync_status', 'no_new_records');
            update_option('auctionforge_last_tracking_sync', current_time('mysql'));
            return true;
        }
        
        // Push to central server
        $response = $this->api_request('sync-user-tracking', array(
            'records' => $records,
            'site_url' => home_url(),
            'site_name' => get_bloginfo('name'),
            'sync_time' => current_time('mysql'),
        ));
        
        if ($response && !isset($response['error'])) {
            // Update last sync time to the latest record's last_seen
            $latestRecord = end($records);
            update_option('auctionforge_last_tracking_sync', $latestRecord['last_seen']);
            update_option('auctionforge_last_tracking_sync_status', 'success');
            update_option('auctionforge_last_tracking_sync_count', $response['synced'] ?? count($records));
            update_option('auctionforge_last_tracking_sync_alerts', $response['alerts_generated'] ?? 0);
            return true;
        }
        
        update_option('auctionforge_last_tracking_sync_status', 'api_error');
        return false;
    }
    
    /**
     * Manual update check (for admin use)
     */
    public function manual_check() {
        delete_site_transient('update_plugins');
        wp_update_plugins();
        
        $updates = get_site_transient('update_plugins');
        return isset($updates->response[$this->plugin_file]);
    }
    
    /**
     * Add authentication headers to download requests
     */
    public function add_download_auth($args, $url) {
        if (strpos($url, $this->server_url) !== false) {
            if (!isset($args['headers'])) {
                $args['headers'] = array();
            }
            $args['headers']['X-API-Key'] = $this->api_key;
        }
        return $args;
    }
    
    /**
     * Test connection to deployment server
     */
    public function test_connection() {
        if (!$this->is_configured()) {
            return array('success' => false, 'message' => 'Not configured');
        }
        
        $result = $this->api_request('info', array(), 'GET');
        
        if (isset($result['app_version'])) {
            return array('success' => true, 'version' => $result['app_version']);
        } else {
            return array('success' => false, 'message' => $result['error'] ?? 'Unknown error');
        }
    }
    
    /**
     * Request automatic access to deployment server (no master key needed)
     */
    public function request_access() {
        if (empty($this->server_url)) {
            return array('success' => false, 'message' => 'Server URL required');
        }
        
        $site_url = get_site_url();
        $site_name = get_bloginfo('name');
        
        $url = rtrim($this->server_url, '/') . '/api.php/request-access';
        
        $response = wp_remote_post($url, array(
            'timeout' => 30,
            'headers' => array(
                'Content-Type' => 'application/json',
            ),
            'body' => json_encode(array(
                'site_url' => $site_url,
                'site_name' => $site_name,
            )),
        ));
        
        if (is_wp_error($response)) {
            return array('success' => false, 'message' => $response->get_error_message());
        }
        
        $body = wp_remote_retrieve_body($response);
        $result = json_decode($body, true);
        
        if (!empty($result['success']) && !empty($result['api_key'])) {
            update_option('auctionforge_update_api_key', $result['api_key']);
            $this->api_key = $result['api_key'];
            
            if ($this->is_configured()) {
                $this->init_hooks();
            }
            
            return array(
                'success' => true,
                'message' => 'Access granted! Your site is now registered with the deployment server.',
                'api_key' => $result['api_key'],
            );
        } else {
            return array(
                'success' => false,
                'message' => $result['error'] ?? 'Access request failed',
            );
        }
    }
    
    /**
     * Register site with deployment server using master key (legacy method)
     */
    public function register_site($master_key) {
        if (empty($this->server_url) || empty($master_key)) {
            return array('success' => false, 'message' => 'Server URL and Master Key required');
        }
        
        $site_url = get_site_url();
        $site_name = get_bloginfo('name');
        
        $url = rtrim($this->server_url, '/') . '/api.php/register-site';
        
        $response = wp_remote_post($url, array(
            'timeout' => 30,
            'headers' => array(
                'Content-Type' => 'application/json',
            ),
            'body' => json_encode(array(
                'site_url' => $site_url,
                'site_name' => $site_name,
                'master_key' => $master_key,
            )),
        ));
        
        if (is_wp_error($response)) {
            return array('success' => false, 'message' => $response->get_error_message());
        }
        
        $body = wp_remote_retrieve_body($response);
        $result = json_decode($body, true);
        
        if (!empty($result['success']) && !empty($result['api_key'])) {
            update_option('auctionforge_update_api_key', $result['api_key']);
            $this->api_key = $result['api_key'];
            
            if ($this->is_configured()) {
                $this->init_hooks();
            }
            
            return array(
                'success' => true,
                'message' => 'Site registered successfully!',
                'api_key' => $result['api_key'],
            );
        } else {
            return array(
                'success' => false,
                'message' => $result['error'] ?? 'Registration failed',
            );
        }
    }
}
