<?php
declare(strict_types=1);


/**
 * Elementor Integration for ProRank SEO
 *
 * Provides native Elementor widgets for SEO features
 *
 * @package ProRank\Integrations\Elementor
 */

namespace ProRank\SEO\Integrations\Elementor;

use ProRank\SEO\Plugin;

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




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

/**
 * Main Elementor integration class
 */
class ElementorIntegration {

    /**
     * Instance
     */
    private static ?self $instance = null;

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

    /**
     * Constructor
     */
    private function __construct() {
        // Only load if Elementor is active
        if (!$this->is_elementor_active()) {
            return;
        }

        $this->init_hooks();
    }

    /**
     * Check if Elementor is active
     */
    private function is_elementor_active(): bool {
        return defined('ELEMENTOR_VERSION');
    }

    /**
     * Initialize hooks
     */
    private function init_hooks(): void {
        // Register widget category
        add_action('elementor/elements/categories_registered', [$this, 'register_widget_category']);

        // Register widgets
        add_action('elementor/widgets/register', [$this, 'register_widgets']);

        // Enqueue editor styles
        add_action('elementor/editor/after_enqueue_styles', [$this, 'enqueue_editor_styles']);
        add_action('elementor/editor/before_enqueue_scripts', [$this, 'enqueue_editor_scripts']);
        add_action('elementor/editor/footer', [$this, 'render_editor_panel_mount']);

        // Enqueue frontend styles
        add_action('elementor/frontend/after_enqueue_styles', [$this, 'enqueue_frontend_styles']);
    }

    /**
     * Register ProRank SEO widget category
     */
    public function register_widget_category(\Elementor\Elements_Manager $elements_manager): void {
        $elements_manager->add_category(
            'prorank-seo',
            [
                'title' => __('ProRank SEO', 'prorank-seo'),
                'icon'  => 'eicon-search',
            ]
        );
    }

    /**
     * Register widgets
     */
    public function register_widgets(\Elementor\Widgets_Manager $widgets_manager): void {
        // Load widget classes
        require_once __DIR__ . '/Widgets/BreadcrumbsWidget.php';
        require_once __DIR__ . '/Widgets/FAQWidget.php';

        // Register widgets
        $widgets_manager->register(new Widgets\BreadcrumbsWidget());
        $widgets_manager->register(new Widgets\FAQWidget());
    }

    /**
     * Enqueue editor styles
     */
    public function enqueue_editor_styles(): void {
        wp_enqueue_style(
            'prorank-elementor-editor',
            PRORANK_PLUGIN_URL . 'includes/Integrations/Elementor/assets/css/elementor-widgets.css',
            [],
            PRORANK_VERSION
        );
    }

    /**
     * Enqueue ProRank SEO meta panel assets inside Elementor editor.
     *
     * @return void
     */
    public function enqueue_editor_scripts(): void {
        if (!$this->is_elementor_post_editor()) {
            return;
        }

        $post_id = isset($_GET['post']) ? absint($_GET['post']) : 0;
        if ($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');
    }

    /**
     * Render floating mount for ProRank SEO controls in Elementor editor.
     *
     * @return void
     */
    public function render_editor_panel_mount(): void {
        if (!$this->is_elementor_post_editor()) {
            return;
        }

        ?>
        <style id="prorank-elementor-seo-panel-style">
            #prorank-elementor-seo-app {
                position: fixed;
                right: 18px;
                bottom: 18px;
                z-index: 100000;
                display: flex;
                flex-direction: column;
                align-items: flex-end;
                gap: 8px;
            }
            #prorank-elementor-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;
            }
            #prorank-elementor-seo-toggle.prorank-topbar-button {
                width: 34px;
                height: 34px;
                min-width: 34px;
                padding: 0;
                border-radius: 8px;
                background: rgba(248, 250, 252, 0.98) !important;
                background-image: none !important;
                border: 1px solid rgba(203, 213, 225, 0.95) !important;
                color: #0f172a;
                box-shadow: none;
                font-size: 11px;
                line-height: 1;
                letter-spacing: .2px;
            }
            #prorank-elementor-seo-toggle.prorank-topbar-button:hover,
            #prorank-elementor-seo-toggle.prorank-topbar-button:focus-visible {
                background: rgba(248, 250, 252, 1) !important;
                border-color: rgba(148, 163, 184, 0.9) !important;
                outline: none;
            }
            #prorank-elementor-seo-toggle.prorank-topbar-button:active,
            #prorank-elementor-seo-toggle.prorank-topbar-button[aria-expanded="true"] {
                background: linear-gradient(135deg, #eff6ff 0%, #dbeafe 100%) !important;
                background-image: linear-gradient(135deg, #eff6ff 0%, #dbeafe 100%) !important;
                border-color: #93c5fd !important;
                box-shadow: inset 0 0 0 1px #bfdbfe, 0 0 0 2px rgba(59, 130, 246, 0.18);
            }
            #prorank-elementor-seo-toggle .prorank-elementor-icon {
                width: 20px;
                height: 20px;
                display: block;
                opacity: 1;
                filter: none !important;
                background: rgba(255, 255, 255, 1);
                border-radius: 4px;
                box-shadow: 0 0 0 1px rgba(148, 163, 184, 0.35);
            }
            #prorank-elementor-seo-toggle.prorank-topbar-button[aria-expanded="true"] .prorank-elementor-icon {
                filter: none !important;
                box-shadow: inset 0 0 0 1px rgba(37, 99, 235, 0.35);
            }
            #prorank-elementor-seo-toggle .prorank-elementor-fallback {
                display: none;
                font-size: 11px;
                font-weight: 700;
                line-height: 1;
            }
            #prorank-elementor-seo-toggle.icon-fallback .prorank-elementor-icon {
                display: none;
            }
            #prorank-elementor-seo-toggle.icon-fallback .prorank-elementor-fallback {
                display: block;
            }
            #prorank-elementor-seo-panel {
                position: fixed;
                right: 14px;
                top: 58px;
                width: min(430px, calc(100vw - 32px));
                max-height: calc(100vh - 70px);
                overflow: auto;
                background: #fff;
                border: 1px solid #dcdcde;
                border-radius: 10px;
                box-shadow: 0 12px 38px rgba(0,0,0,.22);
                display: none;
            }
            #prorank-elementor-seo-panel.is-open {
                display: block;
            }
            #prorank-elementor-seo-head {
                display: flex;
                align-items: center;
                justify-content: space-between;
                padding: 10px 12px;
                border-bottom: 1px solid #dcdcde;
                font-weight: 600;
            }
            #prorank-elementor-seo-close {
                background: transparent;
                border: 0;
                color: #50575e;
                cursor: pointer;
                font-size: 18px;
                line-height: 1;
                padding: 0 4px;
            }
            #prorank-elementor-seo-body {
                padding: 10px;
            }

            /* Elementor UI skin can force low-contrast controls. Keep ProRank panel readable. */
            #prorank-elementor-seo-body .prorank-metabox-shell,
            #prorank-elementor-seo-body .prorank-metabox-shell * {
                color: #1f2937;
            }
            #prorank-elementor-seo-body .components-base-control__label,
            #prorank-elementor-seo-body .components-checkbox-control__label {
                color: #1f2937 !important;
                opacity: 1 !important;
            }
            #prorank-elementor-seo-body .components-base-control__help,
            #prorank-elementor-seo-body .description {
                color: #475569 !important;
                opacity: 1 !important;
            }
            #prorank-elementor-seo-body .components-input-control__input,
            #prorank-elementor-seo-body .components-text-control__input,
            #prorank-elementor-seo-body .components-textarea-control__input,
            #prorank-elementor-seo-body input[type="text"],
            #prorank-elementor-seo-body input[type="url"],
            #prorank-elementor-seo-body textarea {
                background: #ffffff !important;
                color: #0f172a !important;
                -webkit-text-fill-color: #0f172a !important;
                border-color: #cbd5e1 !important;
            }
            #prorank-elementor-seo-body .components-button.is-primary,
            #prorank-elementor-seo-body .components-button.is-primary *,
            #prorank-elementor-seo-body .components-button.is-primary[disabled],
            #prorank-elementor-seo-body .components-button.is-primary[disabled] * {
                color: #ffffff !important;
                -webkit-text-fill-color: #ffffff !important;
            }
        </style>
        <div id="prorank-elementor-seo-app">
            <button type="button" id="prorank-elementor-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-elementor-icon" src="<?php echo esc_url(PRORANK_PLUGIN_URL . 'assets/images/favicon.png'); ?>" alt="" aria-hidden="true" />
                <span class="prorank-elementor-fallback">PR</span>
            </button>
            <div id="prorank-elementor-seo-panel" aria-live="polite">
                <div id="prorank-elementor-seo-head">
                    <span><?php esc_html_e('ProRank SEO', 'prorank-seo'); ?></span>
                    <button type="button" id="prorank-elementor-seo-close" aria-label="<?php esc_attr_e('Close', 'prorank-seo'); ?>">&times;</button>
                </div>
                <div id="prorank-elementor-seo-body">
                    <div id="prorank-seo-metabox-root"></div>
                </div>
            </div>
        </div>
        <script id="prorank-elementor-seo-panel-script">
            (function () {
                if (document.getElementById('prorank-elementor-seo-app') === null) {
                    return;
                }

                var app = document.getElementById('prorank-elementor-seo-app');
                var panel = document.getElementById('prorank-elementor-seo-panel');
                var toggle = document.getElementById('prorank-elementor-seo-toggle');
                var close = document.getElementById('prorank-elementor-seo-close');
                var icon = toggle ? toggle.querySelector('.prorank-elementor-icon') : null;

                if (!app || !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');
                }

                var findTopBarSlot = function () {
                    var preview = document.querySelector('button[aria-label=\"Preview Changes\"]');
                    if (preview && preview.closest('div.MuiStack-root')) {
                        return preview.closest('div.MuiStack-root');
                    }

                    var finder = document.querySelector('button[aria-label=\"Finder\"]');
                    if (finder && finder.closest('div.MuiStack-root')) {
                        return finder.closest('div.MuiStack-root');
                    }

                    var toolbar = document.querySelector('div.MuiToolbar-root');
                    if (!toolbar) {
                        return null;
                    }

                    var stacks = toolbar.querySelectorAll('div.MuiStack-root');
                    if (stacks.length) {
                        return stacks[stacks.length - 1];
                    }

                    return toolbar;
                };

                var mountToggleInTopBar = function () {
                    var slot = findTopBarSlot();
                    if (slot && !slot.contains(toggle)) {
                        slot.appendChild(toggle);
                        toggle.classList.add('prorank-topbar-button');
                        return;
                    }

                    if (!slot && !app.contains(toggle)) {
                        app.insertBefore(toggle, panel);
                        toggle.classList.remove('prorank-topbar-button');
                    }
                };

                var setOpen = function (open) {
                    panel.classList.toggle('is-open', open);
                    toggle.setAttribute('aria-expanded', open ? 'true' : 'false');
                };

                toggle.addEventListener('click', function () {
                    setOpen(!panel.classList.contains('is-open'));
                });

                close.addEventListener('click', function () {
                    setOpen(false);
                });

                mountToggleInTopBar();
                setTimeout(mountToggleInTopBar, 500);
                setTimeout(mountToggleInTopBar, 1500);

                var mountQueued = false;
                var scheduleMount = function () {
                    if (mountQueued) {
                        return;
                    }
                    mountQueued = true;
                    window.requestAnimationFrame(function () {
                        mountQueued = false;
                        mountToggleInTopBar();
                    });
                };

                var observer = new MutationObserver(scheduleMount);
                observer.observe(document.body, { childList: true, subtree: true });
            })();
        </script>
        <?php
    }

    /**
     * Enqueue frontend styles
     */
    public function enqueue_frontend_styles(): void {
        wp_enqueue_style(
            'prorank-elementor-widgets',
            PRORANK_PLUGIN_URL . 'includes/Integrations/Elementor/assets/css/elementor-widgets.css',
            [],
            PRORANK_VERSION
        );
    }

    /**
     * Whether this request is Elementor post editor.
     *
     * @return bool
     */
    private function is_elementor_post_editor(): bool {
        $action = isset($_GET['action']) ? sanitize_key(wp_unslash((string) $_GET['action'])) : '';
        return $action === 'elementor';
    }

    /**
     * Check if the SEO meta box is enabled for a given post type.
     *
     * @param string $post_type Post type slug.
     * @return bool
     */
    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;
    }

    /**
     * Resolve license context for editor UI gating.
     *
     * @return array{0:string,1:bool}
     */
    private function resolve_license_context(): array {
        return ['free', false];
    }
}
