<?php
/**
 * SEO Readability Analyzer
 * Analyzes content readability using Flesch Kincaid and other metrics
 */

class ReadabilityAnalyzer {
    
    /**
     * Analyze text readability
     */
    public static function analyze($content) {
        // Remove HTML tags
        $text = strip_tags($content);
        
        // Get metrics
        $sentences = self::countSentences($text);
        $words = self::countWords($text);
        $syllables = self::countSyllables($text);
        $paragraphs = self::countParagraphs($content);
        $avg_word_length = $words > 0 ? strlen(str_replace(' ', '', $text)) / $words : 0;
        
        // Calculate readability scores
        $flesch_reading_ease = self::fleschReadingEase($sentences, $words, $syllables);
        $flesch_kincaid_grade = self::fleschKincaidGrade($sentences, $words, $syllables);
        $gunning_fog_index = self::gunningFogIndex($sentences, $words, $text);
        
        // Determine grade level
        $grade_level = self::getGradeLevel($flesch_kincaid_grade);
        
        // Get issues
        $issues = self::analyzeIssues($text, $sentences, $words, $paragraphs);
        
        // Calculate overall score (0-100)
        $score = self::calculateOverallScore($flesch_reading_ease, $flesch_kincaid_grade, $gunning_fog_index);
        
        return [
            'score' => $score,
            'grade_level' => $grade_level,
            'grade_description' => self::getGradeDescription($grade_level),
            'flesch_reading_ease' => round($flesch_reading_ease, 1),
            'flesch_kincaid_grade' => round($flesch_kincaid_grade, 1),
            'gunning_fog_index' => round($gunning_fog_index, 1),
            'metrics' => [
                'sentences' => $sentences,
                'words' => $words,
                'syllables' => $syllables,
                'paragraphs' => $paragraphs,
                'avg_word_length' => round($avg_word_length, 2),
                'avg_sentence_length' => $sentences > 0 ? round($words / $sentences, 1) : 0,
                'avg_syllables_per_word' => $words > 0 ? round($syllables / $words, 2) : 0
            ],
            'issues' => $issues,
            'suggestions' => self::generateSuggestions($issues, $flesch_reading_ease)
        ];
    }
    
    /**
     * Count sentences in text
     */
    private static function countSentences($text) {
        // Match sentences ending with . ! or ?
        preg_match_all('/[.!?]+/', $text, $matches);
        $count = count($matches[0]);
        return max($count, 1); // At least 1 sentence
    }
    
    /**
     * Count words in text
     */
    private static function countWords($text) {
        return count(preg_split('/\s+/', trim($text), -1, PREG_SPLIT_NO_EMPTY));
    }
    
    /**
     * Count syllables in text (simplified)
     */
    private static function countSyllables($text) {
        // Convert to lowercase
        $text = strtolower($text);
        
        // Remove punctuation
        $text = preg_replace('/[^a-z\s]/', '', $text);
        
        $syllable_count = 0;
        $words = preg_split('/\s+/', trim($text), -1, PREG_SPLIT_NO_EMPTY);
        
        foreach ($words as $word) {
            $syllable_count += self::estimateSyllables($word);
        }
        
        return max($syllable_count, 1);
    }
    
    /**
     * Estimate syllables for a single word
     */
    private static function estimateSyllables($word) {
        $word = strtolower($word);
        $syllables = 0;
        $vowels = 'aeiouy';
        $previous_was_vowel = false;
        
        for ($i = 0; $i < strlen($word); $i++) {
            $is_vowel = strpos($vowels, $word[$i]) !== false;
            
            if ($is_vowel && !$previous_was_vowel) {
                $syllables++;
            }
            
            $previous_was_vowel = $is_vowel;
        }
        
        // Adjust for silent 'e'
        if (substr($word, -1) === 'e') {
            $syllables--;
        }
        
        // Adjust for common endings
        if (preg_match('/(le)$/', $word)) {
            $syllables++;
        }
        
        return max($syllables, 1);
    }
    
    /**
     * Count paragraphs in HTML content
     */
    private static function countParagraphs($content) {
        preg_match_all('/<p[^>]*>.*?<\/p>/is', $content, $matches);
        $count = count($matches[0]);
        
        if ($count === 0) {
            // Fallback: count double line breaks
            $count = count(array_filter(array_map('trim', explode("\n\n", $content))));
        }
        
        return max($count, 1);
    }
    
    /**
     * Calculate Flesch Reading Ease score
     * Scale: 0-100 (higher = easier to read)
     */
    private static function fleschReadingEase($sentences, $words, $syllables) {
        if ($words === 0 || $sentences === 0) {
            return 0;
        }
        
        return 206.835 - 1.015 * ($words / $sentences) - 84.6 * ($syllables / $words);
    }
    
    /**
     * Calculate Flesch-Kincaid Grade Level
     * US school grade needed to understand the text
     */
    private static function fleschKincaidGrade($sentences, $words, $syllables) {
        if ($words === 0 || $sentences === 0) {
            return 0;
        }
        
        return 0.39 * ($words / $sentences) + 11.8 * ($syllables / $words) - 15.59;
    }
    
    /**
     * Calculate Gunning Fog Index
     * Years of formal education needed to understand the text
     */
    private static function gunningFogIndex($sentences, $words, $text) {
        if ($words === 0 || $sentences === 0) {
            return 0;
        }
        
        // Count complex words (3+ syllables, excluding common suffixes)
        $complex_words = 0;
        $word_list = preg_split('/\s+/', strtolower($text), -1, PREG_SPLIT_NO_EMPTY);
        
        foreach ($word_list as $word) {
            $word = preg_replace('/[^a-z]/', '', $word);
            $syllables = self::estimateSyllables($word);
            
            if ($syllables >= 3) {
                // Check for common suffixes
                if (!preg_match('/(ing|ed|er|tion|ness)$/', $word)) {
                    $complex_words++;
                }
            }
        }
        
        return 0.4 * (($words / $sentences) + 100 * ($complex_words / $words));
    }
    
    /**
     * Determine US grade level from Flesch-Kincaid score
     */
    private static function getGradeLevel($kincaid_score) {
        $kincaid_score = max(0, min($kincaid_score, 18));
        return round($kincaid_score);
    }
    
    /**
     * Get grade level description
     */
    private static function getGradeDescription($grade) {
        if ($grade <= 5) return 'Very Easy (Grade School)';
        if ($grade <= 8) return 'Easy (Middle School)';
        if ($grade <= 12) return 'Standard (High School)';
        if ($grade <= 16) return 'Difficult (College)';
        return 'Very Difficult (Graduate)';
    }
    
    /**
     * Analyze content for readability issues
     */
    private static function analyzeIssues($text, $sentences, $words, $paragraphs) {
        $issues = [];
        
        // Check for very long sentences
        if ($sentences > 0 && ($words / $sentences) > 20) {
            $issues[] = [
                'type' => 'warning',
                'message' => 'Sentences are too long on average. Keep sentences under 20 words.',
                'severity' => 'medium'
            ];
        }
        
        // Check for short content
        if ($words < 300) {
            $issues[] = [
                'type' => 'warning',
                'message' => 'Content is too short. Aim for at least 300 words.',
                'severity' => 'medium'
            ];
        }
        
        // Check for paragraph organization
        if ($paragraphs < 3 && $words > 500) {
            $issues[] = [
                'type' => 'info',
                'message' => 'Break content into more paragraphs for better readability.',
                'severity' => 'low'
            ];
        }
        
        // Check for passive voice (simple detection)
        $passive_count = preg_match_all('/\bwas\s+\w+ed\b|\bwere\s+\w+ed\b|\bbeing\b/i', $text);
        if ($passive_count > ($words * 0.15)) {
            $issues[] = [
                'type' => 'info',
                'message' => 'Consider using more active voice instead of passive voice.',
                'severity' => 'low'
            ];
        }
        
        // Check for variety in word length
        $word_lengths = array_map('strlen', preg_split('/\s+/', $text, -1, PREG_SPLIT_NO_EMPTY));
        $avg_length = array_sum($word_lengths) / count($word_lengths);
        if ($avg_length > 6.5) {
            $issues[] = [
                'type' => 'info',
                'message' => 'Try using shorter words to improve readability.',
                'severity' => 'low'
            ];
        }
        
        // Check for headings (H1, H2, H3, etc.)
        $heading_count = preg_match_all('/<h[1-6][^>]*>.*?<\/h[1-6]>/i', $text);
        if ($heading_count === 0 && $words > 500) {
            $issues[] = [
                'type' => 'warning',
                'message' => 'Add headings to structure your content better.',
                'severity' => 'medium'
            ];
        }
        
        return $issues;
    }
    
    /**
     * Calculate overall readability score (0-100)
     */
    private static function calculateOverallScore($flesch, $kincaid, $gunning) {
        // Normalize scores to 0-100
        $flesch_score = max(0, min(100, $flesch));
        $kincaid_score = max(0, min(100, 100 - ($kincaid * 5)));
        $gunning_score = max(0, min(100, 100 - ($gunning * 5)));
        
        // Weight the scores
        $score = ($flesch_score * 0.5 + $kincaid_score * 0.25 + $gunning_score * 0.25);
        
        return round($score);
    }
    
    /**
     * Generate improvement suggestions
     */
    private static function generateSuggestions($issues, $flesch_score) {
        $suggestions = [];
        
        if ($flesch_score < 30) {
            $suggestions[] = [
                'priority' => 'high',
                'suggestion' => 'Text is very difficult to read. Simplify vocabulary and sentence structure.',
                'action' => 'Reduce sentence length and use simpler words'
            ];
        } elseif ($flesch_score < 50) {
            $suggestions[] = [
                'priority' => 'medium',
                'suggestion' => 'Text is difficult to read. Try to simplify your content.',
                'action' => 'Break long sentences into shorter ones'
            ];
        } elseif ($flesch_score > 90) {
            $suggestions[] = [
                'priority' => 'low',
                'suggestion' => 'Text is very easy to read, but might be too simplistic for professional content.',
                'action' => 'Consider adding more depth where appropriate'
            ];
        }
        
        return $suggestions;
    }
}
?>
