<?php

declare(strict_types=1);

namespace ProRank\SEO\CLI;

use WP_CLI;

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

/**
 * ProRank performance presets.
 *
 * Named bundles that flip a sensible set of toggles in one command, instead of
 * walking the merchant through each setting. Each preset is a merge against
 * the existing option arrays — values not mentioned by the preset stay as-is.
 *
 * ## EXAMPLES
 *
 *     # List available presets
 *     wp prorank presets list
 *
 *     # Show what a preset would change without applying it
 *     wp prorank presets show standard
 *
 *     # Apply a preset
 *     wp prorank presets apply aggressive
 */
class PresetsCommand {

    /**
     * @return array<string,array{label:string,description:string,options:array<string,array<string,mixed>>}>
     */
    private function presets(): array {
        return [
            'standard' => [
                'label'       => 'Standard',
                'description' => 'Conservative defaults: page cache, image lazy-load, basic compression. Safe on most themes.',
                'options'     => [
                    'prorank_cache_settings' => [
                        'cache_enabled'        => true,
                        'enabled'              => true,
                        'cache_compression'    => 'gzip',
                        'dns_prefetch_enabled' => true,
                        'js_defer'             => false,
                        'js_delay'             => false,
                        'css_minify'           => false,
                    ],
                    'prorank_asset_optimization_settings' => [
                        'js_minify_enabled' => false,
                        'minify_html'       => false,
                    ],
                    'prorank_image_optimization_settings' => [
                        'lazyload_enabled' => true,
                        'lazyload_images'  => true,
                        'lazyload_iframes' => true,
                        'webp_enabled'     => true,
                        'avif_enabled'     => false,
                    ],
                ],
            ],
            'aggressive' => [
                'label'       => 'Aggressive',
                'description' => 'Maximum optimization: defer + delay + combine, CSS minify, AVIF. May need exclusion tuning.',
                'options'     => [
                    'prorank_cache_settings' => [
                        'cache_enabled'        => true,
                        'enabled'              => true,
                        'cache_compression'    => 'both',
                        'dns_prefetch_enabled' => true,
                        'js_defer'             => true,
                        'js_delay'             => true,
                        'css_minify'           => true,
                        'css_combine'          => true,
                    ],
                    'prorank_asset_optimization_settings' => [
                        'js_minify_enabled' => true,
                        'minify_html'       => true,
                    ],
                    'prorank_image_optimization_settings' => [
                        'lazyload_enabled' => true,
                        'lazyload_images'  => true,
                        'lazyload_iframes' => true,
                        'lazyload_videos'  => true,
                        'webp_enabled'     => true,
                        'avif_enabled'     => true,
                    ],
                ],
            ],
            'ecommerce' => [
                'label'       => 'E-commerce',
                'description' => 'WooCommerce-safe: cache variants on, defer off for jQuery-heavy themes, image opt on.',
                'options'     => [
                    'prorank_cache_settings' => [
                        'cache_enabled'              => true,
                        'enabled'                    => true,
                        'cache_compression'          => 'gzip',
                        'dns_prefetch_enabled'       => true,
                        'woocommerce_cache_variants' => true,
                        'js_defer'                   => false,
                        'js_delay'                   => false,
                        'css_minify'                 => true,
                    ],
                    'prorank_asset_optimization_settings' => [
                        'js_minify_enabled' => false,
                        'minify_html'       => true,
                    ],
                    'prorank_image_optimization_settings' => [
                        'lazyload_enabled' => true,
                        'lazyload_images'  => true,
                        'lazyload_iframes' => true,
                        'webp_enabled'     => true,
                        'avif_enabled'     => false,
                    ],
                ],
            ],
        ];
    }

    /**
     * List the available presets.
     *
     * ## OPTIONS
     *
     * [--format=<format>]
     * : table|json|yaml. Default table.
     *
     * @when after_wp_load
     */
    public function list($args, $assoc_args): void {
        $format = (string) ($assoc_args['format'] ?? 'table');
        $rows = [];
        foreach ($this->presets() as $key => $preset) {
            $rows[] = [
                'name'        => $key,
                'label'       => $preset['label'],
                'description' => $preset['description'],
            ];
        }
        \WP_CLI\Utils\format_items($format, $rows, ['name', 'label', 'description']);
    }

    /**
     * Show the keys a preset would set, without applying.
     *
     * ## OPTIONS
     *
     * <name>
     * : Preset to inspect.
     *
     * @when after_wp_load
     */
    public function show($args): void {
        $name = isset($args[0]) ? (string) $args[0] : '';
        $presets = $this->presets();
        if (!isset($presets[$name])) {
            WP_CLI::error('Unknown preset: ' . $name);
        }

        $preset = $presets[$name];
        WP_CLI::log('Preset      : ' . $preset['label']);
        WP_CLI::log('Description : ' . $preset['description']);
        WP_CLI::log('');
        foreach ($preset['options'] as $option_name => $values) {
            WP_CLI::log($option_name . ':');
            foreach ($values as $k => $v) {
                $printable = is_bool($v) ? ($v ? 'true' : 'false') : (string) $v;
                WP_CLI::log('  ' . $k . ' = ' . $printable);
            }
            WP_CLI::log('');
        }
    }

    /**
     * Apply a preset to the option store.
     *
     * Merges the preset's values into the existing options; keys not in the
     * preset are left untouched. Existing cache is purged after the change.
     *
     * ## OPTIONS
     *
     * <name>
     * : Preset to apply.
     *
     * [--dry-run]
     * : Print what would change without writing.
     *
     * @when after_wp_load
     */
    public function apply($args, $assoc_args): void {
        $name = isset($args[0]) ? (string) $args[0] : '';
        $presets = $this->presets();
        if (!isset($presets[$name])) {
            WP_CLI::error('Unknown preset: ' . $name);
        }

        $dry_run = !empty($assoc_args['dry-run']);
        $preset  = $presets[$name];
        $changed = 0;

        foreach ($preset['options'] as $option_name => $values) {
            $current = get_option($option_name, []);
            if (!is_array($current)) {
                $current = [];
            }

            $patched = array_merge($current, $values);

            if ($patched === $current) {
                continue;
            }

            $changed++;
            WP_CLI::log(($dry_run ? '[dry-run] ' : '') . 'Updating ' . $option_name);

            if (!$dry_run) {
                update_option($option_name, $patched);
            }
        }

        if ($changed === 0) {
            WP_CLI::log('No options needed changes.');
            return;
        }

        if ($dry_run) {
            WP_CLI::success(sprintf('Would update %d option group%s.', $changed, $changed === 1 ? '' : 's'));
            return;
        }

        // Hook the cache module to purge so the new settings take effect on the next request.
        do_action('prorank_clear_cache');

        WP_CLI::success(sprintf('Applied preset "%s" (%d option group%s updated).', $name, $changed, $changed === 1 ? '' : 's'));
    }
}

if (defined('WP_CLI') && WP_CLI) {
    WP_CLI::add_command('prorank presets', 'ProRank\\SEO\\CLI\\PresetsCommand');
}
