from __future__ import annotations

import re
import unicodedata

DIGIT_TRANS = str.maketrans(
    '\u06f0\u06f1\u06f2\u06f3\u06f4\u06f5\u06f6\u06f7\u06f8\u06f9'
    '\u0660\u0661\u0662\u0663\u0664\u0665\u0666\u0667\u0668\u0669',
    '0123456789' * 2,
)
CHAR_TRANS = str.maketrans({'\u064a': '\u06cc', '\u0643': '\u06a9', '\u200c': ' '})


class TextNormalizer:
    @staticmethod
    def normalize(text: str | None) -> str:
        if text is None:
            return ''
        value = unicodedata.normalize('NFKC', str(text))
        value = value.translate(DIGIT_TRANS).translate(CHAR_TRANS)
        value = re.sub(r'[\t\r\n]+', ' ', value)
        value = re.sub(r'\s+', ' ', value).strip()
        return value.casefold()

    @staticmethod
    def explain(text: str | None) -> dict:
        original = '' if text is None else str(text)
        normalized = TextNormalizer.normalize(original)
        changes = []
        if original != original.strip():
            changes.append('Trim')
        if '\u064a' in original:
            changes.append('Arabic Ye -> Persian Ye')
        if '\u0643' in original:
            changes.append('Arabic Kaf -> Persian Kaf')
        if '\u200c' in original:
            changes.append('ZWNJ normalized')
        if re.search(r'\s{2,}|[\t\r\n]', original):
            changes.append('Multiple whitespace removed')
        if any(ch in original for ch in '\u06f0\u06f1\u06f2\u06f3\u06f4\u06f5\u06f6\u06f7\u06f8\u06f9\u0660\u0661\u0662\u0663\u0664\u0665\u0666\u0667\u0668\u0669'):
            changes.append('Digits normalized')
        if unicodedata.normalize('NFKC', original) != original:
            changes.append('Unicode normalized')
        return {'original': original, 'normalized': normalized, 'changes': changes}


def matches(user_text: str, keyword: str, match_type: str = 'exact') -> bool:
    text = TextNormalizer.normalize(user_text)
    key = TextNormalizer.normalize(keyword)
    match_type = (match_type or 'exact').lower()
    if not key:
        return False
    if match_type == 'contains':
        return key in text
    if match_type == 'starts_with':
        return text.startswith(key)
    if match_type == 'ends_with':
        return text.endswith(key)
    return text == key
