<?php

/**
 * Sitemaps Module
 *
 * Handles XML sitemap generation and management
 *
 * @package ProRank\SEO\Modules\Indexing
 * @since   0.1.0
 */

declare(strict_types=1);

namespace ProRank\SEO\Modules\TechnicalSEO;

use ProRank\SEO\Modules\BaseModule;
use ProRank\SEO\Core\ModuleManager;
use ProRank\SEO\Core\Compatibility\CompetitorDetector;

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


/**
 * Sitemaps module class
 */


if (!class_exists(__NAMESPACE__ . '\\SitemapsModule', false)) {
class SitemapsModule extends BaseModule {
    
    /**
     * Module slug
     *
     * @var string
     */
    protected string $slug = 'sitemaps';
    
    /**
     * Module name
     *
     * @var string
     */
    protected string $name = 'XML Sitemaps';
    
    /**
     * Module description
     *
     * @var string
     */
    protected string $description = 'Automatic XML sitemap generation';
    
    /**
     * Required tier
     *
     * @var string
     */
    protected string $feature_tier = 'free';
    
    /**
     * Parent module
     *
     * @var string|null
     */
    protected ?string $parent_slug = 'technical-seo';
    
    /**
     * Sitemap providers
     *
     * @var array
     */
    private array $providers = [];
    
    /**
     * Settings manager instance
     *
     * @var \ProRank\SEO\Core\SettingsManager|null
     */
    private ?\ProRank\SEO\Core\SettingsManager $settings_manager = null;
    
    /**
     * License manager instance
     *
     * @var \ProRank\SEO\Core\LicenseManager|null
     */
    private ?\ProRank\SEO\Core\LicenseManager $license_manager = null;

    /**
     * SEO conflict safe mode state.
     *
     * @var bool
     */
    private bool $seo_conflict_safe_mode = false;
    
    /**
     * Initialize the module
     *
     * @return void
     */
    public function init(): void {
        // Set safe mode BEFORE parent::init() which calls init_hooks().
        $detector = new CompetitorDetector();
        $this->seo_conflict_safe_mode = $detector->should_enable_seo_safe_mode();

        parent::init();
        
        // Get manager instances from plugin
        try {
            $plugin = $this->plugin();
            $this->settings_manager = $plugin->settings();
            $this->license_manager = $plugin->license();
        } catch (\Exception $e) {
            // Managers not available, skip initialization
            return;
        }
        
        // Register default providers
        $this->register_default_providers();
        
        // Allow other modules to register providers
        do_action('prorank_seo_register_sitemap_providers', $this);
    }
    
    /**
     * Initialize module hooks
     *
     * @return void
     */
    public function init_hooks(): void {
        // In SEO conflict safe mode, skip ProRank sitemap output to avoid duplicates
        // with competing SEO plugins (e.g. Rank Math).
        if ($this->seo_conflict_safe_mode) {
            return;
        }

        // Module is already active if init_hooks is being called
        add_filter('wp_sitemaps_enabled', [$this, 'disable_wp_core_sitemaps'], 20);
        
        // Register query vars early
        add_filter('query_vars', [$this, 'add_query_vars'], 10);
        
        // Register rewrite rules — add immediately if 'init' already fired (e.g. WP-CLI),
        // otherwise hook into 'init' for normal page loads.
        if ( did_action('init') ) {
            $this->add_rewrite_rules();
        } else {
            add_action('init', [$this, 'add_rewrite_rules'], 10);
        }
        
        // Handle sitemap requests
        add_action('template_redirect', [$this, 'handle_sitemap_request'], 1);
        
        // Alternative handler for sitemap requests
        add_action('parse_request', [$this, 'parse_sitemap_request'], 1);
        
        // Flush rewrite rules on activation/deactivation
        add_action('prorank_seo_module_activated_' . $this->slug, [$this, 'flush_rewrite_rules']);
        add_action('prorank_seo_module_deactivated_' . $this->slug, [$this, 'flush_rewrite_rules']);
        
        // Add robots.txt rules
        add_filter('robots_txt', [$this, 'add_robots_txt_rules'], 10, 2);
        
        // Ping search engines when content is updated
        add_action('transition_post_status', [$this, 'maybe_ping_search_engines'], 10, 3);
        add_action('created_term', [$this, 'ping_on_term_change'], 10, 3);
        add_action('edited_term', [$this, 'ping_on_term_change'], 10, 3);
        add_action('delete_term', [$this, 'ping_on_term_change'], 10, 3);

        // 2025 Enhancement: Invalidate sitemap cache when content changes
        add_action('save_post', [$this, 'invalidate_sitemap_cache_on_save'], 10, 2);
        add_action('delete_post', [$this, 'invalidate_sitemap_cache_on_delete'], 10);
        add_action('created_term', [$this, 'invalidate_sitemap_cache_on_term_change'], 10, 3);
        add_action('edited_term', [$this, 'invalidate_sitemap_cache_on_term_change'], 10, 3);
        add_action('delete_term', [$this, 'invalidate_sitemap_cache_on_term_change'], 10, 3);
    }
    
    /**
     * Register default sitemap providers
     *
     * @return void
     */
    private function register_default_providers(): void {
        $settings = $this->get_sitemap_settings();
        $enabled_post_types = array_values(array_filter(
            array_map('strval', $settings['include_post_types'] ?? ['post', 'page'])
        ));
        $enabled_taxonomies = array_values(array_filter(
            array_map('strval', $settings['include_taxonomies'] ?? ['category', 'post_tag'])
        ));

        // Register post provider
        if (in_array('post', $enabled_post_types, true)) {
            $this->register_provider(new \ProRank\SEO\Modules\Indexing\Sitemaps\PostSitemapProvider());
        }
        
        // Register page provider
        if (in_array('page', $enabled_post_types, true)) {
            $this->register_provider(new \ProRank\SEO\Modules\Indexing\Sitemaps\PageSitemapProvider());
        }

        if (
            in_array('product', $enabled_post_types, true) &&
            class_exists('\\ProRank\\SEO\\Modules\\Indexing\\Sitemaps\\ProductSitemapProvider')
        ) {
            $this->register_provider(new \ProRank\SEO\Modules\Indexing\Sitemaps\ProductSitemapProvider());
        }

        // Register enabled custom post types (for example treatment).
        foreach ($this->get_enabled_custom_post_types($enabled_post_types) as $post_type) {
            $this->register_provider(new \ProRank\SEO\Modules\Indexing\Sitemaps\CustomPostTypeSitemapProvider($post_type));
        }
        
        // Register category provider
        if (in_array('category', $enabled_taxonomies, true)) {
            $this->register_provider(new \ProRank\SEO\Modules\Indexing\Sitemaps\CategorySitemapProvider());
        }
        
        // Register tag provider
        if (in_array('post_tag', $enabled_taxonomies, true)) {
            $this->register_provider(new \ProRank\SEO\Modules\Indexing\Sitemaps\TagSitemapProvider());
        }

        if (
            in_array('product_cat', $enabled_taxonomies, true) &&
            class_exists('\\ProRank\\SEO\\Modules\\Indexing\\Sitemaps\\ProductCategorySitemapProvider')
        ) {
            $this->register_provider(new \ProRank\SEO\Modules\Indexing\Sitemaps\ProductCategorySitemapProvider());
        }

        if (
            in_array('product_tag', $enabled_taxonomies, true) &&
            class_exists('\\ProRank\\SEO\\Modules\\Indexing\\Sitemaps\\ProductTagSitemapProvider')
        ) {
            $this->register_provider(new \ProRank\SEO\Modules\Indexing\Sitemaps\ProductTagSitemapProvider());
        }

    }

    /**
     * Get public custom post types that should have sitemap providers.
     *
     * @return string[]
     */
    private function get_enabled_custom_post_types(array $enabled_post_types): array {
        $post_types = [];

        foreach ($enabled_post_types as $slug) {
            if (in_array($slug, ['post', 'page', 'attachment', 'product'], true)) {
                continue;
            }

            $object = get_post_type_object($slug);
            if (!$object instanceof \WP_Post_Type) {
                continue;
            }

            if (!$object->public) {
                continue;
            }

            $post_types[] = $slug;
        }

        sort($post_types);

        return $post_types;
    }
    
    /**
     * Register a sitemap provider
     *
     * @param \ProRank\SEO\Modules\Indexing\Sitemaps\BaseSitemapProvider $provider Provider instance
     * @return void
     */
    public function register_provider(\ProRank\SEO\Modules\Indexing\Sitemaps\BaseSitemapProvider $provider): void {
        // Configure provider with settings if available
        if ($this->settings_manager) {
            // Inject settings manager
            if (method_exists($provider, 'set_settings_manager')) {
                $provider->set_settings_manager($this->settings_manager);
            }
            
            // Configure max entries
            $settings = $this->get_sitemap_settings();
            $max_entries = isset($settings['posts_per_sitemap']) ? (int) $settings['posts_per_sitemap'] : 1000;
            if (method_exists($provider, 'set_max_entries')) {
                $provider->set_max_entries($max_entries);
            }
        }
        
        // Inject license manager for providers that need it
        if ($this->license_manager && property_exists($provider, 'license_manager')) {
            try {
                $reflection = new \ReflectionClass($provider);
                $property = $reflection->getProperty('license_manager');
                $property->setAccessible(true);
                $property->setValue($provider, $this->license_manager);
            } catch (\Exception $e) {
                // Ignore if property doesn't exist or can't be set
            }
        }
        
        $this->providers[$provider->get_slug()] = $provider;
    }
    
    /**
     * Get registered providers
     *
     * @return array
     */
    public function get_providers(): array {
        return apply_filters('prorank_seo_sitemap_providers', $this->providers);
    }
    
    /**
     * Add rewrite rules for sitemaps
     *
     * @return void
     */
    public function add_rewrite_rules(): void {
        $sitemap_index_pattern = preg_quote($this->get_sitemap_index_filename(), '/');

        // Compatibility alias so /sitemap.xml resolves to the ProRank index.
        add_rewrite_rule(
            'sitemap\.xml$',
            'index.php?prorank_sitemap=index',
            'top'
        );

        // Sitemap index
        add_rewrite_rule(
            $sitemap_index_pattern . '$',
            'index.php?prorank_sitemap=index',
            'top'
        );
        
        // Individual sitemaps
        add_rewrite_rule(
            '([^/]+)-sitemap([0-9]+)?\.xml$',
            'index.php?prorank_sitemap=$matches[1]&prorank_sitemap_page=$matches[2]',
            'top'
        );
    }
    
    /**
     * Add query vars for sitemaps
     *
     * @param array $vars Query vars
     * @return array
     */
    public function add_query_vars(array $vars): array {
        $vars[] = 'prorank_sitemap';
        $vars[] = 'prorank_sitemap_page';
        return $vars;
    }
    
    /**
     * Parse sitemap requests directly from URL
     *
     * @param \WP $wp WordPress environment object
     * @return void
     */
    public function parse_sitemap_request(\WP $wp): void {
        $request_uri = prorank_get_server_var( 'REQUEST_URI' );
        $request_path = (string) wp_parse_url($request_uri, PHP_URL_PATH);
        $sitemap_index_pattern = '/' . preg_quote($this->get_sitemap_index_filename(), '/') . '$/';
        
        // Check if this is a sitemap request
        if ($this->is_sitemap_alias_request($request_path) || preg_match($sitemap_index_pattern, $request_path)) {
            // Set query vars manually
            $wp->query_vars['prorank_sitemap'] = 'index';
        } elseif (preg_match('/([^\/]+)-sitemap(\d+)?\.xml$/', $request_path, $matches)) {
            // Set query vars manually
            $wp->query_vars['prorank_sitemap'] = $matches[1];
            if (!empty($matches[2])) {
                $wp->query_vars['prorank_sitemap_page'] = $matches[2];
            }
        }
    }
    
    /**
     * Handle sitemap requests
     *
     * @return void
     */
    public function handle_sitemap_request(): void {
        global $wp_query;
        
        $sitemap_type = get_query_var('prorank_sitemap');
        if (empty($sitemap_type)) {
            return;
        }
        
        // Module is already active if this method is being called
        
        // Check if sitemaps feature is enabled in settings
        $settings = $this->get_sitemap_settings();
        // Default to enabled for free tier
        $enabled = isset($settings['enable_xml_sitemap']) ? $settings['enable_xml_sitemap'] : true;
        if (!$enabled) {
            $wp_query->set_404();
            status_header(404);
            return;
        }
        
        // Set XML headers — skip PHP-level gzip (ob_gzhandler) because nginx/Apache
        // already handle Content-Encoding compression. Double-encoding corrupts output.
        header('Content-Type: application/xml; charset=utf-8');
        header('X-Robots-Tag: noindex, follow');

        // Handle sitemap index
        if ($sitemap_type === 'index') {
            status_header(200);
            // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- XML output
            echo $this->generate_sitemap_index();
            exit;
        }
        
        // Handle individual sitemaps
        $providers = $this->get_providers();
        if (isset($providers[$sitemap_type]) && is_object($providers[$sitemap_type])) {
            $provider = $providers[$sitemap_type];
            $page_raw = get_query_var('prorank_sitemap_page', 1);
            $page = max(1, (int) $page_raw); // Ensure page is at least 1
            
            if (method_exists($provider, 'is_enabled') && $provider->is_enabled()) {
                // Validate page number
                if (method_exists($provider, 'get_total_pages')) {
                    $total_pages = $provider->get_total_pages();
                    if ($page > $total_pages) {
                        $wp_query->set_404();
                        status_header(404);
                        return;
                    }
                }
                
                // Generate sitemap with caching
                $force_refresh = prorank_get_query_var('refresh') === '1';

                if (method_exists($provider, 'generate_cached')) {
                    // Use cached version (2025 enhancement)
                    status_header(200);
                    // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- XML output
                    echo $provider->generate_cached($page, $force_refresh);
                    exit;
                } elseif (method_exists($provider, 'generate_xml')) {
                    // Fallback to direct generation
                    status_header(200);
                    // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- XML output
                    echo $provider->generate_xml($page);
                    exit;
                } elseif (method_exists($provider, 'generate')) {
                    // Backward compatibility
                    status_header(200);
                    // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- XML output
                    echo $provider->generate($page);
                    exit;
                }
            }
        }
        
        // If we get here, sitemap not found
        $wp_query->set_404();
        status_header(404);
    }
    
    /**
     * Generate sitemap index
     *
     * @return string XML content
     */
    private function generate_sitemap_index(): string {
        $xml = new \XMLWriter();
        $xml->openMemory();
        $xml->setIndent(true);
        
        // Start XML document
        $xml->startDocument('1.0', 'UTF-8');
        
        // Branding comment
        $xml->writeComment(' Generated by ProRank SEO - https://prorank.io ');
        
        // Start sitemapindex
        $xml->startElement('sitemapindex');
        $xml->writeAttribute('xmlns', 'http://www.sitemaps.org/schemas/sitemap/0.9');
        
        // Get all sitemap entries from providers
        foreach ($this->get_providers() as $slug => $provider) {
            // Skip if provider is not an object
            if (!is_object($provider)) {
                continue;
            }
            
            // Check if provider is enabled
            if (!method_exists($provider, 'is_enabled') || !$provider->is_enabled()) {
                continue;
            }
            
            // Get index entries
            if (method_exists($provider, 'get_index_entries')) {
                $entries = $provider->get_index_entries();
                
                foreach ($entries as $entry) {
                    $xml->startElement('sitemap');
                    $xml->writeElement('loc', $entry['loc']);
                    
                    if (!empty($entry['lastmod'])) {
                        $xml->writeElement('lastmod', $entry['lastmod']);
                    }
                    
                    $xml->endElement(); // sitemap
                }
            }
        }
        
        $xml->endElement(); // sitemapindex
        $xml->endDocument();
        
        return $xml->outputMemory();
    }
    
    /**
     * Add sitemap URL to robots.txt
     *
     * @param string $output Robots.txt output
     * @param bool   $public Whether the site is public
     * @return string Modified output
     */
    public function add_robots_txt_rules(string $output, bool $public): string {
        if (!$public) {
            return $output;
        }

        $sitemap_url = $this->get_sitemap_index_url();

        // Only add if not already present
        if (strpos($output, 'Sitemap:') === false) {
            $output .= "\nSitemap: " . $sitemap_url . "\n";
        }

        return $output;
    }
    
    /**
     * Flush rewrite rules
     *
     * @return void
     */
    public function flush_rewrite_rules(): void {
        flush_rewrite_rules();
    }
    
    /**
     * Maybe ping search engines on post status change
     *
     * @param string  $new_status New post status
     * @param string  $old_status Old post status
     * @param \WP_Post $post      Post object
     * @return void
     */
    public function maybe_ping_search_engines(string $new_status, string $old_status, \WP_Post $post): void {
        // Only ping if transitioning to published
        if ($new_status !== 'publish' || $old_status === 'publish') {
            return;
        }
        
        // Check if this post type is included in sitemaps
        $settings = $this->get_sitemap_settings();
        $enabled_post_types = $settings['include_post_types'] ?? ['post', 'page'];
        
        if (!in_array($post->post_type, $enabled_post_types, true)) {
            return;
        }
        
        $this->ping_search_engines();
    }
    
    /**
     * Ping search engines on term changes
     *
     * @param int    $term_id  Term ID
     * @param int    $tt_id    Term taxonomy ID
     * @param string $taxonomy Taxonomy slug
     * @return void
     */
    public function ping_on_term_change(int $term_id, int $tt_id, string $taxonomy): void {
        // Check if this taxonomy is included in sitemaps
        $settings = $this->get_sitemap_settings();
        $enabled_taxonomies = $settings['include_taxonomies'] ?? ['category', 'post_tag'];
        
        if (!in_array($taxonomy, $enabled_taxonomies, true)) {
            return;
        }
        
        $this->ping_search_engines();
    }
    
    /**
     * Ping search engines about sitemap update
     *
     * @return void
     */
    private function ping_search_engines(): void {
        // Check if pinging is enabled
        $settings = $this->get_sitemap_settings();
        if (empty($settings['ping_search_engines'])) {
            return;
        }
        
        // Don't ping more than once per hour
        $last_ping = get_transient('prorank_seo_sitemap_last_ping');
        if ($last_ping !== false) {
            return;
        }
        
        $sitemap_url = $this->get_sitemap_index_url();
        
        // Ping Google
        wp_remote_get(
            'https://www.google.com/ping?sitemap=' . urlencode($sitemap_url),
            [
                'timeout' => 10,
                'blocking' => false,
                'user-agent' => 'ProRank SEO/' . PRORANK_SEO_VERSION,
            ]
        );
        
        // Ping Bing
        wp_remote_get(
            'https://www.bing.com/ping?sitemap=' . urlencode($sitemap_url),
            [
                'timeout' => 10,
                'blocking' => false,
                'user-agent' => 'ProRank SEO/' . PRORANK_SEO_VERSION,
            ]
        );
        
        // Set transient to prevent over-pinging
        set_transient('prorank_seo_sitemap_last_ping', time(), HOUR_IN_SECONDS);
        
        // Log the ping
        if (defined('WP_DEBUG') && WP_DEBUG) {
            prorank_log('[ProRank SEO] Pinged search engines with sitemap: ' . $sitemap_url);
        }
    }
    
    /**
     * Maybe enable gzip compression for sitemap output
     *
     * Enables gzip compression if available and not already enabled.
     * 2025 Enhancement: Reduces sitemap transfer size by ~70-90%.
     *
     * @return bool True if gzip was enabled, false otherwise
     */
    private function maybe_enable_gzip_compression(): bool {
        // Check if gzip is already enabled
        if (ini_get('zlib.output_compression')) {
            return false;
        }

        // Check if zlib extension is loaded
        if (!extension_loaded('zlib')) {
            return false;
        }

        // Check if client accepts gzip
        $accept_encoding = prorank_get_server_var('HTTP_ACCEPT_ENCODING');
        if (stripos($accept_encoding, 'gzip') === false) {
            return false;
        }

        // Check if gzip compression is enabled in settings
        $settings = $this->get_sitemap_settings();
        $gzip_enabled = $settings['enable_gzip'] ?? true; // Default: enabled

        if (!$gzip_enabled) {
            return false;
        }

        // Enable output buffering with gzip handler
        if (ob_start('ob_gzhandler')) {
            return true;
        }

        return false;
    }

    /**
     * Get configured sitemap index filename.
     *
     * @return string
     */
    private function get_sitemap_index_filename(): string {
        $default_filename = 'sitemap_index.xml';
        $settings = $this->get_sitemap_settings();

        $filename = isset($settings['sitemap_index_url']) ? sanitize_file_name((string) $settings['sitemap_index_url']) : $default_filename;
        if (!preg_match('/^[A-Za-z0-9_-]+\.xml$/', $filename)) {
            return $default_filename;
        }

        return $filename;
    }

    /**
     * Get sitemap index URL.
     *
     * @return string
     */
    private function get_sitemap_index_url(): string {
        return home_url('/' . ltrim($this->get_sitemap_index_filename(), '/'));
    }

    /**
     * Get sitemap settings with legacy fallback.
     *
     * Returns group-prefixed settings and overlays any legacy nested payload.
     * Group-prefixed keys take priority so admin REST/UI and runtime stay in sync.
     *
     * @return array
     */
    private function get_sitemap_settings(): array {
        if (!$this->settings_manager) {
            $flat_legacy = get_option('prorank_seo_sitemap', []);
            return is_array($flat_legacy) ? $flat_legacy : [];
        }

        $flat_legacy = get_option('prorank_seo_sitemap', []);
        $legacy = [];
        if (method_exists($this->settings_manager, 'get')) {
            $legacy = (array) $this->settings_manager->get('sitemaps', []);
        }

        $group = [];
        if (method_exists($this->settings_manager, 'get_settings')) {
            $group = (array) $this->settings_manager->get_settings('sitemaps');
        }

        return array_merge(
            is_array($flat_legacy) ? $flat_legacy : [],
            $legacy,
            $group
        );
    }

    /**
     * Disable WordPress core sitemaps when ProRank XML sitemaps are enabled.
     *
     * @param bool $enabled Current core sitemap state.
     * @return bool
     */
    public function disable_wp_core_sitemaps(bool $enabled): bool {
        $settings = $this->get_sitemap_settings();
        $prorank_enabled = isset($settings['enable_xml_sitemap']) ? (bool) $settings['enable_xml_sitemap'] : true;

        if ($prorank_enabled) {
            return false;
        }

        return $enabled;
    }

    /**
     * Check whether the request targets the compatibility alias /sitemap.xml.
     *
     * @param string $request_path Parsed request path.
     * @return bool
     */
    private function is_sitemap_alias_request(string $request_path): bool {
        return (bool) preg_match('#/sitemap\.xml$#', $request_path);
    }

    /**
     * Invalidate sitemap cache on content changes
     *
     * Called when posts are saved, deleted, or status changes.
     *
     * @param int      $post_id Post ID
     * @param \WP_Post $post    Post object
     * @return void
     */
    public function invalidate_sitemap_cache_on_save(int $post_id, \WP_Post $post): void {
        if ( \ProRank\SEO\Plugin::is_elementor_builder_save_request() ) {
            return;
        }

        // Skip autosaves and revisions
        if (wp_is_post_autosave($post_id) || wp_is_post_revision($post_id)) {
            return;
        }

        // Skip if post type is not included in sitemaps
        $settings = $this->get_sitemap_settings();
        $enabled_post_types = $settings['include_post_types'] ?? ['post', 'page'];

        if (!in_array($post->post_type, $enabled_post_types, true)) {
            return;
        }

        // Invalidate all sitemap caches
        \ProRank\SEO\Modules\Indexing\Sitemaps\BaseSitemapProvider::invalidate_all_caches();

        // Log cache invalidation
        if (defined('WP_DEBUG') && WP_DEBUG) {
            prorank_log(sprintf(
                '[ProRank SEO] Sitemap cache invalidated due to post save: %s (ID: %d)',
                $post->post_title,
                $post_id
            ));
        }
    }

    /**
     * Invalidate sitemap cache on post deletion
     *
     * @param int $post_id Post ID
     * @return void
     */
    public function invalidate_sitemap_cache_on_delete(int $post_id): void {
        // Get post before it's deleted
        $post = get_post($post_id);
        if (!$post) {
            return;
        }

        // Skip if post type is not included in sitemaps
        $settings = $this->get_sitemap_settings();
        $enabled_post_types = $settings['include_post_types'] ?? ['post', 'page'];

        if (!in_array($post->post_type, $enabled_post_types, true)) {
            return;
        }

        // Invalidate all sitemap caches
        \ProRank\SEO\Modules\Indexing\Sitemaps\BaseSitemapProvider::invalidate_all_caches();
    }

    /**
     * Invalidate sitemap cache on term changes
     *
     * @param int    $term_id  Term ID
     * @param int    $tt_id    Term taxonomy ID
     * @param string $taxonomy Taxonomy slug
     * @return void
     */
    public function invalidate_sitemap_cache_on_term_change(int $term_id, int $tt_id, string $taxonomy): void {
        // Skip if taxonomy is not included in sitemaps
        $settings = $this->get_sitemap_settings();
        $enabled_taxonomies = $settings['include_taxonomies'] ?? ['category', 'post_tag'];

        if (!in_array($taxonomy, $enabled_taxonomies, true)) {
            return;
        }

        // Invalidate all sitemap caches
        \ProRank\SEO\Modules\Indexing\Sitemaps\BaseSitemapProvider::invalidate_all_caches();
    }

    /**
     * Get module configuration
     *
     * @return array
     */
    public function get_config(): array {
        return [
            'name' => __('XML Sitemaps', 'prorank-seo'),
            'description' => __('Automatic XML sitemap generation', 'prorank-seo'),
            'icon' => 'dashicons-editor-ul',
            'tier' => 'free',
            'parent' => 'technical-seo',
            'settings_group' => 'sitemaps',
            'features' => [
                'base' => [
                    'tier' => 'free',
                    'items' => [
                        __('Post sitemaps', 'prorank-seo'),
                        __('Page sitemaps', 'prorank-seo'),
                        __('Category sitemaps', 'prorank-seo'),
                        __('Tag sitemaps', 'prorank-seo'),
                        __('Image sitemaps', 'prorank-seo'),
                    ],
                ],
                'advanced' => [
                    'tier' => 'pro',
                    'items' => [
                        __('Author sitemaps', 'prorank-seo'),
                        __('Custom post type sitemaps', 'prorank-seo'),
                    ],
                ],
                'pro' => [
                    'tier' => 'pro',
                    'items' => [
                        __('Video sitemaps', 'prorank-seo'),
                        __('News sitemaps', 'prorank-seo'),
                    ],
                ],
            ],
        ];
    }
}
}
