<?php
/**
 * Bootstrap for the LolaCore for Bricks addon.
 *
 * @package LolaCoreForBricks
 */

declare(strict_types=1);

namespace LolaCoreForBricks;

/**
 * Dependency gate and service loader (4 doors + catalog + affinity + knowledge doors).
 */
class Bootstrap
{
    private const MIN_WP_VERSION = '7.0';

    /**
     * Minimum LolaCore version this addon release is built against.
     * Must match the "Requires LolaCore" plugin header.
     */
    public const MIN_LOLACORE_VERSION = '2.7.0';

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

        $this->loadServices();
    }

    /**
     * @return bool True when LolaCore and Bricks floor are available.
     */
    private function checkDependencies(): bool
    {
        $missing = [];

        if (!defined('LOLACORE_VERSION')) {
            $missing[] = __('LolaCore', 'lolacore-for-bricks');
        }

        if (!$this->meetsWordPressFloor()) {
            $missing[] = sprintf(
                /* translators: %s: minimum WordPress version. */
                __('WordPress %s or later', 'lolacore-for-bricks'),
                self::MIN_WP_VERSION
            );
        }

        if (!BricksEnv::isAvailable()) {
            $missing[] = __('Bricks theme', 'lolacore-for-bricks');
        } elseif (!BricksEnv::meetsFloor()) {
            $missing[] = sprintf(
                /* translators: %s: minimum Bricks version. */
                __('Bricks %s or newer', 'lolacore-for-bricks'),
                BricksEnv::FLOOR_VERSION
            );
        }

        if ($missing !== []) {
            $this->registerMissingNotice($missing);
            return false;
        }

        if (version_compare((string) LOLACORE_VERSION, self::MIN_LOLACORE_VERSION, '<')) {
            $this->registerOutdatedCoreNotice();
            return false;
        }

        return true;
    }

    private function registerOutdatedCoreNotice(): void
    {
        add_action('admin_notices', static function (): void {
            if (!current_user_can('activate_plugins')) {
                return;
            }

            printf(
                '<div class="notice notice-error"><p>%s</p></div>',
                sprintf(
                    /* translators: %s: minimum required LolaCore version. */
                    esc_html__(
                        'LolaCore for Bricks needs LolaCore %s or newer. Update LolaCore and the addon will pick up right where it left off.',
                        'lolacore-for-bricks'
                    ),
                    esc_html(self::MIN_LOLACORE_VERSION)
                )
            );
        });
    }

    private function meetsWordPressFloor(): bool
    {
        global $wp_version;

        return isset($wp_version)
            && version_compare((string) $wp_version, self::MIN_WP_VERSION, '>=');
    }

    /**
     * @param string[] $missing Requirements that are not satisfied.
     */
    private function registerMissingNotice(array $missing): void
    {
        add_action('admin_notices', static function () use ($missing): void {
            if (!current_user_can('activate_plugins')) {
                return;
            }

            $list = implode(', ', $missing);
            printf(
                '<div class="notice notice-error"><p>%s</p></div>',
                sprintf(
                    /* translators: %s: comma-separated list of missing requirements. */
                    esc_html__(
                        'LolaCore for Bricks is waiting on: %s. Install or update what is missing, then reload this page.',
                        'lolacore-for-bricks'
                    ),
                    '<strong>' . esc_html($list) . '</strong>'
                )
            );
        });
    }

    private function loadServices(): void
    {
        (new AbilitiesProvider())->register();
        (new ActionHandler())->register();
        (new WPAbilitiesRegistrar())->register();
        (new Index\IndexInvalidator())->register();

        add_filter('lolacore_addon_domains', [$this, 'registerAddonDomain']);
        add_filter('lolacore_addon_catalog', [$this, 'registerCatalogEntry']);
        add_filter('lolacore_category_affinity', [$this, 'registerCategoryAffinity']);
        add_filter('lolacore_register_skills', [$this, 'registerSkillDirectory']);
        add_filter('lolacore_register_playbooks', [$this, 'registerPlaybookDirectory']);
        add_filter('lolacore_register_memory_bootstraps', [$this, 'registerMemoryBootstrap']);
        add_filter('lolacore_holistic_monitoring_patterns', [$this, 'registerHolisticMonitoringPatterns']);
    }

    /**
     * Door 4 — free bridge domain registration.
     *
     * @param array<string, array<string, mixed>> $domains
     * @return array<string, array<string, mixed>>
     */
    public function registerAddonDomain(array $domains): array
    {
        $domains['bricks'] = [
            'label'             => 'Bricks',
            'icon'              => 'dashicons-art',
            'is_premium'        => false,
            'is_free'           => true,
            'license_active'    => true,
            'category'          => AbilitiesProvider::CATEGORY,
            'version'           => \LOLACORE_FOR_BRICKS_VERSION,
            'ability_namespace' => 'lolacore-bricks',
        ];

        return $domains;
    }

    /**
     * @param array<string, array<string, mixed>> $catalog
     * @return array<string, array<string, mixed>>
     */
    public function registerCatalogEntry(array $catalog): array
    {
        $catalog['bricks'] = [
            'addon_key'          => 'bricks',
            'domain_slug'        => 'bricks',
            'name'               => __('LolaCore for Bricks', 'lolacore-for-bricks'),
            'tagline'            => __(
                'Lola runs your Bricks design system, pages, templates, and components from chat. She uses the classes you already have and previews every change.',
                'lolacore-for-bricks'
            ),
            'ability_count'      => BricksEnv::abilityCount(),
            'is_free'            => true,
            'wporg_slug'         => 'lolacore-for-bricks',
            'marketing_url'      => 'https://lolacore.com/lolacore-for-bricks/',
            'addon_plugin_files' => ['lolacore-for-bricks/lolacore-for-bricks.php'],
            'base_plugin_files'  => [],
            'catalog_order'      => 11,
        ];

        return $catalog;
    }

    /**
     * Door 6 — bidirectional affinity with ACF and WooCommerce.
     *
     * @param array<string, string[]> $map
     * @return array<string, string[]>
     */
    public function registerCategoryAffinity(array $map): array
    {
        $siblings = ['acf', 'woocommerce'];

        $map['bricks'] = array_values(array_unique(array_merge($map['bricks'] ?? [], $siblings)));

        foreach ($siblings as $sibling) {
            $existing = $map[$sibling] ?? [];
            if (!in_array('bricks', $existing, true)) {
                $existing[] = 'bricks';
            }
            $map[$sibling] = $existing;
        }

        return $map;
    }

    /**
     * @param array<string, string> $paths
     * @return array<string, string>
     */
    public function registerSkillDirectory(array $paths): array
    {
        $paths['lolacore-for-bricks'] = \LOLACORE_FOR_BRICKS_PATH . 'skills/';

        return $paths;
    }

    /**
     * @param array<string, string> $paths
     * @return array<string, string>
     */
    public function registerPlaybookDirectory(array $paths): array
    {
        $paths['lolacore-for-bricks'] = \LOLACORE_FOR_BRICKS_PATH . 'playbooks/';

        return $paths;
    }

    /**
     * Door 7 — register Bricks design baseline facts for Lola memory.
     *
     * @param array<int, object> $bootstraps
     * @return array<int, object>
     */
    public function registerMemoryBootstrap(array $bootstraps): array
    {
        if (!interface_exists(\LolaCore\Addon\Contract\MemoryBootstrapInterface::class)) {
            return $bootstraps;
        }

        $bootstraps[] = new MemoryBootstrap();

        return $bootstraps;
    }

    /**
     * Holistic monitoring patterns for cross-layer Bricks design questions.
     *
     * @param string[] $patterns
     * @return string[]
     */
    public function registerHolisticMonitoringPatterns(array $patterns): array
    {
        $patterns[] = '/\b(design system|global class|theme style|design token|sistema de diseño|clase global)\b/iu';
        $patterns[] = '/\b(rebrand|brand palette|color palette|paleta de color|convención de nombres)\b/iu';
        $patterns[] = '/\b(bricks template|bricks component|plantilla bricks|componente bricks)\b/iu';
        $patterns[] = '/\b(unused class|duplicate class|clase duplicada|clase sin usar)\b/iu';
        $patterns[] = '/\b(page structure|element tree|estructura de (la )?p[aá]gina|árbol de elementos)\b/iu';
        $patterns[] = '/\b(clone structure|clonar secci[oó]n|bulk update|mismas p[aá]ginas)\b/iu';
        $patterns[] = '/\b(shop template|plantilla de (producto|tienda)|add to cart|ficha de producto)\b/iu';
        $patterns[] = '/\b(dynamic data|datos din[aá]micos|element conditions|condiciones de elemento)\b/iu';

        return $patterns;
    }
}
