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

class Vulnity_Core_Update_Alert extends Vulnity_Alert_Base {

    private $request_initial_version = '';
    private $pending_auto_update = null;
    
    public function __construct() {
        $this->alert_type = 'core_updated';
        $this->request_initial_version = $this->normalize_version(get_bloginfo('version'));
        parent::__construct();
    }
    
    protected function register_hooks() {
        add_action('pre_auto_update', array($this, 'capture_auto_update_context'), 10, 3);
        add_action('_core_updated_successfully', array($this, 'on_core_updated'));
    }

    public function capture_auto_update_context($type, $item, $context) {
        if ($type !== 'core') {
            return;
        }

        $this->pending_auto_update = array(
            'new_version' => $this->extract_version_from_update_item($item),
            'context' => is_string($context) ? $context : ''
        );
    }
    
    public function on_core_updated($wp_version) {
        $new_version = $this->normalize_version($wp_version);
        $is_auto_update = is_array($this->pending_auto_update);

        $this->evaluate(array(
            'action' => $is_auto_update ? 'auto_update' : 'manual_update',
            'new_version' => $new_version !== '' ? $new_version : $this->extract_pending_auto_version(),
            'old_version' => $this->request_initial_version,
            'context' => $is_auto_update ? $this->pending_auto_update : array()
        ));

        $this->pending_auto_update = null;
    }
    
    /**
     * Compare version numbers to detect downgrades
     */
    private function is_downgrade($old_version, $new_version) {
        // Use WordPress version_compare function
        // Returns -1 if old < new (upgrade)
        // Returns 0 if old == new (same)
        // Returns 1 if old > new (downgrade)
        return version_compare($old_version, $new_version) > 0;
    }
    
    protected function evaluate($data) {
        $current_user_info = $this->get_current_user_info();
        $old_version = isset($data['old_version']) ? $this->normalize_version($data['old_version']) : '';
        $new_version = isset($data['new_version']) ? $this->normalize_version($data['new_version']) : '';

        if ($new_version === '') {
            $new_version = $this->normalize_version(get_bloginfo('version'));
        }

        if ($old_version !== '' && $new_version !== '' && version_compare($old_version, $new_version) === 0) {
            return;
        }

        if ($this->is_duplicate_update_event($old_version, $new_version)) {
            return;
        }
        
        // Default to info severity for normal updates
        $severity = 'info';
        $title = '';
        $message = '';
        
        // Check if this is a downgrade (HIGH severity)
        if ($old_version !== '' && $new_version !== '') {
            if ($this->is_downgrade($old_version, $new_version)) {
                $severity = 'high';
                $title = 'WordPress Core Downgraded';
                $message = sprintf(
                    'WordPress was downgraded from version %s to %s via %s update by user "%s" from IP %s',
                    $old_version,
                    $new_version,
                    $data['action'] === 'auto_update' ? 'automatic' : 'manual',
                    $current_user_info['user_login'],
                    $current_user_info['user_ip']
                );
            }
        }
        
        if ($severity === 'info') {
            if ($data['action'] === 'manual_update') {
                $title = 'WordPress Core Updated';
                $message = sprintf(
                    'WordPress was manually updated from version %s to %s by user "%s" from IP %s',
                    $old_version !== '' ? $old_version : 'unknown',
                    $new_version !== '' ? $new_version : 'unknown',
                    $current_user_info['user_login'],
                    $current_user_info['user_ip']
                );
            } elseif ($data['action'] === 'auto_update') {
                $title = 'WordPress Auto-Updated';
                $message = sprintf(
                    'WordPress was automatically updated from version %s to %s',
                    $old_version !== '' ? $old_version : 'unknown',
                    $new_version !== '' ? $new_version : 'unknown'
                );
            }
        }
        
        if (empty($title)) {
            return;
        }
        
        $details = array(
            'action' => $data['action'],
            'update_mode' => $data['action'] === 'auto_update' ? 'automatic' : 'manual',
            'old_version' => $old_version,
            'new_version' => $new_version,
            'update_context' => isset($data['context']) && is_array($data['context']) ? $data['context'] : array(),
            'wordpress_version' => get_bloginfo('version'),
            'php_version' => PHP_VERSION,
            'user_id' => $current_user_info['user_id'],
            'user_login' => $current_user_info['user_login'],
            'user_ip' => $current_user_info['user_ip'],
            'timestamp' => current_time('mysql')
        );
        
        if ($severity === 'high' && $old_version !== '' && $new_version !== '') {
            $details['is_downgrade'] = true;
            $details['version_change'] = sprintf('%s → %s', $old_version, $new_version);
            $details['risk_assessment'] = 'High risk - WordPress downgrades are unusual and potentially dangerous';
        }
        
        $this->create_alert(array(
            'severity' => $severity,
            'title' => $title,
            'message' => $message,
            'details' => $details
        ));
    }

    private function extract_pending_auto_version() {
        if (!is_array($this->pending_auto_update) || empty($this->pending_auto_update['new_version'])) {
            return '';
        }

        return $this->normalize_version($this->pending_auto_update['new_version']);
    }

    private function extract_version_from_update_item($item) {
        if (!is_object($item)) {
            return '';
        }

        if (isset($item->version) && is_scalar($item->version)) {
            return $this->normalize_version($item->version);
        }

        if (isset($item->current) && is_scalar($item->current)) {
            return $this->normalize_version($item->current);
        }

        return '';
    }

    private function normalize_version($version) {
        if (!is_scalar($version)) {
            return '';
        }

        return trim((string) $version);
    }

    private function is_duplicate_update_event($old_version, $new_version) {
        $fingerprint = md5($old_version . '|' . $new_version);
        $transient_key = 'vulnity_core_update_' . $fingerprint;

        if (get_transient($transient_key)) {
            return true;
        }

        set_transient($transient_key, true, 600);

        return false;
    }
}
