<?php
/**
 * Token Manager Class
 * Handles secure token storage with encryption
 */

// Prevent direct access
if (!defined('WPINC')) {
    die('Direct access not permitted.');
}

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

class MCB_Token_Manager {
    
    /**
     * Check if encryption is available
     */
    public static function encryption_available() {
        return function_exists('openssl_encrypt') && function_exists('openssl_decrypt');
    }
    
    /**
     * Encrypt token for secure storage
     */
    public static function encrypt_token($token) {
        if (empty($token)) {
            return '';
        }
        
        // Use WordPress salts for encryption
        if (self::encryption_available()) {
            $key = substr(hash('sha256', wp_salt('auth')), 0, 32);
            $iv = substr(hash('sha256', wp_salt('secure')), 0, 16);
            
            $encrypted = openssl_encrypt($token, 'AES-256-CBC', $key, 0, $iv);
            if ($encrypted !== false) {
                return base64_encode($encrypted);
            }
        }
        
        // Fallback to base64 if encryption not available
        return base64_encode($token);
    }
    
    /**
     * Decrypt token for use
     */
    public static function decrypt_token($encrypted_token) {
        if (empty($encrypted_token)) {
            return '';
        }
        
        // Use WordPress salts for decryption
        if (self::encryption_available()) {
            $key = substr(hash('sha256', wp_salt('auth')), 0, 32);
            $iv = substr(hash('sha256', wp_salt('secure')), 0, 16);
            
            $decoded = base64_decode($encrypted_token);
            if ($decoded !== false) {
                $decrypted = openssl_decrypt($decoded, 'AES-256-CBC', $key, 0, $iv);
                if ($decrypted !== false) {
                    return $decrypted;
                }
            }
        }
        
        // Fallback to base64 if encryption not available
        return base64_decode($encrypted_token);
    }
    
    /**
     * Store encrypted token
     */
    public static function store_token($platform, $token) {
        if (empty($token)) {
            delete_option('mcb_' . $platform . '_token_encrypted');
            return true;
        }
        
        $encrypted = self::encrypt_token($token);
        return update_option('mcb_' . $platform . '_token_encrypted', $encrypted);
    }
    
    /**
     * Retrieve and decrypt token
     */
    public static function get_token($platform) {
        $encrypted = get_option('mcb_' . $platform . '_token_encrypted', '');
        if (empty($encrypted)) {
            // Check for legacy unencrypted token
            $legacy = get_option('mcb_' . $platform . '_token', '');
            if (!empty($legacy)) {
                // Migrate to encrypted storage
                self::store_token($platform, $legacy);
                delete_option('mcb_' . $platform . '_token');
                return $legacy;
            }
            return '';
        }
        
        return self::decrypt_token($encrypted);
    }
    
    /**
     * Remove all tokens (for privacy/GDPR)
     */
    public static function remove_all_tokens() {
        $platforms = array('github', 'gitlab', 'bitbucket', 'codeberg');
        foreach ($platforms as $platform) {
            delete_option('mcb_' . $platform . '_token');
            delete_option('mcb_' . $platform . '_token_encrypted');
        }
    }
}

/**
 * Privacy Manager Class
 * Handles GDPR compliance and privacy features
 */
class MCB_Privacy_Manager {
    
    /**
     * Initialize privacy features
     */
    public static function init() {
        // WordPress privacy policy content
        add_action('admin_init', array(__CLASS__, 'privacy_policy_content'));
        
        // Data exporter for GDPR
        add_filter('wp_privacy_personal_data_exporters', array(__CLASS__, 'register_data_exporter'));
        
        // Data eraser for GDPR
        add_filter('wp_privacy_personal_data_erasers', array(__CLASS__, 'register_data_eraser'));
    }
    
    /**
     * Check if privacy mode is enabled
     */
    public static function is_privacy_mode() {
        return get_option('mcb_privacy_mode', false);
    }
    
    /**
     * Add suggested privacy policy content
     */
    public static function privacy_policy_content() {
        if (!function_exists('wp_add_privacy_policy_content')) {
            return;
        }
        
        $content = '
            <h3>Git Code Viewer Plugin</h3>
            <p>When you visit pages that display code repositories using the Git Code Viewer plugin:</p>
            <ul>
                <li>We temporarily store an anonymized version of your IP address (for 60 seconds) to prevent abuse through rate limiting.</li>
                <li>If security events occur, we may log your browser user agent (for 7 days) for security monitoring.</li>
                <li>We do not use cookies or tracking technologies.</li>
                <li>We only access publicly available repository data from GitHub, GitLab, Bitbucket, and Codeberg.</li>
                <li>No personal information is shared with third parties.</li>
                <li>All data is automatically deleted after the retention period.</li>
            </ul>
            <p>If Privacy Mode is enabled, no IP addresses or user agents are collected.</p>
        ';
        
        wp_add_privacy_policy_content(
            'Git Code Viewer',
            wp_kses_post($content)
        );
    }
    
    /**
     * Register data exporter for GDPR requests
     */
    public static function register_data_exporter($exporters) {
        $exporters['git-code-viewer'] = array(
            'exporter_friendly_name' => __('Git Code Viewer Plugin'),
            'callback' => array(__CLASS__, 'data_exporter')
        );
        return $exporters;
    }
    
    /**
     * Export user data for GDPR requests
     */
    public static function data_exporter($email_address, $page = 1) {
        $export_items = array();
        
        // Get security logs that might contain this user's data
        $logs = get_transient('mcb_security_logs');
        
        if (is_array($logs)) {
            $user_data = array();
            
            // Note: We don't store email addresses, so we can't directly match
            // This is actually good for privacy!
            $user_data[] = array(
                'name' => 'Security Logs Notice',
                'value' => 'The Git Code Viewer plugin does not store email addresses. Any security logs contain only anonymized IP addresses and user agents.'
            );
            
            $export_items[] = array(
                'group_id' => 'git-code-viewer',
                'group_label' => 'Git Code Viewer Data',
                'item_id' => 'gcv-notice',
                'data' => $user_data
            );
        }
        
        return array(
            'data' => $export_items,
            'done' => true
        );
    }
    
    /**
     * Register data eraser for GDPR requests
     */
    public static function register_data_eraser($erasers) {
        $erasers['git-code-viewer'] = array(
            'eraser_friendly_name' => __('Git Code Viewer Plugin'),
            'callback' => array(__CLASS__, 'data_eraser')
        );
        return $erasers;
    }
    
    /**
     * Erase user data for GDPR requests
     */
    public static function data_eraser($email_address, $page = 1) {
        // Since we don't store email addresses or persistent user data,
        // we can only clear all transient data if requested
        
        if ($page === 1) {
            // Clear all security logs
            delete_transient('mcb_security_logs');
            
            // Clear all rate limit transients (they expire in 60 seconds anyway)
            global $wpdb;
            $wpdb->query("DELETE FROM {$wpdb->options} WHERE option_name LIKE '_transient_mcb_rate_%'");
            $wpdb->query("DELETE FROM {$wpdb->options} WHERE option_name LIKE '_transient_timeout_mcb_rate_%'");
        }
        
        return array(
            'items_removed' => true,
            'items_retained' => false,
            'messages' => array('All temporary Git Code Viewer data has been removed.'),
            'done' => true
        );
    }
    
    /**
     * Get anonymized IP for privacy compliance
     */
    public static function get_anonymized_ip($ip) {
        if (self::is_privacy_mode()) {
            return 'privacy-mode';
        }
        
        // Anonymize IP by removing last octet for IPv4 or last 80 bits for IPv6
        if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4)) {
            $parts = explode('.', $ip);
            $parts[3] = '0';
            return implode('.', $parts);
        } elseif (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6)) {
            // Zero out last 80 bits
            return substr($ip, 0, strrpos($ip, ':')) . ':0:0:0:0:0';
        }
        
        return 'unknown';
    }
    
    /**
     * Clean up old data automatically
     */
    public static function cleanup_old_data() {
        // This is called on a daily schedule
        global $wpdb;
        
        // Remove expired rate limit transients
        $wpdb->query("DELETE FROM {$wpdb->options} WHERE option_name LIKE '_transient_timeout_mcb_%' AND option_value < UNIX_TIMESTAMP()");
        
        // Remove orphaned transients (fixed MySQL compatibility issue)
        // First get all valid transient names
        $valid_transients = $wpdb->get_col(
            "SELECT CONCAT('_transient_', SUBSTRING(option_name, 20)) 
             FROM {$wpdb->options} 
             WHERE option_name LIKE '_transient_timeout_mcb_%'"
        );
        
        if (!empty($valid_transients)) {
            // Build a safe IN clause
            $placeholders = array_fill(0, count($valid_transients), '%s');
            $in_clause = implode(',', $placeholders);
            
            // Delete orphaned transients
            $wpdb->query(
                $wpdb->prepare(
                    "DELETE FROM {$wpdb->options} 
                     WHERE option_name LIKE '_transient_mcb_%' 
                     AND option_name NOT IN ($in_clause)",
                    $valid_transients
                )
            );
        } else {
            // No valid transients with timeouts, remove all MCB transients
            $wpdb->query("DELETE FROM {$wpdb->options} WHERE option_name LIKE '_transient_mcb_%'");
        }
        
        // Also clean up expired timeout options
        $wpdb->query("DELETE FROM {$wpdb->options} WHERE option_name LIKE '_transient_timeout_mcb_%' AND option_value < UNIX_TIMESTAMP()");
    }
}

// Initialize privacy features
MCB_Privacy_Manager::init();

// Schedule cleanup (weekly is sufficient for transient cleanup)
if (!wp_next_scheduled('mcb_privacy_cleanup')) {
    wp_schedule_event(time(), 'weekly', 'mcb_privacy_cleanup');
}
add_action('mcb_privacy_cleanup', array('MCB_Privacy_Manager', 'cleanup_old_data'));
