<?php
if ( ! defined( 'ABSPATH' ) ) { exit; }

class Vulnity_Inventory_Sync {
    const DEFERRED_SYNC_HOOK = 'vulnity_sync_inventory_deferred';
    
    private static $instance = null;
    private $sync_interval = 86400;
    private $previous_state_option = 'vulnity_previous_state';
    
    public static function get_instance() {
        if (self::$instance === null) {
            self::$instance = new self();
        }
        return self::$instance;
    }
    
    private function __construct() {
        add_action('vulnity_sync_inventory', array($this, 'perform_sync'));
        add_action(self::DEFERRED_SYNC_HOOK, array($this, 'perform_deferred_update_sync'));
        
        if (!wp_next_scheduled('vulnity_sync_inventory')) {
            wp_schedule_event(time(), 'daily', 'vulnity_sync_inventory');
        }
        
        add_action('activated_plugin', array($this, 'handle_plugin_change'), 10);
        add_action('deactivated_plugin', array($this, 'handle_plugin_change'), 10);
        add_action('upgrader_process_complete', array($this, 'handle_updates'), 10, 2);
        add_action('switch_theme', array($this, 'handle_theme_change'), 10);
        add_action('deleted_plugin', array($this, 'handle_plugin_change'), 10);
        add_action('_core_updated_successfully', array($this, 'handle_core_update'), 10);
    }
    
    public function get_inventory_data($scan_type = 'auto_sync') {
        $previous_state = get_option($this->previous_state_option, array());
        
        $wordpress_core = $this->get_wordpress_core_data($previous_state);
        $plugins = $this->get_plugins_data($previous_state);
        $themes = $this->get_themes_data($previous_state);
        $server_info = $this->get_server_data();
        
        $inventory = array(
            'site_id' => $this->get_site_id(),
            'wordpress_core' => $wordpress_core,
            'plugins' => $plugins,
            'themes' => $themes,
            'server_info' => $server_info,
            'scan_type' => $scan_type
        );
        
        $this->save_current_state($wordpress_core, $plugins, $themes);
        
        return $inventory;
    }
    
    private function get_site_id() {
        $config = get_option('vulnity_config');
        return isset($config['site_id']) ? $config['site_id'] : '';
    }
    
    private function get_wordpress_core_data($previous_state) {
        global $wp_version;
        
        $previous_version = isset($previous_state['wordpress_version']) ? $previous_state['wordpress_version'] : null;
        
        $data = array(
            'version' => $wp_version
        );
        
        if ($previous_version && $previous_version !== $wp_version) {
            $data['previous_version'] = $previous_version;
        }
        
        return $data;
    }
    
    private function get_plugins_data($previous_state) {
        if (!function_exists('get_plugins')) {
            $plugin_include = path_join(ABSPATH, 'wp-admin/includes/plugin.php');

            if (file_exists($plugin_include)) {
                require_once $plugin_include;
            }
        }
        
        $all_plugins = get_plugins();
        $active_plugins = get_option('active_plugins', array());
        $previous_plugins = isset($previous_state['plugins']) ? $previous_state['plugins'] : array();
        
        $plugins_data = array();
        
        foreach ($all_plugins as $plugin_file => $plugin_data) {
            $slug = dirname($plugin_file) !== '.' ? dirname($plugin_file) : basename($plugin_file, '.php');
            $is_active = in_array($plugin_file, $active_plugins);
            
            $plugin_info = array(
                'slug' => $slug,
                'name' => $plugin_data['Name'],
                'version' => $plugin_data['Version'],
                'status' => $is_active ? 'active' : 'inactive',
                'action' => 'inventory',
                'plugin_file' => $plugin_file,
                'author' => $plugin_data['Author'],
                'description' => substr($plugin_data['Description'], 0, 500),
                'plugin_uri' => $plugin_data['PluginURI'],
                'network' => is_multisite() && is_plugin_active_for_network($plugin_file)
            );
            
            if (isset($previous_plugins[$plugin_file])) {
                if ($previous_plugins[$plugin_file]['version'] !== $plugin_data['Version']) {
                    $plugin_info['previous_version'] = $previous_plugins[$plugin_file]['version'];
                    $plugin_info['action'] = 'updated';
                }
            } else {
                $plugin_info['action'] = 'installed';
            }
            
            $plugins_data[] = $plugin_info;
        }
        
        foreach ($previous_plugins as $plugin_file => $prev_plugin) {
            if (!isset($all_plugins[$plugin_file])) {
                $plugins_data[] = array(
                    'slug' => $prev_plugin['slug'],
                    'name' => $prev_plugin['name'],
                    'version' => $prev_plugin['version'],
                    'status' => 'deleted',
                    'action' => 'deleted',
                    'plugin_file' => $plugin_file,
                    'author' => $prev_plugin['author'],
                    'description' => '',
                    'plugin_uri' => '',
                    'network' => false
                );
            }
        }
        
        return $plugins_data;
    }
    
    private function get_themes_data($previous_state) {
        $all_themes = wp_get_themes();
        $current_theme = wp_get_theme();
        $previous_themes = isset($previous_state['themes']) ? $previous_state['themes'] : array();
        
        $themes_data = array();
        
        foreach ($all_themes as $theme_slug => $theme) {
            $is_active = ($theme->get_stylesheet() === $current_theme->get_stylesheet());
            
            $theme_info = array(
                'slug' => $theme->get_stylesheet(),
                'name' => $theme->get('Name'),
                'version' => $theme->get('Version'),
                'status' => $is_active ? 'active' : 'inactive',
                'action' => 'inventory',
                'author' => $theme->get('Author'),
                'description' => substr($theme->get('Description'), 0, 500),
                'template' => $theme->get_template(),
                'parent_theme' => $theme->parent() ? $theme->parent()->get('Name') : null
            );
            
            if (isset($previous_themes[$theme_slug])) {
                if ($previous_themes[$theme_slug]['version'] !== $theme->get('Version')) {
                    $theme_info['previous_version'] = $previous_themes[$theme_slug]['version'];
                    $theme_info['action'] = 'updated';
                }
                if ($is_active && !$previous_themes[$theme_slug]['active']) {
                    $theme_info['action'] = 'activated';
                }
            } else {
                $theme_info['action'] = 'installed';
            }
            
            $themes_data[] = $theme_info;
        }
        
        foreach ($previous_themes as $theme_slug => $prev_theme) {
            if (!isset($all_themes[$theme_slug])) {
                $themes_data[] = array(
                    'slug' => $theme_slug,
                    'name' => $prev_theme['name'],
                    'version' => $prev_theme['version'],
                    'status' => 'deleted',
                    'action' => 'deleted',
                    'author' => $prev_theme['author'],
                    'description' => '',
                    'template' => $theme_slug,
                    'parent_theme' => null
                );
            }
        }
        
        return $themes_data;
    }
    
    private function get_server_data() {
        global $wpdb;

        $server_software = 'Unknown';
        if (isset($_SERVER['SERVER_SOFTWARE'])) {
            $server_software = sanitize_text_field(wp_unslash((string) $_SERVER['SERVER_SOFTWARE']));
        }

        return array(
            'php_version' => PHP_VERSION,
            'mysql_version' => $wpdb->db_version(),
            'server_software' => $server_software,
            'php_sapi' => php_sapi_name(),
            'memory_limit' => ini_get('memory_limit'),
            'max_execution_time' => ini_get('max_execution_time'),
            'upload_max_filesize' => ini_get('upload_max_filesize'),
            'post_max_size' => ini_get('post_max_size'),
            'wordpress_memory_limit' => defined('WP_MEMORY_LIMIT') ? WP_MEMORY_LIMIT : '40M',
            'multisite' => is_multisite(),
            'wp_debug' => defined('WP_DEBUG') && WP_DEBUG,
            'wp_debug_log' => defined('WP_DEBUG_LOG') && WP_DEBUG_LOG
        );
    }
    
    private function save_current_state($wordpress_core, $plugins, $themes) {
        $state = array(
            'wordpress_version' => $wordpress_core['version'],
            'plugins' => array(),
            'themes' => array()
        );
        
        foreach ($plugins as $plugin) {
            if ($plugin['status'] !== 'deleted') {
                $state['plugins'][$plugin['plugin_file']] = array(
                    'slug' => $plugin['slug'],
                    'name' => $plugin['name'],
                    'version' => $plugin['version'],
                    'author' => $plugin['author']
                );
            }
        }
        
        foreach ($themes as $theme) {
            if ($theme['status'] !== 'deleted') {
                $state['themes'][$theme['slug']] = array(
                    'name' => $theme['name'],
                    'version' => $theme['version'],
                    'author' => $theme['author'],
                    'active' => $theme['status'] === 'active'
                );
            }
        }
        
        update_option($this->previous_state_option, $state);
    }
    
    public function perform_sync($scan_type = 'auto_sync') {
        $inventory = $this->get_inventory_data($scan_type);
        
        update_option('vulnity_last_sync', array(
            'timestamp' => current_time('mysql'),
            'status' => 'pending'
        ));
        
        $siem = Vulnity_SIEM_Connector::get_instance();
        $result = $siem->send_inventory($inventory);
        
        $sync_status = array(
            'timestamp' => current_time('mysql'),
            'status' => $result['success'] ? 'success' : 'failed',
            'message' => $result['success'] ? 'Inventory synchronized successfully' : $result['error']
        );
        
        update_option('vulnity_last_sync', $sync_status);
        
        if ($result['success']) {
            $this->update_summary($inventory);
        }
        
        vulnity_log('[Vulnity] Inventory sync completed: ' . $sync_status['status']); 
        
        return $result;
    }
    
    private function update_summary($inventory) {
        $active_plugins = 0;
        $plugin_updates = 0;
        $theme_updates = 0;
        
        foreach ($inventory['plugins'] as $plugin) {
            if ($plugin['status'] === 'active') {
                $active_plugins++;
            }
            if (isset($plugin['previous_version'])) {
                $plugin_updates++;
            }
        }
        
        foreach ($inventory['themes'] as $theme) {
            if (isset($theme['previous_version'])) {
                $theme_updates++;
            }
        }
        
        $summary = array(
            'plugins_total' => count($inventory['plugins']),
            'plugins_active' => $active_plugins,
            'plugins_updates' => $plugin_updates,
            'themes_total' => count($inventory['themes']),
            'themes_updates' => $theme_updates,
            'wordpress_version' => $inventory['wordpress_core']['version'],
            'wordpress_update' => isset($inventory['wordpress_core']['previous_version']),
            'php_version' => $inventory['server_info']['php_version'],
            'users_total' => count_users()['total_users'],
            'administrators' => count(get_users(array('role' => 'administrator')))
        );
        
        update_option('vulnity_inventory_summary', $summary);
    }
    
    public function handle_plugin_change() {
        $this->queue_update_sync();
    }
    
    public function handle_theme_change() {
        $this->queue_update_sync();
    }
    
    public function handle_core_update() {
        $this->queue_update_sync();
    }
    
    public function handle_updates($upgrader, $hook_extra) {
        if (isset($hook_extra['type']) && in_array($hook_extra['type'], array('plugin', 'theme'))) {
            $this->queue_update_sync();
        }
    }

    public function perform_deferred_update_sync() {
        $this->perform_sync('update');
    }

    private function queue_update_sync() {
        if (wp_next_scheduled(self::DEFERRED_SYNC_HOOK)) {
            return;
        }

        // Debounce update-triggered syncs to avoid expensive immediate remote calls.
        wp_schedule_single_event(time() + 60, self::DEFERRED_SYNC_HOOK);
    }
    
    public function get_last_sync_info() {
        $last_sync = get_option('vulnity_last_sync', false);
        
        if (!$last_sync) {
            return array(
                'status' => 'never',
                'message' => 'Never synchronized',
                'timestamp' => null
            );
        }
        
        return $last_sync;
    }
    
    public function get_inventory_summary() {
        return get_option('vulnity_inventory_summary', array());
    }
    
    public function cleanup() {
        wp_clear_scheduled_hook('vulnity_sync_inventory');
        wp_clear_scheduled_hook(self::DEFERRED_SYNC_HOOK);
        delete_option('vulnity_last_sync');
        delete_option('vulnity_inventory_summary');
        delete_option($this->previous_state_option);
    }
}
