import logging
import re

_logger = logging.getLogger(__name__)


class QualityChecker:
    """Content quality gate: readability, CEFR alignment, grammar."""

    CEFR_FLESCH_RANGES = {
        'pre_a1': (90, 100), 'a1': (80, 90), 'a2': (70, 80),
        'b1': (60, 70), 'b2': (50, 60), 'c1': (30, 50), 'c2': (0, 30),
    }

    @staticmethod
    def check_readability(text):
        """Compute Flesch-Kincaid readability metrics."""
        try:
            import textstat
            score = textstat.flesch_reading_ease(text)
            grade = textstat.flesch_kincaid_grade(text)

            cefr = 'b1'
            for level, (low, high) in QualityChecker.CEFR_FLESCH_RANGES.items():
                if low <= score < high:
                    cefr = level
                    break
            if score < 0:
                cefr = 'c2'
            elif score >= 100:
                cefr = 'pre_a1'

            return {
                'flesch_score': round(score, 1),
                'grade_level': round(grade, 1),
                'cefr_estimate': cefr,
                'word_count': textstat.lexicon_count(text),
                'sentence_count': textstat.sentence_count(text),
                'avg_sentence_length': round(textstat.avg_sentence_length(text), 1),
            }
        except ImportError:
            _logger.warning("textstat not installed, using fallback readability check")
            return QualityChecker._fallback_readability(text)

    @staticmethod
    def _fallback_readability(text):
        words = text.split()
        sentences = re.split(r'[.!?]+', text)
        sentences = [s for s in sentences if s.strip()]
        word_count = len(words)
        sentence_count = max(len(sentences), 1)
        syllable_count = sum(QualityChecker._count_syllables(w) for w in words)

        if word_count == 0:
            return {
                'flesch_score': 100, 'grade_level': 0, 'cefr_estimate': 'pre_a1',
                'word_count': 0, 'sentence_count': 0, 'avg_sentence_length': 0,
            }

        asl = word_count / sentence_count
        asw = syllable_count / word_count
        flesch = 206.835 - 1.015 * asl - 84.6 * asw
        grade = 0.39 * asl + 11.8 * asw - 15.59

        cefr = 'b1'
        for level, (low, high) in QualityChecker.CEFR_FLESCH_RANGES.items():
            if low <= flesch < high:
                cefr = level
                break

        return {
            'flesch_score': round(flesch, 1),
            'grade_level': round(max(grade, 0), 1),
            'cefr_estimate': cefr,
            'word_count': word_count,
            'sentence_count': sentence_count,
            'avg_sentence_length': round(asl, 1),
        }

    @staticmethod
    def _count_syllables(word):
        word = word.lower().strip('.,!?;:')
        if not word:
            return 0
        count = 0
        vowels = 'aeiouy'
        prev_vowel = False
        for char in word:
            is_vowel = char in vowels
            if is_vowel and not prev_vowel:
                count += 1
            prev_vowel = is_vowel
        if word.endswith('e') and count > 1:
            count -= 1
        return max(count, 1)

    @staticmethod
    def check_cefr_alignment(text, target_cefr):
        """Check if text readability aligns with target CEFR level."""
        readability = QualityChecker.check_readability(text)
        actual_cefr = readability['cefr_estimate']

        cefr_order = ['pre_a1', 'a1', 'a2', 'b1', 'b2', 'c1', 'c2']
        actual_idx = cefr_order.index(actual_cefr) if actual_cefr in cefr_order else 3
        target_idx = cefr_order.index(target_cefr) if target_cefr in cefr_order else 3

        aligned = abs(actual_idx - target_idx) <= 1

        return {
            'aligned': aligned,
            'actual_cefr': actual_cefr,
            'target_cefr': target_cefr,
            'deviation': actual_idx - target_idx,
            'readability': readability,
        }

    @staticmethod
    def check_grammar(text):
        """Check grammar using language_tool_python."""
        try:
            import language_tool_python
            tool = language_tool_python.LanguageTool('en-US')
            matches = tool.check(text)
            errors = []
            for match in matches:
                errors.append({
                    'message': match.message,
                    'offset': match.offset,
                    'length': match.errorLength,
                    'rule': match.ruleId,
                    'category': match.category,
                    'replacements': match.replacements[:3] if match.replacements else [],
                })
            tool.close()
            return {
                'error_count': len(errors),
                'errors': errors,
            }
        except ImportError:
            _logger.warning("language_tool_python not installed, skipping grammar check")
            return {'error_count': 0, 'errors': [], 'note': 'Grammar checker not available'}

    @staticmethod
    def run_all_checks(text, target_cefr='b1'):
        readability = QualityChecker.check_readability(text)
        alignment = QualityChecker.check_cefr_alignment(text, target_cefr)
        grammar = QualityChecker.check_grammar(text)

        passed = alignment['aligned'] and grammar['error_count'] < 5

        return {
            'passed': passed,
            'readability': readability,
            'cefr_alignment': alignment,
            'grammar': grammar,
        }
