<?php
/**
 * SCHEMAFY SEO Detector Class
 * 
 * Handles detection of meta title and description from various SEO plugins
 * 
 * @package CustomSchemaSchemafy
 * @since 1.1.85
 * @author SCHEMAFY Team
 */

// Prevent direct access
if (!defined('ABSPATH')) {
    exit;
}

/**
 * Class SCHEMAFY_SEO_Detector
 * 
 * Detects and retrieves meta title and description from all major SEO plugins
 */
class SCHEMAFY_SEO_Detector {
    
    /**
     * Validator instance
     * 
     * @var SCHEMAFY_Validator
     */
    private $validator;
    
    /**
     * Constructor
     * 
     * @param SCHEMAFY_Validator $validator Validator instance
     */
    public function __construct($validator) {
        $this->validator = $validator;
    }
    
    /**
     * Get meta title with cascading detection
     * 
     * @param int $post_id Post ID
     * @param string $url Current URL
     * @return string Meta title
     */
    public function get_meta_title($post_id, $url) {
        $meta_title = '';
        
        // 1A: Whatever the site stores for this post — the active SEO plugin's
        // rows when one owns these fields, Schemafy's own otherwise. Same
        // storage the Meta Tags Manager writes to, so both screens agree.
        if ($post_id > 0) {
            list($meta_title) = SCHEMAFY_Meta_Store::get($post_id);
        }

        // 1A.1: If empty, check options table by URL
        if (empty($meta_title) && !empty($url)) {
            $meta_tags = get_option('schemafy_custom_meta_tags', array());
            if (is_array($meta_tags)) {
                foreach ($this->get_meta_url_candidates($url) as $try_url) {
                    if (isset($meta_tags[$try_url]) && !empty($meta_tags[$try_url]['title'])) {
                        $meta_title = $meta_tags[$try_url]['title'];
                        break;
                    }
                }
            }
        }
        
        // 1B: If empty, try Yoast SEO
        if (empty($meta_title)) {
            $meta_title = $this->detect_yoast_title($post_id);
        }
        
        // 1C: If empty, try Rank Math
        if (empty($meta_title)) {
            $meta_title = $this->detect_rankmath_title($post_id);
        }
        
        // 1D: If empty, try All in One SEO
        if (empty($meta_title)) {
            $meta_title = $this->detect_aioseo_title($post_id);
        }
        
        // 1E: If empty, try SEOPress
        if (empty($meta_title)) {
            $meta_title = $this->detect_seopress_title($post_id);
        }
        
        // 1F: If empty, try The SEO Framework
        if (empty($meta_title)) {
            $meta_title = $this->detect_seo_framework_title($post_id);
        }
        
        // 1G: Fallback to WordPress defaults
        if (empty($meta_title)) {
            $meta_title = $this->get_wordpress_default_title($post_id);
        }
        
        // 1H: Fallback to SCHEMAFY table
        if (empty($meta_title)) {
            $meta_title = $this->get_schemafy_fallback_title($url);
        }
        
        // 1I: Process SEO variables
        if (!empty($meta_title)) {
            $meta_title = $this->process_seo_variables($meta_title, $post_id);
        }
        
        return $meta_title;
    }
    
    /**
     * Get meta description with cascading detection
     * 
     * @param int $post_id Post ID
     * @param string $url Current URL
     * @return string Meta description
     */
    public function get_meta_description($post_id, $url) {
        $meta_description = '';
        
        // 1A: See get_meta_title() — one storage, shared with the SEO plugin.
        if ($post_id > 0) {
            list(, $meta_description) = SCHEMAFY_Meta_Store::get($post_id);
        }

        // 1A.1: If empty, check options table by URL
        if (empty($meta_description) && !empty($url)) {
            $meta_tags = get_option('schemafy_custom_meta_tags', array());
            if (is_array($meta_tags)) {
                foreach ($this->get_meta_url_candidates($url) as $try_url) {
                    if (isset($meta_tags[$try_url]) && !empty($meta_tags[$try_url]['description'])) {
                        $meta_description = $meta_tags[$try_url]['description'];
                        break;
                    }
                }
            }
        }
        
        // 1B: If empty, try Yoast SEO
        if (empty($meta_description)) {
            $meta_description = $this->detect_yoast_description($post_id);
        }
        
        // 1C: If empty, try Rank Math
        if (empty($meta_description)) {
            $meta_description = $this->detect_rankmath_description($post_id);
        }
        
        // 1D: If empty, try All in One SEO
        if (empty($meta_description)) {
            $meta_description = $this->detect_aioseo_description($post_id);
        }
        
        // 1E: If empty, try SEOPress
        if (empty($meta_description)) {
            $meta_description = $this->detect_seopress_description($post_id);
        }
        
        // 1F: If empty, try The SEO Framework
        if (empty($meta_description)) {
            $meta_description = $this->detect_seo_framework_description($post_id);
        }
        
        // 1G: Fallback to WordPress defaults
        if (empty($meta_description)) {
            $meta_description = $this->get_wordpress_default_description($post_id);
        }
        
        // 1H: Fallback to SCHEMAFY table
        if (empty($meta_description)) {
            $meta_description = $this->get_schemafy_fallback_description($url);
        }
        
        // 1I: Process SEO variables
        if (!empty($meta_description)) {
            $meta_description = $this->process_seo_variables($meta_description, $post_id);
        }
        
        return $meta_description;
    }
    
    /**
     * Detect Yoast SEO title
     * 
     * @param int $post_id Post ID
     * @return string Title or empty string
     */
    private function detect_yoast_title($post_id) {
        if ($post_id > 0 && defined('WPSEO_VERSION')) {
            return get_post_meta($post_id, '_yoast_wpseo_title', true);
        }
        return '';
    }
    
    /**
     * Detect Yoast SEO description
     * 
     * @param int $post_id Post ID
     * @return string Description or empty string
     */
    private function detect_yoast_description($post_id) {
        if ($post_id > 0 && defined('WPSEO_VERSION')) {
            return get_post_meta($post_id, '_yoast_wpseo_metadesc', true);
        }
        return '';
    }
    
    /**
     * Detect Rank Math title
     * 
     * @param int $post_id Post ID
     * @return string Title or empty string
     */
    private function detect_rankmath_title($post_id) {
        if ($post_id > 0 && class_exists('RankMath')) {
            return get_post_meta($post_id, 'rank_math_title', true);
        }
        return '';
    }
    
    /**
     * Detect Rank Math description
     * 
     * @param int $post_id Post ID
     * @return string Description or empty string
     */
    private function detect_rankmath_description($post_id) {
        if ($post_id > 0 && class_exists('RankMath')) {
            return get_post_meta($post_id, 'rank_math_description', true);
        }
        return '';
    }
    
    /**
     * Detect All in One SEO title
     * 
     * @param int $post_id Post ID
     * @return string Title or empty string
     */
    private function detect_aioseo_title($post_id) {
        if ($post_id > 0 && function_exists('aioseo')) {
            $title = get_post_meta($post_id, '_aioseo_title', true);
            if (!empty($title)) {
                return $title;
            }
        }
        return '';
    }
    
    /**
     * Detect All in One SEO description
     * 
     * @param int $post_id Post ID
     * @return string Description or empty string
     */
    private function detect_aioseo_description($post_id) {
        if ($post_id > 0 && function_exists('aioseo')) {
            $description = get_post_meta($post_id, '_aioseo_description', true);
            if (!empty($description)) {
                return $description;
            }
        }
        return '';
    }
    
    /**
     * Detect SEOPress title
     * 
     * @param int $post_id Post ID
     * @return string Title or empty string
     */
    private function detect_seopress_title($post_id) {
        if ($post_id > 0 && function_exists('seopress_titles_the_title')) {
            return get_post_meta($post_id, '_seopress_titles_title', true);
        }
        return '';
    }
    
    /**
     * Detect SEOPress description
     * 
     * @param int $post_id Post ID
     * @return string Description or empty string
     */
    private function detect_seopress_description($post_id) {
        if ($post_id > 0 && function_exists('seopress_titles_the_title')) {
            return get_post_meta($post_id, '_seopress_titles_desc', true);
        }
        return '';
    }
    
    /**
     * Detect Slim SEO title
     * 
     * @param int $post_id Post ID
     * @return string Title or empty string
     */
    private function detect_slim_seo_title($post_id) {
        if ($post_id > 0 && function_exists('slim_seo')) {
            return get_post_meta($post_id, 'slim_seo_title', true);
        }
        return '';
    }
    
    /**
     * Detect Slim SEO description
     * 
     * @param int $post_id Post ID
     * @return string Description or empty string
     */
    private function detect_slim_seo_description($post_id) {
        if ($post_id > 0 && function_exists('slim_seo')) {
            return get_post_meta($post_id, 'slim_seo_description', true);
        }
        return '';
    }
    
    /**
     * Detect The SEO Framework title
     * 
     * @param int $post_id Post ID
     * @return string Title or empty string
     */
    private function detect_seo_framework_title($post_id) {
        if ($post_id > 0 && function_exists('the_seo_framework')) {
            return get_post_meta($post_id, '_genesis_title', true);
        }
        return '';
    }
    
    /**
     * Detect The SEO Framework description
     * 
     * @param int $post_id Post ID
     * @return string Description or empty string
     */
    private function detect_seo_framework_description($post_id) {
        if ($post_id > 0 && function_exists('the_seo_framework')) {
            return get_post_meta($post_id, '_genesis_description', true);
        }
        return '';
    }
    
    /**
     * Get WordPress default title
     * 
     * @param int $post_id Post ID
     * @return string Title or empty string
     */
    private function get_wordpress_default_title($post_id) {
        if ($post_id > 0) {
            return get_the_title($post_id);
        }
        return '';
    }
    
    /**
     * Get WordPress default description
     * 
     * @param int $post_id Post ID
     * @return string Description or empty string
     */
    private function get_wordpress_default_description($post_id) {
        if ($post_id > 0) {
            $description = get_the_excerpt($post_id);
            if (empty($description)) {
                $post_content = get_post_field('post_content', $post_id);
                $description = wp_trim_words(wp_strip_all_tags($post_content), 30, '...');
            }
            return $description;
        }
        return '';
    }
    
    /**
     * Get fallback title from SCHEMAFY table
     * 
     * @param string $url Current URL
     * @return string Title or empty string
     */
    private function get_schemafy_fallback_title($url) {
        global $wpdb;
        $table_name = $wpdb->prefix . 'schemafy_custom_schemas';

        $normalized = untrailingslashit(strtok($url, '?'));
        $meta = $wpdb->get_var($wpdb->prepare(
            "SELECT meta_title FROM $table_name
             WHERE (url = %s OR url = %s) AND is_active = 1 AND meta_title IS NOT NULL AND meta_title != ''
             ORDER BY updated_at DESC LIMIT 1",
            $normalized,
            trailingslashit($normalized)
        ));

        return $meta ? $meta : '';
    }
    
    /**
     * Get fallback description from SCHEMAFY table
     * 
     * @param string $url Current URL
     * @return string Description or empty string
     */
    private function get_schemafy_fallback_description($url) {
        global $wpdb;
        $table_name = $wpdb->prefix . 'schemafy_custom_schemas';

        $normalized = untrailingslashit(strtok($url, '?'));
        $meta = $wpdb->get_var($wpdb->prepare(
            "SELECT meta_description FROM $table_name
             WHERE (url = %s OR url = %s) AND is_active = 1 AND meta_description IS NOT NULL AND meta_description != ''
             ORDER BY updated_at DESC LIMIT 1",
            $normalized,
            trailingslashit($normalized)
        ));

        return $meta ? $meta : '';
    }
    
    /**
     * Process SEO plugin variables (Yoast, Rank Math, etc.)
     * 
     * @param string $text Text containing variables
     * @param int $post_id Post ID
     * @return string Processed text
     */
    public function process_seo_variables($text, $post_id = 0) {
        if (empty($text)) {
            return $text;
        }
        
        $post = null;
        if ($post_id > 0) {
            $post = get_post($post_id);
        }
        
        // Common SEO variables
        $replacements = array(
            // Yoast style (double %%)
            '%%title%%' => $post ? get_the_title($post_id) : '',
            '%%sitename%%' => get_bloginfo('name'),
            '%%sitedesc%%' => get_bloginfo('description'),
            '%%sep%%' => '-',
            '%%excerpt%%' => $post ? wp_trim_words(wp_strip_all_tags($post->post_content), 30) : '',
            
            // Rank Math style (single %)
            '%title%' => $post ? get_the_title($post_id) : '',
            '%sitename%' => get_bloginfo('name'),
            '%sitedesc%' => get_bloginfo('description'),
            '%sep%' => '-',
            '%excerpt%' => $post ? wp_trim_words(wp_strip_all_tags($post->post_content), 30) : '',
        );
        
        // Replace all variables
        foreach ($replacements as $var => $value) {
            $text = str_replace($var, $value, $text);
        }
        
        return $text;
    }

    /**
     * Get Open Graph title from SEO plugins
     *
     * @param int $post_id Post ID
     * @return string OG title or empty string
     */
    public function get_og_title_from_seo_plugins($post_id) {
        if ($post_id <= 0) {
            return '';
        }

        // Try Yoast SEO
        if (defined('WPSEO_VERSION')) {
            $og_title = get_post_meta($post_id, '_yoast_wpseo_opengraph-title', true);
            if (!empty($og_title)) {
                return $this->process_seo_variables($og_title, $post_id);
            }
        }

        // Try Rank Math
        if (class_exists('RankMath')) {
            $og_title = get_post_meta($post_id, 'rank_math_facebook_title', true);
            if (!empty($og_title)) {
                return $this->process_seo_variables($og_title, $post_id);
            }
        }

        // Try All in One SEO
        if (function_exists('aioseo')) {
            $og_title = get_post_meta($post_id, '_aioseo_og_title', true);
            if (!empty($og_title)) {
                return $og_title;
            }
        }

        // Fallback to regular meta title
        return $this->get_meta_title($post_id, '');
    }

    /**
     * Get Open Graph description from SEO plugins
     *
     * @param int $post_id Post ID
     * @return string OG description or empty string
     */
    public function get_og_description_from_seo_plugins($post_id) {
        if ($post_id <= 0) {
            return '';
        }

        // Try Yoast SEO
        if (defined('WPSEO_VERSION')) {
            $og_desc = get_post_meta($post_id, '_yoast_wpseo_opengraph-description', true);
            if (!empty($og_desc)) {
                return $this->process_seo_variables($og_desc, $post_id);
            }
        }

        // Try Rank Math
        if (class_exists('RankMath')) {
            $og_desc = get_post_meta($post_id, 'rank_math_facebook_description', true);
            if (!empty($og_desc)) {
                return $this->process_seo_variables($og_desc, $post_id);
            }
        }

        // Try All in One SEO
        if (function_exists('aioseo')) {
            $og_desc = get_post_meta($post_id, '_aioseo_og_description', true);
            if (!empty($og_desc)) {
                return $og_desc;
            }
        }

        // Fallback to regular meta description
        return $this->get_meta_description($post_id, '');
    }

    /**
     * Get Open Graph image from SEO plugins
     *
     * @param int $post_id Post ID
     * @return string OG image URL or empty string
     */
    public function get_og_image_from_seo_plugins($post_id) {
        if ($post_id <= 0) {
            return '';
        }

        // Try Yoast SEO
        if (defined('WPSEO_VERSION')) {
            $og_image = get_post_meta($post_id, '_yoast_wpseo_opengraph-image', true);
            if (!empty($og_image)) {
                return $og_image;
            }
        }

        // Try Rank Math
        if (class_exists('RankMath')) {
            $og_image = get_post_meta($post_id, 'rank_math_facebook_image', true);
            if (!empty($og_image)) {
                return $og_image;
            }
        }

        // Try All in One SEO
        if (function_exists('aioseo')) {
            $og_image = get_post_meta($post_id, '_aioseo_og_image', true);
            if (!empty($og_image)) {
                return $og_image;
            }
        }

        // Fallback to featured image
        if (has_post_thumbnail($post_id)) {
            return get_the_post_thumbnail_url($post_id, 'large');
        }

        return '';
    }

    /**
     * Get Twitter Card title from SEO plugins
     *
     * @param int $post_id Post ID
     * @return string Twitter title or empty string
     */
    public function get_twitter_title_from_seo_plugins($post_id) {
        if ($post_id <= 0) {
            return '';
        }

        // Try Yoast SEO
        if (defined('WPSEO_VERSION')) {
            $twitter_title = get_post_meta($post_id, '_yoast_wpseo_twitter-title', true);
            if (!empty($twitter_title)) {
                return $this->process_seo_variables($twitter_title, $post_id);
            }
        }

        // Try Rank Math
        if (class_exists('RankMath')) {
            $twitter_title = get_post_meta($post_id, 'rank_math_twitter_title', true);
            if (!empty($twitter_title)) {
                return $this->process_seo_variables($twitter_title, $post_id);
            }
        }

        // Try All in One SEO
        if (function_exists('aioseo')) {
            $twitter_title = get_post_meta($post_id, '_aioseo_twitter_title', true);
            if (!empty($twitter_title)) {
                return $twitter_title;
            }
        }

        // Fallback to OG title or meta title
        return $this->get_og_title_from_seo_plugins($post_id);
    }

    /**
     * Get Twitter Card description from SEO plugins
     *
     * @param int $post_id Post ID
     * @return string Twitter description or empty string
     */
    public function get_twitter_description_from_seo_plugins($post_id) {
        if ($post_id <= 0) {
            return '';
        }

        // Try Yoast SEO
        if (defined('WPSEO_VERSION')) {
            $twitter_desc = get_post_meta($post_id, '_yoast_wpseo_twitter-description', true);
            if (!empty($twitter_desc)) {
                return $this->process_seo_variables($twitter_desc, $post_id);
            }
        }

        // Try Rank Math
        if (class_exists('RankMath')) {
            $twitter_desc = get_post_meta($post_id, 'rank_math_twitter_description', true);
            if (!empty($twitter_desc)) {
                return $this->process_seo_variables($twitter_desc, $post_id);
            }
        }

        // Try All in One SEO
        if (function_exists('aioseo')) {
            $twitter_desc = get_post_meta($post_id, '_aioseo_twitter_description', true);
            if (!empty($twitter_desc)) {
                return $twitter_desc;
            }
        }

        // Fallback to OG description or meta description
        return $this->get_og_description_from_seo_plugins($post_id);
    }

    /**
     * Get Twitter Card image from SEO plugins
     *
     * @param int $post_id Post ID
     * @return string Twitter image URL or empty string
     */
    public function get_twitter_image_from_seo_plugins($post_id) {
        if ($post_id <= 0) {
            return '';
        }

        // Try Yoast SEO
        if (defined('WPSEO_VERSION')) {
            $twitter_image = get_post_meta($post_id, '_yoast_wpseo_twitter-image', true);
            if (!empty($twitter_image)) {
                return $twitter_image;
            }
        }

        // Try Rank Math
        if (class_exists('RankMath')) {
            $twitter_image = get_post_meta($post_id, 'rank_math_twitter_image', true);
            if (!empty($twitter_image)) {
                return $twitter_image;
            }
        }

        // Try All in One SEO
        if (function_exists('aioseo')) {
            $twitter_image = get_post_meta($post_id, '_aioseo_twitter_image', true);
            if (!empty($twitter_image)) {
                return $twitter_image;
            }
        }

        // Fallback to OG image
        return $this->get_og_image_from_seo_plugins($post_id);
    }

    /**
     * Get detected SEO plugin name
     *
     * @return string Plugin name or 'None'
     */
    public function get_detected_seo_plugin() {
        if (defined('WPSEO_VERSION')) {
            return 'Yoast SEO';
        }
        if (class_exists('RankMath')) {
            return 'Rank Math';
        }
        if (function_exists('aioseo')) {
            return 'All in One SEO';
        }
        if (function_exists('seopress_titles_the_title')) {
            return 'SEOPress';
        }
        if (function_exists('the_seo_framework')) {
            return 'The SEO Framework';
        }
        if (function_exists('slim_seo')) {
            return 'Slim SEO';
        }
        return 'None';
    }

    /**
     * Return URL variants used by older and newer Schemafy meta storage.
     *
     * @param string $url URL.
     * @return array
     */
    private function get_meta_url_candidates($url) {
        $normalized = $this->normalize_meta_url($url);
        $candidates = array_filter(array(esc_url_raw($url), $normalized));

        foreach ($candidates as $candidate) {
            if (strpos($candidate, '?') !== false) {
                continue;
            }

            $candidates[] = trailingslashit($candidate);
            $candidates[] = untrailingslashit($candidate);
        }

        if (empty($candidates) && $url !== '') {
            $candidates[] = (string) $url;
        }

        return array_values(array_unique(array_filter($candidates)));
    }

    /**
     * Normalize a URL key for Schemafy meta storage lookup.
     *
     * @param string $url URL.
     * @return string
     */
    private function normalize_meta_url($url) {
        $url = trim((string) $url);
        if ($url === '') {
            return '';
        }

        $url = esc_url_raw($url);
        if (!$url) {
            return '';
        }

        $parts = wp_parse_url($url);
        if (empty($parts['scheme']) || empty($parts['host']) || !in_array(strtolower($parts['scheme']), array('http', 'https'), true)) {
            return '';
        }

        $scheme = strtolower($parts['scheme']);
        $host = strtolower($parts['host']);
        $path = isset($parts['path']) ? preg_replace('#/+#', '/', $parts['path']) : '/';
        $path = '/' . ltrim((string) $path, '/');
        $path = $path === '/' ? '/' : untrailingslashit($path);
        $port = '';

        if (!empty($parts['port'])) {
            $default_port = $scheme === 'https' ? 443 : 80;
            if ((int) $parts['port'] !== $default_port) {
                $port = ':' . absint($parts['port']);
            }
        }

        $query = isset($parts['query']) && $parts['query'] !== '' ? '?' . $parts['query'] : '';

        return esc_url_raw($scheme . '://' . $host . $port . $path . $query);
    }
}
