<?php
/**
 * TamRank Meta Calculator
 *
 * Lichtgewicht calculator voor metadata scores.
 * Bevat puur de rekenregels, geen database interacties of caching.
 *
 * @package TamRank
 * @since 8.2.0
 */

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

class TamRank_Meta_Calculator
{

    /**
     * Check if a keyword exists as a whole word in text (case-insensitive).
     * Uses Unicode word boundaries so Dutch characters (é, ë, ü, ij) work correctly.
     *
     * @param string $text    The text to search in
     * @param string $keyword The keyword to find
     * @return bool
     */
    public static function keyword_exists(string $text, string $keyword): bool
    {
        if (empty($keyword) || empty($text)) {
            return false;
        }
        // Normalize accents: "interné" matches "interne" and vice versa
        $text_normalized = remove_accents($text);
        $keyword_normalized = remove_accents($keyword);
        // Replace punctuation with space so "robots.txt" matches "robots txt" and "WordPress," matches "WordPress"
        $text_normalized = preg_replace('/[^\p{L}\p{N}\s]/u', ' ', $text_normalized);
        $keyword_normalized = preg_replace('/[^\p{L}\p{N}\s]/u', ' ', $keyword_normalized);
        // Collapse runs of whitespace so phrase matches survive "WordPress, robots.txt" → "WordPress  robots txt"
        $text_normalized = preg_replace('/\s+/u', ' ', $text_normalized);
        $keyword_normalized = trim(preg_replace('/\s+/u', ' ', $keyword_normalized));
        $pattern = '/\b' . preg_quote($keyword_normalized, '/') . '\b/iu';
        return (bool) preg_match($pattern, $text_normalized);
    }

    /**
     * Count whole-word occurrences of a keyword in text (case-insensitive).
     *
     * @param string $text    The text to search in
     * @param string $keyword The keyword to count
     * @return int
     */
    public static function keyword_count(string $text, string $keyword): int
    {
        if (empty($keyword) || empty($text)) {
            return 0;
        }
        $text_normalized = remove_accents($text);
        $keyword_normalized = remove_accents($keyword);
        // Replace punctuation with space so "robots.txt" matches "robots txt" and "WordPress," matches "WordPress"
        $text_normalized = preg_replace('/[^\p{L}\p{N}\s]/u', ' ', $text_normalized);
        $keyword_normalized = preg_replace('/[^\p{L}\p{N}\s]/u', ' ', $keyword_normalized);
        // Collapse runs of whitespace so phrase matches survive "WordPress, robots.txt" → "WordPress  robots txt"
        $text_normalized = preg_replace('/\s+/u', ' ', $text_normalized);
        $keyword_normalized = trim(preg_replace('/\s+/u', ' ', $keyword_normalized));
        $pattern = '/\b' . preg_quote($keyword_normalized, '/') . '\b/iu';
        return (int) preg_match_all($pattern, $text_normalized);
    }

    /**
     * Calculate score based on meta data
     *
     * @param array $data Array met title, description, focus_keyword, slug, url
     * @return int Score 0-100
     */
    public static function calculate(array $data): int
    {
        $analysis = self::analyze($data);
        return $analysis['total_score'];
    }

    /**
     * Voer volledige analyse uit en retourneer details
     */
    public static function analyze(array $data): array
    {
        $score = 0;
        $max_score = 50;
        $details = [];

        $meta_title = isset($data['title']) ? (string) $data['title'] : '';
        $meta_description = isset($data['description']) ? (string) $data['description'] : '';
        $focus_keyword = isset($data['focus_keyword']) ? (string) $data['focus_keyword'] : '';
        $slug = isset($data['slug']) ? (string) $data['slug'] : '';

        // 1. Check Meta Title
        $title_analysis = self::analyze_meta_title($meta_title, $focus_keyword);
        $score += $title_analysis['score'];
        $details['meta_title'] = $title_analysis;

        // 2. Check Meta Description
        $desc_analysis = self::analyze_meta_description($meta_description, $focus_keyword);
        $score += $desc_analysis['score'];
        $details['meta_description'] = $desc_analysis;

        // 3. Focus Keyword Set
        if (!empty($focus_keyword)) {
            $score += 10;
            $details['focus_keyword'] = ['name' => __('Focus Keyword', 'tam-rank'), 'score' => 10, 'passed' => true, 'issues' => []];
        } else {
            $details['focus_keyword'] = ['name' => __('Focus Keyword', 'tam-rank'), 'score' => 0, 'passed' => false, 'issues' => [__('No focus keyword set', 'tam-rank')]];
        }

        // 4. URL Structure
        $slug_analysis = self::analyze_url($slug, $focus_keyword);
        $score += $slug_analysis['score'];
        $details['url_slug'] = $slug_analysis;

        // Convert to 0-100 scale
        $final_score = min(100, round(($score / $max_score) * 100));

        return [
            'total_score' => $final_score,
            'raw_score' => $score,
            'max_score' => $max_score,
            'details' => $details
        ];
    }

    /**
     * Analyseer de Meta Title
     */
    public static function analyze_meta_title(string $title, string $keyword = ''): array
    {
        $score = 0;
        $issues = [];
        $passed = true;
        $length = mb_strlen($title);

        // Lengte check (10 punten)
        if ($length >= 30 && $length <= 60) {
            $score += 10;
        } elseif ($length > 0 && $length < 30) {
            $score += 3;
            $issues[] = __('Too short (less than 30 characters)', 'tam-rank');
            $passed = false;
        } elseif ($length > 60) {
            $score += 5;
            $issues[] = __('Too long (more than 60 characters)', 'tam-rank');
            $passed = false;
        } else {
            // $issues[] = __('Meta Title not set', 'tam-rank'); // Wordt impliciet afgehandeld door lege issues
            $passed = false;
        }

        // Focus keyword in title (5 punten) — whole-word, case-insensitive
        if (!empty($keyword)) {
            if (self::keyword_exists($title, $keyword)) {
                $score += 5;
            } else {
                $issues[] = __('Focus keyword not present in title', 'tam-rank');
                if ($length > 0)
                    $passed = false;
            }
        }

        return [
            'name' => __('Meta Title', 'tam-rank'),
            'score' => $score,
            'max_score' => 15,
            'issues' => $issues,
            'passed' => $passed && $score >= 8, // Minimaal redelijk (3+5)
            'current_length' => $length
        ];
    }

    /**
     * Analyseer de Meta Description
     */
    public static function analyze_meta_description(string $description, string $keyword = ''): array
    {
        $score = 0;
        $issues = [];
        $passed = true;
        $length = mb_strlen($description);

        // Lengte check (10 punten)
        if ($length >= 120 && $length <= 160) {
            $score += 10;
        } elseif ($length > 0 && $length < 120) {
            $score += 3;
            $issues[] = __('Too short (less than 120 characters)', 'tam-rank');
            $passed = false;
        } elseif ($length > 160) {
            $score += 5;
            $issues[] = __('Too long (more than 160 characters)', 'tam-rank');
            $passed = false;
        } else {
            $issues[] = __('No meta description set', 'tam-rank');
            $passed = false;
        }

        // Focus keyword in description (5 punten) — whole-word, case-insensitive
        if (!empty($keyword)) {
            if (self::keyword_exists($description, $keyword)) {
                $score += 5;
            } else {
                $issues[] = __('Focus keyword not present in description', 'tam-rank');
                if ($length > 0)
                    $passed = false;
            }
        }

        return [
            'name' => __('Meta Description', 'tam-rank'),
            'score' => $score,
            'max_score' => 15,
            'issues' => $issues,
            'passed' => $passed && $score >= 8,
            'current_length' => $length
        ];
    }

    /**
     * Analyseer de URL
     */
    public static function analyze_url(string $slug, string $keyword = ''): array
    {
        $score = 0;
        $issues = [];
        $passed = true;

        if (!empty($slug)) {
            $score += 5;

            if (!empty($keyword)) {
                if (self::keyword_exists($slug, sanitize_title($keyword))) {
                    $score += 5;
                } else {
                    $issues[] = __('Focus keyword not in URL', 'tam-rank');
                    $passed = false;
                }
            }
        } else {
            $issues[] = __('No URL slug set', 'tam-rank');
            $passed = false;
        }

        return [
            'name' => __('URL Structure', 'tam-rank'),
            'score' => $score,
            'max_score' => 10,
            'issues' => $issues,
            'passed' => $passed
        ];
    }

    /**
     * Get score class voor UI
     */
    public static function get_score_class(int $score): string
    {
        if ($score >= 80)
            return 'tam-score-excellent';
        if ($score >= 60)
            return 'tam-score-good';
        if ($score >= 40)
            return 'tam-score-average';
        return 'tam-score-poor';
    }

    /**
     * Get score color voor UI
     */
    public static function get_score_color(int $score): string
    {
        if ($score >= 80)
            return '#10b981'; // --tr-color-status-excellent
        if ($score >= 60)
            return '#14b8a6'; // --tr-color-status-good
        if ($score >= 40)
            return '#f59e0b'; // --tr-color-status-attention
        return '#f43f5e'; // --tr-color-status-improve
    }
}
