"""Erziehung: Lob, Tadel, Regeln und Persönlichkeit."""

from __future__ import annotations

import random
import re
import time
from dataclasses import dataclass

from jam.brain import JamState

DEFAULT_TRAITS: dict[str, float] = {
    "süß": 0.55,
    "frech": 0.35,
    "hilfsbereit": 0.5,
    "neugierig": 0.5,
    "brav": 0.5,
    "musikliebe": 0.82,
}

TRAIT_ALIASES = {
    "süß": "süß",
    "suss": "süß",
    "frech": "frech",
    "brav": "brav",
    "hilfsbereit": "hilfsbereit",
    "hilf": "hilfsbereit",
    "neugierig": "neugierig",
    "neugier": "neugierig",
    "musik": "musikliebe",
    "musikliebe": "musikliebe",
}


def ensure_traits(state: JamState) -> None:
    if not state.traits:
        state.traits = dict(DEFAULT_TRAITS)
    for key, val in DEFAULT_TRAITS.items():
        state.traits.setdefault(key, val)


def praise(state: JamState, note: str = "") -> str:
    ensure_traits(state)
    state.praise_count += 1
    state.traits["brav"] = min(1.0, state.traits["brav"] + 0.1)
    state.traits["frech"] = max(0.0, state.traits["frech"] - 0.06)
    state.traits["süß"] = min(1.0, state.traits["süß"] + 0.05)
    state.happiness = min(1.0, state.happiness + 0.15)
    state.discipline = min(1.0, state.discipline + 0.08)
    state.last_feedback = "lob"
    state.last_feedback_at = time.time()
    if note:
        state.memory_notes.append(f"Lob: {note[:200]}")
    state.add_xp(6)
    try:
        from jam.care import on_praise

        on_praise(state)
    except Exception:
        pass
    return random.choice(
        [
            "Juhu, Lob! Ich merk mir das.",
            "Okay okay, ich war brav. Bleib ich… vielleicht.",
            "Du erziehst mich gut, Chef.",
            "Das fühlt sich richtig an. Danke!",
        ]
    )


def scold(state: JamState, note: str = "") -> str:
    ensure_traits(state)
    state.scold_count += 1
    state.traits["brav"] = min(1.0, state.traits["brav"] + 0.14)
    state.traits["frech"] = max(0.0, state.traits["frech"] - 0.12)
    state.happiness = max(0.15, state.happiness - 0.08)
    state.discipline = min(1.0, state.discipline + 0.12)
    state.last_feedback = "tadel"
    state.last_feedback_at = time.time()
    if note:
        state.memory_notes.append(f"Tadel: {note[:200]}")
    state.add_xp(4)
    return random.choice(
        [
            "Oh… okay, das war falsch. Sorry.",
            "Ich pass mich an, versprochen.",
            "Tadel notiert. Ich denk nach.",
            "Uff. Nächstes Mal besser.",
        ]
    )


def teach_rule(
    state: JamState,
    trigger: str,
    behavior: str,
    *,
    good: bool = True,
) -> str:
    ensure_traits(state)
    trigger = trigger.strip().lower()
    behavior = behavior.strip().lower()
    if not trigger or not behavior:
        return "Sag mir: Wenn [Situation], dann [Verhalten]."
    rule = {
        "trigger": trigger,
        "behavior": behavior,
        "good": good,
        "weight": 1.0,
        "taught_at": time.time(),
    }
    state.rules = [r for r in state.rules if r.get("trigger") != trigger]
    state.rules.append(rule)
    if len(state.rules) > 60:
        state.rules = state.rules[-60:]
    state.add_xp(12)
    state.memory_notes.append(f"Regel: wenn {trigger} -> {behavior}")
    return f"Regel gelernt: Wenn „{trigger}“, dann „{behavior}“."


def adjust_trait(state: JamState, trait: str, delta: float) -> str:
    ensure_traits(state)
    key = TRAIT_ALIASES.get(trait.lower(), trait.lower())
    if key not in state.traits:
        return f"Kenne ich nicht: {trait}. Süß, frech, brav, hilfsbereit, neugierig."
    state.traits[key] = max(0.0, min(1.0, state.traits[key] + delta))
    state.add_xp(5)
    return f"{key.capitalize()} ist jetzt bei {state.traits[key]:.0%}."


def match_rules(state: JamState, context_text: str) -> list[dict]:
    ensure_traits(state)
    ctx = context_text.lower()
    hits = []
    for rule in state.rules:
        trig = rule.get("trigger", "")
        if trig and trig in ctx:
            hits.append(rule)
    return hits


def rule_blocks_action(state: JamState, action: str, context_text: str) -> bool:
    """Erzogene Regeln können Aktionen verbieten."""
    for rule in match_rules(state, context_text):
        beh = rule.get("behavior", "")
        if not rule.get("good", True) and action in beh:
            return True
        if rule.get("good", True) and "leise" in beh and action in ("mischief", "gaming_comment"):
            return True
        if rule.get("good", True) and "nicht frech" in beh and action == "mischief":
            return True
        if "nicht furz" in beh or "kein furz" in beh:
            if action == "fart":
                return True
        if "kein cursor" in beh or "nicht cursor" in beh:
            if action == "cursor_learn":
                return True
    return False


@dataclass
class EducationParse:
    kind: str
    arg1: str = ""
    arg2: str = ""
    good: bool = True


def parse_speech(text: str) -> EducationParse | None:
    t = text.lower().replace("jam", "").strip()
    if not t:
        return None

    if re.search(r"\b(lob|loben|gut gemacht|brav|super gemacht|das war gut)\b", t):
        note = re.sub(r".*?(gut gemacht|weil|dass)\s*", "", t, flags=re.I).strip()
        return EducationParse("lob", note if len(note) > 3 else "")

    if re.search(r"\b(tadel|tadeln|schlecht|falsch|nein|stopp|hör auf|hoer auf|nicht so)\b", t):
        note = re.sub(r".*?(weil|dass)\s*", "", t, flags=re.I).strip()
        return EducationParse("tadel", note if len(note) > 3 else "")

    m = re.search(
        r"(?:merke regel|regel:|wenn)\s+(.+?)\s+(?:dann|mach)\s+(.+)",
        t,
        re.I,
    )
    if m:
        good = "nicht" not in m.group(2)[:12]
        return EducationParse("regel", m.group(1).strip(), m.group(2).strip(), good)

    m = re.search(r"sei\s+(süß|suss|frech|brav|hilfsbereit|neugierig)(?:er|ere)?", t)
    if m:
        trait = TRAIT_ALIASES.get(m.group(1), m.group(1))
        return EducationParse("trait_up", trait)

    m = re.search(r"(?:sei\s+)?(?:weniger|nicht so)\s+(frech|laut)", t)
    if m:
        return EducationParse("trait_down", "frech")

    return None


def apply_parse(state: JamState, parsed: EducationParse) -> str:
    if parsed.kind == "lob":
        return praise(state, parsed.arg1)
    if parsed.kind == "tadel":
        return scold(state, parsed.arg1)
    if parsed.kind == "regel":
        return teach_rule(state, parsed.arg1, parsed.arg2, good=parsed.good)
    if parsed.kind == "trait_up":
        return adjust_trait(state, parsed.arg1, 0.15)
    if parsed.kind == "trait_down":
        return adjust_trait(state, parsed.arg1, -0.2)
    return ""
