<?php
/**
 * Plugin Name: PageSpark WP
 * Plugin URI: https://github.com/davidrepasky/wp-bootstrap-studio
 * Description: PageSpark WP — AI-powered Bootstrap 5 page builder. Generate professional, clean-code pages using Claude AI with visual validation.
 * Version: 3.5.0
 * Author: David Repasky
 * Author URI: https://davidrepaskyconsulting.com
 * License: GPL v2 or later
 * Text Domain: wp-bootstrap-studio
 */

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

define('WPBS_VERSION', '3.5.0');
define('WPBS_PLUGIN_DIR', plugin_dir_path(__FILE__));
define('WPBS_PLUGIN_URL', plugin_dir_url(__FILE__));

require_once WPBS_PLUGIN_DIR . 'includes/class-api-client.php';
require_once WPBS_PLUGIN_DIR . 'includes/class-editor.php';
require_once WPBS_PLUGIN_DIR . 'includes/class-chat-panel.php';
require_once WPBS_PLUGIN_DIR . 'includes/class-smtp.php';
require_once WPBS_PLUGIN_DIR . 'includes/class-accessibility.php';
require_once WPBS_PLUGIN_DIR . 'includes/class-template.php';
require_once WPBS_PLUGIN_DIR . 'includes/class-playwright-user.php';
require_once WPBS_PLUGIN_DIR . 'includes/class-plugin-builder.php';
require_once WPBS_PLUGIN_DIR . 'includes/class-media-indexer.php';

class WP_Bootstrap_Studio {
    
    private static $instance = null;
    
    public static function instance() {
        if (null === self::$instance) {
            self::$instance = new self();
        }
        return self::$instance;
    }
    
    private function __construct() {
        add_action('init', [$this, 'init']);
        add_action('admin_menu', [$this, 'add_admin_menu']);
        add_action('admin_enqueue_scripts', [$this, 'enqueue_admin_assets']);
        add_action('wp_enqueue_scripts', [$this, 'enqueue_frontend_assets']);
        add_action('add_meta_boxes', [$this, 'add_meta_boxes']);
        add_action('save_post', [$this, 'save_meta']);
        add_action('rest_api_init', [$this, 'register_rest_routes']);
        add_action('wp_head', [$this, 'output_custom_css'], 99);
        add_action('wp_footer', [$this, 'output_custom_js'], 99);

        WPBS_SMTP::init();
        WPBS_Template::init();
        WPBS_Playwright_User::instance();
        WPBS_Plugin_Builder::instance();
        WPBS_Media_Indexer::instance();

        // Allow iframes and HTML comments in PageSpark pages
        add_filter('wp_kses_allowed_html', [$this, 'allow_iframes_kses'], 10, 2);
        add_filter('tiny_mce_before_init', [$this, 'configure_tinymce']);
        add_action('admin_init', [$this, 'remove_kses_for_admins']);
        add_action('rest_api_init', [$this, 'remove_kses_for_admins']);
    }
    
    public function init() {
        register_post_meta('page', '_wpbs_enabled', [
            'type' => 'boolean',
            'single' => true,
            'show_in_rest' => true,
            'default' => false,
        ]);
        register_post_meta('page', '_wpbs_site_context', [
            'type' => 'string',
            'single' => true,
            'show_in_rest' => true,
            'default' => '',
        ]);

        // Register CSS/JS meta for all public post types so REST API can update them
        $post_types = get_post_types(['public' => true], 'names');
        foreach ($post_types as $pt) {
            if ($pt === 'attachment') continue;
            register_post_meta($pt, '_wpbs_custom_css', [
                'type' => 'string',
                'single' => true,
                'show_in_rest' => true,
                'default' => '',
                'auth_callback' => function() { return current_user_can('edit_posts'); },
            ]);
            register_post_meta($pt, '_wpbs_custom_js', [
                'type' => 'string',
                'single' => true,
                'show_in_rest' => true,
                'default' => '',
                'auth_callback' => function() { return current_user_can('edit_posts'); },
            ]);
        }
    }
    
    public function add_admin_menu() {
        add_menu_page('PageSpark WP', 'PageSpark WP', 'manage_options', 'wp-bootstrap-studio', [$this, 'render_settings_page'], 'dashicons-layout', 30);
        add_submenu_page('wp-bootstrap-studio', 'Settings', 'Settings', 'manage_options', 'wp-bootstrap-studio', [$this, 'render_settings_page']);
        add_submenu_page('wp-bootstrap-studio', 'SMTP', 'SMTP', 'manage_options', 'wpbs-smtp', [WPBS_SMTP::class, 'render_settings_page']);
        add_submenu_page('wp-bootstrap-studio', 'Accessibility', 'Accessibility', 'manage_options', 'wpbs-accessibility', [WPBS_Accessibility::class, 'render_dashboard']);
        add_submenu_page('wp-bootstrap-studio', 'Plugin Builder', 'Plugin Builder', 'manage_options', 'wpbs-plugin-builder', [WPBS_Plugin_Builder::instance(), 'render_page']);
    }
    
    public function register_rest_routes() {
        register_rest_route('wpbs/v1', '/generate', [
            'methods' => 'POST',
            'callback' => [WPBS_API_Client::instance(), 'generate'],
            'permission_callback' => function() { return current_user_can('edit_posts'); },
        ]);
        register_rest_route('wpbs/v1', '/edit', [
            'methods' => 'POST',
            'callback' => [WPBS_API_Client::instance(), 'edit'],
            'permission_callback' => function() { return current_user_can('edit_posts'); },
        ]);
        register_rest_route('wpbs/v1', '/test-connection', [
            'methods' => 'GET',
            'callback' => [WPBS_API_Client::instance(), 'test_connection'],
            'permission_callback' => function() { return current_user_can('manage_options'); },
        ]);
    }
    
    public function enqueue_admin_assets($hook) {
        if (strpos($hook, 'wp-bootstrap-studio') !== false || strpos($hook, 'wpbs-') !== false) {
            wp_enqueue_style('wpbs-admin', WPBS_PLUGIN_URL . 'assets/css/admin.css', [], WPBS_VERSION);
            wp_enqueue_script('wpbs-admin', WPBS_PLUGIN_URL . 'assets/js/admin.js', ['jquery'], WPBS_VERSION, true);
            wp_localize_script('wpbs-admin', 'wpbs', [
                'nonce' => wp_create_nonce('wp_rest'),
                'restUrl' => rest_url('wpbs/v1/'),
                'ajaxUrl' => admin_url('admin-ajax.php'),
                'settingsNonce' => wp_create_nonce('wpbs_settings'),
            ]);
        }

        // Plugin Builder page
        if (strpos($hook, 'wpbs-plugin-builder') !== false) {
            wp_enqueue_style('wpbs-plugin-builder', WPBS_PLUGIN_URL . 'assets/css/plugin-builder.css', [], WPBS_VERSION);
            wp_enqueue_script('wpbs-plugin-builder', WPBS_PLUGIN_URL . 'assets/js/plugin-builder.js', ['jquery'], WPBS_VERSION, true);
            wp_localize_script('wpbs-plugin-builder', 'pspb', [
                'nonce' => wp_create_nonce('pspb_nonce'),
            ]);
        }
        
        if (in_array($hook, ['post.php', 'post-new.php'])) {
            global $post;
            if ($post && $post->post_type === 'page') {
                wp_enqueue_code_editor(['type' => 'text/html']);
                wp_enqueue_style('wpbs-editor', WPBS_PLUGIN_URL . 'assets/css/editor.css', [], WPBS_VERSION);
                wp_enqueue_script('wpbs-chat-panel', WPBS_PLUGIN_URL . 'assets/js/chat-panel.js', ['jquery', 'wp-util'], WPBS_VERSION, true);
                wp_enqueue_script('wpbs-editor', WPBS_PLUGIN_URL . 'assets/js/editor.js', ['jquery'], WPBS_VERSION, true);
                $post_type_rest = get_post_type_object($post->post_type)->rest_base ?: $post->post_type;
                wp_localize_script('wpbs-chat-panel', 'wpbs', [
                    'nonce' => wp_create_nonce('wp_rest'),
                    'restUrl' => rest_url('wpbs/v1/'),
                    'wpRestUrl' => rest_url('wp/v2/'),
                    'postId' => $post->ID,
                    'postType' => $post_type_rest,
                    'bootstrapCss' => 'https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css',
                    'bootstrapJs' => 'https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js',
                    'bootstrapIcons' => 'https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.3/font/bootstrap-icons.css',
                ]);
            }
        }
    }
    
    public function enqueue_frontend_assets() {
        if (!is_singular('page')) return;
        $enabled = get_post_meta(get_the_ID(), '_wpbs_enabled', true);
        if (!$enabled) return;

        wp_dequeue_style('wp-block-library');
        wp_dequeue_style('classic-theme-styles');
        wp_dequeue_style('global-styles');

        // If the active theme already loads Bootstrap, don't double-load from CDN.
        // But KEEP bootstrap-icons — themes rarely provide the icon font.
        add_action('wp_print_scripts', function() {
            if (wp_script_is('bootstrap', 'enqueued')) {
                wp_dequeue_script('bootstrap-5');
                wp_dequeue_style('bootstrap-5');
            }
        }, 1);

        // Enqueue CDN versions as fallback
        wp_enqueue_style('bootstrap-5', 'https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css', [], '5.3.3');
        wp_enqueue_style('bootstrap-icons', 'https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.3/font/bootstrap-icons.css', [], '1.11.3');
        wp_enqueue_script('bootstrap-5', 'https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js', [], '5.3.3', true);
    }
    
    public function add_meta_boxes() {
        add_meta_box('wpbs-settings', 'PageSpark Settings', [$this, 'render_settings_metabox'], 'page', 'side', 'high');
        add_meta_box('wpbs-chat', 'AI Page Builder', [$this, 'render_chat_metabox'], 'page', 'normal', 'high');
        add_meta_box('wpbs-preview', 'PageSpark Preview', [$this, 'render_preview_metabox'], 'page', 'normal', 'high');

        // Custom CSS meta box on all public post types
        $post_types = get_post_types(['public' => true], 'names');
        foreach ($post_types as $pt) {
            if ($pt === 'attachment') continue;
            add_meta_box('wpbs-custom-css', 'Custom CSS & JS', [$this, 'render_custom_css_metabox'], $pt, 'normal', 'low');
        }
    }
    
    public function render_settings_metabox($post) {
        $enabled = get_post_meta($post->ID, '_wpbs_enabled', true);
        $context = get_post_meta($post->ID, '_wpbs_site_context', true);
        wp_nonce_field('wpbs_meta', 'wpbs_meta_nonce');
        ?>
        <p>
            <label><input type="checkbox" name="_wpbs_enabled" value="1" <?php checked($enabled, true); ?>> Enable PageSpark</label>
        </p>
        <p class="description">Loads Bootstrap 5 and uses a clean template.</p>
        <p>
            <label for="wpbs-site-context"><strong>Page Context</strong></label>
            <textarea id="wpbs-site-context" name="_wpbs_site_context" rows="3" style="width:100%;" placeholder="e.g., Services page for a painting contractor..."><?php echo esc_textarea($context); ?></textarea>
        </p>
        <?php
    }
    
    public function render_chat_metabox($post) {
        ?>
        <div id="wpbs-chat-panel">
            <div id="wpbs-chat-messages" class="wpbs-chat-messages">
                <div class="wpbs-chat-welcome">
                    <p><strong>AI Page Builder</strong></p>
                    <p>Describe the page you want to build, or ask to modify existing content.</p>
                    <p><em>Try:</em> "Build a hero section with a background image and CTA" or "Add a 4-card services grid for a painting contractor"</p>
                </div>
            </div>
            <div class="wpbs-chat-input-area">
                <textarea id="wpbs-chat-input" placeholder="Describe what you want to build or change..." rows="3"></textarea>
                <div class="wpbs-chat-actions">
                    <label><input type="checkbox" id="wpbs-edit-mode"> Edit existing content</label>
                    <select id="wpbs-quality-tier" style="margin-left:8px;">
                        <option value="standard">Standard (faster)</option>
                        <option value="premium">Premium (best quality, 1.5x tokens)</option>
                    </select>
                    <button type="button" id="wpbs-chat-send" class="button button-primary">Generate</button>
                </div>
            </div>
            <div id="wpbs-chat-loading" style="display:none;">
                <span class="spinner is-active"></span> Claude is building your page...
            </div>
        </div>
        <?php
    }
    
    public function render_preview_metabox($post) {
        ?>
        <div id="wpbs-preview-container">
            <div class="wpbs-preview-toolbar">
                <button type="button" class="button wpbs-preview-size active" data-width="100%">Desktop</button>
                <button type="button" class="button wpbs-preview-size" data-width="768px">Tablet</button>
                <button type="button" class="button wpbs-preview-size" data-width="375px">Mobile</button>
                <button type="button" class="button" id="wpbs-toggle-code">Toggle Code</button>
                <button type="button" class="button button-primary" id="wpbs-apply-html">Apply to Page</button>
            </div>
            <iframe id="wpbs-preview-frame" style="width:100%; min-height:600px; border:1px solid #ddd;"></iframe>
            <div id="wpbs-code-editor-wrapper" style="display:none;">
                <textarea id="wpbs-code-editor" rows="20" style="width:100%; font-family:monospace;"></textarea>
            </div>
        </div>
        <?php
    }
    
    public function render_custom_css_metabox($post) {
        $css = get_post_meta($post->ID, '_wpbs_custom_css', true);
        $js = get_post_meta($post->ID, '_wpbs_custom_js', true);
        wp_nonce_field('wpbs_custom_css', 'wpbs_custom_css_nonce');
        ?>
        <p><strong>Custom CSS</strong></p>
        <p class="description">Output in a <code>&lt;style&gt;</code> tag in the <code>&lt;head&gt;</code> of this page only.</p>
        <textarea name="_wpbs_custom_css" rows="12" style="width:100%; font-family:monospace; font-size:13px; tab-size:4;"><?php echo esc_textarea($css); ?></textarea>
        <p style="margin-top:16px;"><strong>Custom JavaScript</strong></p>
        <p class="description">Output in a <code>&lt;script&gt;</code> tag in the footer of this page only.</p>
        <textarea name="_wpbs_custom_js" rows="8" style="width:100%; font-family:monospace; font-size:13px; tab-size:4;"><?php echo esc_textarea($js); ?></textarea>
        <?php
    }

    public function output_custom_css() {
        if (!is_singular()) return;
        $css = get_post_meta(get_the_ID(), '_wpbs_custom_css', true);
        if (empty($css)) return;
        echo '<style id="wpbs-custom-css">' . "\n" . wp_strip_all_tags($css) . "\n" . '</style>' . "\n";
    }

    public function output_custom_js() {
        if (!is_singular()) return;
        $js = get_post_meta(get_the_ID(), '_wpbs_custom_js', true);
        if (empty($js)) return;
        echo '<script id="wpbs-custom-js">' . "\n" . $js . "\n" . '</script>' . "\n";
    }

    public function save_meta($post_id) {
        if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) return;
        if (!current_user_can('edit_post', $post_id)) return;

        // Bootstrap Studio settings (page only)
        if (isset($_POST['wpbs_meta_nonce']) && wp_verify_nonce($_POST['wpbs_meta_nonce'], 'wpbs_meta')) {
            update_post_meta($post_id, '_wpbs_enabled', isset($_POST['_wpbs_enabled']));
            if (isset($_POST['_wpbs_site_context'])) {
                update_post_meta($post_id, '_wpbs_site_context', sanitize_textarea_field($_POST['_wpbs_site_context']));
            }
        }

        // Custom CSS & JS (all post types)
        if (isset($_POST['wpbs_custom_css_nonce']) && wp_verify_nonce($_POST['wpbs_custom_css_nonce'], 'wpbs_custom_css')) {
            if (isset($_POST['_wpbs_custom_css'])) {
                update_post_meta($post_id, '_wpbs_custom_css', wp_strip_all_tags($_POST['_wpbs_custom_css']));
            }
            if (isset($_POST['_wpbs_custom_js'])) {
                update_post_meta($post_id, '_wpbs_custom_js', $_POST['_wpbs_custom_js']);
            }
        }
    }
    
    /**
     * Allow iframes in wp_kses post content
     */
    public function allow_iframes_kses($tags, $context) {
        if ($context === 'post') {
            $tags['iframe'] = [
                'src' => true, 'width' => true, 'height' => true,
                'frameborder' => true, 'allowfullscreen' => true,
                'allow' => true, 'loading' => true, 'referrerpolicy' => true,
                'style' => true, 'class' => true, 'id' => true,
                'title' => true, 'name' => true, 'sandbox' => true,
            ];
        }
        return $tags;
    }

    /**
     * Configure TinyMCE to preserve iframes and HTML comments
     */
    public function configure_tinymce($settings) {
        // Allow iframes in TinyMCE
        $existing = isset($settings['extended_valid_elements']) ? $settings['extended_valid_elements'] . ',' : '';
        $settings['extended_valid_elements'] = $existing . 'iframe[src|width|height|frameborder|allowfullscreen|allow|loading|referrerpolicy|style|class|id|title|name|sandbox]';

        // Preserve HTML comments and don't strip unknown elements
        $settings['verify_html'] = 'false';
        $settings['cleanup'] = 'false';
        $settings['remove_linebreaks'] = 'false';

        // Protect HTML comments from being encoded or stripped
        $settings['protect'] = '[/<!--[\s\S]*?-->/g]';

        return $settings;
    }

    /**
     * Completely remove kses filtering — allows iframes,
     * HTML comments, and all HTML to be saved without modification.
     */
    public function remove_kses_for_admins() {
        kses_remove_filters();
    }

    public function render_settings_page() {
        if (isset($_POST['wpbs_settings_nonce']) && wp_verify_nonce($_POST['wpbs_settings_nonce'], 'wpbs_settings')) {
            update_option('wpbs_api_key', sanitize_text_field($_POST['wpbs_api_key'] ?? ''));
            update_option('wpbs_anthropic_key', sanitize_text_field($_POST['wpbs_anthropic_key'] ?? ''));
            update_option('wpbs_default_context', sanitize_textarea_field($_POST['wpbs_default_context'] ?? ''));
            echo '<div class="notice notice-success"><p>Settings saved.</p></div>';
        }
        $api_key = get_option('wpbs_api_key', '');
        $anthropic_key = get_option('wpbs_anthropic_key', '');
        $default_context = get_option('wpbs_default_context', '');
        ?>
        <div class="wrap">
            <h1>PageSpark WP <small style="font-size:13px; color:#666;">v<?php echo WPBS_VERSION; ?></small></h1>
            <form method="post">
                <?php wp_nonce_field('wpbs_settings', 'wpbs_settings_nonce'); ?>
                <table class="form-table">
                    <tr>
                        <th><label for="wpbs-api-key">API Secret Key</label></th>
                        <td>
                            <input type="password" id="wpbs-api-key" name="wpbs_api_key" value="<?php echo esc_attr($api_key); ?>" class="regular-text">
                            <button type="button" id="wpbs-test-connection" class="button">Test Connection</button>
                            <span id="wpbs-connection-result"></span>
                        </td>
                    </tr>
                    <tr>
                        <th><label>Site API Key</label></th>
                        <td>
                            <?php
                            $site_api_key = defined('PAGESPARK_API_KEY') ? PAGESPARK_API_KEY : get_option('pagespark_site_api_key_display', '');
                            if ($site_api_key): ?>
                                <input type="text" value="<?php echo esc_attr($site_api_key); ?>" class="regular-text" readonly onclick="this.select();">
                                <p class="description">Used internally by Plugin Builder to authenticate automated installs. No action needed.</p>
                            <?php else: ?>
                                <p class="description">Deactivate and reactivate the plugin to generate a Site API Key.</p>
                            <?php endif; ?>
                        </td>
                    </tr>
                    <tr>
                        <th><label for="wpbs-default-context">Default Site Context</label></th>
                        <td>
                            <textarea id="wpbs-default-context" name="wpbs_default_context" rows="4" class="large-text"><?php echo esc_textarea($default_context); ?></textarea>
                            <p class="description">Sent with every AI request. Describe your business, industry, brand voice.</p>
                        </td>
                    </tr>
                    <tr>
                        <th><label for="wpbs-anthropic-key">Anthropic API Key (for media indexing)</label></th>
                        <td>
                            <input type="password" id="wpbs-anthropic-key" name="wpbs_anthropic_key" value="<?php echo esc_attr($anthropic_key); ?>" class="regular-text">
                            <button type="button" id="wpbs-test-anthropic" class="button">Test Key</button>
                            <button type="button" id="wpbs-reindex-media" class="button">Re-index Media Library</button>
                            <span id="wpbs-anthropic-result"></span>
                            <p class="description">Used by PageSpark to auto-generate alt text and image descriptions using Claude Haiku. Get your key at <a href="https://console.anthropic.com" target="_blank">console.anthropic.com</a></p>
                        </td>
                    </tr>
                </table>
                <?php submit_button('Save Settings'); ?>
            </form>
        </div>
        <?php
    }
}

WP_Bootstrap_Studio::instance();

// Activation / Deactivation hooks for Playwright user lifecycle
register_activation_hook(__FILE__, function() {
    WPBS_Playwright_User::instance()->activate();
    WPBS_Media_Indexer::instance()->activate();
});
register_deactivation_hook(__FILE__, function() {
    WPBS_Playwright_User::instance()->deactivate();
});
