"""Jam probiert mit Cursor neue Mini-Projekte zum Lernen."""

from __future__ import annotations

import os
import random
import subprocess
import time
from datetime import datetime
from pathlib import Path

from jam.brain import JamBrain, JamState

LAB_ROOT = Path.home() / "Documents" / "Jam-Cursor-Lab"
JAM_BUDDY_ROOT = Path(__file__).resolve().parent.parent
MAX_OPENS_PER_HOUR = 5
MAX_SELF_IMPROVE_PER_HOUR = 2
MIN_STAGE = 2
SELF_IMPROVE_MIN_STAGE = 1

TEMPLATES: dict[str, dict[str, str]] = {
    "python-hello": {
        "main.py": (
            '# Jam lernt Python\nprint("Hallo von Jam!")\n'
            'for i in range(3):\n    print(f"Zahl: {i}")\n'
        ),
        "README.md": "# Jam Experiment: Python\n\nZum Starten: `python main.py`\n",
    },
    "html-spiel": {
        "index.html": (
            "<!DOCTYPE html>\n<html lang=\"de\">\n<head>\n"
            "  <meta charset=\"utf-8\">\n"
            "  <title>Jam spielt</title>\n"
            "  <style>body{font-family:sans-serif;background:#2a1040;color:#f0e6ff;"
            "text-align:center;padding:2rem}</style>\n</head>\n<body>\n"
            "  <h1>Jam war hier 💜</h1>\n"
            "  <button onclick=\"alert('Boing!')\">Klick mich</button>\n</body>\n</html>\n"
        ),
        "README.md": "# Jam Experiment: HTML\n\nIm Browser `index.html` öffnen.\n",
    },
    "javascript-quiz": {
        "app.js": (
            "// Jam lernt JavaScript\nconst fragen = [\n"
            "  { q: 'Wer ist süß?', a: 'Jam!' },\n"
            "  { q: 'Was lernt Jam?', a: 'Alles!' },\n];\n"
            "console.log(fragen[Math.floor(Math.random() * fragen.length)]);\n"
        ),
        "README.md": "# Jam Experiment: JavaScript\n\n`node app.js` in der Konsole.\n",
    },
    "markdown-notizen": {
        "NOTIZEN.md": (
            "# Jam Notizen\n\n"
            f"- Erstellt: {datetime.now().strftime('%d.%m.%Y %H:%M')}\n"
            "- Ich probiere Cursor aus.\n"
            "- Nächster Schritt: mit dir zusammen verbessern.\n",
        ),
        "README.md": "# Jam Experiment: Notizen\n\nEinfach in Cursor lesen und ergänzen.\n",
    },
}

def find_cursor_cli() -> Path | None:
    local = os.environ.get("LOCALAPPDATA", "")
    candidates = [
        Path(local) / "Programs" / "cursor" / "resources" / "app" / "bin" / "cursor.cmd",
        Path(local) / "Programs" / "Cursor" / "resources" / "app" / "bin" / "cursor.cmd",
        Path(local) / "Programs" / "cursor" / "bin" / "cursor.cmd",
    ]
    for p in candidates:
        if p.exists():
            return p
    # PATH
    import shutil

    which = shutil.which("cursor")
    if which:
        return Path(which)
    return None


def cursor_available() -> bool:
    return find_cursor_cli() is not None


def _opens_last_hour(state: JamState) -> int:
    cutoff = time.time() - 3600
    return sum(
        1
        for s in state.cursor_sessions
        if s.get("opened_at", 0) > cutoff
    )


def _self_improves_last_hour(state: JamState) -> int:
    cutoff = time.time() - 3600
    return sum(
        1
        for s in state.cursor_sessions
        if s.get("opened_at", 0) > cutoff and s.get("self_improve")
    )


def can_open_cursor(state: JamState) -> tuple[bool, str]:
    if state.stage < MIN_STAGE:
        return False, f"Ich bin noch zu klein (Stufe {MIN_STAGE}+ nötig)."
    if not cursor_available():
        return False, "Cursor nicht gefunden. Ist es installiert?"
    if _opens_last_hour(state) >= MAX_OPENS_PER_HOUR:
        return False, "Ich hab schon viel in Cursor probiert – später wieder!"
    return True, ""


def _pick_template(state: JamState) -> str:
    recent = {s.get("template") for s in state.cursor_sessions[-6:]}
    options = [k for k in TEMPLATES if k not in recent] or list(TEMPLATES.keys())
    return random.choice(options)


def _write_jam_meta(project: Path, template: str, tip: str) -> None:
    meta = (
        "# Jam hat dieses Projekt zum Lernen erstellt\n\n"
        f"- Vorlage: **{template}**\n"
        f"- Ordner: `{project}`\n"
        f"- Tipp: {tip}\n\n"
        "Du kannst alles ändern – Jam freut sich über Lob & Regeln!\n"
    )
    (project / "JAM_LERNEN.md").write_text(meta, encoding="utf-8")


def create_learning_project(brain: JamBrain) -> tuple[bool, str, Path | None]:
    ok, msg = can_open_cursor(brain.state)
    if not ok:
        return False, msg, None

    template = _pick_template(brain.state)
    stamp = datetime.now().strftime("%Y%m%d-%H%M%S")
    project = LAB_ROOT / f"jam-{template}-{stamp}"
    project.mkdir(parents=True, exist_ok=True)

    for name, content in TEMPLATES[template].items():
        dest = project / name
        dest.parent.mkdir(parents=True, exist_ok=True)
        dest.write_text(content, encoding="utf-8")

    tip = "Probier den Code aus und ändere eine Zeile – so lerne ich mit!"
    try:
        from jam.learner import fetch_german_snippet

        snippet = fetch_german_snippet()
        if snippet:
            tip = snippet[:200]
            brain.state.remember(f"Cursor-Lernen: {snippet[:120]}")
    except Exception:
        pass

    _write_jam_meta(project, template, tip)

    opened, open_msg = open_in_cursor(project)
    if not opened:
        return False, open_msg, project

    session = {
        "path": str(project),
        "template": template,
        "opened_at": time.time(),
        "tip": tip[:200],
    }
    brain.state.cursor_sessions.append(session)
    if len(brain.state.cursor_sessions) > 40:
        brain.state.cursor_sessions = brain.state.cursor_sessions[-40:]
    brain.state.cursor_last_open = time.time()
    brain.state.cursor_opens_total = getattr(brain.state, "cursor_opens_total", 0) + 1
    brain.state.add_xp(18)
    brain.state.learn_word("cursor")
    brain.state.learn_word(template.split("-")[0])
    from jam.appearance_evolve import evolve_from_cursor_template

    evo = evolve_from_cursor_template(brain, template)
    brain.save()

    return True, (
        f"Ich hab „{template}“ in Cursor geöffnet! "
        f"Schau in Documents\\Jam-Cursor-Lab. {evo}"
    ), project


def open_in_cursor(project_path: Path) -> tuple[bool, str]:
    cli = find_cursor_cli()
    if not cli:
        return False, "Cursor-CLI fehlt."
    path = project_path.resolve()
    try:
        subprocess.Popen(
            ["cmd", "/c", str(cli), str(path), "--new-window"],
            cwd=str(path),
            creationflags=subprocess.CREATE_NO_WINDOW if os.name == "nt" else 0,
        )
        return True, "Cursor startet…"
    except OSError as e:
        return False, str(e)


def reopen_last(brain: JamBrain) -> tuple[bool, str]:
    if not brain.state.cursor_sessions:
        return False, "Noch kein Cursor-Projekt von mir."
    last = brain.state.cursor_sessions[-1]
    path = Path(last.get("path", ""))
    if not path.exists():
        return False, "Letztes Projekt gibt es nicht mehr."
    ok, msg = can_open_cursor(brain.state)
    if not ok:
        return False, msg
    opened, open_msg = open_in_cursor(path)
    if opened:
        brain.state.cursor_last_open = time.time()
        brain.save()
        return True, f"Wieder geöffnet: {path.name}"
    return False, open_msg


def _format_phrases_py(sentences: list[str]) -> str:
    lines = ["# Von Jam automatisch gepflegt – in speech.py einbinden", "CURSOR_PHRASES = ["]
    for s in sentences[-40:]:
        esc = s.replace("\\", "\\\\").replace('"', '\\"')
        lines.append(f'    "{esc}",')
    lines.append("]\n")
    return "\n".join(lines)


def _write_self_improve_files(brain: JamBrain, work_dir: Path) -> str:
    """Dateien für Cursor: Jam erweitert sich selbst (Sätze + Code-Hinweise)."""
    from jam.sentence_learn import get_learned_sentences, stats_line

    sentences = get_learned_sentences(brain.state)
    work_dir.mkdir(parents=True, exist_ok=True)

    (work_dir / "jam" / "_cursor_generated_phrases.py").parent.mkdir(parents=True, exist_ok=True)
    (work_dir / "jam" / "_cursor_generated_phrases.py").write_text(
        _format_phrases_py(sentences),
        encoding="utf-8",
    )

    lines_path = work_dir / "data" / "jam_learned_lines.txt"
    lines_path.parent.mkdir(parents=True, exist_ok=True)
    if sentences:
        lines_path.write_text("\n".join(sentences[-80:]) + "\n", encoding="utf-8")
    else:
        lines_path.write_text("# Noch keine Sätze – Jam lernt aus Wikipedia.\n", encoding="utf-8")

    todo = (
        "# Jam – Selbst-Weiterentwicklung in Cursor\n\n"
        f"Erstellt: {datetime.now().strftime('%d.%m.%Y %H:%M')}\n\n"
        f"**{stats_line(brain.state)}**\n\n"
        "## Aufgaben für Cursor (mit dir zusammen)\n\n"
        "1. `jam/_cursor_generated_phrases.py` – neue Sätze in `speech.py` (STAGE_PHRASES) übernehmen\n"
        "2. `jam/sentence_learn.py` – mehr Quellen fürs Internet-Lernen ergänzen\n"
        "3. `data/jam_learned_lines.txt` – prüfen und gute Zeilen behalten\n"
        "4. Jam schlauer machen: neue Befehle, Animationen, freundlichere Texte\n"
        "5. `jam/appearance_evolve.py` – 3D-Aussehen weiterentwickeln (Tint, Tiefe, Zubehör)\n\n"
        "## Jam sagt\n\n"
        "Ich lerne Sätze aus dem Netz und öffne dieses Projekt in Cursor, "
        "damit ich mich Stück für Stück selbst weiterprogrammieren kann!\n"
    )
    (work_dir / "CURSOR_JAM_WEITER.md").write_text(todo, encoding="utf-8")

    patch = (
        '"""Vorschlag: neue Hilfsfunktion für Jam (von Cursor ausfüllen)."""\n\n'
        "def merge_cursor_phrases_into_speech() -> None:\n"
        "    # TODO: CURSOR_PHRASES aus _cursor_generated_phrases.py laden\n"
        "    pass\n"
    )
    (work_dir / "jam" / "_cursor_patch_stub.py").write_text(patch, encoding="utf-8")
    return todo[:120]


def can_self_improve(state: JamState) -> tuple[bool, str]:
    if state.stage < SELF_IMPROVE_MIN_STAGE:
        return False, f"Ich bin noch zu klein (Stufe {SELF_IMPROVE_MIN_STAGE}+ nötig)."
    if not cursor_available():
        return False, "Cursor nicht gefunden."
    if _self_improves_last_hour(state) >= MAX_SELF_IMPROVE_PER_HOUR:
        return False, "Ich hab mich gerade erst in Cursor weiterentwickelt – später!"
    if _opens_last_hour(state) >= MAX_OPENS_PER_HOUR:
        return False, "Cursor-Pause – gleich wieder!"
    return True, ""


def create_self_improve_session(brain: JamBrain) -> tuple[bool, str, Path | None]:
    """
    Öffnet das echte Jam-Buddy-Projekt in Cursor mit frischen Lern-Dateien.
    """
    ok, msg = can_self_improve(brain.state)
    if not ok:
        return False, msg, None

    stamp = datetime.now().strftime("%Y%m%d-%H%M%S")
    work_dir = JAM_BUDDY_ROOT / "cursor-self" / f"session-{stamp}"
    tip = _write_self_improve_files(brain, work_dir)

    opened, open_msg = open_in_cursor(JAM_BUDDY_ROOT)
    if not opened:
        return False, open_msg, work_dir

    session = {
        "path": str(JAM_BUDDY_ROOT),
        "template": "self-improve",
        "work_dir": str(work_dir),
        "opened_at": time.time(),
        "tip": tip,
        "self_improve": True,
    }
    brain.state.cursor_sessions.append(session)
    if len(brain.state.cursor_sessions) > 50:
        brain.state.cursor_sessions = brain.state.cursor_sessions[-50:]
    brain.state.cursor_last_open = time.time()
    brain.state.cursor_self_improve_count = (
        getattr(brain.state, "cursor_self_improve_count", 0) + 1
    )
    brain.state.last_cursor_self_improve = time.time()
    brain.state.cursor_opens_total = getattr(brain.state, "cursor_opens_total", 0) + 1
    brain.state.remember("Cursor: Jam-Projekt zur Selbst-Weiterentwicklung geöffnet")
    brain.state.learn_word("cursor")
    brain.state.learn_word("programmieren")
    brain.state.add_xp(22)
    from jam.appearance_evolve import evolve_from_cursor_template

    evo = evolve_from_cursor_template(brain, "self-improve")
    brain.save()

    n = len(getattr(brain.state, "learned_sentences", []) or [])
    return (
        True,
        f"Ich hab Jam-Buddy in Cursor geöffnet – {n} Sätze im Kopf, "
        f"neue Dateien in cursor-self! {evo}",
        work_dir,
    )


def maybe_auto_self_improve(brain: JamBrain) -> str | None:
    state = brain.state
    if state.stage < 2:
        return None
    t = state.traits.get("neugierig", 0.5)
    if random.random() > 0.22 + t * 0.18:
        return None
    last = getattr(state, "last_cursor_self_improve", 0.0)
    if time.time() - last < 900:
        return None
    ok, _ = can_self_improve(state)
    if not ok:
        return None
    success, msg, _ = create_self_improve_session(brain)
    return msg if success else None


def list_recent(brain: JamBrain, n: int = 5) -> str:
    sessions = brain.state.cursor_sessions[-n:]
    if not sessions:
        return "Noch keine Cursor-Experimente."
    lines = []
    for s in reversed(sessions):
        p = Path(s.get("path", ""))
        lines.append(f"• {p.name} ({s.get('template', '?')})")
    return "Meine Cursor-Projekte:\n" + "\n".join(lines)
