<?php

/**
 * Sitemaps REST API Controller
 *
 * @package ProRank\SEO\Core\RestApi
 * @since   0.1.0
 */

declare(strict_types=1);

namespace ProRank\SEO\Core\RestApi;

use ProRank\SEO\Core\SettingsManager;
use ProRank\SEO\Modules\Indexing\Sitemaps\BaseSitemapProvider;
use WP_REST_Controller;
use WP_REST_Request;
use WP_REST_Response;
use WP_REST_Server;
use WP_Error;

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


/**
 * Sitemaps Controller class
 */


class SitemapsController extends WP_REST_Controller {
    
    /**
     * Constructor
     */
    public function __construct() {
        $this->namespace = 'prorank-seo/v1';
        $this->rest_base = 'settings/sitemaps';
    }
    
    /**
     * Register routes
     *
     * @return void
     */
    public function register_routes(): void {
        // Get sitemap settings
        register_rest_route(
            $this->namespace,
            '/' . $this->rest_base,
            [
                [
                    'methods'             => WP_REST_Server::READABLE,
                    'callback'            => [$this, 'get_settings'],
                    'permission_callback' => [$this, 'check_permission'],
                ],
                [
                    'methods'             => WP_REST_Server::CREATABLE,
                    'callback'            => [$this, 'update_settings'],
                    'permission_callback' => [$this, 'check_permission'],
                    'args'                => $this->get_settings_args(),
                ],
            ]
        );
        
        // Get sitemap preview
        register_rest_route(
            $this->namespace,
            '/' . $this->rest_base . '/preview',
            [
                [
                    'methods'             => WP_REST_Server::READABLE,
                    'callback'            => [$this, 'get_preview'],
                    'permission_callback' => [$this, 'check_permission'],
                ],
            ]
        );
        
        // Ping search engines
        register_rest_route(
            $this->namespace,
            '/' . $this->rest_base . '/ping',
            [
                [
                    'methods'             => WP_REST_Server::CREATABLE,
                    'callback'            => [$this, 'ping_search_engines'],
                    'permission_callback' => [$this, 'check_permission'],
                ],
            ]
        );
    }
    
    /**
     * Check permissions
     *
     * @param WP_REST_Request $request Request object
     * @return bool|WP_Error
     */
    public function check_permission(WP_REST_Request $request) {
        if (!current_user_can('manage_options')) {
            return new WP_Error(
                'prorank_seo_rest_forbidden',
                __('You do not have permission to access this resource.', 'prorank-seo'),
                ['status' => 403]
            );
        }
        
        return true;
    }
    
    /**
     * Get sitemap settings
     *
     * @param WP_REST_Request $request Request object
     * @return WP_REST_Response|WP_Error
     */
    public function get_settings(WP_REST_Request $request) {
        try {
            $settings = $this->get_saved_settings();
            
            return rest_ensure_response([
                'success' => true,
                'settings' => $settings,
            ]);
        } catch (\Exception $e) {
            return new WP_Error(
                'prorank_seo_rest_error',
                $e->getMessage(),
                ['status' => 500]
            );
        }
    }
    
    /**
     * Update sitemap settings
     *
     * @param WP_REST_Request $request Request object
     * @return WP_REST_Response|WP_Error
     */
    public function update_settings(WP_REST_Request $request) {
        try {
            $params = $request->get_params();
            
            // Extract settings from the nested structure
            $settings = isset($params['settings']) ? $params['settings'] : $params;
            
            // Validate settings
            $validated_settings = $this->validate_settings($settings);
            
            // Save settings to the grouped store used by the runtime module, and
            // keep the legacy option in sync for backward compatibility.
            $this->persist_settings($validated_settings);

            BaseSitemapProvider::invalidate_all_caches();
            
            // Flush rewrite rules if sitemap is enabled/disabled
            flush_rewrite_rules();
            
            return rest_ensure_response([
                'success' => true,
                'message' => __('Sitemap settings updated successfully.', 'prorank-seo'),
                'settings' => $validated_settings,
            ]);
        } catch (\Exception $e) {
            return new WP_Error(
                'prorank_seo_rest_error',
                $e->getMessage(),
                ['status' => 500]
            );
        }
    }
    
    /**
     * Get sitemap preview
     *
     * @param WP_REST_Request $request Request object
     * @return WP_REST_Response|WP_Error
     */
    public function get_preview(WP_REST_Request $request) {
        try {
            $settings = $this->get_saved_settings();
            
            if (!$settings['enable_xml_sitemap']) {
                return rest_ensure_response([
                    'success' => false,
                    'message' => __('XML sitemap is disabled.', 'prorank-seo'),
                ]);
            }
            
            // Get sample sitemap entries
            $preview_data = [
                'sitemap_index_url' => home_url($settings['sitemap_index_url']),
                'sitemaps' => [],
                'total_urls' => 0,
            ];
            
            // Add post type sitemaps
            foreach ($settings['include_post_types'] as $post_type) {
                $post_type_obj = get_post_type_object($post_type);
                if ($post_type_obj) {
                    $count = wp_count_posts($post_type)->publish;
                    $preview_data['sitemaps'][] = [
                        'type' => 'post_type',
                        'name' => $post_type_obj->labels->name,
                        'url' => home_url("{$post_type}-sitemap.xml"),
                        'count' => $count,
                    ];
                    $preview_data['total_urls'] += $count;
                }
            }
            
            // Add taxonomy sitemaps
            foreach ($settings['include_taxonomies'] as $taxonomy) {
                $taxonomy_obj = get_taxonomy($taxonomy);
                if ($taxonomy_obj) {
                    $count = wp_count_terms(['taxonomy' => $taxonomy]);
                    if (!is_wp_error($count)) {
                        $preview_data['sitemaps'][] = [
                            'type' => 'taxonomy',
                            'name' => $taxonomy_obj->labels->name,
                            'url' => home_url("{$taxonomy}-sitemap.xml"),
                            'count' => $count,
                        ];
                        $preview_data['total_urls'] += $count;
                    }
                }
            }
            
            return rest_ensure_response([
                'success' => true,
                'preview' => $preview_data,
            ]);
        } catch (\Exception $e) {
            return new WP_Error(
                'prorank_seo_rest_error',
                $e->getMessage(),
                ['status' => 500]
            );
        }
    }
    
    /**
     * Ping search engines
     *
     * @param WP_REST_Request $request Request object
     * @return WP_REST_Response|WP_Error
     */
    public function ping_search_engines(WP_REST_Request $request) {
        try {
            $settings = $this->get_saved_settings();
            
            if (!$settings['enable_xml_sitemap']) {
                return new WP_Error(
                    'prorank_seo_sitemap_disabled',
                    __('XML sitemap is disabled.', 'prorank-seo'),
                    ['status' => 400]
                );
            }
            
            $sitemap_url = home_url($settings['sitemap_index_url']);
            $results = [];
            
            // Ping Google
            $google_url = 'https://www.google.com/ping?sitemap=' . urlencode($sitemap_url);
            $google_response = wp_remote_get($google_url);
            $results['google'] = !is_wp_error($google_response) && wp_remote_retrieve_response_code($google_response) === 200;
            
            // Ping Bing
            $bing_url = 'https://www.bing.com/ping?sitemap=' . urlencode($sitemap_url);
            $bing_response = wp_remote_get($bing_url);
            $results['bing'] = !is_wp_error($bing_response) && wp_remote_retrieve_response_code($bing_response) === 200;
            
            // Update last ping time
            update_option('prorank_seo_sitemap_last_ping', current_time('mysql'));
            
            return rest_ensure_response([
                'success' => true,
                'message' => __('Sitemap ping requests sent. Search engines may ignore legacy ping endpoints.', 'prorank-seo'),
                'results' => $results,
            ]);
        } catch (\Exception $e) {
            return new WP_Error(
                'prorank_seo_rest_error',
                $e->getMessage(),
                ['status' => 500]
            );
        }
    }
    
    /**
     * Get default settings
     *
     * @return array
     */
    private function get_default_settings(): array {
        return [
            'enable_xml_sitemap' => true,
            'posts_per_sitemap' => 1000,
            'include_post_types' => ['post', 'page'],
            'include_taxonomies' => ['category', 'post_tag'],
            'exclude_empty_terms' => true,
            'include_images' => true,
            'include_featured_images' => true,
            'include_author_archives' => false,
            'author_roles' => ['administrator', 'editor', 'author'],
            'exclude_noindex' => true,
            'ping_search_engines' => true,
            'sitemap_index_url' => 'sitemap_index.xml',
            'exclude_posts' => '',
            'exclude_terms' => '',
            'landing_page_priority_enabled' => false,
            'landing_page_priority' => 0.9,
            'landing_page_patterns' => '',
        ];
    }

    /**
     * Read sitemap settings from the grouped settings store with a legacy
     * fallback for older installs that still use the standalone sitemap option.
     *
     * @return array
     */
    private function get_saved_settings(): array {
        $defaults = $this->get_default_settings();
        $legacy = get_option('prorank_seo_sitemap_settings', []);
        $group = $this->get_settings_manager()->get_settings('sitemaps');

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

    /**
     * Persist sitemap settings to the grouped settings store and the legacy
     * standalone option for backward compatibility.
     *
     * @param array $settings Validated sitemap settings.
     * @return void
     */
    private function persist_settings(array $settings): void {
        $this->get_settings_manager()->update_settings_group('sitemaps', $settings);
        update_option('prorank_seo_sitemap_settings', $settings);
    }

    /**
     * Resolve the settings manager used by runtime modules.
     *
     * @return SettingsManager
     */
    private function get_settings_manager(): SettingsManager {
        return new SettingsManager();
    }
    
    /**
     * Validate settings
     *
     * @param array $settings Settings to validate
     * @return array Validated settings
     */
    private function validate_settings(array $settings): array {
        $defaults = $this->get_default_settings();
        $validated = [];
        
        // Boolean settings
        $bool_settings = [
            'enable_xml_sitemap',
            'exclude_empty_terms',
            'include_images',
            'include_featured_images',
            'include_author_archives',
            'exclude_noindex',
            'ping_search_engines',
            'landing_page_priority_enabled',
        ];
        
        foreach ($bool_settings as $key) {
            $validated[$key] = isset($settings[$key]) ? (bool) $settings[$key] : $defaults[$key];
        }
        
        // Integer settings
        $validated['posts_per_sitemap'] = isset($settings['posts_per_sitemap']) 
            ? max(1, min(50000, (int) $settings['posts_per_sitemap'])) 
            : $defaults['posts_per_sitemap'];

        $validated['landing_page_priority'] = isset($settings['landing_page_priority'])
            ? max(0.0, min(1.0, round((float) $settings['landing_page_priority'], 1)))
            : $defaults['landing_page_priority'];
        
        // Array settings
        $validated['include_post_types'] = isset($settings['include_post_types']) && is_array($settings['include_post_types'])
            ? array_filter($settings['include_post_types'], 'post_type_exists')
            : $defaults['include_post_types'];
        
        $validated['include_taxonomies'] = isset($settings['include_taxonomies']) && is_array($settings['include_taxonomies'])
            ? array_filter($settings['include_taxonomies'], 'taxonomy_exists')
            : $defaults['include_taxonomies'];
        
        // Author roles for author sitemaps (Pro+ feature)
        if (isset($settings['author_roles']) && is_array($settings['author_roles'])) {
            $validated['author_roles'] = array_filter($settings['author_roles'], function($role) {
                return !empty($role) && is_string($role);
            });
        }
        
        // String settings
        $validated['sitemap_index_url'] = isset($settings['sitemap_index_url']) && !empty($settings['sitemap_index_url'])
            ? sanitize_text_field($settings['sitemap_index_url'])
            : $defaults['sitemap_index_url'];
        
        // Exclusion settings - sanitize comma-separated IDs
        $validated['exclude_posts'] = isset($settings['exclude_posts']) 
            ? preg_replace('/[^0-9,]/', '', $settings['exclude_posts'])
            : $defaults['exclude_posts'];
            
        $validated['exclude_terms'] = isset($settings['exclude_terms'])
            ? preg_replace('/[^0-9,]/', '', $settings['exclude_terms'])
            : $defaults['exclude_terms'];

        $validated['landing_page_patterns'] = isset($settings['landing_page_patterns'])
            ? sanitize_textarea_field((string) $settings['landing_page_patterns'])
            : $defaults['landing_page_patterns'];
        
        return $validated;
    }
    
    /**
     * Get settings args for REST API
     *
     * @return array
     */
    private function get_settings_args(): array {
        return [
            'enable_xml_sitemap' => [
                'type' => 'boolean',
                'default' => true,
            ],
            'posts_per_sitemap' => [
                'type' => 'integer',
                'minimum' => 1,
                'maximum' => 50000,
                'default' => 1000,
            ],
            'include_post_types' => [
                'type' => 'array',
                'items' => ['type' => 'string'],
                'default' => ['post', 'page'],
            ],
            'include_taxonomies' => [
                'type' => 'array',
                'items' => ['type' => 'string'],
                'default' => ['category', 'post_tag'],
            ],
            'exclude_empty_terms' => [
                'type' => 'boolean',
                'default' => true,
            ],
            'include_images' => [
                'type' => 'boolean',
                'default' => true,
            ],
            'include_featured_images' => [
                'type' => 'boolean',
                'default' => true,
            ],
            'include_author_archives' => [
                'type' => 'boolean',
                'default' => false,
            ],
            'author_roles' => [
                'type' => 'array',
                'items' => ['type' => 'string'],
                'default' => ['administrator', 'editor', 'author'],
            ],
            'exclude_noindex' => [
                'type' => 'boolean',
                'default' => true,
            ],
            'ping_search_engines' => [
                'type' => 'boolean',
                'default' => true,
            ],
            'sitemap_index_url' => [
                'type' => 'string',
                'default' => 'sitemap_index.xml',
            ],
            'exclude_posts' => [
                'type' => 'string',
                'default' => '',
                'description' => 'Comma-separated list of post IDs to exclude',
            ],
            'exclude_terms' => [
                'type' => 'string',
                'default' => '',
                'description' => 'Comma-separated list of term IDs to exclude',
            ],
            'landing_page_priority_enabled' => [
                'type' => 'boolean',
                'default' => false,
            ],
            'landing_page_priority' => [
                'type' => 'number',
                'minimum' => 0,
                'maximum' => 1,
                'default' => 0.9,
            ],
            'landing_page_patterns' => [
                'type' => 'string',
                'default' => '',
                'description' => 'Comma-separated or line-separated list of landing page IDs, slugs, or URL fragments to boost',
            ],
        ];
    }
}
