<?php

/**
 * Post Sitemap Provider
 *
 * Generates sitemaps for posts
 *
 * @package ProRank\SEO\Modules\Indexing\Sitemaps
 * @since   0.1.0
 */

declare(strict_types=1);

namespace ProRank\SEO\Modules\Indexing\Sitemaps;

use ProRank\SEO\Core\SettingsManager;

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


/**
 * Post sitemap provider class
 */


class PostSitemapProvider extends BaseSitemapProvider {
    
    /**
     * Provider slug
     *
     * @var string
     */
    protected string $slug = 'post';
    
    /**
     * Provider name
     *
     * @var string
     */
    protected string $name = 'Posts';
    
    /**
     * Settings manager instance
     *
     * @var SettingsManager|null
     */
    private ?SettingsManager $settings_manager = null;
    
    /**
     * Constructor
     */
    public function __construct() {
        parent::__construct();
        // Settings manager will be injected if needed
    }
    
    /**
     * Check if provider is enabled
     *
     * @return bool
     */
    public function is_enabled(): bool {
        if (!$this->settings_manager) {
            return true; // Default to enabled
        }
        
        $settings = $this->resolve_sitemap_settings($this->settings_manager);
        $enabled_post_types = $settings['include_post_types'] ?? ['post'];
        
        return in_array('post', $enabled_post_types, true);
    }
    
    /**
     * Get total number of pages
     *
     * @return int
     */
    public function get_total_pages(): int {
        $total_posts = $this->get_total_posts();
        return (int) ceil($total_posts / $this->max_entries);
    }
    
    /**
     * Get total number of posts
     *
     * @return int
     */
    private function get_total_posts(): int {
        $settings = $this->resolve_sitemap_settings($this->settings_manager);

        return count(
            $this->get_sitemap_post_ids(
                'post',
                $settings,
                [
                    'orderby' => 'modified',
                    'order' => 'DESC',
                ]
            )
        );
    }
    
    /**
     * Generate sitemap XML content
     *
     * @param int $page Page number
     * @return string XML content
     */
    public function generate_xml(int $page = 1): string {
        $urls = $this->get_post_urls($page);
        return $this->generate_urlset_xml($urls);
    }
    
    /**
     * Get post URLs for sitemap
     *
     * @param int $page Page number
     * @return array
     */
    private function get_post_urls(int $page): array {
        $offset = ($page - 1) * $this->max_entries;
        
        $settings = $this->resolve_sitemap_settings($this->settings_manager);
        $post_ids = $this->get_sitemap_post_ids(
            'post',
            $settings,
            [
                'orderby' => 'modified',
                'order' => 'DESC',
            ]
        );
        $page_post_ids = array_slice($post_ids, $offset, $this->max_entries);
        $urls = [];

        foreach ($page_post_ids as $post_id) {
            $post = get_post($post_id);
            if (!$post instanceof \WP_Post) {
                continue;
            }

            $url_data = [
                'loc' => get_permalink($post),
                'lastmod' => get_post_modified_time('c', true, $post),
                'changefreq' => $this->get_change_frequency(get_post_modified_time('U', true, $post)),
                'priority' => $this->resolve_post_priority($post, 0.6, $settings)
            ];

            if ($this->should_include_images()) {
                $images = $this->get_post_images($post_id);
                if (!empty($images)) {
                    $url_data['images'] = $images;
                }
            }

            $url_data = apply_filters('prorank_seo_sitemap_url_data', $url_data, $post, 'post');

            $urls[] = $url_data;
        }

        return $urls;
    }
    
    /**
     * Get change frequency based on last modified date
     *
     * @param string $last_modified Unix timestamp
     * @return string
     */
    private function get_change_frequency(string|int $last_modified): string {
        $days_ago = (time() - (int) $last_modified) / DAY_IN_SECONDS;
        
        if ($days_ago < 1) {
            return 'hourly';
        } elseif ($days_ago < 7) {
            return 'daily';
        } elseif ($days_ago < 30) {
            return 'weekly';
        } elseif ($days_ago < 365) {
            return 'monthly';
        }
        
        return 'yearly';
    }
    
    /**
     * Check if images should be included
     *
     * @return bool
     */
    private function should_include_images(): bool {
        if (!$this->settings_manager) {
            return true; // Default to enabled
        }
        
        $settings = $this->resolve_sitemap_settings($this->settings_manager);
        return $settings['include_images'] ?? true;
    }
    
    /**
     * Get images for a post
     *
     * @param int $post_id Post ID
     * @return array
     */
    private function get_post_images(int $post_id): array {
        $images = [];
        
        // Get settings
        $settings = $this->resolve_sitemap_settings($this->settings_manager);
        $include_featured_images = $settings['include_featured_images'] ?? true;
        
        // Get featured image if enabled
        if ($include_featured_images && has_post_thumbnail($post_id)) {
            $thumbnail_id = get_post_thumbnail_id($post_id);
            $image_url = wp_get_attachment_url($thumbnail_id);
            
            if ($image_url) {
                $attachment = get_post($thumbnail_id);
                $images[] = [
                    'loc' => $image_url,
                    'title' => $attachment ? $attachment->post_title : '',
                    'caption' => $attachment ? $attachment->post_excerpt : ''
                ];
            }
        }
        
        // Get images from content
        $post = get_post($post_id);
        if ($post && !empty($post->post_content)) {
            $content_images = $this->extract_images_from_content($post->post_content);
            $images = array_merge($images, $content_images);
        }
        
        // Limit to 1000 images per URL (Google's limit)
        return array_slice($images, 0, 1000);
    }
    
    /**
     * Extract images from post content
     *
     * @param string $content Post content
     * @return array
     */
    private function extract_images_from_content(string $content): array {
        $images = [];
        
        // Find all img tags
        preg_match_all('/<img[^>]+>/i', $content, $matches);
        
        foreach ($matches[0] as $img_tag) {
            // Extract src
            if (preg_match('/src=["\']([^"\']+)["\']/', $img_tag, $src_match)) {
                $image_url = $src_match[1];
                
                // Skip external images
                if (strpos($image_url, home_url()) !== 0) {
                    continue;
                }
                
                $image_data = ['loc' => $image_url];
                
                // Extract alt text as title
                if (preg_match('/alt=["\']([^"\']+)["\']/', $img_tag, $alt_match)) {
                    $image_data['title'] = $alt_match[1];
                }
                
                $images[] = $image_data;
            }
        }
        
        return $images;
    }
    
    /**
     * Get last modified date for sitemap
     *
     * @param int $page Page number
     * @return string ISO 8601 date
     */
    protected function get_last_modified(int $page = 1): string {
        global $wpdb;
        
        $offset = ($page - 1) * $this->max_entries;
        
        $last_modified = $wpdb->get_var(
            $wpdb->prepare(
                "SELECT MAX(post_modified_gmt) FROM {$wpdb->posts} 
                WHERE post_type = %s 
                AND post_status = 'publish' 
                AND post_password = ''
                ORDER BY post_modified_gmt DESC
                LIMIT %d OFFSET %d",
                'post',
                $this->max_entries,
                $offset
            )
        );
        
        return $last_modified ? $this->format_date($last_modified) : $this->format_date('now');
    }
}
