# """
# Configuration et dictionnaires multilingues pour mkdocs-superquiz
# Charge maintenant les synonymes et mots-clés depuis les fichiers i18n JSON
# """

# import json
# from pathlib import Path


# # ✅ aliases for nested "defaults" config in mkdocs.yml
# DEFAULTS_ALIASES = ("defaults", "global")


# def load_i18n_config(language='en'):
#     i18n_dir = Path(__file__).parent / 'i18n'
#     i18n_file = i18n_dir / f'{language}.json'

#     if not i18n_file.exists():
#         i18n_file = i18n_dir / 'en.json'

#     with open(i18n_file, 'r', encoding='utf-8') as f:
#         return json.load(f)


# def _merge_dedup_ci(primary_list, secondary_list):
#     out = []
#     seen = set()

#     for src in (primary_list or []) + (secondary_list or []):
#         s = str(src).strip()
#         if not s:
#             continue
#         key = s.lower()
#         if key in seen:
#             continue
#         seen.add(key)
#         out.append(s)

#     return out


# def build_quiz_types_dict(language='en'):
#     cfg_lang = load_i18n_config(language)
#     cfg_en = load_i18n_config('en')

#     quiz_types = {}
#     all_types = set((cfg_en.get('quiz_types', {}) or {}).keys()) | set((cfg_lang.get('quiz_types', {}) or {}).keys())

#     for quiz_type in all_types:
#         en_syn = (cfg_en.get('quiz_types', {}).get(quiz_type, {}) or {}).get('synonyms', []) or []
#         lang_syn = (cfg_lang.get('quiz_types', {}).get(quiz_type, {}) or {}).get('synonyms', []) or []

#         # language first, then english (but both accepted)
#         quiz_types[quiz_type] = _merge_dedup_ci(lang_syn, en_syn)

#     return quiz_types


# def build_keywords_dict(language='en'):
#     cfg_lang = load_i18n_config(language).get('quiz_configs', {}) or {}
#     cfg_en = load_i18n_config('en').get('quiz_configs', {}) or {}

#     def merged(key_name, default_list):
#         lang_list = cfg_lang.get(key_name, default_list) or []
#         en_list = cfg_en.get(key_name, default_list) or []
#         return _merge_dedup_ci(lang_list, en_list)

#     return {
#         'preamble': merged('preamble_keywords', ['preamble', 'pre']),
#         'question': merged('question_keywords', ['question', 'q']),
#         'answers': merged('answers_keywords', ['answers', 'ans']),
#     }


# QUIZ_TYPES = build_quiz_types_dict('en')
# KEYWORDS = build_keywords_dict('en')


# DEFAULT_CONFIG = {
#     'security_mode': 'obfuscated',
#     'teacher_code': None,
#     'encryption_key': 'default-key-change-me',
#     'api_endpoint': None,
#     'correction_granularity': 'exercise',

#     'min_score': None,            # ✅ allow penalties if negative values are used in losing_mode
#     'clamp_max_score': True,      # ✅ prevent score > points_max

#     'correction_locked_icon': '❌',
#     'correction_unlock_icon': '🔐',
#     'correction_unlocked_icon': '✅',

#     'mcquiz': {
#         'scoring_mode': 'proportional',   # all_or_nothing / some_or_nothing / proportional
#         'default_false': 0,
#         'default_points': 1,
#         'show_correction': 'on_demand',
#         'save_answers': True,
#         'randomize_questions': False,
#         'randomize_answers': False,
#         'synonyms': []
#     },
#     'scquiz': {
#         'scoring_mode': 'all_or_nothing',  # (kept for future extension)
#         'default_false': 0,
#         'default_points': 1,
#         'show_correction': 'on_demand',
#         'save_answers': True,
#         'randomize_answers': True,
#         'synonyms': []
#     },
#     'gapfill': {
#         'scoring_mode': 'proportional',    # all_or_nothing / some_or_nothing / proportional
#         'default_false': 0,
#         'default_points': 1,

#         # Legacy flags (kept for backward compatibility)
#         'case_sensitive': False,
#         'strict_latex': False,
#         'ignore_spaces': True,
#         'strip_spaces': True,

#         # New unified config
#         'compare_answers': None,           # if None, built from legacy flags in renderer/JS

#         'show_correction': 'on_demand',
#         'save_answers': True,
#         'randomize_questions': False,
#         'synonyms': []
#     },
#     'dropdown': {
#         'scoring_mode': 'all_or_nothing',  # all_or_nothing / some_or_nothing / proportional
#         'default_false': 0,
#         'default_points': 1,
#         'show_correction': 'on_demand',
#         'save_answers': True,
#         'randomize_options': False,
#         'synonyms': []
#     }
# }


# def normalize_quiz_type(quiz_type_str, language='en'):
#     quiz_types = build_quiz_types_dict(language)
#     quiz_type_lower = quiz_type_str.lower()

#     for canonical_type, synonyms in quiz_types.items():
#         if quiz_type_lower in [s.lower() for s in synonyms]:
#             return canonical_type

#     return None


# def normalize_keyword(keyword_str, language='en'):
#     keywords = build_keywords_dict(language)

#     import re
#     keyword_base = re.sub(r'\d+$', '', keyword_str.lower())

#     for canonical_keyword, synonyms in keywords.items():
#         if keyword_base in [s.lower() for s in synonyms]:
#             return canonical_keyword

#     return None

# ==============================================================================================================
# ==============================================================================================================
# ==============================================================================================================

"""
Configuration et dictionnaires multilingues pour mkdocs-superquiz
"""

import json
from pathlib import Path
from typing import Any, Dict, List, Optional


DEFAULTS_ALIASES = ("defaults", "global")


# ─────────────────────────────────────────────────────────────────────────────
# i18n helpers
# ─────────────────────────────────────────────────────────────────────────────

def load_i18n_config(language='en'):
    i18n_dir = Path(__file__).parent / 'i18n'
    i18n_file = i18n_dir / f'{language}.json'
    if not i18n_file.exists():
        i18n_file = i18n_dir / 'en.json'
    with open(i18n_file, 'r', encoding='utf-8') as f:
        return json.load(f)


def _merge_dedup_ci(primary_list, secondary_list):
    out = []
    seen = set()
    for src in (primary_list or []) + (secondary_list or []):
        s = str(src).strip()
        if not s:
            continue
        key = s.lower()
        if key in seen:
            continue
        seen.add(key)
        out.append(s)
    return out


def build_quiz_types_dict(language='en'):
    cfg_lang = load_i18n_config(language)
    cfg_en   = load_i18n_config('en')
    quiz_types = {}
    all_types = set((cfg_en.get('quiz_types', {}) or {}).keys()) | \
                set((cfg_lang.get('quiz_types', {}) or {}).keys())
    for quiz_type in all_types:
        en_syn   = (cfg_en.get('quiz_types', {}).get(quiz_type, {}) or {}).get('synonyms', []) or []
        lang_syn = (cfg_lang.get('quiz_types', {}).get(quiz_type, {}) or {}).get('synonyms', []) or []
        quiz_types[quiz_type] = _merge_dedup_ci(lang_syn, en_syn)
    return quiz_types


def build_keywords_dict(language='en'):
    cfg_lang = load_i18n_config(language).get('quiz_configs', {}) or {}
    cfg_en   = load_i18n_config('en').get('quiz_configs', {}) or {}

    def merged(key_name, default_list):
        lang_list = cfg_lang.get(key_name, default_list) or []
        en_list   = cfg_en.get(key_name, default_list) or []
        return _merge_dedup_ci(lang_list, en_list)

    return {
        'preamble': merged('preamble_keywords', ['preamble', 'pre']),
        'question': merged('question_keywords',  ['question', 'q']),
        'answers':  merged('answers_keywords',   ['answers', 'ans']),
    }


QUIZ_TYPES = build_quiz_types_dict('en')
KEYWORDS   = build_keywords_dict('en')


# ─────────────────────────────────────────────────────────────────────────────
# compare_answers — new format only (no legacy)
# ─────────────────────────────────────────────────────────────────────────────

DEFAULT_COMPARE_ANSWERS: Dict[str, Any] = {
    "ignore": {
        "spaces":     "all",
        "characters": "?,.;/:!¡-_",
        "case":       True,
        "diacritics": False
    },
    "equivalence": {}
}

_VALID_SPACES = frozenset(('all', 'inside', 'outside', 'none'))


def normalize_compare_answers(raw: Any) -> Dict[str, Any]:
    """
    Normalize a compare_answers config dict to canonical format:

        {
            "ignore": {
                "spaces":     "all" | "inside" | "outside" | "none",
                "characters": "<string>",
                "case":       True | False,
                "diacritics": True | False
            },
            "equivalence": { "base": ["variant", ...], ... }
        }

    Only the new format { ignore: {...}, equivalence: {...} } is accepted.
    Missing keys fall back to defaults. None / empty → returns defaults.
    """
    import copy

    if not raw or not isinstance(raw, dict):
        return copy.deepcopy(DEFAULT_COMPARE_ANSWERS)

    ignore = dict(DEFAULT_COMPARE_ANSWERS['ignore'])
    raw_ignore = raw.get('ignore', {})
    if isinstance(raw_ignore, dict):
        ignore.update(raw_ignore)

    if ignore.get('spaces') not in _VALID_SPACES:
        ignore['spaces'] = 'all'

    equivalence = _normalize_equivalence(raw.get('equivalence', {}))

    return {'ignore': ignore, 'equivalence': equivalence}


def _normalize_equivalence(raw_equiv: Any) -> Dict[str, List[str]]:
    """Normalize equivalence dict: all values become lists of strings."""
    if not isinstance(raw_equiv, dict):
        return {}
    out: Dict[str, List[str]] = {}
    for base, variants in raw_equiv.items():
        if isinstance(variants, str):
            out[str(base)] = [variants]
        elif isinstance(variants, list):
            out[str(base)] = [str(v) for v in variants]
        else:
            out[str(base)] = [str(variants)]
    return out


# ─────────────────────────────────────────────────────────────────────────────
# DEFAULT_CONFIG
# ─────────────────────────────────────────────────────────────────────────────

DEFAULT_CONFIG = {
    'security_mode': 'obfuscated',
    'teacher_code': None,
    'encryption_key': 'default-key-change-me',
    'api_endpoint': None,
    'correction_granularity': 'exercise',

    'min_score': None,
    'clamp_max_score': True,

    'correction_locked_icon':   '❌',
    'correction_unlock_icon':   '🔐',
    'correction_unlocked_icon': '✅',

    'mcquiz': {
        'scoring_mode':        'proportional',
        'default_false':       0,
        'default_points':      1,
        'show_correction':     'on_demand',
        'save_answers':        True,
        'randomize_questions': False,
        'randomize_answers':   False,
        'synonyms':            []
    },

    'scquiz': {
        'scoring_mode':       'all_or_nothing',
        'default_false':      0,
        'default_points':     1,
        'show_correction':    'on_demand',
        'save_answers':       True,
        'randomize_answers':  True,
        'synonyms':           []
    },

    'gapfill': {
        'scoring_mode':        'proportional',
        'default_false':       0,
        'default_points':      1,
        'show_correction':     'on_demand',
        'save_answers':        True,
        'randomize_questions': False,
        'synonyms':            [],
        'compare_answers': {
            'ignore': {
                'spaces':     'all',
                'characters': '?,.;/:!¡-_',
                'case':       True,
                'diacritics': False
            },
            'equivalence': {}
        }
    },

    'dropdown': {
        'scoring_mode':      'all_or_nothing',
        'default_false':     0,
        'default_points':    1,
        'show_correction':   'on_demand',
        'save_answers':      True,
        'randomize_options': False,
        'synonyms':          []
    }
}


# ─────────────────────────────────────────────────────────────────────────────
# Helpers
# ─────────────────────────────────────────────────────────────────────────────

def normalize_quiz_type(quiz_type_str: str, language: str = 'en') -> Optional[str]:
    quiz_types = build_quiz_types_dict(language)
    quiz_type_lower = quiz_type_str.lower()
    for canonical_type, synonyms in quiz_types.items():
        if quiz_type_lower in [s.lower() for s in synonyms]:
            return canonical_type
    return None


def normalize_keyword(keyword_str: str, language: str = 'en') -> Optional[str]:
    import re
    keywords = build_keywords_dict(language)
    keyword_base = re.sub(r'\d+$', '', keyword_str.lower())
    for canonical_keyword, synonyms in keywords.items():
        if keyword_base in [s.lower() for s in synonyms]:
            return canonical_keyword
    return None