<?php
/**
 * TalkGenAI File Generator
 * 
 * Handles secure generation and management of static CSS/JS files
 * 
 * @package TalkGenAI
 * @since 1.0.0
 */

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

class TalkGenAI_File_Generator {
    
    /**
     * Initialize the file generator
     */
    public function __construct() {
        // Ensure secure directory exists on init
        add_action('init', array($this, 'init_secure_directory'), 5);
    }
    
    /**
     * Initialize secure directory with .htaccess protection
     */
    public function init_secure_directory() {
        $upload_dir = wp_upload_dir();
        $talkgenai_dir = $upload_dir['basedir'] . '/talkgenai/';
        
        // Create directory if it doesn't exist
        if (!file_exists($talkgenai_dir)) {
            wp_mkdir_p($talkgenai_dir);
            // Prefer WP_Filesystem for permissions
            if (!function_exists('WP_Filesystem')) {
                require_once ABSPATH . 'wp-admin/includes/file.php';
            }
            global $wp_filesystem;
            WP_Filesystem();
            if ($wp_filesystem && method_exists($wp_filesystem, 'chmod')) {
                $wp_filesystem->chmod($talkgenai_dir, defined('FS_CHMOD_DIR') ? FS_CHMOD_DIR : 0755);
            }
            
            // Debug logging removed for WordPress.org submission
            // if (defined('WP_DEBUG') && WP_DEBUG) {
            //     error_log('TalkGenAI: Created uploads directory: ' . $talkgenai_dir);
            // }
        }
        
        // Create .htaccess for security (blocks PHP execution)
        $htaccess_file = $talkgenai_dir . '.htaccess';
        if (!file_exists($htaccess_file)) {
            $htaccess = "# TalkGenAI Security - Only allow CSS and JS files\n";
            $htaccess .= "Order Deny,Allow\n";
            $htaccess .= "Deny from all\n\n";
            $htaccess .= "# Allow CSS and JS files only\n";
            $htaccess .= "<FilesMatch \"\\.(css|js)$\">\n";
            $htaccess .= "    Allow from all\n";
            $htaccess .= "</FilesMatch>\n\n";
            $htaccess .= "# Block PHP execution completely\n";
            $htaccess .= "<Files *.php>\n";
            $htaccess .= "    deny from all\n";
            $htaccess .= "</Files>\n\n";
            $htaccess .= "# Prevent directory listing\n";
            $htaccess .= "Options -Indexes\n";
            
            file_put_contents($htaccess_file, $htaccess);
            if (!function_exists('WP_Filesystem')) {
                require_once ABSPATH . 'wp-admin/includes/file.php';
            }
            global $wp_filesystem;
            WP_Filesystem();
            if ($wp_filesystem && method_exists($wp_filesystem, 'chmod')) {
                $wp_filesystem->chmod($htaccess_file, defined('FS_CHMOD_FILE') ? FS_CHMOD_FILE : 0644);
            }
        }
        
        // Create index.php to prevent directory listing (extra protection)
        $index_file = $talkgenai_dir . 'index.php';
        if (!file_exists($index_file)) {
            file_put_contents($index_file, '<?php // Silence is golden');
            if (!function_exists('WP_Filesystem')) {
                require_once ABSPATH . 'wp-admin/includes/file.php';
            }
            global $wp_filesystem;
            WP_Filesystem();
            if ($wp_filesystem && method_exists($wp_filesystem, 'chmod')) {
                $wp_filesystem->chmod($index_file, defined('FS_CHMOD_FILE') ? FS_CHMOD_FILE : 0644);
            }
        }
    }
    
    /**
     * Generate static CSS and JS files for an app
     * 
     * @param int $app_id The app ID
     * @param array $app_data Array containing css_content and js_content
     * @return array|WP_Error Array with file URLs or WP_Error on failure
     */
    public function generate_static_files($app_id, $app_data) {
        // Ensure directory exists
        $this->init_secure_directory();
        
        $upload_dir = wp_upload_dir();
        $talkgenai_dir = $upload_dir['basedir'] . '/talkgenai/';
        
        // SECURITY: Validate app_id is positive integer
        $app_id = absint($app_id);
        if ($app_id === 0) {
            // Debug logging removed for WordPress.org submission
            // error_log('TalkGenAI: Invalid app ID for file generation');
            return new WP_Error('invalid_id', __('Invalid app ID', 'talkgenai'));
        }
        
        // SECURITY: Hardcoded filenames with safe extensions (no user input)
        $css_filename = 'app-' . $app_id . '.css';
        $js_filename = 'app-' . $app_id . '.js';
        
        $css_file = $talkgenai_dir . $css_filename;
        $js_file = $talkgenai_dir . $js_filename;
        
        // Generate files
        $results = array(
            'css_url' => '',
            'js_url' => '',
            'css_generated' => false,
            'js_generated' => false,
            'version' => $this->generate_cache_buster()
        );
        
        // Generate CSS file if content exists
        if (!empty($app_data['css_content'])) {
            $safe_css = $this->sanitize_css_content($app_data['css_content']);
            
            if (file_put_contents($css_file, $safe_css) !== false) {
                if (!function_exists('WP_Filesystem')) {
                    require_once ABSPATH . 'wp-admin/includes/file.php';
                }
                global $wp_filesystem;
                WP_Filesystem();
                if ($wp_filesystem && method_exists($wp_filesystem, 'chmod')) {
                    $wp_filesystem->chmod($css_file, defined('FS_CHMOD_FILE') ? FS_CHMOD_FILE : 0644);
                }
                $results['css_url'] = $upload_dir['baseurl'] . '/talkgenai/' . $css_filename;
                $results['css_generated'] = true;
                
                // Debug logging removed for WordPress.org submission
                // if (defined('WP_DEBUG') && WP_DEBUG) {
                //     error_log('TalkGenAI: Generated CSS file for app ' . $app_id);
                // }
            } else {
                // Debug logging removed for WordPress.org submission
                // error_log('TalkGenAI: Failed to write CSS file for app ' . $app_id);
            }
        }
        
        // Generate JS file if content exists
        if (!empty($app_data['js_content'])) {
            $safe_js = $this->sanitize_js_content($app_data['js_content']);
            
            if (file_put_contents($js_file, $safe_js) !== false) {
                if (!function_exists('WP_Filesystem')) {
                    require_once ABSPATH . 'wp-admin/includes/file.php';
                }
                global $wp_filesystem;
                WP_Filesystem();
                if ($wp_filesystem && method_exists($wp_filesystem, 'chmod')) {
                    $wp_filesystem->chmod($js_file, defined('FS_CHMOD_FILE') ? FS_CHMOD_FILE : 0644);
                }
                $results['js_url'] = $upload_dir['baseurl'] . '/talkgenai/' . $js_filename;
                $results['js_generated'] = true;
                
                // Debug logging removed for WordPress.org submission
                // if (defined('WP_DEBUG') && WP_DEBUG) {
                //     error_log('TalkGenAI: Generated JS file for app ' . $app_id);
                // }
            } else {
                // Debug logging removed for WordPress.org submission
                // error_log('TalkGenAI: Failed to write JS file for app ' . $app_id);
            }
        }
        
        return $results;
    }
    
    /**
     * Regenerate files if they're missing (safety check)
     * 
     * @param int $app_id The app ID
     * @param array $app_data App data from database
     * @return array|WP_Error Regeneration results
     */
    public function regenerate_if_missing($app_id, $app_data) {
        $upload_dir = wp_upload_dir();
        $talkgenai_dir = $upload_dir['basedir'] . '/talkgenai/';
        
        $app_id = absint($app_id);
        $css_file = $talkgenai_dir . 'app-' . $app_id . '.css';
        $js_file = $talkgenai_dir . 'app-' . $app_id . '.js';
        
        $needs_regeneration = false;
        
        // Check if files are missing
        if (!empty($app_data['css_content']) && !file_exists($css_file)) {
            $needs_regeneration = true;
            // Debug logging removed for WordPress.org submission
            // if (defined('WP_DEBUG') && WP_DEBUG) {
            //     error_log('TalkGenAI: CSS file missing for app ' . $app_id . ', regenerating...');
            // }
        }
        
        if (!empty($app_data['js_content']) && !file_exists($js_file)) {
            $needs_regeneration = true;
            // Debug logging removed for WordPress.org submission
            // if (defined('WP_DEBUG') && WP_DEBUG) {
            //     error_log('TalkGenAI: JS file missing for app ' . $app_id . ', regenerating...');
            // }
        }
        
        if ($needs_regeneration) {
            // Debug logging removed for WordPress.org submission
            // if (defined('WP_DEBUG') && WP_DEBUG) {
            //     error_log('TalkGenAI: Regenerating missing files for app ' . $app_id);
            // }
            return $this->generate_static_files($app_id, $app_data);
        }
        
        return array('already_exists' => true);
    }
    
    /**
     * Delete static files for an app
     * 
     * @param int $app_id The app ID
     * @return bool True on success
     */
    public function delete_static_files($app_id) {
        $upload_dir = wp_upload_dir();
        $talkgenai_dir = $upload_dir['basedir'] . '/talkgenai/';
        
        $app_id = absint($app_id);
        $css_file = $talkgenai_dir . 'app-' . $app_id . '.css';
        $js_file = $talkgenai_dir . 'app-' . $app_id . '.js';
        
        // Debug logging removed for WordPress.org submission
        // if (defined('WP_DEBUG') && WP_DEBUG) {
        //     error_log('TalkGenAI DELETE: Attempting to delete files for app ' . $app_id);
        //     error_log('TalkGenAI DELETE: TalkGenAI dir: ' . $talkgenai_dir);
        //     error_log('TalkGenAI DELETE: CSS file path: ' . $css_file);
        //     error_log('TalkGenAI DELETE: CSS file exists: ' . (file_exists($css_file) ? 'YES' : 'NO'));
        //     error_log('TalkGenAI DELETE: JS file path: ' . $js_file);
        //     error_log('TalkGenAI DELETE: JS file exists: ' . (file_exists($js_file) ? 'YES' : 'NO'));
        // }
        
        $deleted = true;
        
        // Delete CSS file if exists
        if (file_exists($css_file)) {
            // Use wp_delete_file() which handles permissions internally
            if (!wp_delete_file($css_file)) {
                $error = error_get_last();
                // Debug logging removed for WordPress.org submission
                // if (defined('WP_DEBUG') && WP_DEBUG) {
                //     error_log('TalkGenAI DELETE ERROR: Failed to delete CSS file for app ' . $app_id);
                //     error_log('TalkGenAI DELETE ERROR: CSS file permissions: ' . substr(sprintf('%o', fileperms($css_file)), -4));
                //     error_log('TalkGenAI DELETE ERROR: Last PHP error: ' . ($error ? $error['message'] : 'Unknown'));
                // }
                $deleted = false;
            } else {
                // Debug logging removed for WordPress.org submission
                // if (defined('WP_DEBUG') && WP_DEBUG) {
                //     error_log('TalkGenAI DELETE: Successfully deleted CSS file for app ' . $app_id);
                // }
            }
        } else {
            // Debug logging removed for WordPress.org submission
            // if (defined('WP_DEBUG') && WP_DEBUG) {
            //     error_log('TalkGenAI DELETE: CSS file does not exist, skipping');
            // }
        }
        
        // Delete JS file if exists
        if (file_exists($js_file)) {
            // Use wp_delete_file() which handles permissions internally
            if (!wp_delete_file($js_file)) {
                $error = error_get_last();
                // Debug logging removed for WordPress.org submission
                // if (defined('WP_DEBUG') && WP_DEBUG) {
                //     error_log('TalkGenAI DELETE ERROR: Failed to delete JS file for app ' . $app_id);
                //     error_log('TalkGenAI DELETE ERROR: JS file permissions: ' . substr(sprintf('%o', fileperms($js_file)), -4));
                //     error_log('TalkGenAI DELETE ERROR: Last PHP error: ' . ($error ? $error['message'] : 'Unknown'));
                // }
                $deleted = false;
            } else {
                // Debug logging removed for WordPress.org submission
                // if (defined('WP_DEBUG') && WP_DEBUG) {
                //     error_log('TalkGenAI DELETE: Successfully deleted JS file for app ' . $app_id);
                // }
            }
        } else {
            // Debug logging removed for WordPress.org submission
            // if (defined('WP_DEBUG') && WP_DEBUG) {
            //     error_log('TalkGenAI DELETE: JS file does not exist, skipping');
            // }
        }
        
        // Debug logging removed for WordPress.org submission
        // if (defined('WP_DEBUG') && WP_DEBUG) {
        //     error_log('TalkGenAI DELETE: Final status - deleted: ' . ($deleted ? 'YES' : 'NO'));
        // }
        
        return $deleted;
    }
    
    /**
     * Sanitize CSS content - remove any potentially dangerous code
     * 
     * @param string $css Raw CSS content
     * @return string Sanitized CSS
     */
    private function sanitize_css_content($css) {
        if (!is_string($css)) {
            return '';
        }
        
        // Remove any PHP tags (should never be there, but be safe)
        $css = preg_replace('/<\?php.*?\?>/s', '', $css);
        $css = preg_replace('/<\?.*?\?>/s', '', $css);
        
        // Remove HTML tags
        $css = wp_strip_all_tags($css);
        
        // Remove javascript: protocol (rare but possible in CSS)
        $css = preg_replace('/javascript:/i', '', $css);
        
        // Remove IE expression() (old IE exploit)
        $css = preg_replace('/expression\s*\(/i', '', $css);
        
        return $css;
    }
    
    /**
     * Sanitize JavaScript content - remove PHP and dangerous patterns
     * 
     * @param string $js Raw JavaScript content
     * @return string Sanitized JavaScript
     */
    private function sanitize_js_content($js) {
        if (!is_string($js)) {
            return '';
        }
        
        // Remove any PHP tags
        $js = preg_replace('/<\?php.*?\?>/s', '', $js);
        $js = preg_replace('/<\?.*?\?>/s', '', $js);
        $js = str_replace(['<?php', '<?', '?>'], '', $js);
        
        // JavaScript is meant to execute, so we can't strip too much
        // But we ensure no PHP can sneak in
        
        return $js;
    }
    
    /**
     * Generate a cache busting version string
     * 
     * @return string Hash for cache busting
     */
    private function generate_cache_buster() {
        return md5(current_time('mysql') . wp_rand());
    }
    
    /**
     * Get file URLs for an app
     * 
     * @param int $app_id The app ID
     * @return array Array with css_url and js_url
     */
    public function get_file_urls($app_id) {
        $upload_dir = wp_upload_dir();
        $app_id = absint($app_id);
        
        return array(
            'css_url' => $upload_dir['baseurl'] . '/talkgenai/app-' . $app_id . '.css',
            'js_url' => $upload_dir['baseurl'] . '/talkgenai/app-' . $app_id . '.js'
        );
    }
    
    /**
     * Check if files exist for an app
     * 
     * @param int $app_id The app ID
     * @return array Array with css_exists and js_exists booleans
     */
    public function files_exist($app_id) {
        $upload_dir = wp_upload_dir();
        $talkgenai_dir = $upload_dir['basedir'] . '/talkgenai/';
        $app_id = absint($app_id);
        
        return array(
            'css_exists' => file_exists($talkgenai_dir . 'app-' . $app_id . '.css'),
            'js_exists' => file_exists($talkgenai_dir . 'app-' . $app_id . '.js')
        );
    }
}


