<?php

/**
 * Dynamic Variables Parser
 *
 * Handles parsing and replacement of dynamic variables in strings.
 *
 * @package ProRank\SEO\Core
 * @since   1.0.0
 */

declare(strict_types=1);

namespace ProRank\SEO\Core;

use ProRank\SEO\Plugin;

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


/**
 * DynamicVariables class
 *
 * Parses %%variable%% placeholders and replaces them with actual values.
 */


class DynamicVariables {
    
    /**
     * Context object (post, term, etc.)
     *
     * @var mixed
     */
    private $context_object = null;
    
    /**
     * Context type
     *
     * @var string
     */
    private string $context_type = '';
    
    /**
     * Parse a string and replace dynamic variables
     *
     * @param string $string  The string to parse.
     * @param mixed  $context Context object (post, term, etc.).
     * @param string $type    Context type.
     * @return string
     */
    public function parse(string $string, $context = null, string $type = ''): string {
        
        $this->context_object = $context;
        $this->context_type = $type;
        
        // Get all variables
        $variables = $this->get_all_variables();
        
        // Replace variables
        foreach ($variables as $var => $value) {
            $string = str_replace($var, $value, $string);
        }
        
        // Apply filter for extensibility
        $string = apply_filters('prorank_seo_dynamic_variables_parsed', $string, $context, $type);
        
        return $string;
    }
    
    /**
     * Get all available variables with their values
     *
     * @return array
     */
    private function get_all_variables(): array {
        $variables = [];
        
        // Common variables
        $variables = array_merge($variables, $this->get_common_variables());
        
        // Context-specific variables
        switch ($this->context_type) {
            case 'post':
            case 'page':
                $variables = array_merge($variables, $this->get_post_variables());
                break;
                
            case 'term':
            case 'category':
            case 'tag':
                $variables = array_merge($variables, $this->get_term_variables());
                break;
                
            case 'archive':
                $variables = array_merge($variables, $this->get_archive_variables());
                break;
                
            case 'product':
                $variables = array_merge($variables, $this->get_post_variables());
                $variables = array_merge($variables, $this->get_product_variables());
                break;
        }
        
        // Allow filtering
        $variables = apply_filters('prorank_seo_dynamic_variables', $variables, $this->context_object, $this->context_type);
        
        return $variables;
    }
    
    /**
     * Get common variables
     *
     * @return array
     */
    private function get_common_variables(): array {
        return [
            '%%sitename%%' => get_bloginfo('name'),
            '%%tagline%%' => get_bloginfo('description'),
            '%%sep%%' => $this->get_separator(),
            '%%currentyear%%' => gmdate('Y'),
            '%%currentmonth%%' => gmdate('F'),
            '%%currentday%%' => gmdate('j'),
        ];
    }
    
    /**
     * Get post-specific variables
     *
     * @return array
     */
    private function get_post_variables(): array {
        if (!$this->context_object instanceof \WP_Post) {
            return [];
        }
        
        $post = $this->context_object;
        $variables = [
            '%%title%%' => get_the_title($post),
            '%%excerpt%%' => $this->get_excerpt($post),
            '%%author%%' => get_the_author_meta('display_name', $post->post_author),
            '%%date%%' => get_the_date('', $post),
            '%%modified%%' => get_the_modified_date('', $post),
            '%%id%%' => $post->ID,
        ];
        
        // Get primary category
        $category = $this->get_primary_category($post);
        if ($category) {
            $variables['%%category%%'] = $category->name;
        }
        
        // Get focus keyword
        $focus_keyword = FocusKeywords::get_primary($post->ID);
        if ($focus_keyword) {
            $variables['%%focuskeyword%%'] = $focus_keyword;
        }
        
        return $variables;
    }
    
    /**
     * Get term-specific variables
     *
     * @return array
     */
    private function get_term_variables(): array {
        if (!$this->context_object instanceof \WP_Term) {
            return [];
        }
        
        $term = $this->context_object;
        $variables = [
            '%%term_title%%' => $term->name,
            '%%term_description%%' => $term->description,
        ];
        
        // Get term hierarchy
        $hierarchy = $this->get_term_hierarchy($term);
        if ($hierarchy) {
            $variables['%%term_hierarchy%%'] = $hierarchy;
        }
        
        return $variables;
    }
    
    /**
     * Get archive-specific variables
     *
     * @return array
     */
    private function get_archive_variables(): array {
        global $wp_query;
        
        $variables = [
            '%%archive_title%%' => $this->get_archive_title(),
        ];
        
        // Page numbers
        $paged = get_query_var('paged', 1);
        if ($paged > 1) {
            $variables['%%pagenumber%%'] = $paged;
            $variables['%%pagetotal%%'] = $wp_query->max_num_pages;
        }
        
        return $variables;
    }
    
    /**
     * Get product-specific variables
     *
     * @return array
     */
    private function get_product_variables(): array {
        if (!$this->context_object instanceof \WP_Post || $this->context_object->post_type !== 'product') {
            return [];
        }
        
        if (!function_exists('wc_get_product')) {
            return [];
        }
        
        $product = wc_get_product($this->context_object->ID);
        if (!$product) {
            return [];
        }
        
        $variables = [
            '%%product_name%%' => $product->get_name(),
            '%%product_short_description%%' => $product->get_short_description(),
            '%%product_price%%' => $product->get_price_html(),
            '%%product_sku%%' => $product->get_sku(),
        ];
        
        return $variables;
    }
    
    /**
     * Get separator character
     *
     * @return string
     */
    private function get_separator(): string {
        $settings_manager = Plugin::get_instance()->settings();
        $separator = $settings_manager->get('title_separator', 'titles_meta', '');

        if ($separator === '' || $separator === null) {
            $site_basics = get_option('prorank_seo_site_basics', []);
            $separator = $site_basics['title_separator'] ?? '-';
        }

        return ' ' . $separator . ' ';
    }
    
    /**
     * Get post excerpt
     *
     * @param \WP_Post $post Post object.
     * @return string
     */
    private function get_excerpt(\WP_Post $post): string {
        if ($post->post_excerpt) {
            return wp_strip_all_tags($post->post_excerpt);
        }
        
        // Generate excerpt from content
        $content = wp_strip_all_tags($post->post_content);
        $excerpt = wp_trim_words($content, 55, '');
        
        return $excerpt;
    }
    
    /**
     * Get primary category for a post
     *
     * @param \WP_Post $post Post object.
     * @return \WP_Term|null
     */
    private function get_primary_category(\WP_Post $post): ?\WP_Term {
        // Check for primary category meta (from other SEO plugins)
        $primary_cat_id = get_post_meta($post->ID, '_primary_category', true);
        
        if ($primary_cat_id) {
            $term = get_term($primary_cat_id, 'category');
            if ($term && !is_wp_error($term)) {
                return $term;
            }
        }
        
        // Get first category
        $categories = get_the_category($post->ID);
        if (!empty($categories)) {
            return $categories[0];
        }
        
        return null;
    }
    
    /**
     * Get term hierarchy
     *
     * @param \WP_Term $term Term object.
     * @return string
     */
    private function get_term_hierarchy(\WP_Term $term): string {
        $ancestors = get_ancestors($term->term_id, $term->taxonomy, 'taxonomy');
        
        if (empty($ancestors)) {
            return $term->name;
        }
        
        $hierarchy = [];
        foreach (array_reverse($ancestors) as $ancestor_id) {
            $ancestor = get_term($ancestor_id, $term->taxonomy);
            if ($ancestor && !is_wp_error($ancestor)) {
                $hierarchy[] = $ancestor->name;
            }
        }
        
        $hierarchy[] = $term->name;
        
        return implode(' ' . $this->get_separator() . ' ', $hierarchy);
    }
    
    /**
     * Get archive title
     *
     * @return string
     */
    private function get_archive_title(): string {
        if (is_category()) {
            return single_cat_title('', false);
        } elseif (is_tag()) {
            return single_tag_title('', false);
        } elseif (is_author()) {
            return get_the_author();
        } elseif (is_date()) {
            if (is_year()) {
                return get_the_date('Y');
            } elseif (is_month()) {
                return get_the_date('F Y');
            } elseif (is_day()) {
                return get_the_date('F j, Y');
            }
        } elseif (is_post_type_archive()) {
            return post_type_archive_title('', false);
        } elseif (is_tax()) {
            return single_term_title('', false);
        }
        
        return '';
    }
    
    /**
     * Get list of available variables for a context
     *
     * @param string $context Context type.
     * @return array
     */
    public static function get_available_variables(string $context = 'post'): array {
        $variables = [
            'common' => [
                '%%sitename%%' => __('Site Name', 'prorank-seo'),
                '%%tagline%%' => __('Site Tagline', 'prorank-seo'),
                '%%sep%%' => __('Separator', 'prorank-seo'),
                '%%currentyear%%' => __('Current Year', 'prorank-seo'),
                '%%currentmonth%%' => __('Current Month', 'prorank-seo'),
                '%%currentday%%' => __('Current Day', 'prorank-seo'),
            ],
            'post' => [
                '%%title%%' => __('Post Title', 'prorank-seo'),
                '%%excerpt%%' => __('Excerpt', 'prorank-seo'),
                '%%category%%' => __('Primary Category', 'prorank-seo'),
                '%%focuskeyword%%' => __('Focus Keyword', 'prorank-seo'),
                '%%author%%' => __('Author Name', 'prorank-seo'),
                '%%date%%' => __('Publish Date', 'prorank-seo'),
                '%%modified%%' => __('Modified Date', 'prorank-seo'),
                '%%id%%' => __('Post ID', 'prorank-seo'),
            ],
            'term' => [
                '%%term_title%%' => __('Term Title', 'prorank-seo'),
                '%%term_description%%' => __('Term Description', 'prorank-seo'),
                '%%term_hierarchy%%' => __('Term Hierarchy', 'prorank-seo'),
            ],
            'archive' => [
                '%%archive_title%%' => __('Archive Title', 'prorank-seo'),
                '%%pagenumber%%' => __('Page Number', 'prorank-seo'),
                '%%pagetotal%%' => __('Total Pages', 'prorank-seo'),
            ],
            'product' => [
                '%%product_name%%' => __('Product Name', 'prorank-seo'),
                '%%product_short_description%%' => __('Short Description', 'prorank-seo'),
                '%%product_price%%' => __('Product Price', 'prorank-seo'),
                '%%product_sku%%' => __('Product SKU', 'prorank-seo'),
            ],
        ];
        
        return apply_filters('prorank_seo_available_variables', $variables, $context);
    }
}
