<?php

declare(strict_types=1);

namespace Numinix\SeekmodoWordPress\Elementor;

use Numinix\SeekmodoWordPress\Elementor\Widgets\AskWidget;
use Numinix\SeekmodoWordPress\Elementor\Widgets\ChatWidget;
use Numinix\SeekmodoWordPress\Elementor\Widgets\QuizWidget;
use Numinix\SeekmodoWordPress\Elementor\Widgets\RecommendWidget;
use Numinix\SeekmodoWordPress\Elementor\Widgets\SearchWidget;

/**
 * Sprint 11 PR 2 — Elementor widget loader for the four Seekmodo
 * web components: search, recommend, chat, quiz.
 *
 * Gating model:
 *
 *   1. {@see register()} runs on `plugins_loaded` priority 20 (one
 *      tick after Elementor's own `plugins_loaded` priority 10
 *      bootstrap). It checks `did_action('elementor/loaded')` and
 *      bails silently if Elementor isn't active. The connector
 *      stays fully functional without Elementor — the four widgets
 *      simply don't appear in the Elementor panel.
 *
 *   2. The four widget classes themselves guard their `class`
 *      definitions on `class_exists(\Elementor\Widget_Base::class)`
 *      so a site that somehow autoloads a widget file before
 *      Elementor (unlikely with our hook order, but defense in
 *      depth) doesn't fatal.
 *
 *   3. The widget category is registered via
 *      `elementor/elements/categories_registered`. The four
 *      widgets are registered via `elementor/widgets/register`
 *      (Elementor 3.5+) which fires after Elementor's own widget
 *      registry is ready.
 *
 * Mirrors the {@see \Numinix\SeekmodoWordPress\Blocks\Registry}
 * shape so an operator who reads one knows how the other works.
 */
final class Loader
{
    /**
     * Wire registration into WP. Called from
     * {@see \Numinix\SeekmodoWordPress\Bootstrap::boot()}.
     */
    public static function register(): void
    {
        if (function_exists('add_action')) {
            add_action('plugins_loaded', [self::class, 'maybeRegisterElementorIntegration'], 20);
        }
    }

    /**
     * Decision gate. Public so unit tests can exercise it directly
     * without booting WordPress.
     */
    public static function maybeRegisterElementorIntegration(): bool
    {
        if (!self::isElementorActive()) {
            return false;
        }

        if (function_exists('add_action')) {
            add_action('elementor/elements/categories_registered', [Category::class, 'register']);
            add_action('elementor/widgets/register', [self::class, 'registerWidgets']);
        }

        return true;
    }

    /**
     * Check whether Elementor has fully loaded. Public for tests.
     */
    public static function isElementorActive(): bool
    {
        if (!function_exists('did_action')) {
            return false;
        }

        return did_action('elementor/loaded') > 0;
    }

    /**
     * Register the four widgets against Elementor's widget registry.
     * Called from the `elementor/widgets/register` action; receives
     * the widgets manager as its single argument.
     *
     * @param object $widgetsManager Elementor's `Widgets_Manager`.
     */
    public static function registerWidgets($widgetsManager): void
    {
        if (!is_object($widgetsManager) || !method_exists($widgetsManager, 'register')) {
            return;
        }

        $widgets = self::widgetClasses();
        foreach ($widgets as $cls) {
            if (class_exists($cls)) {
                $widgetsManager->register(new $cls());
            }
        }
    }

    /**
     * Test helper — returns the FQCNs of the four widgets in the
     * canonical registration order.
     *
     * @return list<class-string>
     */
    public static function widgetClasses(): array
    {
        return [
            SearchWidget::class,
            RecommendWidget::class,
            ChatWidget::class,
            AskWidget::class,
            QuizWidget::class,
        ];
    }
}
