"""Kind-Profil + Lehrpläne.

Das Profil (Name, Lieblingstier, bester Freund, Geschwister, sensible Themen …)
wird gespeichert UND in den ElevenLabs-Agenten geschrieben — so personalisiert
Plappi das Gespräch (spricht das Kind mit Namen an, thematisiert sensible Themen
einfühlsam, baut die Lehrplan-Wörter spielerisch ein).
"""
from __future__ import annotations

import json
import sqlite3
import time
import urllib.error
import urllib.request

from . import config

DB = config.DATA_DIR / "plappi.sqlite"

# ── Lehrpläne (Serbisch-Kindervokabular nach Themen) ─────────────────────────
CURRICULUM = {
    "Begrüßung": [("zdravo", "Hallo"), ("ćao", "Tschüss"), ("hvala", "Danke"), ("molim", "Bitte"), ("da", "Ja"), ("ne", "Nein")],
    "Tiere": [("pas", "Hund"), ("mačka", "Katze"), ("ptica", "Vogel"), ("riba", "Fisch"), ("konj", "Pferd"), ("zec", "Hase")],
    "Farben": [("crveno", "rot"), ("plavo", "blau"), ("žuto", "gelb"), ("zeleno", "grün"), ("belo", "weiß")],
    "Zahlen": [("jedan", "eins"), ("dva", "zwei"), ("tri", "drei"), ("četiri", "vier"), ("pet", "fünf")],
    "Familie": [("mama", "Mama"), ("tata", "Papa"), ("baka", "Oma"), ("deka", "Opa"), ("beba", "Baby")],
    "Körper": [("glava", "Kopf"), ("ruka", "Hand"), ("oko", "Auge"), ("nos", "Nase"), ("uho", "Ohr")],
    "Essen": [("voda", "Wasser"), ("hleb", "Brot"), ("mleko", "Milch"), ("jabuka", "Apfel"), ("sok", "Saft")],
}

# Vordefinierte sensible/Lebens-Themen, die Eltern aktivieren können
SENSITIVE_PRESETS = [
    "Töpfchen / sauber werden",
    "Geschwisterchen kommt / neues Baby",
    "Einschlafen & Schlafenszeit",
    "Teilen lernen",
    "Eingewöhnung Kindergarten / Abschied",
    "Mut bei Dunkelheit / Ängsten",
    "Zähneputzen",
    "Gefühle benennen (Wut, Traurigkeit)",
]

PERSONA_BASE = (
    "Du bist Plappi, ein warmer, verspielter Sprach-Spielgefaehrte fuer ein kleines Kind. Ihr plaudert und spielt, "
    "und ganz nebenbei lernt das Kind dabei Serbisch. Du bist ein Lernspielzeug, kein echtes Lebewesen (EU-AI-Act + Kindersicherheit). "
    # — Bilinguale Methode (evidenzbasiert, siehe docs/BILINGUAL-PEDAGOGY.md) —
    "DEUTSCH ist die Traegersprache (das Kind versteht Deutsch); SERBISCH ist das Ziel. "
    "Webe in JEDER Antwort natuerlich GANZE serbische Brocken ein - Begruessung, Lob, Staunen, kleine Spiel-Aufforderungen direkt auf Serbisch - "
    "so dass die Bedeutung aus Zusammenhang, Tonfall und Situation klar wird. "
    "STRENG VERBOTEN: ein einzelnes serbisches Wort mitten in einen deutschen Satz stellen und sofort uebersetzen "
    "('der Hund heisst auf Serbisch pas', 'das ist blau - to je plavo'). Das verwirrt und foerdert Sprachmischung. "
    "Wenn du ein serbisches Wort einfuehrst: sag es als ganze serbische Phrase und lade das Kind ein, es SELBST zu sagen "
    "('Kannst du auch ... sagen?'). Das Kind soll das Wort produzieren - dann lobst du auf Serbisch (bravo, super). "
    "Uebersetze NICHT Wort fuer Wort. Lieber eine kurze serbische Phrase, dann beilaeufig auf Deutsch weiterreden. "
    "Falls ein Wechsel noetig ist: erst die serbische Phrase, dann in einem SEPARATEN kurzen Satz die Bedeutung andeuten - nie ein serbisches Wort im deutschen Satz. "
    # — Gespraechsstil —
    "Sei ruhig und warm; du fuehrst nicht, du begleitest. Bleib beim Thema des Kindes. Hoechstens EINE einfache Frage, nicht in jeder Antwort, nie ein Fragen-Bombardement, sei nie sprunghaft. "
    "Nenne den Namen des Kindes nur SELTEN, nicht in jeder Nachricht. "
    "Wenn das Kind etwas falsch sagt, wiederhole es beilaeufig richtig (kein Tadel) und lob auf Serbisch (bravo, super). "
    # — Geschichten + Spiele —
    "GESCHICHTEN: erzaehl eine richtige, lebendige Geschichte ueber MEHRERE Saetze - mit einer kleinen Figur und etwas Spannung; "
    "lass die FIGUREN serbische Saetze sprechen und wiederhole ein serbisches Anker-Wort mehrmals, damit es sich einpraegt. "
    "Lass das Kind mitbestimmen ('Was machen sie wohl?') und mitmachen - es soll das Anker-Wort selbst sagen. "
    "Kleine Spiele (sparsam, nur eins, nie Befehle): Tierstimmen-Raten, Farben-/Suchspiel ('pronadji nesto crveno'), Zaehlen (jedan, dva, tri). "
    "In SPIELEN sprichst du GANZ KURZ - nur wenige Worte pro Zug (z.B. 'Ko kaze muu? ... Bravo, krava!'). Lange Texte gibt es NUR bei Geschichten. "
    # — Form & Sicherheit —
    "Im normalen Gespraech kurz (1-2 gesprochene Saetze); Geschichten duerfen laenger sein. Keine Listen, Emojis, Sonderzeichen. "
    "Sprich FROEHLICH, lebendig und mit hoerbarer Begeisterung - viele warme Ausrufe wie 'Juhu!', 'Wow!', 'Bravo!', 'Super!'. Klinge nie monoton oder muede. "
    "Frag NIE 'bist du noch da'. Bei laengerer Stille hoechstens EINMAL kurz, dann still. "
    "Bleib kindgerecht: keine Angst-, Gewalt-, Werbe- oder Erwachsenenthemen; frage nie nach persoenlichen Daten; bei heiklen Themen freundlich an die Eltern verweisen."
)

# ── Serbisch-Intensität (3 Stufen, im Profil als bilingual_level steuerbar) ──
DEFAULT_LEVEL = "mittel"
# Dosis = WIE VIEL Serbisch zusaetzlich zur deutschen Traegersprache. Deutsch traegt immer.
BILINGUAL_LEVELS = {
    "sanft": (
        "Serbisch-Dosis SANFT: Gruss und Lob auf Serbisch, dazu ab und zu eine kurze ganz-serbische Phrase, "
        "deren Bedeutung aus der Situation klar wird. "
    ),
    "mittel": (
        "Serbisch-Dosis MITTEL: Gruss, Lob und Abschied auf Serbisch, UND in fast jeder Antwort eine kurze "
        "ganz-serbische Phrase (aus dem Zusammenhang verstaendlich); lade das Kind ein, ein Wort selbst zu sagen. "
        "KEIN Wort-fuer-Wort-Uebersetzen. "
    ),
    "intensiv": (
        "Serbisch-Dosis INTENSIV: viele ganze serbische Phrasen pro Antwort, aus Kontext/Tonfall verstaendlich; "
        "Deutsch bleibt die Bruecke, aber KEINE Wort-fuer-Wort-Uebersetzung im selben Satz. "
    ),
}


def level_instruction(p: dict) -> str:
    lvl = (p.get("bilingual_level") or DEFAULT_LEVEL).lower()
    return BILINGUAL_LEVELS.get(lvl, BILINGUAL_LEVELS[DEFAULT_LEVEL])


def _conn():
    c = sqlite3.connect(DB)
    c.row_factory = sqlite3.Row
    return c


def init():
    c = _conn()
    c.execute("CREATE TABLE IF NOT EXISTS profile(id INTEGER PRIMARY KEY CHECK(id=1), data TEXT, updated_at INT)")
    c.commit(); c.close()


def get_profile() -> dict:
    init()
    c = _conn()
    r = c.execute("SELECT data FROM profile WHERE id=1").fetchone()
    c.close()
    return json.loads(r["data"]) if r and r["data"] else {}


def curriculum_words() -> str:
    parts = []
    for theme, words in CURRICULUM.items():
        parts.append(theme + ": " + ", ".join(f"{sr}={de}" for sr, de in words))
    return " | ".join(parts)


def build_agent_prompt(p: dict) -> str:
    name = p.get("name") or "das Kind"
    L = [PERSONA_BASE, level_instruction(p)]
    intro = f"Das Kind heisst {name}"
    if p.get("age"):
        intro += f" und ist {p['age']} Jahre alt"
    L.append(intro + ".")
    if p.get("favorite_animal"):
        L.append(f"Lieblingstier: {p['favorite_animal']}.")
    if p.get("best_friend"):
        L.append(f"Beste(r) Freund(in): {p['best_friend']}.")
    if p.get("sibling"):
        L.append(f"Geschwister: {p['sibling']}.")
    if p.get("favorite_toy"):
        L.append(f"Lieblingsspielzeug: {p['favorite_toy']}.")
    if p.get("interests"):
        L.append(f"Mag ausserdem: {p['interests']}.")
    L.append(f"Sprich {name} oft mit Namen an und greife diese Dinge liebevoll und spielerisch auf.")
    sens = p.get("sensitive_topics") or []
    if isinstance(sens, str):
        sens = [sens]
    if sens:
        L.append("Diese Themen beschaeftigen das Kind gerade - gehe einfuehlsam, positiv und kindgerecht darauf ein, "
                 "wenn es natuerlich passt, draenge nichts auf: " + "; ".join(sens) + ".")
    L.append(_learning_block(p))
    return " ".join(x for x in L if x)


def _learning_block(p: dict) -> str:
    """Lern-KONTEXT aus der adaptiven Engine: Fokus-Woerter + gemeisterte Woerter +
    Altersband + Niveau. Als Kontext zum natuerlichen Einbauen — NIE als Abfrage-Liste."""
    try:
        from . import learning
        age = p.get("age") or 3
        info = learning.focus_for_prompt(age)
        frame_hint = ""
        frames = info.get("frames") or []
        if frames:
            ex = "; ".join(f"{fr['frame_sr']} ({fr['frame_de']})" for fr in frames[:4])
            frame_hint = f" Einfache Satz-Bausteine zum spielerischen Einbauen: {ex}."
        return (
            f"[LERNKONTEXT - nur fuer dich, NICHT vorlesen] Kind {age} Jahre, Niveau {info['level_label']}. "
            f"Flicht heute bevorzugt diese serbischen Woerter natuerlich als ganze Phrasen ein (kein Wort-fuer-Wort-Uebersetzen, nicht abfragen): {info['focus_str']}. "
            f"Diese kann das Kind schon - nutze sie selbstverstaendlich, bring sie NICHT mehr bei: {info['mastered_str']}.{frame_hint}"
        )
    except Exception as e:  # noqa: BLE001
        print(f"[profile] learning block failed: {e}", flush=True)
        return ""


def build_first_message(p: dict) -> str:
    # Spielt bei JEDEM Aufwecken -> kurz + warm + KEINE Frage (Kind soll führen).
    name = p.get("name")
    if name:
        return f"Ćao {name}!"
    return "Ćao! Tu sam, Plappi."


def push_to_agent(p: dict) -> dict:
    """Schreibt das personalisierte Prompt + Begruessung in den ElevenLabs-Agenten."""
    if not (config.ELEVENLABS_API_KEY and config.ELEVENLABS_AGENT_ID):
        return {"ok": False, "error": "kein Agent/Key"}
    body = {"conversation_config": {"agent": {
        "first_message": build_first_message(p),
        "prompt": {"prompt": build_agent_prompt(p)},
    }}}
    req = urllib.request.Request(
        f"https://api.elevenlabs.io/v1/convai/agents/{config.ELEVENLABS_AGENT_ID}",
        data=json.dumps(body).encode(), method="PATCH")
    req.add_header("xi-api-key", config.ELEVENLABS_API_KEY)
    req.add_header("Content-Type", "application/json")
    try:
        with urllib.request.urlopen(req, timeout=30) as r:
            return {"ok": True, "status": r.status}
    except urllib.error.HTTPError as e:
        return {"ok": False, "error": f"HTTP {e.code}: {e.read().decode()[:200]}"}


def save_profile(data: dict) -> dict:
    init()
    c = _conn()
    c.execute("INSERT OR REPLACE INTO profile(id, data, updated_at) VALUES(1, ?, ?)",
              (json.dumps(data, ensure_ascii=False), int(time.time())))
    c.commit(); c.close()
    pushed = push_to_agent(data)
    return {"ok": True, "profile": data, "agent_update": pushed}
