# -*- coding: utf-8 -*-
"""Compact builders for Level-4 lessons (age 11). Every id is prefixed «l4-» so it never collides with Level 1.

Conventions in the data:
  fill items   "Il (avoir – présent) ___ faim. = a"          one '=' then the answer(s), several blanks separated by ' | '
  rewrite      ("Il est content.", "Il sera content.")
  identify     ("Nous avons des tickets.", "avons", "présent")
  match        ("Mes grands-parents", "étaient en Égypte.")
"""
import random

TENSES = ["présent", "futur simple", "imparfait", "passé composé", "plus-que-parfait", "conditionnel présent", "impératif présent"]
TENSE_AR = {"présent": "المضارع", "futur simple": "المستقبل البسيط", "imparfait": "الماضي الناقص", "passé composé": "الماضي المركّب",
            "plus-que-parfait": "الماضي الأسبق", "conditionnel présent": "الشرطي الحاضر", "impératif présent": "الأمر"}
PERSONS = ["je", "tu", "il / elle / on", "nous", "vous", "ils / elles"]


def act(lid, n, typ, title, title_ar, instr, instr_ar, points, data):
    return dict(id=f"{lid}-{n}", type=typ, title=title, title_ar=title_ar, instr=instr, instr_ar=instr_ar, points=points, data=data)


def table(lid, n, verbs, title="Je conjugue", title_ar="أصرّف الأفعال"):
    """verbs: [(verb, tense, "f1 f2 f3 f4 f5 f6")] — forms separated by ' / ' when they contain spaces."""
    items = []
    for verb, tense, forms in verbs:
        fs = [x.strip() for x in (forms.split(" / ") if " / " in forms else forms.split())]
        pron = ["2e pers. sing.", "1re pers. plur.", "2e pers. plur."] if tense == "impératif présent" else PERSONS
        assert len(fs) == len(pron), (verb, tense, fs)
        items.append(dict(verb=verb, tense=tense, tense_ar=TENSE_AR.get(tense, ""), rows=[dict(p=p, answer=f) for p, f in zip(pron, fs)]))
    return act(lid, n, "conjugate", title, title_ar, "Je conjugue le verbe à toutes les personnes.", "صرّف الفعل مع كل الضمائر. استعمل أزرار الحروف المنبورة.", 20, dict(items=items))


def fill(lid, n, lines, title, title_ar, instr="Je complète avec le verbe au temps demandé.", instr_ar="اكتب الفعل مصرّفاً في الفراغ.", points=20):
    items = []
    for ln in lines:
        text, ans = ln.rsplit(" = ", 1)
        blanks = [b.strip() for b in ans.split(" | ")]
        assert text.count("___") == len(blanks), ln
        items.append(dict(text=text, blanks=[b.split(" ; ") for b in blanks]))
    return act(lid, n, "type_answer", title, title_ar, instr, instr_ar, points, dict(items=items))


def rewrite(lid, n, task, task_ar, pairs, title="Je transforme", title_ar="أحوّل الجمل", points=20):
    return act(lid, n, "rewrite", title, title_ar, task, task_ar, points,
               dict(task=task, task_ar=task_ar, items=[dict(**{"from": a}, answers=b.split(" ; ")) for a, b in pairs]))


def identify(lid, n, triples, title="Quel temps ?", title_ar="ما الزمن؟", points=15):
    """Multiple choice: the tense of the underlined verb."""
    rng = random.Random(f"{lid}-{n}")
    qs = []
    for sent, verb, tense in triples:
        others = rng.sample([t for t in TENSES if t != tense], 3)
        ch = [tense] + others
        rng.shuffle(ch)
        qs.append(dict(q=f"{sent}  →  « {verb} »", choices=ch, answer=tense, ar=f"ما زمن الفعل « {verb} »؟"))
    return act(lid, n, "mcq", title, title_ar, "Je trouve le temps du verbe.", "حدّد زمن الفعل بين القوسين.", points, dict(questions=qs))


def speed(lid, n, triples, title="Défi chrono : quel temps ?", title_ar="تحدّي السرعة: ما الزمن؟", seconds=60, target=10, pool=None, ask=None, instr=None):
    """Timed round on verb forms -> tense (uses the same triples as identify).
    With `pool` the answers are something else (e.g. infinitives): distractors come from the pool."""
    rng = random.Random(f"{lid}-{n}")
    pool = pool or TENSES
    ask = ask or ("ما الزمن؟" if pool is TENSES else "ما المصدر؟")
    items = []
    for sent, verb, ans in triples:
        ch = [ans] + rng.sample([t for t in pool if t != ans], 3)
        items.append(dict(q=sent if len(sent) <= 32 else verb, choices=ch, answer=ans, ar=ask))
    instr = instr or ("Le plus vite possible : le temps de chaque verbe.", "بأسرع ما يمكن: حدّد زمن كل فعل قبل انتهاء الوقت.") if pool is TENSES else             ("Le plus vite possible : l'infinitif de chaque verbe.", "بأسرع ما يمكن: حدّد مصدر كل فعل قبل انتهاء الوقت.")
    return act(lid, n, "speed_round", title, title_ar, *instr, 25, dict(seconds=seconds, target=min(target, len(items)), items=items))


def match(lid, n, pairs, title="Je relie", title_ar="أصل", points=15):
    return act(lid, n, "match", title, title_ar, "Je relie chaque début de phrase à sa fin.", "صِل بداية كل جملة بنهايتها الصحيحة.", points,
               dict(pairs=[dict(text=a, rtext=b, emoji="", img=None) for a, b in pairs]))


def choose(lid, n, questions, title="Je choisis la bonne réponse", title_ar="أختار الإجابة الصحيحة", points=15):
    """questions: [(question, [choices], answer, ar?, why_ar?)] — ar is shown with the question, why_ar only after the right answer."""
    def one(q, c, a, ar=None, why=None):
        return dict(q=q, choices=c, answer=a, **({"ar": ar} if ar else {}), **({"why_ar": why} if why else {}))
    return act(lid, n, "mcq", title, title_ar, "Je choisis la bonne réponse.", "اختر الإجابة الصحيحة.", points,
               dict(questions=[one(*x) for x in questions]))


def hunt(lid, n, items, title="Chasse aux erreurs", title_ar="اكتشف الخطأ", points=20, case=False, instr=None, instr_ar=None):
    """items: [(sentence with the wrong word between *stars*, fix, why_ar)]"""
    out = []
    for sent, fix, why in items:
        words = sent.split()
        k = next(i for i, w in enumerate(words) if "*" in w)
        pre, _, rest = words[k].partition("*")
        _, _, post = rest.partition("*")   # t'*aidons* -> fix keeps the "t'" and any "-tu"
        words[k] = words[k].replace("*", "")
        out.append(dict(words=words, wrong=k, fix=pre + fix + post, alt=[fix], why_ar=why, **({"case": True} if case else {})))  # the bare verb is accepted too
    return act(lid, n, "error_hunt", title, title_ar, instr or "Je trouve le mot faux et je le corrige.", instr_ar or "المس الكلمة الخاطئة ثم صحّحها.", points,
               dict(hint_ar="المس الكلمة الخاطئة ثم اكتب الصواب", items=out))


def sort(lid, n, bins, items, title="Je range", title_ar="أصنّف", points=20):
    """bins: [(id, label, ar, emoji)], items: [(text, bin_id)]"""
    return act(lid, n, "sort", title, title_ar, "Je mets chaque mot dans la bonne boîte.", "ضع كل كلمة في الصندوق المناسب.", points,
               dict(bins=[dict(id=b, label=l, ar=a, emoji=e) for b, l, a, e in bins], items=[dict(text=t, bin=b) for t, b in items]))


def rules(lid, n, cards, title="Je retiens", title_ar="أتذكّر القاعدة"):
    """cards: [(French rule / example, Arabic explanation, emoji)]"""
    return act(lid, n, "flashcards", title, title_ar, "Je lis la règle et l'exemple, puis j'écoute.", "اقرأ القاعدة والمثال واستمع إليهما.", 10,
               dict(cards=[dict(kind="word", text=f, ar=a, emoji=e, img=None, tts=f) for f, a, e in cards]))


def lesson(lid, code, title, title_ar, icon, acts, kind="chapter", extra=False):
    return dict(id=lid, code=code, title=title, title_ar=title_ar, icon=icon, kind=kind, extra=extra, chapter=0, activities=acts)


def order(lid, n, sentences, title="Je remets les mots en ordre", title_ar="أرتّب الكلمات", points=15):
    """Word-order puzzle: each sentence is split on spaces and shuffled (never left in order)."""
    rng = random.Random(f"{lid}-{n}")
    out = []
    for s in sentences:
        ws = s.split(" ")
        sh = ws[:]
        while len(ws) > 1 and sh == ws:
            rng.shuffle(sh)
        out.append(dict(words=sh, answer=s))
    return act(lid, n, "word_order", title, title_ar, "Je touche les mots dans le bon ordre pour former la phrase.",
               "المس الكلمات بالترتيب الصحيح لتكوّن الجملة.", points, dict(items=out))


def vf(lid, n, items, title="Vrai ou faux ?", title_ar="صواب أم خطأ؟", points=15):
    """items: [(statement, True/False, why_ar shown after the answer)]"""
    return choose(lid, n, [(s, ["Vrai", "Faux"], "Vrai" if ok else "Faux", None, why) for s, ok, why in items], title, title_ar, points)
