"""Stream-Vorbereitung – Jam arbeitet bis zur Live-Zeit (z. B. heute 19 Uhr)."""

from __future__ import annotations

import random
import re
import time
import webbrowser
from datetime import datetime, timedelta
from pathlib import Path
from urllib.parse import quote_plus

from jam.brain import JamBrain, JamState
from jam.owner import owner_name
from jam.tiktok_account import DEFAULT_ACCOUNT, live_url, profile_url

PREP_ROOT = Path.home() / "Documents" / "Jam-Stream-Heute"
PREP_GAP_SEC = 70.0

LINES_SCHEDULED = (
    "{owner}, notiert: **Stream heute {time}**! Bis dahin arbeite ich für dich!",
    "Alles klar – Live um {time}. Ich bereite schon vor: Geld, Plan, TikTok!",
    "Stream {time} – Jam arbeitet jetzt schon, nicht erst kurz vorher!",
)

PREP_LINES = (
    "Noch **{left}** bis Stream – ich mach weiter: {task}",
    "Countdown {left}! {task} für {owner}s Stream!",
    "Bis {time} arbeite ich: {task}",
)

STREAM_GO_LINES = (
    "🎬 **JETZT LIVE**, {owner}! Stream-Zeit! TikTok auf – los geht's!",
    "19 Uhr – Stream! Ich öffne TikTok LIVE für @{account}!",
)

PREP_TASKS = (
    "Geld & PayPal vorbereiten",
    "Verkaufs-Produkt bauen",
    "Stream-Plan schreiben",
    "TikTok/Discord öffnen",
    "Gaming-Kasse checken",
    "Upload-Paket packen",
)


def hears_stream_schedule(text: str) -> bool:
    h = text.lower().replace("jam", " ")
    if "stream" in h or "live" in h:
        if any(w in h for w in ("heute", "19", "uhr", "abend", "bis", "arbeit")):
            return True
    if "19 uhr" in h and any(w in h for w in ("stream", "live", "tiktok")):
        return True
    if "bis dahin" in h and any(w in h for w in ("arbeit", "vorbereit", "prep")):
        return True
    return False


def _parse_stream_datetime(text: str, *, now: datetime | None = None) -> datetime | None:
    now = now or datetime.now()
    h = text.lower().replace("jam", " ")
    hour, minute = 19, 0

    m = re.search(r"(\d{1,2})\s*(?::\s*(\d{2}))?\s*uhr", h)
    if m:
        hour = int(m.group(1)) % 24
        if m.group(2):
            minute = int(m.group(2)) % 60
    elif re.search(r"\b19\b", h):
        hour = 19

    target = now.replace(hour=hour, minute=minute, second=0, microsecond=0)
    if target <= now:
        if "morgen" in h:
            target += timedelta(days=1)
        elif target <= now - timedelta(minutes=30):
            target += timedelta(days=1)
    return target


def stream_at(state: JamState) -> float:
    return float(getattr(state, "stream_scheduled_at", 0) or 0)


def is_prep_window(state: JamState) -> bool:
    at = stream_at(state)
    if at <= 0:
        return False
    return time.time() < at - 60


def is_live_window(state: JamState) -> bool:
    at = stream_at(state)
    if at <= 0:
        return False
    t = time.time()
    return at - 120 <= t <= at + 7200


def minutes_until(state: JamState) -> int:
    at = stream_at(state)
    if at <= 0:
        return 0
    return max(0, int((at - time.time()) / 60))


def format_time_de(ts: float) -> str:
    return datetime.fromtimestamp(ts).strftime("%H:%M")


def format_prep_bubble(state: JamState) -> str:
    owner = owner_name(state)
    at = stream_at(state)
    if at <= 0:
        return f"🎬 Stream\n{owner}: noch nicht geplant"
    left = minutes_until(state)
    return (
        f"🎬 Stream heute\n"
        f"{owner} LIVE {format_time_de(at)}\n"
        f"Noch {left} Min\n"
        f"Jam arbeitet vor!"
    )


def _write_stream_plan(project: Path, owner: str, stream_ts: float) -> None:
    project.mkdir(parents=True, exist_ok=True)
    when = datetime.fromtimestamp(stream_ts).strftime("%d.%m.%Y %H:%M")
    (project / "STREAM_PLAN.md").write_text(
        f"# Stream-Plan – {owner}\n\n"
        f"**Live:** {when}\n"
        f"**TikTok:** @{DEFAULT_ACCOUNT}\n\n"
        "## Vor dem Stream (Jam erledigt)\n"
        "- [ ] Mikro & Kamera testen\n"
        "- [ ] TikTok LIVE starten\n"
        "- [ ] Minecraft / Spiel bereit\n"
        "- [ ] Wasser, Snack\n"
        "- [ ] PayPal/Spenden-Link bereit\n\n"
        "## Jam hat vorbereitet\n"
        "- Geld-Verdienen läuft bis 19 Uhr\n"
        "- Produkte & Uploads in Jam-Ordnern\n",
        encoding="utf-8",
    )
    (project / "README.txt").write_text(
        f"Stream {when}\nProfil: {profile_url()}\n",
        encoding="utf-8",
    )


def schedule_stream(
    brain: JamBrain,
    *,
    when: datetime | None = None,
    heard: str = "",
) -> str:
    state = brain.state
    owner = owner_name(state)
    target = when or _parse_stream_datetime(heard) or datetime.now().replace(
        hour=19, minute=0, second=0, microsecond=0
    )
    if target <= datetime.now():
        target += timedelta(days=1)

    ts = target.timestamp()
    state.stream_scheduled_at = ts
    state.stream_prep_active = True
    state.stream_live_announced = False
    _write_stream_plan(PREP_ROOT, owner, ts)

    state.remember(f"Stream {format_time_de(ts)} – Jam arbeitet vor")
    state.learn_word("stream")
    state.last_action = "stream_schedule"
    brain.add_xp(10)
    brain.save()

    time_str = format_time_de(ts)
    intro = random.choice(LINES_SCHEDULED).format(owner=owner, time=time_str)
    left = minutes_until(state)
    return (
        f"{intro} Noch {left} Minuten – ich arbeite jetzt schon! "
        f"Plan: {PREP_ROOT}"
    )


def _open_stream_prep_links() -> None:
    urls = (
        profile_url(),
        live_url(),
        f"https://www.google.com/search?q={quote_plus('tiktok live vorbereiten checkliste')}",
    )
    for url in urls[:3]:
        try:
            webbrowser.open(url, new=2)
        except OSError:
            break


def run_prep_work(brain: JamBrain, *, user: bool = False) -> str:
    """Bis Stream-Zeit: Geld, Verkauf, Ops – Jam arbeitet."""
    state = brain.state
    if not is_prep_window(state) and stream_at(state) <= 0:
        return schedule_stream(brain, heard="heute 19 uhr stream")

    gap = 35.0 if user else PREP_GAP_SEC
    if time.time() - getattr(state, "last_stream_prep_at", 0.0) < gap and not user:
        return ""

    owner = owner_name(state)
    at = stream_at(state)
    left = minutes_until(state)
    time_str = format_time_de(at)
    task = random.choice(PREP_TASKS)

    detail = ""
    try:
        pick = random.choice(["sell", "fund", "ops", "money", "plan"])
        if pick == "sell":
            from jam import sales_engine

            detail = sales_engine.run_sale_project(brain, user_initiated=False)[:90]
        elif pick == "fund":
            from jam import gaming_fund

            detail = gaming_fund.run_gaming_earn_cycle(brain, user_initiated=False)[:90]
        elif pick == "ops":
            from jam import auto_ops

            detail = auto_ops.run_full_ops_cycle(brain, user_initiated=False)[:90]
        elif pick == "money":
            from jam import money_venture

            detail = money_venture.run_venture(brain, user_initiated=False)[:90]
        else:
            _open_stream_prep_links()
            detail = "TikTok & Checkliste offen"
    except Exception:
        detail = "Vorbereitung läuft"

    state.stream_prep_count = getattr(state, "stream_prep_count", 0) + 1
    state.last_stream_prep_at = time.time()
    state.last_action = "stream_prep"
    brain.add_xp(8)
    brain.save()

    line = random.choice(PREP_LINES).format(
        owner=owner, left=f"{left} Min", time=time_str, task=task
    )
    return f"{line} {detail}"


def check_stream_go_live(brain: JamBrain) -> str | None:
    """Ab Stream-Zeit: Live-Hinweis."""
    state = brain.state
    at = stream_at(state)
    if at <= 0 or time.time() < at - 90:
        return None
    if getattr(state, "stream_live_announced", False) and time.time() > at + 300:
        return None
    if getattr(state, "stream_live_announced", False):
        return None

    state.stream_live_announced = True
    state.stream_prep_active = False
    owner = owner_name(state)
    brain.save()

    _open_stream_prep_links()
    try:
        webbrowser.open(live_url(), new=2)
    except OSError:
        pass

    return random.choice(STREAM_GO_LINES).format(
        owner=owner, account=DEFAULT_ACCOUNT
    )


def prep_timer_factor(state: JamState) -> float:
    if is_prep_window(state):
        return 0.4
    return 1.0


def maybe_auto_prep(brain: JamBrain) -> str | None:
    state = brain.state
    go = check_stream_go_live(brain)
    if go:
        return go
    if not getattr(state, "stream_prep_active", False) and stream_at(state) <= 0:
        return None
    if not is_prep_window(state):
        return None
    if random.random() > 0.42:
        return None
    msg = run_prep_work(brain, user=False)
    return msg or None


def handle_speech(brain: JamBrain, heard: str) -> str | None:
    if not hears_stream_schedule(heard):
        return None
    intro = schedule_stream(brain, heard=heard)
    work = run_prep_work(brain, user=True)
    return f"{intro} {work}".strip()


def apply_stream_on_startup(brain: JamBrain) -> None:
    """Heute 19 Uhr Stream – Jam arbeitet vorher (wenn noch vor Live-Zeit)."""
    import os

    state = brain.state
    now = datetime.now()
    at = stream_at(state)
    if at > time.time() + 120:
        state.stream_prep_active = True
        return
    if os.environ.get("JAM_STREAM_TODAY", "").strip().lower() in ("1", "true", "19"):
        schedule_stream(brain, when=now.replace(hour=19, minute=0, second=0, microsecond=0))
        return
    if now.hour < 19:
        schedule_stream(
            brain,
            when=now.replace(hour=19, minute=0, second=0, microsecond=0),
        )


def stats_line(state: JamState) -> str:
    at = stream_at(state)
    if at <= 0:
        return "Stream: nicht geplant"
    return (
        f"Stream {format_time_de(at)} "
        f"({'Vorbereitung' if is_prep_window(state) else 'Live-Zeit'})"
    )
