<?php
/**
 * Certificate Security Class
 *
 * Handles security aspects of certificate generation and storage.
 *
 * @package HVAC_Community_Events
 * @subpackage Certificates
 */

// Exit if accessed directly
if (!defined('ABSPATH')) {
    exit;
}

/**
 * Certificate Security class.
 *
 * Provides security functions for certificates.
 *
 * @since 1.0.0
 */
class HVAC_Certificate_Security {

    /**
     * The single instance of the class.
     *
     * @var HVAC_Certificate_Security
     */
    protected static $_instance = null;

    /**
     * Main HVAC_Certificate_Security Instance.
     *
     * Ensures only one instance of HVAC_Certificate_Security is loaded or can be loaded.
     *
     * @return HVAC_Certificate_Security - Main instance.
     */
    public static function instance() {
        if (is_null(self::$_instance)) {
            self::$_instance = new self();
        }
        return self::$_instance;
    }

    /**
     * Constructor.
     */
    public function __construct() {
        // Initialize hooks
        add_action('init', array($this, 'init_secure_download'), 1); // Early priority
        
        // Add admin action to manually flush rewrite rules
        add_action('admin_init', array($this, 'maybe_flush_rewrite_rules'));
        
        // Alternative URL handling without rewrite rules
        add_action('parse_request', array($this, 'parse_certificate_request'), 1);
    }

    /**
     * Initialize the secure download endpoint.
     */
    public function init_secure_download() {
        // Add rewrite rule for certificate downloads
        add_rewrite_rule(
            'hvac-certificate/([^/]+)/?$',
            'index.php?certificate_token=$matches[1]',
            'top'
        );
        
        // Add query var
        add_filter('query_vars', array($this, 'add_query_vars'));
        
        // Handle certificate download requests
        add_action('template_redirect', array($this, 'handle_certificate_download'));
    }
    

    /**
     * Add custom query variables.
     *
     * @param array $vars Query variables.
     * 
     * @return array Modified query variables.
     */
    public function add_query_vars($vars) {
        $vars[] = 'certificate_token';
        return $vars;
    }

    /**
     * Handle certificate download requests.
     */
    public function handle_certificate_download() {
        $certificate_token = get_query_var('certificate_token');
        
        if (empty($certificate_token)) {
            return;
        }
        
        // Validate the token
        $certificate_data = $this->validate_download_token($certificate_token);
        
        if (!$certificate_data) {
            wp_die(__('Invalid or expired certificate download link.', 'hvac-community-events'));
        }
        
        // Get file path
        $file_path = $this->get_certificate_file_path($certificate_data);
        
        if (!$file_path || !file_exists($file_path)) {
            wp_die(__('Certificate file not found.', 'hvac-community-events'));
        }
        
        // Serve the file
        $this->serve_certificate_file($file_path, $certificate_data);
        exit;
    }
    
    /**
     * Parse certificate requests directly without relying on rewrite rules.
     * This is a fallback method that works even if rewrite rules fail.
     */
    public function parse_certificate_request($wp) {
        // Only process if we haven't already handled via template_redirect
        if (did_action('template_redirect')) {
            return;
        }
        
        $request_uri = $_SERVER['REQUEST_URI'];
        
        // Only match exact certificate download URLs - be very specific
        if (preg_match('#^/hvac-certificate/([a-zA-Z0-9]{32})/?$#', $request_uri, $matches)) {
            $certificate_token = $matches[1];
            
            // Validate the token exists (don't delete it yet - let the normal handler do that)
            $certificate_data = get_transient('hvac_certificate_token_' . $certificate_token);
            
            if (!$certificate_data) {
                // Return 404 instead of wp_die to avoid interfering with other pages
                status_header(404);
                return;
            }
            
            // If we have valid certificate data, let the normal template_redirect handler take over
            // Set the query var so the normal handler can pick it up
            set_query_var('certificate_token', $certificate_token);
            return;
        }
    }

    /**
     * Validate a certificate download token.
     *
     * @param string $token The token to validate.
     * 
     * @return array|false Certificate data if valid, false otherwise.
     */
    protected function validate_download_token($token) {
        // Check if token exists in transients
        $certificate_data = get_transient('hvac_certificate_token_' . $token);
        
        if (!$certificate_data) {
            return false;
        }
        
        // Delete the transient to prevent reuse
        delete_transient('hvac_certificate_token_' . $token);
        
        return $certificate_data;
    }

    /**
     * Get the full file path for a certificate.
     *
     * @param array $certificate_data Certificate data.
     * 
     * @return string|false Full file path or false if not found.
     */
    protected function get_certificate_file_path($certificate_data) {
        if (empty($certificate_data['file_path'])) {
            return false;
        }
        
        $upload_dir = wp_upload_dir();
        $file_path = $upload_dir['basedir'] . '/' . $certificate_data['file_path'];
        
        if (file_exists($file_path)) {
            return $file_path;
        }
        
        return false;
    }

    /**
     * Serve a certificate file for download.
     *
     * @param string $file_path       Full path to certificate file.
     * @param array  $certificate_data Certificate data.
     */
    protected function serve_certificate_file($file_path, $certificate_data) {
        // Get file information
        $file_name = basename($file_path);
        $file_size = filesize($file_path);
        $file_ext = pathinfo($file_path, PATHINFO_EXTENSION);
        
        // Set download filename
        $event_name = sanitize_title($certificate_data['event_name'] ?? 'event');
        $attendee_name = sanitize_title($certificate_data['attendee_name'] ?? 'attendee');
        $download_filename = "certificate-{$event_name}-{$attendee_name}.{$file_ext}";
        
        // Send headers
        nocache_headers();
        header('Content-Type: application/pdf');
        header('Content-Disposition: attachment; filename="' . $download_filename . '"');
        header('Content-Transfer-Encoding: binary');
        header('Content-Length: ' . $file_size);
        
        // Disable output buffering
        if (ob_get_level()) {
            ob_end_clean();
        }
        
        // Output the file
        readfile($file_path);
    }

    /**
     * Generate a secure download token for a certificate.
     *
     * @param int   $certificate_id The certificate ID.
     * @param array $certificate_data Additional certificate data.
     * @param int   $expiry          Token expiry time in seconds (default 1 hour).
     * 
     * @return string|false The download URL or false on failure.
     */
    public function generate_download_token($certificate_id, $certificate_data, $expiry = 3600) {
        if (!$certificate_id || empty($certificate_data['file_path'])) {
            return false;
        }
        
        // Generate a unique token
        $token = wp_generate_password(32, false);
        
        // Store in transient
        set_transient('hvac_certificate_token_' . $token, $certificate_data, $expiry);
        
        // Generate URL
        return home_url('hvac-certificate/' . $token);
    }

    /**
     * Create a secure storage directory for certificates.
     *
     * @param string $dir_path The directory path to secure.
     * 
     * @return bool True if successful, false otherwise.
     */
    public function create_secure_directory($dir_path) {
        // Check if directory exists
        if (!file_exists($dir_path)) {
            // Create directory
            if (!wp_mkdir_p($dir_path)) {
                return false;
            }
        }
        
        // Create/update .htaccess file
        $htaccess_content = "# Prevent direct access to files\n";
        $htaccess_content .= "<Files ~ \".*\">\n";
        $htaccess_content .= "    Order Allow,Deny\n";
        $htaccess_content .= "    Deny from all\n";
        $htaccess_content .= "</Files>\n";
        $htaccess_content .= "# Prevent directory listing\n";
        $htaccess_content .= "Options -Indexes\n";
        
        $htaccess_file = $dir_path . '/.htaccess';
        
        if (!@file_put_contents($htaccess_file, $htaccess_content)) {
            return false;
        }
        
        // Create empty index.php
        $index_content = "<?php\n// Silence is golden.";
        $index_file = $dir_path . '/index.php';
        
        if (!@file_put_contents($index_file, $index_content)) {
            return false;
        }
        
        return true;
    }
    
    /**
     * Check if we need to flush rewrite rules.
     * This provides a way to manually trigger a flush via URL parameter.
     */
    public function maybe_flush_rewrite_rules() {
        // Only allow admins to flush rewrite rules
        if (!current_user_can('manage_options')) {
            return;
        }
        
        // Check for flush parameter
        if (isset($_GET['hvac_flush_rewrite_rules']) && $_GET['hvac_flush_rewrite_rules'] === '1') {
            // Re-register our rewrite rule
            $this->init_secure_download();
            
            // Flush the rules
            flush_rewrite_rules();
            
            // Log the action
            if (class_exists('HVAC_Logger')) {
                HVAC_Logger::info('Rewrite rules flushed manually via admin parameter', 'Certificate Security');
            }
            
            // Redirect to remove the parameter
            wp_redirect(remove_query_arg('hvac_flush_rewrite_rules'));
            exit;
        }
    }
}