<?php

/**
 * Lightweight Speculation Rules output
 *
 * Outputs safe prefetch rules for faster client-side navigation.
 *
 * @package ProRank\SEO\Frontend
 */

declare(strict_types=1);

namespace ProRank\SEO\Frontend;

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


/**
 * SpeculationRules
 */


class SpeculationRules {
    /**
     * Boot hooks
     */
    public function init(): void {
        add_action( 'wp_head', [ $this, 'output_rules' ], 1 );
    }

    /**
     * Output speculationrules script
     */
    public function output_rules(): void {
        static $output_done = false;
        if ($output_done) return;
        $output_done = true;
        if ( is_admin() || is_preview() || is_customize_preview() ) {
            return;
        }

        $settings = get_option('prorank_cache_settings', []);
        if (!is_array($settings)) {
            $settings = [];
        }

        $prefetch_enabled = !empty($settings['prefetch_enabled']);
        $prerender_enabled = !empty($settings['prerender_enabled']);
        if (!$prefetch_enabled && !$prerender_enabled) {
            return;
        }

        $prefetch_eagerness = (string) ($settings['prefetch_eagerness'] ?? 'moderate');
        if (!in_array($prefetch_eagerness, ['conservative', 'moderate', 'eager', 'immediate'], true)) {
            $prefetch_eagerness = 'moderate';
        }

        // Basic rules: prefetch document links without query strings; safe excludes
        $rules = [];
        if ($prefetch_enabled) {
            $rules['prefetch'] = [
                [
                    'source'    => 'document',
                    'where'     => [
                        'and' => array_values( array_filter( [
                            [ 'href_matches' => '/*' ],
                            [ 'not' => [ 'href_matches' => '/*\\?*' ] ],
                            [ 'not' => [ 'selector_matches' => '[data-no-prefetch], [rel~=nofollow]' ] ],
                            $this->woo_excludes(),
                        ] ) ),
                    ],
                    'eagerness' => $prefetch_eagerness,
                ],
            ];
        }
        if ($prerender_enabled) {
            $rules['prerender'] = [
                [
                    'source' => 'document',
                    'where' => [
                        'and' => array_values(array_filter([
                            ['href_matches' => '/*'],
                            ['not' => ['href_matches' => '/*\\?*']],
                            ['not' => ['selector_matches' => '[data-no-prerender], [rel~=nofollow]']],
                            $this->woo_excludes(),
                        ])),
                    ],
                    'eagerness' => (string) ($settings['prerender_eagerness'] ?? 'conservative'),
                ],
            ];
        }

        $json = wp_json_encode( $rules, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES );
        if ( empty( $json ) ) {
            return;
        }

        echo '<script type="speculationrules">' . "\n" . wp_kses($json, []) . "\n" . '</script>' . "\n";
    }

    /**
     * Exclude WooCommerce carts/checkout from prefetch
     */
    private function woo_excludes() {
        if ( class_exists( 'WooCommerce' ) ) {
            return [
                'not' => [
                    'href_matches' => '/{cart,checkout,my-account}/*',
                ],
            ];
        }
        return null;
    }
}
