<?php

if (!defined('WPINC')) {
    die;
}

class Aysa_Optimization_Metrics {
    
    private $api_base_url;
    private $project_id;

    private function resolve_api_base_url() {
        if (class_exists('Aysa_API_Config') && method_exists('Aysa_API_Config', 'get_api_base_url')) {
            return rtrim((string) Aysa_API_Config::get_api_base_url(), '/') . '/';
        }

        return 'https://api.aysa.ai/';
    }
    
    public function __construct() {
        $this->api_base_url = $this->resolve_api_base_url();
        $this->project_id = get_option('aysa_project_id', 0);
        
        // Schedule automated metric collection
        add_action('aysa_daily_metrics_calculation', array($this, 'calculate_and_store_metrics'));
        add_action('aysa_weekly_metrics_snapshot', array($this, 'store_weekly_snapshot'));
        
        // Hook into content updates
        add_action('save_post', array($this, 'trigger_metrics_update'), 10, 3);
        add_action('created_term', array($this, 'trigger_metrics_update_term'), 10, 3);
    }
    
    /**
     * Schedule automation tasks
     */
    public function schedule_metrics_tasks() {
        if (!wp_next_scheduled('aysa_daily_metrics_calculation')) {
            wp_schedule_event(time(), 'daily', 'aysa_daily_metrics_calculation');
        }
        
        if (!wp_next_scheduled('aysa_weekly_metrics_snapshot')) {
            wp_schedule_event(strtotime('next sunday'), 'weekly', 'aysa_weekly_metrics_snapshot');
        }
    }
    
    /**
     * Get dashboard data from API
     */
    public function get_dashboard_data() {
        if (!$this->project_id) {
            return $this->get_fallback_data();
        }
        
        $endpoint = "/api/OptimizationMetrics/project/{$this->project_id}/dashboard";
        $response = $this->make_api_request($endpoint, 'GET');
        
        if (is_wp_error($response)) {
            aysa_debug_log('Aysa Optimization Metrics: API Error - ' . $response->get_error_message());
            return $this->get_fallback_data();
        }
        
        return $response;
    }
    
    /**
     * Get current metrics for display
     */
    public function get_current_metrics() {
        $dashboard_data = $this->get_dashboard_data();
        
        if (isset($dashboard_data['currentMetrics'])) {
            return $dashboard_data['currentMetrics'];
        }
        
        return $this->get_fallback_metrics();
    }
    
    /**
     * Get weekly progress comparison
     */
    public function get_weekly_progress_comparison() {
        $dashboard_data = $this->get_dashboard_data();
        
        if (isset($dashboard_data['progressComparison'])) {
            return $dashboard_data['progressComparison'];
        }
        
        return $this->get_fallback_progress();
    }
    
    /**
     * Get chart data for visualization
     */
    public function get_chart_data($weeks = 8) {
        $dashboard_data = $this->get_dashboard_data();
        
        if (isset($dashboard_data['chartData'])) {
            return $dashboard_data['chartData'];
        }
        
        return $this->get_fallback_chart_data($weeks);
    }
    
    /**
     * Calculate and store current metrics
     */
    public function calculate_and_store_metrics() {
        if (!$this->project_id) {
            aysa_debug_log('Aysa Optimization Metrics: No project ID configured');
            return false;
        }
        
        try {
            // Calculate all metrics
            $title_tags = $this->calculate_title_tags_score();
            $meta_descriptions = $this->calculate_meta_descriptions_score();
            $headings = $this->calculate_headings_score();
            $internal_links = $this->calculate_internal_links_score();
            
            // Prepare bulk metrics data
            $bulk_data = array(
                'weekStartDate' => $this->get_week_start_date(),
                'titleTags' => $title_tags,
                'metaDescriptions' => $meta_descriptions,
                'headings' => $headings,
                'internalLinks' => $internal_links
            );
            
            // Send to API
            $endpoint = "/api/OptimizationMetrics/project/{$this->project_id}/bulk";
            $response = $this->make_api_request($endpoint, 'POST', $bulk_data);
            
            if (is_wp_error($response)) {
                aysa_debug_log('Aysa Optimization Metrics: Failed to store metrics - ' . $response->get_error_message());
                return false;
            }
            
            return true;
            
        } catch (Exception $e) {
            aysa_debug_log('Aysa Optimization Metrics: Exception in calculate_and_store_metrics - ' . $e->getMessage());
            return false;
        }
    }
    
    /**
     * Calculate title tags optimization score
     */
    public function calculate_title_tags_score() {
        $posts = get_posts(array(
            'post_type' => array('post', 'page', 'product'),
            'post_status' => 'publish',
            'numberposts' => -1,
            // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_query -- Reviewed WordPress query: the metadata selector is required by the feature and is constrained by the surrounding post type, status, limit, or administrative scope.
            'meta_query' => array(
                'relation' => 'OR',
                array(
                    'key' => '_yoast_wpseo_title',
                    'compare' => 'EXISTS'
                ),
                array(
                    'key' => '_yoast_wpseo_title',
                    'compare' => 'NOT EXISTS'
                )
            )
        ));
        
        $total = count($posts);
        $optimized = 0;
        
        foreach ($posts as $post) {
            $title = get_post_meta($post->ID, '_yoast_wpseo_title', true);
            if (empty($title)) {
                $title = $post->post_title;
            }
            
            if ($this->is_title_optimized($title, $post)) {
                $optimized++;
            }
        }
        
        $score = $total > 0 ? round(($optimized / $total) * 100, 2) : 0;
        
        return array(
            'score' => $score,
            'totalItems' => $total,
            'optimizedItems' => $optimized
        );
    }
    
    /**
     * Calculate meta descriptions optimization score
     */
    public function calculate_meta_descriptions_score() {
        $posts = get_posts(array(
            'post_type' => array('post', 'page', 'product'),
            'post_status' => 'publish',
            'numberposts' => -1
        ));
        
        $total = count($posts);
        $optimized = 0;
        
        foreach ($posts as $post) {
            $meta_desc = get_post_meta($post->ID, '_yoast_wpseo_metadesc', true);
            
            if ($this->is_meta_description_optimized($meta_desc, $post)) {
                $optimized++;
            }
        }
        
        $score = $total > 0 ? round(($optimized / $total) * 100, 2) : 0;
        
        return array(
            'score' => $score,
            'totalItems' => $total,
            'optimizedItems' => $optimized
        );
    }
    
    /**
     * Calculate headings optimization score
     */
    public function calculate_headings_score() {
        $posts = get_posts(array(
            'post_type' => array('post', 'page', 'product'),
            'post_status' => 'publish',
            'numberposts' => -1
        ));
        
        $total = count($posts);
        $optimized = 0;
        
        foreach ($posts as $post) {
            if ($this->is_headings_optimized($post)) {
                $optimized++;
            }
        }
        
        $score = $total > 0 ? round(($optimized / $total) * 100, 2) : 0;
        
        return array(
            'score' => $score,
            'totalItems' => $total,
            'optimizedItems' => $optimized
        );
    }
    
    /**
     * Calculate internal links optimization score
     */
    public function calculate_internal_links_score() {
        $posts = get_posts(array(
            'post_type' => array('post', 'page', 'product'),
            'post_status' => 'publish',
            'numberposts' => -1
        ));
        
        $total = count($posts);
        $optimized = 0;
        
        foreach ($posts as $post) {
            if ($this->is_internal_links_optimized($post)) {
                $optimized++;
            }
        }
        
        $score = $total > 0 ? round(($optimized / $total) * 100, 2) : 0;
        
        return array(
            'score' => $score,
            'totalItems' => $total,
            'optimizedItems' => $optimized
        );
    }
    
    /**
     * Check if title is optimized
     */
    private function is_title_optimized($title, $post) {
        // Use mb_strlen for proper Unicode character counting
        $length = mb_strlen($title, 'UTF-8');
        $has_keyword = $this->has_target_keyword($title, $post->ID);
        
        // Title should be between 30-60 characters and contain target keyword
        // Length is measured in actual characters, not bytes
        return ($length >= 30 && $length <= 60 && $has_keyword);
    }
    
    /**
     * Check if meta description is optimized
     */
    private function is_meta_description_optimized($meta_desc, $post) {
        if (empty($meta_desc)) {
            return false;
        }
        
        // Use mb_strlen for proper Unicode character counting
        $length = mb_strlen($meta_desc, 'UTF-8');
        $has_keyword = $this->has_target_keyword($meta_desc, $post->ID);
        
        // More balanced scoring: length is primary, keyword is bonus
        // Optimal length: 150-160 characters
        // Acceptable length: 140-170 characters
        // Minimum acceptable: 120 characters
        $length_score = 0;
        if ($length >= 150 && $length <= 160) {
            $length_score = 1.0; // Perfect length
        } elseif ($length >= 140 && $length <= 170) {
            $length_score = 0.8; // Good length
        } elseif ($length >= 120 && $length <= 180) {
            $length_score = 0.5; // Acceptable length
        } else {
            $length_score = 0; // Poor length
        }
        
        // Keyword presence gives additional score, but isn't required
        $keyword_bonus = $has_keyword ? 0.3 : 0;
        
        // Uniqueness check (avoid generic descriptions)
        $generic_descriptions = array('lorem ipsum', 'sample text', 'default description', 'add description here', 'enter description');
        $is_unique = true;
        foreach ($generic_descriptions as $generic) {
            if (stripos($meta_desc, $generic) !== false) {
                $is_unique = false;
                break;
            }
        }
        $uniqueness_score = $is_unique ? 0.2 : 0;
        
        // Total score calculation (max 1.5: length 1.0 + keyword 0.3 + uniqueness 0.2)
        $total_score = $length_score + $keyword_bonus + $uniqueness_score;
        
        // Consider optimized if score >= 0.7 (roughly 50% of max possible)
        return $total_score >= 0.7;
    }
    
    /**
     * Check if headings are optimized
     */
    private function is_headings_optimized($post) {
        $content = $post->post_content;
        
        // Check for H1 tag
        $has_h1 = preg_match('/<h1[^>]*>.*?<\/h1>/i', $content);
        
        // Check for proper heading hierarchy (H2, H3, etc.)
        $has_h2 = preg_match('/<h2[^>]*>.*?<\/h2>/i', $content);
        
        // Check if headings contain keywords
        $has_keyword_in_headings = $this->has_keyword_in_headings($content, $post->ID);
        
        return ($has_h1 && $has_h2 && $has_keyword_in_headings);
    }
    
    /**
     * Check if internal links are optimized
     */
    private function is_internal_links_optimized($post) {
        $content = $post->post_content;
        $site_url = home_url();
        
        // Count internal links
        preg_match_all('/<a[^>]+href=["\']([^"\']+)["\'][^>]*>/i', $content, $matches);
        
        $internal_links = 0;
        foreach ($matches[1] as $url) {
            if (strpos($url, $site_url) !== false || strpos($url, '/') === 0) {
                $internal_links++;
            }
        }
        
        // Should have at least 2-3 internal links for longer content
        $word_count = str_word_count(wp_strip_all_tags($content));
        $expected_links = max(2, floor($word_count / 300)); // 1 link per 300 words, minimum 2
        
        return ($internal_links >= $expected_links);
    }
    
    /**
     * Check if content has target keyword
     */
    /**
     * Normalize text by removing diacritics and converting to lowercase
     */
    private function normalize_text($text) {
        if (empty($text)) return '';
        
        // Convert to UTF-8 if not already
        if (!mb_check_encoding($text, 'UTF-8')) {
            $text = mb_convert_encoding($text, 'UTF-8');
        }
        
        // Decompose characters with diacritics and remove the diacritical marks
        $text = normalizer_normalize($text, Normalizer::FORM_D);
        $text = preg_replace('/\p{Mn}/u', '', $text); // Remove diacritics
        
        // Convert to lowercase and trim
        return trim(mb_strtolower($text, 'UTF-8'));
    }

    private function has_target_keyword($text, $post_id) {
        // Try to get focus keyword from Yoast
        $focus_keyword = get_post_meta($post_id, '_yoast_wpseo_focuskw', true);
        
        if (empty($focus_keyword)) {
            // Fallback: extract keywords from title
            $post = get_post($post_id);
            $focus_keyword = $this->extract_primary_keyword($post->post_title);
        }
        
        if (empty($focus_keyword)) {
            return false;
        }
        
        // Normalize both text and keyword for comparison
        $normalized_text = $this->normalize_text($text);
        $normalized_keyword = $this->normalize_text($focus_keyword);
        
        return mb_stripos($normalized_text, $normalized_keyword) !== false;
    }
    
    /**
     * Check if headings contain keywords
     */
    private function has_keyword_in_headings($content, $post_id) {
        $focus_keyword = get_post_meta($post_id, '_yoast_wpseo_focuskw', true);
        
        if (empty($focus_keyword)) {
            return false;
        }
        
        // Normalize the keyword once
        $normalized_keyword = $this->normalize_text($focus_keyword);
        
        // Extract all headings
        preg_match_all('/<h[1-6][^>]*>(.*?)<\/h[1-6]>/i', $content, $matches);
        
        foreach ($matches[1] as $heading) {
            // Normalize the heading text for comparison
            $normalized_heading = $this->normalize_text(wp_strip_all_tags($heading));
            if (mb_stripos($normalized_heading, $normalized_keyword) !== false) {
                return true;
            }
        }
        
        return false;
    }
    
    /**
     * Extract primary keyword from title
     */
    private function extract_primary_keyword($title) {
        // Normalize the title first
        $normalized_title = $this->normalize_text($title);
        
        // Split into words using Unicode-aware pattern
        $words = preg_split('/\s+/u', $normalized_title);
        
        // Expanded stop words list including common words in multiple languages
        $stop_words = array(
            // English
            'the', 'and', 'or', 'but', 'in', 'on', 'at', 'to', 'for', 'of', 'with', 'by', 'a', 'an',
            // Romanian
            'si', 'sau', 'dar', 'in', 'pe', 'la', 'pentru', 'cu', 'de', 'un', 'o', 'niste',
            // Add more languages as needed
        );
        
        $keywords = array_diff($words, $stop_words);
        $keywords = array_filter($keywords, function($word) {
            return mb_strlen($word, 'UTF-8') > 3;
        });
        
        return !empty($keywords) ? reset($keywords) : '';
    }
    
    /**
     * Get week start date (Monday)
     */
    private function get_week_start_date() {
        $date = new DateTime();
        $date->modify('monday this week');
        return $date->format('Y-m-d\TH:i:s\Z');
    }
    
    /**
     * Make API request
     */
    private function make_api_request($endpoint, $method = 'GET', $data = null) {
        $url = rtrim($this->api_base_url, '/') . $endpoint;
        
        $args = array(
            'method' => $method,
            'timeout' => 30,
            'headers' => array(
                'Content-Type' => 'application/json',
                'Accept' => 'application/json',
            )
        );
        
        if ($data && in_array($method, array('POST', 'PUT'))) {
            $args['body'] = json_encode($data);
        }
        
        $response = wp_remote_request($url, $args);
        
        if (is_wp_error($response)) {
            return $response;
        }
        
        $status_code = wp_remote_retrieve_response_code($response);
        $body = wp_remote_retrieve_body($response);
        
        if ($status_code >= 400) {
            return new WP_Error('api_error', "API returned status code: {$status_code}");
        }
        
        return json_decode($body, true);
    }
    
    /**
     * Trigger metrics update when content is saved
     */
    public function trigger_metrics_update($post_id, $post, $update) {
        if (!$update || wp_is_post_revision($post_id) || wp_is_post_autosave($post_id)) {
            return;
        }
        
        if (in_array($post->post_type, array('post', 'page', 'product'))) {
            // Schedule metrics recalculation for next cron run
            wp_schedule_single_event(time() + 300, 'aysa_daily_metrics_calculation'); // 5 minutes delay
        }
    }
    
    /**
     * Trigger metrics update when term is created
     */
    public function trigger_metrics_update_term($term_id, $tt_id, $taxonomy) {
        if (in_array($taxonomy, array('category', 'product_cat', 'post_tag'))) {
            wp_schedule_single_event(time() + 300, 'aysa_daily_metrics_calculation');
        }
    }
    
    /**
     * Store weekly snapshot
     */
    public function store_weekly_snapshot() {
        $this->calculate_and_store_metrics();
    }
    
    /**
     * Get fallback data when API is unavailable
     */
    private function get_fallback_data() {
        return array(
            'currentMetrics' => $this->get_fallback_metrics(),
            'progressComparison' => $this->get_fallback_progress(),
            'chartData' => $this->get_fallback_chart_data(8),
            'lastUpdated' => current_time('c')
        );
    }
    
    /**
     * Get fallback metrics
     */
    private function get_fallback_metrics() {
        return array(
            'overallScore' => 0,
            'titleTags' => array('score' => 0, 'totalItems' => 0, 'optimizedItems' => 0),
            'metaDescriptions' => array('score' => 0, 'totalItems' => 0, 'optimizedItems' => 0),
            'headings' => array('score' => 0, 'totalItems' => 0, 'optimizedItems' => 0),
            'internalLinks' => array('score' => 0, 'totalItems' => 0, 'optimizedItems' => 0)
        );
    }
    
    /**
     * Get fallback progress data
     */
    private function get_fallback_progress() {
        return array(
            'changes' => array(
                'overallChange' => 0,
                'titleTagsChange' => 0,
                'metaDescriptionsChange' => 0,
                'headingsChange' => 0,
                'internalLinksChange' => 0
            )
        );
    }
    
    /**
     * Get fallback chart data
     */
    private function get_fallback_chart_data($weeks) {
        return array(
            'weeks' => array(),
            'overallScores' => array(),
            'titleTagsScores' => array(),
            'metaDescriptionsScores' => array(),
            'headingsScores' => array(),
            'internalLinksScores' => array()
        );
    }
}
