<?php
declare(strict_types=1);

namespace Help4BuilderSuite;

use Help4BuilderSuite\Admin\SettingsPage;
use Help4BuilderSuite\Contracts\ModuleContract;
use Help4BuilderSuite\Modules\AddonPack\Module as AddonPackModule;
use Help4BuilderSuite\Modules\Builder\Module as BuilderModule;
use Help4BuilderSuite\Modules\Calendar\Module as CalendarModule;
use Help4BuilderSuite\Modules\StaffDirectory\Module as StaffDirectoryModule;
use Help4BuilderSuite\Modules\Commerce\Module as CommerceModule;
use Help4BuilderSuite\Modules\Cutover\Module as CutoverModule;
use Help4BuilderSuite\Modules\Dependency\Module as DependencyModule;
use Help4BuilderSuite\Modules\Demos\Module as DemosModule;
use Help4BuilderSuite\Modules\EmailMarketing\Module as EmailMarketingModule;
use Help4BuilderSuite\Modules\Feedback\Module as FeedbackModule;
use Help4BuilderSuite\Modules\Fields\Module as FieldsModule;
use Help4BuilderSuite\Modules\Forms\Module as FormsModule;
use Help4BuilderSuite\Modules\ImageOptimization\Module as ImageOptimizationModule;
use Help4BuilderSuite\Modules\Insights\Module as InsightsModule;
use Help4BuilderSuite\Modules\Industry\Module as IndustryModule;
use Help4BuilderSuite\Modules\Licensing\Module as LicensingModule;
use Help4BuilderSuite\Modules\Lms\Module as LmsModule;
use Help4BuilderSuite\Modules\MegaMenu\Module as MegaMenuModule;
use Help4BuilderSuite\Modules\Multisite\Module as MultisiteModule;
use Help4BuilderSuite\Modules\Performance\Module as PerformanceModule;
use Help4BuilderSuite\Modules\ProductInsights\Module as ProductInsightsModule;
use Help4BuilderSuite\Modules\Redirection\Module as RedirectionModule;
use Help4BuilderSuite\Modules\ReleaseBridge\Module as ReleaseBridgeModule;
use Help4BuilderSuite\Modules\Search\Module as SearchModule;
use Help4BuilderSuite\Modules\Security\Module as SecurityModule;
use Help4BuilderSuite\Modules\SEO\Module as SeoModule;
use Help4BuilderSuite\Modules\Slider\Module as SliderModule;
use Help4BuilderSuite\Modules\TemplateLibrary\Module as TemplateLibraryModule;
use Help4BuilderSuite\Support\BusinessProfileDefaults;
use Help4BuilderSuite\Support\FeatureFlags;
use Help4BuilderSuite\Support\ImageInputGuidance;

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

final class Plugin
{
    /**
     * @var ModuleContract[]
     */
    private array $modules = [];

    public function boot(): void
    {
        $flags = new FeatureFlags();
        $businessProfiles = new BusinessProfileDefaults();
        $businessProfiles->boot();
        (new SettingsPage($flags))->boot();

        // First-party updates are core infrastructure. Launch profiles and
        // optional feature flags must never strand an installation.
        (new LicensingModule())->boot();

        $this->modules = [
            new TemplateLibraryModule(),
            new SliderModule(),
            new SeoModule(),
            new MultisiteModule(),
            new CommerceModule(),
            new FormsModule(),
            new EmailMarketingModule(),
            new RedirectionModule(),
            new ReleaseBridgeModule(),
            new SearchModule(),
            new FieldsModule(),
            new IndustryModule(),
            new LmsModule(),
            new MegaMenuModule(),
            new CalendarModule(),
            new StaffDirectoryModule(),
            new BuilderModule(),
            new AddonPackModule(),
            new DependencyModule(),
            new SecurityModule(),
            new PerformanceModule(),
            new ImageOptimizationModule(),
            new InsightsModule(),
            new CutoverModule(),
            new FeedbackModule(),
            new ProductInsightsModule(),
            new DemosModule(),
        ];

        foreach ($this->modules as $module) {
            if ($flags->isEnabled($module->key())) {
                $module->boot();
            }
        }

        add_action('admin_init', [$this, 'cleanupPluginUpdateTempDirectories']);
        add_action('wp_enqueue_scripts', [$this, 'enqueueFrontendAssets'], 90);
        add_action('admin_enqueue_scripts', [$this, 'enqueueAdminAssets']);
        add_filter('body_class', [$this, 'frontendBodyClasses'], 5);
    }

    /**
     * @param array<int, string> $classes
     * @return array<int, string>
     */
    public function frontendBodyClasses(array $classes): array
    {
        if (! is_admin() && $this->shouldLoadFrontendAssets()) {
            $classes[] = 'h4bs-builder-active';
        }

        return array_values(array_unique($classes));
    }

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

        wp_enqueue_style(
            'h4bs-frontend',
            H4BS_URL . 'assets/css/frontend.css',
            wp_style_is('dashicons', 'enqueued') ? ['dashicons'] : [],
            H4BS_VERSION
        );

        wp_enqueue_style(
            'h4bs-builder',
            H4BS_URL . 'assets/css/builder.css',
            ['h4bs-frontend'],
            H4BS_VERSION
        );

        wp_enqueue_script(
            'h4bs-builder-frontend',
            H4BS_URL . 'assets/js/builder-frontend.js',
            [],
            H4BS_VERSION,
            true
        );

        if ($this->currentViewHasShortcode('h4_search')) {
            wp_enqueue_script(
                'h4bs-search',
                H4BS_URL . 'assets/js/search.js',
                [],
                H4BS_VERSION,
                true
            );

            wp_localize_script(
                'h4bs-search',
                'h4bsSearchConfig',
                [
                    'endpoint' => esc_url_raw(rest_url('h4bs/v1/search')),
                    'nonce'    => wp_create_nonce('wp_rest'),
                ]
            );
        }

        if ($this->currentViewHasShortcode('h4_products') || $this->currentViewHasShortcode('h4_checkout') || $this->currentViewHasShortcode('h4_customer_account')) {
            wp_enqueue_script(
                'h4bs-commerce',
                H4BS_URL . 'assets/js/commerce.js',
                [],
                H4BS_VERSION,
                true
            );

            wp_localize_script(
                'h4bs-commerce',
                'h4bsCommerceConfig',
                [
                    'checkoutEndpoint' => esc_url_raw(rest_url('h4bs/v1/checkout')),
                    'restNonce' => wp_create_nonce('wp_rest'),
                    'maxCompareItems' => 4,
                    'labels' => [
                        'compare' => __('Compare', 'help4-builder-suite'),
                        'compared' => __('Compared', 'help4-builder-suite'),
                        'remove' => __('Remove', 'help4-builder-suite'),
                        'compareTrayOpened' => __('Compare tray opened.', 'help4-builder-suite'),
                        'compareListUpdated' => __('Compare list updated.', 'help4-builder-suite'),
                        'compareListCleared' => __('Compare list cleared.', 'help4-builder-suite'),
                        'checkoutWorking' => __('Processing checkout...', 'help4-builder-suite'),
                        'checkoutFailed' => __('Checkout could not be completed.', 'help4-builder-suite'),
                        'checkoutQuantityInvalid' => __('Enter a valid quantity.', 'help4-builder-suite'),
                        /* translators: %d: minimum number of choices required. */
                        'fieldSelectionMinimum' => __('Choose at least %d options.', 'help4-builder-suite'),
                        /* translators: %d: maximum number of choices allowed. */
                        'fieldSelectionMaximum' => __('Choose no more than %d options.', 'help4-builder-suite'),
                        'fieldCalculationUnavailable' => __('Calculation unavailable', 'help4-builder-suite'),
                        'fieldCalculationWaiting' => __('Waiting for numeric values', 'help4-builder-suite'),
                        'checkoutPaymentFailed' => __('Payment could not be started. No inventory or promotion was held.', 'help4-builder-suite'),
                        'checkoutAccepted' => __('Checkout accepted for order', 'help4-builder-suite'),
                        'checkoutAcceptedGeneric' => __('Checkout accepted.', 'help4-builder-suite'),
                        'subtotal' => __('Subtotal', 'help4-builder-suite'),
                        'discount' => __('Discount', 'help4-builder-suite'),
                        'shipping' => __('Shipping', 'help4-builder-suite'),
                        'tax' => __('Tax', 'help4-builder-suite'),
                        'total' => __('Total', 'help4-builder-suite'),
                        'order' => __('Order', 'help4-builder-suite'),
                    ],
                ]
            );
        }
    }

    public function enqueueAdminAssets(string $hook): void
    {
        $screen = get_current_screen();
        $postType = $screen instanceof \WP_Screen ? (string) $screen->post_type : '';
        $isHelp4Screen = str_contains($hook, 'h4bs') || str_starts_with($postType, 'h4_');

        wp_register_style(
            'h4bs-admin-workspace',
            H4BS_URL . 'assets/css/admin-workspace.css',
            [],
            H4BS_VERSION
        );

        $loadsPostEditorGuidance = in_array($hook, ['post.php', 'post-new.php'], true);
        if ($isHelp4Screen || $loadsPostEditorGuidance) {
            wp_enqueue_style(
                'h4bs-image-guidance',
                H4BS_URL . 'assets/css/image-guidance.css',
                $isHelp4Screen ? ['h4bs-admin'] : [],
                H4BS_VERSION
            );
            wp_enqueue_script(
                'h4bs-image-guidance',
                H4BS_URL . 'assets/js/image-guidance.js',
                [],
                H4BS_VERSION,
                true
            );
            wp_localize_script(
                'h4bs-image-guidance',
                'h4bsImageGuidanceData',
                ImageInputGuidance::clientConfig()
            );
        }

        if ($isHelp4Screen) {
            wp_enqueue_style(
                'h4bs-admin',
                H4BS_URL . 'assets/css/admin.css',
                [],
                H4BS_VERSION
            );
            wp_enqueue_style('h4bs-admin-workspace');

            if (! str_contains($hook, 'h4bs-builder-studio')) {
                wp_enqueue_script(
                    'h4bs-admin-workspace',
                    H4BS_URL . 'assets/js/admin-workspace.js',
                    [],
                    H4BS_VERSION,
                    true
                );
                wp_localize_script(
                    'h4bs-admin-workspace',
                    'h4bsAdminWorkspaceData',
                    [
                        'adminNavigation' => __('Help4 admin navigation', 'help4-builder-suite'),
                        'quickNavigation' => __('Quick navigation', 'help4-builder-suite'),
                        'workspace' => __('Workspace', 'help4-builder-suite'),
                        'openWorkspace' => __('Open Help4 workspace', 'help4-builder-suite'),
                        'jumpTo' => __('Jump to', 'help4-builder-suite'),
                        'jumpToSection' => __('Jump to page section', 'help4-builder-suite'),
                        'chooseSection' => __('Choose a section', 'help4-builder-suite'),
                        'details' => __('Details', 'help4-builder-suite'),
                        'scrollableTable' => __('Scrollable data table', 'help4-builder-suite'),
                        'filterRows' => __('Filter table rows', 'help4-builder-suite'),
                        'filterPlaceholder' => __('Filter these rows', 'help4-builder-suite'),
                        /* translators: 1: visible rows, 2: total rows. */
                        'rowCount' => __('%1$d of %2$d rows', 'help4-builder-suite'),
                        'simpleMode' => (string) get_user_meta(get_current_user_id(), 'h4bs_show_advanced_tools', true) !== '1',
                    ]
                );
            }
        }
        if ($hook === 'toplevel_page_h4bs-settings') {
            wp_enqueue_style('h4bs-staff-home', H4BS_URL . 'assets/css/staff-home.css', ['h4bs-admin'], H4BS_VERSION);
            wp_enqueue_style('h4bs-staff-home-accessibility', H4BS_URL . 'assets/css/staff-home-accessibility.css', ['h4bs-staff-home'], H4BS_VERSION);
            wp_enqueue_script('h4bs-staff-home', H4BS_URL . 'assets/js/staff-home.js', [], H4BS_VERSION, true);
        } elseif ($isHelp4Screen) {
            wp_enqueue_style('h4bs-staff-home-accessibility', H4BS_URL . 'assets/css/staff-home-accessibility.css', ['h4bs-admin'], H4BS_VERSION);
        }
        if (str_contains($hook, 'h4bs-commerce-products')) {
            wp_enqueue_script(
                'h4bs-commerce-admin',
                H4BS_URL . 'assets/js/commerce-admin.js',
                [],
                H4BS_VERSION,
                true
            );
        }
    }

    private function shouldLoadFrontendAssets(): bool
    {
        if (! is_singular()) {
            return false;
        }

        $postId = get_queried_object_id();
        if (! $postId) {
            return false;
        }

        $builderEnabled = (string) get_post_meta($postId, '_h4_builder_enabled', true) === '1'
            && (string) get_post_meta($postId, '_h4_builder_mode', true) === 'help4';
        if ($builderEnabled) {
            return true;
        }

        $content = (string) get_post_field('post_content', $postId);
        if ($content === '') {
            return false;
        }

        $shortcodes = [
            'h4_search',
            'h4_products',
            'h4_checkout',
            'h4_customer_account',
            'h4_product_reviews',
            'h4_template_library',
            'h4_slider',
            'h4_website_snapshot',
            'h4_siteshot',
            'h4_industry_templates',
            'h4_builder',
            'h4_form',
            'h4_contact_form',
            'h4_newsletter_form',
            'h4_quote_request',
            'h4_callback_request',
            'h4_booking',
            'h4_lms_courses',
            'h4_lms_progress',
            'h4_lms_certificate',
            'h4_popup',
            'h4_field',
            'h4_google_business',
            'h4_google_reviews',
            'h4_google_map',
            'h4_local_business',
            'h4_local_address',
            'h4_local_opening_hours',
            'h4_local_locations',
            'h4_local_store_locator',
        ];

        foreach ($shortcodes as $shortcode) {
            if (has_shortcode($content, $shortcode)) {
                return true;
            }
        }

        foreach ($this->frontendComponentMarkers() as $marker) {
            if (str_contains($content, $marker)) {
                return true;
            }
        }

        return false;
    }

    /**
     * @return array<int, string>
     */
    private function frontendComponentMarkers(): array
    {
        return [
            'h4wp-',
            'h4-sales-',
            'h4-product-',
            'h4-package-',
            'h4-tier-',
            'h4-support-',
            'h4-bridge-',
            'h4bs-builder-page',
        ];
    }

    private function currentViewHasShortcode(string $shortcode): bool
    {
        if (! is_singular()) {
            return false;
        }

        $postId = get_queried_object_id();
        if (! $postId) {
            return false;
        }

        $content = (string) get_post_field('post_content', $postId);
        if ($content !== '' && has_shortcode($content, $shortcode)) {
            return true;
        }

        $builderEnabled = (string) get_post_meta($postId, '_h4_builder_enabled', true) === '1'
            && (string) get_post_meta($postId, '_h4_builder_mode', true) === 'help4';
        if (! $builderEnabled) {
            return false;
        }

        $layout = json_decode((string) get_post_meta($postId, '_h4_builder_layout', true), true);
        if (! is_array($layout)) {
            return false;
        }

        foreach ($layout as $block) {
            if (! is_array($block) || ($block['type'] ?? '') !== 'shortcode') {
                continue;
            }
            $settings = is_array($block['settings'] ?? null) ? $block['settings'] : [];
            $blockShortcode = (string) ($settings['shortcode'] ?? '');
            if ($blockShortcode !== '' && has_shortcode($blockShortcode, $shortcode)) {
                return true;
            }
        }

        return false;
    }

    public function cleanupPluginUpdateTempDirectories(): void
    {
        if (! current_user_can('activate_plugins')) {
            return;
        }

        $pluginsDir = defined('WP_PLUGIN_DIR') ? (string) WP_PLUGIN_DIR : '';
        if ($pluginsDir === '' || ! is_dir($pluginsDir)) {
            return;
        }

        $candidates = glob($pluginsDir . DIRECTORY_SEPARATOR . 'help4-builder-suite-*', GLOB_ONLYDIR);
        if (! is_array($candidates) || ! $candidates) {
            return;
        }

        foreach ($candidates as $candidate) {
            $basename = basename((string) $candidate);
            if (! preg_match('/^help4-builder-suite-\d+\.\d+\.\d+-[A-Za-z0-9]+$/', $basename)) {
                continue;
            }
            $real = realpath((string) $candidate);
            if ($real === false || ! str_starts_with($real, $pluginsDir . DIRECTORY_SEPARATOR)) {
                continue;
            }
            $this->deleteDirectory($real);
        }
    }

    private function deleteDirectory(string $path): void
    {
        if (! is_dir($path)) {
            return;
        }

        $iterator = new \RecursiveIteratorIterator(
            new \RecursiveDirectoryIterator($path, \FilesystemIterator::SKIP_DOTS),
            \RecursiveIteratorIterator::CHILD_FIRST
        );

        foreach ($iterator as $entry) {
            /** @var \SplFileInfo $entry */
            $target = $entry->getPathname();
            if ($entry->isDir()) {
                // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_rmdir -- Removes plugin-owned module directories during uninstall cleanup.
                @rmdir($target);
                continue;
            }
            wp_delete_file($target);
        }

        // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_rmdir -- Removes plugin-owned module directory after files are deleted.
        @rmdir($path);
    }
}
