<?php
/**
 * Tam Rank™ Total Score Calculator
 *
 * Combineert Meta Score (30%) en Content Score (70%) tot één TamRank™ Score.
 * Biedt ook Schema status tracking (geen score, alleen status).
 *
 * @package TamRank
 * @subpackage Content
 * @since 6.3.0
 */

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

class TamRank_Total_Score
{

    /**
     * Singleton instance
     *
     * @var TamRank_Total_Score
     */
    private static $instance = null;

    /**
     * Score wegingen
     */
    const META_WEIGHT = 0.30;    // 30% voor Meta score
    const CONTENT_WEIGHT = 0.70; // 70% voor Content score

    /**
     * Score drempelwaarden
     */
    const THRESHOLD_EXCELLENT = 80; // 80-100% = groen
    const THRESHOLD_GOOD = 60;      // 60-79% = blauw
    const THRESHOLD_FAIR = 40;      // 40-59% = oranje
    // 0-39% = roze

    /**
     * Score-kleuren — design-system status palette (variables.css /
     * TamRank_Meta_Calculator). Constant names kept for back-compat; values
     * updated from the old brand palette to the current one.
     */
    const COLOR_GREEN = '#10b981';  // status-excellent
    const COLOR_BLUE = '#14b8a6';   // status-good (teal)
    const COLOR_ORANGE = '#f59e0b'; // status-attention
    const COLOR_PINK = '#f43f5e';   // status-improve

    /**
     * Constructor
     */
    private function __construct()
    {
        // Registreer AJAX handlers
        add_action('wp_ajax_tamrank_get_total_score', array($this, 'ajax_get_total_score'));

        // Invalideer content score cache bij post save
        add_action('save_post', array($this, 'invalidate_content_score_cache'), 10, 1);

        // Update audit score bij post save (Meta score)
        // UITGESCHAKELD: Nu afgehandeld door TamRank_Score_Service
        // add_action('save_post', array($this, 'update_audit_score_on_save'), 10, 2);
    }

    /**
     * Invalideer content score cache wanneer een post wordt opgeslagen
     *
     * @param int $post_id Post ID
     */
    public function invalidate_content_score_cache($post_id)
    {
        // Skip autosaves en revisies
        if (wp_is_post_autosave($post_id) || wp_is_post_revision($post_id)) {
            return;
        }

        // Verwijder cache time zodat score opnieuw berekend wordt
        delete_post_meta($post_id, '_tam_rank_content_score_time');
    }

    /**
     * Update de audit score (Meta SEO) direct bij het opslaan van een post
     *
     * Dit zorgt ervoor dat het dashboard altijd up-to-date blijft zonder
     * dat er eerst een bulk audit nodig is.
     *
     * @param int $post_id Post ID
     * @param WP_Post $post Post object
     */
    public function update_audit_score_on_save($post_id, $post)
    {
        // 1. PERFORMANCE GUARDS
        // =====================

        // Skip autosaves en revisies
        if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) {
            return;
        }

        if (wp_is_post_revision($post_id) || wp_is_post_autosave($post_id)) {
            return;
        }

        // Alleen published posts
        if ($post->post_status !== 'publish') {
            return;
        }

        // Alleen ondersteunde post types (posts en pages)
        // We gebruiken hier een hardcoded lijst voor performance (geen optie lookup)
        if (!in_array($post->post_type, array('post', 'page'))) {
            return;
        }

        // 2. BEREKENING (LICHTGEWICHT)
        // ============================

        // Gebruik de bestaande calculate_meta_score functie
        // Deze doet ALLEEN string analyses en database lookups
        // GEEN API calls, GEEN AI requests, GEEN zware parsing
        $score = $this->calculate_meta_score($post);

        // 3. PERSISTENCE
        // ==============

        // Sla de score op in dezelfde meta key die de bulk audit gebruikt
        update_post_meta($post_id, '_tam_rank_audit_score', $score);
    }

    /**
     * Get singleton instance
     *
     * @return TamRank_Total_Score
     */
    public static function get_instance()
    {
        if (null === self::$instance) {
            self::$instance = new self();
        }
        return self::$instance;
    }

    /**
     * Bereken de Meta Score (0-100)
     *
     * Gebaseerd op de bestaande calculate_live_score logica
     *
     * @param WP_Post|int $post Post object of ID
     * @return int Score 0-100
     */
    public function calculate_meta_score($post)
    {
        if (is_numeric($post)) {
            $post = get_post($post);
        }

        if (!$post) {
            return 0;
        }

        $score = 0;
        $max_score = 50;

        // Get meta fields
        $meta_title = get_post_meta($post->ID, '_tam_rank_meta_title', true);
        $meta_description = get_post_meta($post->ID, '_tam_rank_meta_description', true);
        $focus_keyword = get_post_meta($post->ID, '_tam_rank_focus_keyword', true);

        // Use defaults if empty
        if (empty($meta_title)) {
            $meta_title = $post->post_title;
        }

        // Check Meta Title (15 points max)
        if (!empty($meta_title)) {
            $title_length = strlen($meta_title);

            // Length check (10 points)
            if ($title_length >= 30 && $title_length <= 60) {
                $score += 10;
            } elseif ($title_length > 0 && $title_length < 30) {
                $score += 3;
            } elseif ($title_length > 60) {
                $score += 5;
            }

            // Focus keyword in title (5 points)
            if ($focus_keyword && TamRank_Meta_Calculator::keyword_exists($meta_title, $focus_keyword)) {
                $score += 5;
            }
        }

        // Check Meta Description (15 points max)
        if (!empty($meta_description)) {
            $desc_length = strlen($meta_description);

            // Length check (10 points)
            if ($desc_length >= 120 && $desc_length <= 160) {
                $score += 10;
            } elseif ($desc_length > 0 && $desc_length < 120) {
                $score += 3;
            } elseif ($desc_length > 160) {
                $score += 5;
            }

            // Focus keyword in description (5 points)
            if ($focus_keyword && TamRank_Meta_Calculator::keyword_exists($meta_description, $focus_keyword)) {
                $score += 5;
            }
        }

        // Check Focus Keyword (10 points)
        if (!empty($focus_keyword)) {
            $score += 10;
        }

        // Check URL/Slug (10 points)
        $custom_slug = get_post_meta($post->ID, '_tam_rank_custom_slug', true);
        $current_slug = $post->post_name;

        if (!empty($custom_slug) || !empty($current_slug)) {
            $slug_to_check = !empty($custom_slug) ? $custom_slug : $current_slug;

            // Slug contains keyword (5 points)
            if ($focus_keyword && TamRank_Meta_Calculator::keyword_exists($slug_to_check, sanitize_title($focus_keyword))) {
                $score += 5;
            }

            // Slug is not too long (5 points)
            if (strlen($slug_to_check) <= 60) {
                $score += 5;
            }
        }

        // Convert to percentage (0-100)
        return min(100, max(0, round(($score / $max_score) * 100)));
    }

    /**
     * Haal de Content Score op (0-100)
     *
     * Content score komt van de TamRank_Content_Analyzer
     * Met caching voor performance in audit overzichten
     *
     * @param WP_Post|int $post Post object of ID
     * @param bool $force_refresh Forceer herberekening (skip cache)
     * @return int Score 0-100
     */
    public function get_content_score($post, $force_refresh = false)
    {
        if (is_numeric($post)) {
            $post = get_post($post);
        }

        if (!$post) {
            return 0;
        }

        // Check voor gecachte score (tenzij force refresh)
        if (!$force_refresh) {
            $cached_score = get_post_meta($post->ID, '_tam_rank_content_score', true);
            $cache_time = get_post_meta($post->ID, '_tam_rank_content_score_time', true);
            $post_modified = strtotime($post->post_modified);

            // Cache is geldig als:
            // 1. Score bestaat
            // 2. Cache time bestaat
            // 3. Cache is nieuwer dan post modificatie
            // 4. Cache is niet ouder dan 24 uur
            if ($cached_score !== '' && $cache_time) {
                $cache_age = time() - intval($cache_time);
                $is_recent = $cache_age < 86400; // 24 uur
                $is_after_edit = intval($cache_time) >= $post_modified;

                if ($is_recent && $is_after_edit) {
                    return intval($cached_score);
                }
            }
        }

        // Laad de content analyzer
        if (!class_exists('TamRank_Content_Analyzer')) {
            require_once dirname(__FILE__) . '/class-tamrank-content-analyzer.php';
        }

        $analyzer = new TamRank_Content_Analyzer();
        $focus_keyword = get_post_meta($post->ID, '_tam_rank_focus_keyword', true);
        $content = $post->post_content;

        // Voer analyse uit
        $result = $analyzer->analyze($content, $focus_keyword, $post->ID);
        $score = isset($result['score']) ? intval($result['score']) : 0;

        // Sla score op in cache
        update_post_meta($post->ID, '_tam_rank_content_score', $score);
        update_post_meta($post->ID, '_tam_rank_content_score_time', time());

        return $score;
    }

    /**
     * Bereken de Total Score
     *
     * Formule: total_score = round(meta_score * 0.30 + content_score * 0.70)
     *
     * @param int $meta_score Meta score (0-100)
     * @param int $content_score Content score (0-100)
     * @return int Total score (0-100)
     */
    public function calculate_total_score($meta_score, $content_score)
    {
        return round($meta_score * self::META_WEIGHT + $content_score * self::CONTENT_WEIGHT);
    }

    /**
     * Haal de Schema status op
     *
     * Schema heeft geen score, alleen een status indicator
     *
     * @param WP_Post|int $post Post object of ID
     * @return array Status met type en label
     */
    public function get_schema_status($post)
    {
        if (is_numeric($post)) {
            $post = get_post($post);
        }

        if (!$post) {
            return array(
                'status' => 'none',
                'label' => tamrank__('no_schema', 'No schema'),
                'icon' => 'warning',
                'types' => array()
            );
        }

        // Check of schema is ingeschakeld voor deze post
        $schema_enabled = get_post_meta($post->ID, 'tamrank_schema_enabled', true);
        $schema_bron = get_post_meta($post->ID, 'tamrank_schema_bron', true);

        // Default naar 'automatisch' als geen bron is ingesteld
        if (empty($schema_bron)) {
            $schema_bron = 'automatisch';
        }

        // Als bron is 'geen', return geen schema
        if ($schema_bron === 'geen') {
            return array(
                'status' => 'none',
                'label' => tamrank__('no_schema', 'No schema'),
                'icon' => 'warning',
                'types' => array()
            );
        }

        // Haal schema types op uit verschillende bronnen
        $hoofd_schema = '';
        $extra_schemas = array();

        // 1. Probeer eerst de automatisch gedetecteerde schema's (meest betrouwbaar)
        $auto_type = get_post_meta($post->ID, '_tamrank_schema_auto_type', true);
        $auto_extras = get_post_meta($post->ID, '_tamrank_schema_auto_extras', true);

        if (!empty($auto_type)) {
            $hoofd_schema = $auto_type;
            if (!empty($auto_extras) && is_array($auto_extras)) {
                $extra_schemas = $auto_extras;
            }
        }

        // 2. Fallback naar metabox data detectie
        if (empty($hoofd_schema)) {
            $metabox_data = get_post_meta($post->ID, '_tamrank_schema_metabox_data', true);
            if (is_array($metabox_data) && isset($metabox_data['detectie'])) {
                if (!empty($metabox_data['detectie']['hoofd_schema'])) {
                    $hoofd_schema = $metabox_data['detectie']['hoofd_schema'];
                }
                if (!empty($metabox_data['detectie']['extra_schemas']) && is_array($metabox_data['detectie']['extra_schemas'])) {
                    $extra_schemas = $metabox_data['detectie']['extra_schemas'];
                }
            }
        }

        // 3. Fallback naar legacy schema_type meta
        if (empty($hoofd_schema)) {
            $hoofd_schema = get_post_meta($post->ID, 'tamrank_schema_type', true);
        }

        // Bouw array van alle schema types
        $all_types = array();
        if (!empty($hoofd_schema)) {
            $all_types[] = $hoofd_schema;
        }
        if (!empty($extra_schemas) && is_array($extra_schemas)) {
            $all_types = array_merge($all_types, $extra_schemas);
        }

        // BreadcrumbList wordt ALTIJD toegevoegd voor posts, pages en products
        if (tamrank_post_type_has_breadcrumb_schema($post->post_type)) {
            if (!in_array('BreadcrumbList', $all_types, true)) {
                $all_types[] = 'BreadcrumbList';
            }
        }

        $all_types = array_unique(array_filter($all_types));

        // Bepaal status
        if (!empty($all_types)) {
            $status = ($schema_bron === 'automatisch') ? 'auto' : 'active';
            $label = ($schema_bron === 'automatisch') ? tamrank__('schema_auto', 'Schema Auto') : tamrank__('schema_active', 'Schema Active');

            // Als schema enabled is of types gevonden, markeer als actief
            if ($schema_enabled === '1' || $schema_enabled === 'yes' || $schema_bron === 'template') {
                $status = 'active';
                $label = tamrank__('schema_active', 'Schema Active');
            }

            return array(
                'status' => $status,
                'label' => $label,
                'type' => $hoofd_schema,
                'types' => $all_types,
                'bron' => $schema_bron,
                'icon' => $status === 'active' ? 'check' : 'info'
            );
        }

        // 4. Probeer live detectie als laatste optie
        if (class_exists('TAMRANK_Schema_Detector_Manager') && method_exists('TAMRANK_Schema_Detector_Manager', 'krijg_instantie')) {
            $detector_manager = TAMRANK_Schema_Detector_Manager::krijg_instantie();
            if ($detector_manager && method_exists($detector_manager, 'voer_detectie_uit')) {
                $detectie_result = $detector_manager->voer_detectie_uit($post);
                if ($detectie_result && is_object($detectie_result) && method_exists($detectie_result, 'is_geldig') && $detectie_result->is_geldig()) {
                    $hoofd_schema = $detectie_result->krijg_hoofd_schema();
                    $extra_schemas = $detectie_result->krijg_extra_schemas();

                    $all_types = array($hoofd_schema);
                    if (!empty($extra_schemas) && is_array($extra_schemas)) {
                        $all_types = array_merge($all_types, $extra_schemas);
                    }

                    // BreadcrumbList wordt ALTIJD toegevoegd voor posts, pages en products
                    if (tamrank_post_type_has_breadcrumb_schema($post->post_type)) {
                        if (!in_array('BreadcrumbList', $all_types, true)) {
                            $all_types[] = 'BreadcrumbList';
                        }
                    }

                    $all_types = array_unique(array_filter($all_types));

                    if (!empty($all_types)) {
                        return array(
                            'status' => 'auto',
                            'label' => __('Auto-detection', 'tam-rank'),
                            'type' => $hoofd_schema,
                            'types' => $all_types,
                            'bron' => 'automatisch',
                            'icon' => 'info'
                        );
                    }
                }
            }
        }

        // Render fallback: class-schema-render.php::is_schema_enabled() defaults
        // to TRUE when meta is missing, and $schema_bron 'geen' is handled above.
        // If schema is not explicitly disabled, schema WILL be rendered — so the
        // status should mirror that instead of reporting 'none'. This prevents
        // audit/onboarding from reporting 0% on fresh installs where no detector
        // has run yet.
        if ($schema_enabled !== '0') {
            $post_type = $post->post_type;
            if ($post_type === 'post') {
                $fallback_type = 'BlogPosting';
            } elseif ($post_type === 'product') {
                $fallback_type = 'Product';
            } else {
                $fallback_type = 'WebPage';
            }

            $fallback_types = array($fallback_type);
            if (tamrank_post_type_has_breadcrumb_schema($post_type)) {
                $fallback_types[] = 'BreadcrumbList';
            }

            return array(
                'status' => 'auto',
                'label' => tamrank__('schema_auto', 'Schema Auto'),
                'type' => $fallback_type,
                'types' => $fallback_types,
                'bron' => 'automatisch',
                'icon' => 'info',
            );
        }

        return array(
            'status' => 'none',
            'label' => tamrank__('no_schema', 'No schema'),
            'icon' => 'warning',
            'types' => array()
        );
    }

    /**
     * Krijg de kleur voor een score
     *
     * @param int $score Score (0-100)
     * @return string Hex kleurcode
     */
    public function get_score_color($score)
    {
        if ($score >= self::THRESHOLD_EXCELLENT) {
            return self::COLOR_GREEN;
        } elseif ($score >= self::THRESHOLD_GOOD) {
            return self::COLOR_BLUE;
        } elseif ($score >= self::THRESHOLD_FAIR) {
            return self::COLOR_ORANGE;
        }
        return self::COLOR_PINK;
    }

    /**
     * Krijg het label voor een score
     *
     * @param int $score Score (0-100)
     * @return string Label
     */
    public function get_score_label($score)
    {
        if ($score >= self::THRESHOLD_EXCELLENT) {
            return __('Excellent', 'tam-rank');
        } elseif ($score >= self::THRESHOLD_GOOD) {
            return __('Good', 'tam-rank');
        } elseif ($score >= self::THRESHOLD_FAIR) {
            return __('Needs attention', 'tam-rank');
        }
        return __('Improve', 'tam-rank');
    }

    /**
     * Krijg alle score data voor een post
     *
     * @param WP_Post|int $post Post object of ID
     * @return array Complete score data
     */
    public function get_score_data($post)
    {
        if (is_numeric($post)) {
            $post = get_post($post);
        }

        $meta_score = $this->calculate_meta_score($post);
        $content_score = $this->get_content_score($post);
        $total_score = $this->calculate_total_score($meta_score, $content_score);
        $schema_status = $this->get_schema_status($post);

        // Get secondary keywords bonus
        $bonus_data = $this->get_secondary_keywords_bonus($post);

        return array(
            'total' => array(
                'score' => $total_score,
                'color' => $this->get_score_color($total_score),
                'label' => $this->get_score_label($total_score),
            ),
            'meta' => array(
                'score' => $meta_score,
                'color' => $this->get_score_color($meta_score),
                'label' => $this->get_score_label($meta_score),
                'weight' => intval(self::META_WEIGHT * 100),
            ),
            'content' => array(
                'score' => $content_score,
                'color' => $this->get_score_color($content_score),
                'label' => $this->get_score_label($content_score),
                'weight' => intval(self::CONTENT_WEIGHT * 100),
            ),
            'schema' => $schema_status,
            'secondary_keywords_bonus' => $bonus_data,
        );
    }

    /**
     * AJAX handler voor score ophalen
     */
    public function ajax_get_total_score()
    {
        // Controleer nonce
        if (!isset($_POST['nonce']) || !wp_verify_nonce(sanitize_text_field(wp_unslash($_POST['nonce'])), 'tamrank_total_score_nonce')) {
            wp_send_json_error(array('message' => tamrank__('error_security_token', 'Invalid security token. Please refresh the page.'), 'code' => 'nonce_invalid'));
        }

        // Controleer post ID en rechten
        $post_id = isset($_POST['post_id']) ? intval($_POST['post_id']) : 0;
        if (!$post_id || !current_user_can('edit_post', $post_id)) {
            wp_send_json_error(array('message' => tamrank__('error_permission_denied', 'You do not have permission for this action.'), 'code' => 'permission_denied'));
        }

        // Optioneel: realtime score berekening met meegegeven data
        if (isset($_POST['meta_title']) || isset($_POST['meta_description'])) {
            // Gebruik tijdelijke data voor realtime berekening
            $temp_meta_score = $this->calculate_realtime_meta_score($_POST, $post_id); // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized,WordPress.Security.ValidatedSanitizedInput.MissingUnslash -- nonce verified above; each field is unslashed + sanitized inside calculate_realtime_meta_score().
            $content_score = isset($_POST['content_score']) ? intval(wp_unslash($_POST['content_score'])) : $this->get_content_score($post_id);
            $total_score = $this->calculate_total_score($temp_meta_score, $content_score);

            wp_send_json_success(array(
                'total' => array(
                    'score' => $total_score,
                    'color' => $this->get_score_color($total_score),
                    'label' => $this->get_score_label($total_score),
                ),
                'meta' => array(
                    'score' => $temp_meta_score,
                    'color' => $this->get_score_color($temp_meta_score),
                    'label' => $this->get_score_label($temp_meta_score),
                    'weight' => intval(self::META_WEIGHT * 100),
                ),
                'content' => array(
                    'score' => $content_score,
                    'color' => $this->get_score_color($content_score),
                    'label' => $this->get_score_label($content_score),
                    'weight' => intval(self::CONTENT_WEIGHT * 100),
                ),
            ));
            return;
        }

        // Standaard: haal volledige score data op
        $data = $this->get_score_data($post_id);
        wp_send_json_success($data);
    }

    /**
     * Bereken meta score met realtime data
     *
     * @param array $data POST data met meta velden
     * @param int $post_id Post ID
     * @return int Meta score (0-100)
     */
    private function calculate_realtime_meta_score($data, $post_id)
    {
        $score = 0;
        $max_score = 50;

        $meta_title = isset($data['meta_title']) ? sanitize_text_field(wp_unslash($data['meta_title'])) : '';
        $meta_description = isset($data['meta_description']) ? sanitize_textarea_field(wp_unslash($data['meta_description'])) : '';
        $focus_keyword = isset($data['focus_keyword']) ? sanitize_text_field(wp_unslash($data['focus_keyword'])) : '';

        // Fallback naar post titel
        if (empty($meta_title)) {
            $post = get_post($post_id);
            $meta_title = $post ? $post->post_title : '';
        }

        // Check Meta Title (15 points max)
        if (!empty($meta_title)) {
            $title_length = strlen($meta_title);

            if ($title_length >= 30 && $title_length <= 60) {
                $score += 10;
            } elseif ($title_length > 0 && $title_length < 30) {
                $score += 3;
            } elseif ($title_length > 60) {
                $score += 5;
            }

            if ($focus_keyword && TamRank_Meta_Calculator::keyword_exists($meta_title, $focus_keyword)) {
                $score += 5;
            }
        }

        // Check Meta Description (15 points max)
        if (!empty($meta_description)) {
            $desc_length = strlen($meta_description);

            if ($desc_length >= 120 && $desc_length <= 160) {
                $score += 10;
            } elseif ($desc_length > 0 && $desc_length < 120) {
                $score += 3;
            } elseif ($desc_length > 160) {
                $score += 5;
            }

            if ($focus_keyword && TamRank_Meta_Calculator::keyword_exists($meta_description, $focus_keyword)) {
                $score += 5;
            }
        }

        // Check Focus Keyword (10 points)
        if (!empty($focus_keyword)) {
            $score += 10;
        }

        // Slug check (10 points) - gebruik opgeslagen waarde of custom slug
        $custom_slug = isset($data['custom_slug']) ? sanitize_title($data['custom_slug']) : '';
        if (empty($custom_slug)) {
            $post = get_post($post_id);
            $custom_slug = $post ? $post->post_name : '';
        }

        if (!empty($custom_slug)) {
            if ($focus_keyword && TamRank_Meta_Calculator::keyword_exists($custom_slug, sanitize_title($focus_keyword))) {
                $score += 5;
            }
            if (strlen($custom_slug) <= 60) {
                $score += 5;
            }
        }

        return min(100, max(0, round(($score / $max_score) * 100)));
    }

    /**
     * Get secondary keywords bonus data
     *
     * @param WP_Post|int $post Post object of ID
     * @return array Bonus data
     */
    private function get_secondary_keywords_bonus($post)
    {
        if (is_numeric($post)) {
            $post = get_post($post);
        }

        if (!$post) {
            return array(
                'score' => 0,
                'max_score' => 10,
                'enabled' => false,
                'is_pro' => false,
                'keywords' => array(),
            );
        }

        // Load content analyzer to get bonus data
        if (!class_exists('TamRank_Content_Analyzer')) {
            require_once dirname(__FILE__) . '/class-tamrank-content-analyzer.php';
        }

        $analyzer = new TamRank_Content_Analyzer();
        $focus_keyword = get_post_meta($post->ID, '_tam_rank_focus_keyword', true);
        $content = $post->post_content;

        // Run analysis to get bonus data
        $result = $analyzer->analyze($content, $focus_keyword, $post->ID);

        return isset($result['secondary_keywords_bonus']) ? $result['secondary_keywords_bonus'] : array(
            'score' => 0,
            'max_score' => 10,
            'enabled' => false,
            'is_pro' => false,
            'keywords' => array(),
        );
    }
}

// Initialiseer singleton
TamRank_Total_Score::get_instance();
