<?php
declare(strict_types=1);

namespace ProRank\SEO\Integrations\BeaverBuilder;

use ProRank\SEO\Plugin;

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

/**
 * Beaver Builder integration for ProRank SEO.
 *
 * Enqueues the SEO meta-box panel inside Beaver Builder's frontend editor.
 * BB uses ?fl_builder URL parameter and a responsive iframe UI.
 */
class BeaverBuilderIntegration {

    private static ?self $instance = null;

    public static function get_instance(): self {
        if (null === self::$instance) {
            self::$instance = new self();
        }
        return self::$instance;
    }

    private function __construct() {
        if (!$this->is_beaver_builder_active()) {
            return;
        }

        $this->init_hooks();
    }

    private function is_beaver_builder_active(): bool {
        return defined('FL_BUILDER_VERSION') || class_exists('FLBuilderModel');
    }

    /**
     * Is this the Beaver Builder parent chrome (not the content iframe)?
     *
     * BB loads ?fl_builder on the parent and ?fl_builder_ui_iframe on the
     * content iframe. We must only mount the panel in the parent.
     */
    private function is_builder_editor(): bool {
        // phpcs:ignore WordPress.Security.NonceVerification.Recommended
        return isset($_GET['fl_builder']) && !isset($_GET['fl_builder_ui_iframe']);
    }

    private function init_hooks(): void {
        // BB's responsive iframe UI has its own script enqueue hook for the parent chrome.
        // wp_enqueue_scripts fires but scripts are NOT printed by BB's chrome page.
        // fl_builder_ui_enqueue_scripts is the correct hook for the parent window.
        add_action('fl_builder_ui_enqueue_scripts', [$this, 'enqueue_builder_scripts'], 20);
        // Fallback for non-iframe-UI mode (BB setting: Admin > Settings > Advanced)
        add_action('wp_enqueue_scripts', [$this, 'enqueue_builder_scripts'], 20);

        // Render floating panel in footer
        add_action('wp_footer', [$this, 'render_builder_panel'], 90);

        // Add type="module" and importmap for Vite ESM output
        add_filter('script_loader_tag', [$this, 'filter_script_tag'], 10, 2);

        // Render importmap for Vite ESM bare specifiers
        add_action('wp_head', [$this, 'render_import_map'], 1);
    }

    public function enqueue_builder_scripts(): void {
        if (!$this->is_builder_editor()) {
            return;
        }

        $post_id = get_the_ID();
        if (!$post_id || $post_id <= 0) {
            return;
        }

        $post_type = get_post_type($post_id);
        if (!is_string($post_type) || $post_type === '') {
            return;
        }

        $public_post_types = get_post_types(['public' => true], 'names');
        if (!in_array($post_type, $public_post_types, true)) {
            return;
        }

        if (!$this->is_meta_box_enabled($post_type)) {
            return;
        }

        $script_path = PRORANK_PLUGIN_DIR . 'build/meta-box.js';
        if (!file_exists($script_path)) {
            return;
        }

        $script_url = PRORANK_PLUGIN_URL . 'build/meta-box.js';
        $asset_file = PRORANK_PLUGIN_DIR . 'build/meta-box.asset.php';
        $asset_data = file_exists($asset_file) ? require $asset_file : [];
        $dependencies = $asset_data['dependencies'] ?? ['wp-element', 'wp-components', 'wp-i18n', 'wp-data', 'wp-api-fetch', 'wp-dom-ready', 'lodash'];
        $version = \ProRank\SEO\Admin\MetaBox::resolve_meta_box_script_version();

        wp_enqueue_script('prorank-seo-meta-box', $script_url, $dependencies, $version, true);
        wp_enqueue_style('prorank-seo-meta-box', \ProRank\SEO\Admin\MetaBox::resolve_meta_box_css(), [], $version);

        [$license_tier, $is_premium_active] = $this->resolve_license_context();

        wp_localize_script(
            'prorank-seo-meta-box',
            'prorankMetaboxData',
            [
                'licenseTier'     => $license_tier,
                'isPremiumActive' => $is_premium_active,
                'postId'          => $post_id,
                'postType'        => $post_type,
                'nonce'           => wp_create_nonce('prorank_seo_metabox'),
                'apiUrl'          => rest_url('prorank-seo/v1'),
            ]
        );

        $inline = 'window.prorankSettings = window.prorankSettings || {};';
        $inline .= 'window.prorankSettings.adminUrl = ' . wp_json_encode(admin_url()) . ';';
        $inline .= 'window.prorankSettings.upgradeUrl = ' . wp_json_encode('https://prorank.io/pricing') . ';';
        $inline .= 'window.prorankSettings.isPremiumActive = ' . ($is_premium_active ? 'true' : 'false') . ';';
        $inline .= 'window.prorankSettings.license = window.prorankSettings.license || {};';
        $inline .= 'window.prorankSettings.license.tier = ' . wp_json_encode($license_tier) . ';';
        wp_add_inline_script('prorank-seo-meta-box', $inline, 'before');

        wp_set_script_translations('prorank-seo-meta-box', 'prorank-seo', PRORANK_PLUGIN_DIR . 'languages');
    }

    public function render_import_map(): void {
        if (!$this->is_builder_editor()) {
            return;
        }

        $base_url = PRORANK_PLUGIN_URL . 'build/shims/';

        $imports = [
            '@wordpress/dom-ready'          => $base_url . 'wp-dom-ready.js',
            '@wordpress/element'            => $base_url . 'wp-element.js',
            '@wordpress/components'         => $base_url . 'wp-components.js',
            '@wordpress/i18n'               => $base_url . 'wp-i18n.js',
            '@wordpress/api-fetch'          => $base_url . 'wp-api-fetch.js',
            '@wordpress/data'               => $base_url . 'wp-data.js',
            '@wordpress/hooks'              => $base_url . 'wp-hooks.js',
            '@wordpress/icons'              => $base_url . 'wp-icons.js',
            '@wordpress/compose'            => $base_url . 'wp-compose.js',
            '@wordpress/date'               => $base_url . 'wp-date.js',
            '@wordpress/block-editor'       => $base_url . 'wp-block-editor.js',
            '@wordpress/url'                => $base_url . 'wp-url.js',
            '@wordpress/plugins'            => $base_url . 'wp-data.js',
            '@wordpress/editor'             => $base_url . 'wp-data.js',
            '@wordpress/blocks'             => $base_url . 'wp-data.js',
            '@wordpress/edit-post'          => $base_url . 'wp-data.js',
            '@wordpress/rich-text'          => $base_url . 'wp-data.js',
            '@wordpress/server-side-render' => $base_url . 'wp-data.js',
            '@wordpress/notices'            => $base_url . 'wp-data.js',
            '@wordpress/primitives'         => $base_url . 'wp-data.js',
            'react'                         => $base_url . 'react.js',
            'react-dom'                     => $base_url . 'react-dom.js',
            'react/jsx-runtime'             => $base_url . 'jsx-runtime.js',
        ];

        echo '<script type="importmap">' . "\n";
        echo wp_json_encode(['imports' => $imports], JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES) . "\n";
        echo '</script>' . "\n";
    }

    public function filter_script_tag(string $tag, string $handle): string {
        if ($handle !== 'prorank-seo-meta-box') {
            return $tag;
        }

        if (!$this->is_builder_editor()) {
            return $tag;
        }

        if (strpos($tag, 'type="module"') === false && strpos($tag, "type='module'") === false) {
            $tag = str_replace(' src=', ' type="module" src=', $tag);
        }

        return $tag;
    }

    public function render_builder_panel(): void {
        if (!$this->is_builder_editor()) {
            return;
        }

        $post_id = get_the_ID();
        if (!$post_id || $post_id <= 0) {
            return;
        }

        ?>
        <style id="prorank-bb-seo-panel-style">
            #prorank-bb-seo-app {
                position: fixed;
                right: 18px;
                bottom: 18px;
                z-index: 100000;
                display: flex;
                flex-direction: column;
                align-items: flex-end;
                gap: 8px;
            }
            #prorank-bb-seo-toggle {
                background: #2563eb;
                color: #fff;
                border: 0;
                border-radius: 999px;
                padding: 8px 14px;
                font-size: 12px;
                font-weight: 600;
                cursor: pointer;
                box-shadow: 0 8px 24px rgba(0,0,0,.18);
                display: inline-flex;
                align-items: center;
                justify-content: center;
                width: 40px;
                height: 40px;
                min-width: 40px;
            }
            #prorank-bb-seo-toggle .prorank-bb-icon {
                width: 22px;
                height: 22px;
                display: block;
                border-radius: 4px;
            }
            #prorank-bb-seo-toggle .prorank-bb-fallback {
                display: none;
                font-size: 12px;
                font-weight: 700;
                line-height: 1;
            }
            #prorank-bb-seo-toggle.icon-fallback .prorank-bb-icon { display: none; }
            #prorank-bb-seo-toggle.icon-fallback .prorank-bb-fallback { display: block; }
            #prorank-bb-seo-panel {
                position: fixed;
                right: 14px;
                bottom: 70px;
                width: min(430px, calc(100vw - 32px));
                max-height: calc(100vh - 90px);
                overflow: auto;
                background: #fff;
                border: 1px solid #dcdcde;
                border-radius: 10px;
                box-shadow: 0 12px 38px rgba(0,0,0,.22);
                display: none;
            }
            #prorank-bb-seo-panel.is-open { display: block; }
            #prorank-bb-seo-head {
                display: flex;
                align-items: center;
                justify-content: space-between;
                padding: 10px 12px;
                border-bottom: 1px solid #dcdcde;
                font-weight: 600;
                font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
                font-size: 13px;
            }
            #prorank-bb-seo-close {
                background: transparent;
                border: 0;
                color: #50575e;
                cursor: pointer;
                font-size: 18px;
                line-height: 1;
                padding: 0 4px;
            }
            #prorank-bb-seo-body { padding: 10px; }
        </style>
        <div id="prorank-bb-seo-app">
            <div id="prorank-bb-seo-panel" aria-live="polite">
                <div id="prorank-bb-seo-head">
                    <span><?php esc_html_e('ProRank SEO', 'prorank-seo'); ?></span>
                    <button type="button" id="prorank-bb-seo-close" aria-label="<?php esc_attr_e('Close', 'prorank-seo'); ?>">&times;</button>
                </div>
                <div id="prorank-bb-seo-body">
                    <div id="prorank-seo-metabox-root"></div>
                </div>
            </div>
            <button type="button" id="prorank-bb-seo-toggle" aria-label="<?php esc_attr_e('Open ProRank SEO', 'prorank-seo'); ?>" title="<?php esc_attr_e('ProRank SEO', 'prorank-seo'); ?>">
                <img class="prorank-bb-icon" src="<?php echo esc_url(PRORANK_PLUGIN_URL . 'assets/images/favicon.png'); ?>" alt="" aria-hidden="true" />
                <span class="prorank-bb-fallback">PR</span>
            </button>
        </div>
        <script id="prorank-bb-seo-panel-script">
            (function () {
                var panel = document.getElementById('prorank-bb-seo-panel');
                var toggle = document.getElementById('prorank-bb-seo-toggle');
                var close = document.getElementById('prorank-bb-seo-close');
                var icon = toggle ? toggle.querySelector('.prorank-bb-icon') : null;
                if (!panel || !toggle || !close) return;
                if (icon) {
                    icon.addEventListener('error', function () { toggle.classList.add('icon-fallback'); });
                    if (icon.complete && (!icon.naturalWidth || icon.naturalWidth <= 0)) toggle.classList.add('icon-fallback');
                } else { toggle.classList.add('icon-fallback'); }
                toggle.addEventListener('click', function () {
                    var open = !panel.classList.contains('is-open');
                    panel.classList.toggle('is-open', open);
                    toggle.setAttribute('aria-expanded', open ? 'true' : 'false');
                });
                close.addEventListener('click', function () {
                    panel.classList.remove('is-open');
                    toggle.setAttribute('aria-expanded', 'false');
                });
            })();
        </script>
        <?php
    }

    private function is_meta_box_enabled(string $post_type): bool {
        $settings = get_option('prorank_seo_titles_meta', []);
        if (!is_array($settings) || empty($settings)) {
            $settings = get_option('prorank_titles_meta_settings', []);
        }
        if (!is_array($settings)) {
            return true;
        }
        $post_type_settings = $settings['post_type_' . $post_type] ?? [];
        if (!is_array($post_type_settings)) {
            return true;
        }
        return $post_type_settings['show_meta_box'] ?? true;
    }

    private function resolve_license_context(): array {
        return ['free', false];
    }
}
