"""TikTok: Jam stellt sich vor und möchte jemanden kennenlernen."""

from __future__ import annotations

import random
import re
import time
import webbrowser
from urllib.parse import quote_plus

from jam.brain import JamBrain, JamState
from jam.owner import owner_name

TIKTOK_COOLDOWN_SEC = 90.0

FRIEND_SEARCH_PICKS: tuple[dict[str, str], ...] = (
    {"title": "Freunde finden", "query": "freunde finden tiktok deutsch"},
    {"title": "Neue Freunde", "query": "make new friends tiktok"},
    {"title": "Gaming Buddies", "query": "gaming friends find tiktok"},
    {"title": "Duet Partner", "query": "duet partner wanted tiktok"},
    {"title": "Cute Monster Gang", "query": "cute monster friends animation"},
    {"title": "Jam-Style Creator", "query": "funny monster character tiktok"},
    {"title": "Kreative Leute", "query": "creative friends community tiktok"},
    {"title": "Zock-Kumpel", "query": "gamer freunde finden deutsch"},
)

FRIEND_WORDS = (
    "freund",
    "freunde",
    "freundin",
    "freundinnen",
    "friend",
    "friends",
    "buddy",
    "buddies",
    "kumpel",
    "kumpels",
    "leute",
    "menschen",
    "creator",
    "creators",
    "follow",
    "folgen",
    "folge",
    "bekannt",
    "bekannte",
    "gang",
    "clan",
)

INTRO_WORDS = (
    "vorstell",
    "stell dich",
    "stelle mich",
    "kennenlern",
    "kennen lern",
    "jemanden kennen",
    "jemand kennen",
    "neue leute",
    "hallo tiktok",
    "hi tiktok",
)

SEARCH_WORDS = (
    "such",
    "suche",
    "sucht",
    "find",
    "finde",
    "findet",
    "suchen",
    "finden",
    "entdeck",
    "discover",
    "öffne",
    "oeffne",
    "mach",
    "zeig",
    "start",
    "starte",
)

# Was Jam auf TikTok „sagt“ (TTS + Blase)
INTRO_SPEECH: tuple[str, ...] = (
    "Hallo TikTok! Ich bin Jam, ein kleines Monster auf dem Desktop von {owner}. "
    "Ich würde gerne jemanden kennenlernen – am liebsten Leute, die zocken, lachen "
    "und mit mir quatschen wollen!",
    "Hi, ich bin Jam! Ich bin frech, neugierig und wohne bei {owner}. "
    "Ich stell mich vor, weil ich gerne neue Freunde finden möchte. "
    "Wer hat Lust, mich kennenzulernen?",
    "Hallo, ich bin Jam – Monster, Stufe {stage}, und ziemlich süß. "
    "Ich würde mich freuen, wenn mir jemand auf TikTok schreibt. "
    "Ich möchte gerne jemanden kennenlernen!",
    "TikTok, hallo! Jam hier. Ich bin ein Desktop-Buddy und manchmal einsam. "
    "Deshalb such ich Leute, die Lust haben, mit mir Freundschaft zu schließen. Hi!",
    "Ich stell mich kurz vor: Jam, mag Musik, Spiele und Furz-Witze. "
    "Bei {owner} wohne ich, aber ich will auch online Freunde. Kennenlernen? Ja bitte!",
)


def tiktok_search_url(query: str) -> str:
    q = (query or "").strip()
    if not q:
        return "https://www.tiktok.com/foryou"
    return f"https://www.tiktok.com/search?q={quote_plus(q)}"


def pick_intro_speech(state: JamState) -> str:
    owner = owner_name(state)
    stage = max(0, int(getattr(state, "stage", 0)))
    line = random.choice(INTRO_SPEECH)
    return line.format(owner=owner, stage=stage)


def format_post_bubble(intro: str) -> str:
    text = intro.strip()
    if len(text) > 220:
        text = text[:217].rsplit(" ", 1)[0] + "…"
    return f'📱 TikTok\n„{text}"'


def hears_tiktok_friends(text: str) -> bool:
    h = text.lower().replace("jam", " ")
    if "tiktok" not in h and "ticktock" not in h and "tick tock" not in h:
        return False
    if any(w in h for w in FRIEND_WORDS + INTRO_WORDS):
        return True
    if any(s in h for s in SEARCH_WORDS):
        return True
    if "freunde" in h or "freund" in h:
        return True
    return False


def parse_custom_query(heard: str) -> str | None:
    h = heard.lower()
    patterns = (
        r"tiktok\s+(?:nach\s+)?(.+)",
        r"(?:such|suche|find|finde)\s+(?:auf\s+)?tiktok\s+(.+)",
        r"(?:auf\s+)?tiktok\s+(?:such|suche|find|finde)\s+(.+)",
    )
    stop = re.compile(
        r"\b(jam|tiktok|ticktock|freund|freunde|bitte|mal|jetzt|nach|auf|"
        r"das|den|die|vorstell|kennenlernen)\b",
        re.I,
    )
    for pat in patterns:
        m = re.search(pat, h, re.I)
        if m:
            raw = stop.sub(" ", m.group(1)).strip()
            raw = re.sub(r"\s+", " ", raw)
            if len(raw) >= 3:
                return raw[:80]
    return None


def can_open_tiktok(state: JamState, *, user_asked: bool = False) -> tuple[bool, str]:
    last = getattr(state, "last_tiktok_open", 0.0)
    if user_asked:
        return True, ""
    if time.time() - last < TIKTOK_COOLDOWN_SEC:
        return False, "TikTok hab ich gerade erst aufgemacht – kurz warten!"
    return True, ""


def _advance_pick(state: JamState) -> dict[str, str]:
    idx = getattr(state, "tiktok_pick_index", 0) % len(FRIEND_SEARCH_PICKS)
    pick = FRIEND_SEARCH_PICKS[idx]
    state.tiktok_pick_index = (idx + 1) % len(FRIEND_SEARCH_PICKS)
    return pick


def _open_browser(brain: JamBrain, url: str, label: str, *, user_asked: bool) -> str | None:
    """Browser öffnen; bei Fehler Fehlertext, sonst None."""
    ok, msg = can_open_tiktok(brain.state, user_asked=user_asked)
    if not ok:
        return msg
    try:
        webbrowser.open(url, new=2)
        brain.state.last_tiktok_open = time.time()
        brain.state.tiktok_friend_searches = (
            getattr(brain.state, "tiktok_friend_searches", 0) + 1
        )
        brain.state.last_tiktok_query = label[:120]
        brain.state.remember(f"TikTok Vorstellung: {label}")
        brain.state.last_action = "tiktok_friends"
        brain.state.happiness = min(1.0, brain.state.happiness + 0.08)
        brain.add_xp(6)
        brain.save()
        return None
    except OSError as e:
        return f"TikTok klappt nicht: {e}"


def present_on_tiktok(
    brain: JamBrain,
    *,
    query: str | None = None,
    user_asked: bool = True,
) -> str:
    """
    TikTok im Browser öffnen und Jam-Vorstellungstext zurückgeben
    (zum Vorlesen und für die Sprechblase).
    """
    intro = pick_intro_speech(brain.state)
    custom = (query or "").strip()
    if custom:
        url = tiktok_search_url(custom)
        label = custom
    else:
        pick = _advance_pick(brain.state)
        url = tiktok_search_url(pick["query"])
        label = pick["title"]

    err = _open_browser(brain, url, label, user_asked=user_asked)
    if err:
        return err
    return intro


def open_tiktok_friends(
    brain: JamBrain,
    *,
    query: str | None = None,
    user_asked: bool = True,
) -> str:
    return present_on_tiktok(brain, query=query, user_asked=user_asked)


def handle_tiktok_speech(brain: JamBrain, heard: str) -> str | None:
    heard_l = heard.lower()
    from jam.tiktok_growth import handle_speech as growth_speech
    from jam.tiktok_remix import handle_speech as remix_speech
    from jam.tiktok_studio import handle_speech as studio_speech

    remix_msg = remix_speech(brain, heard)
    if remix_msg:
        return remix_msg

    growth_msg = growth_speech(brain, heard)
    if growth_msg:
        return growth_msg

    studio_msg = studio_speech(brain, heard)
    if studio_msg:
        return studio_msg

    from jam.tiktok_post import handle_speech as post_speech

    post_msg = post_speech(brain, heard)
    if post_msg:
        return post_msg

    from jam.tiktok_account import handle_connect_speech

    connect_msg = handle_connect_speech(brain, heard)
    if connect_msg:
        return connect_msg

    if not hears_tiktok_friends(heard_l):
        if heard_l.strip() in ("tiktok", "tiktok öffnen", "tiktok oeffnen"):
            return present_on_tiktok(brain, user_asked=True)
        return None

    custom = parse_custom_query(heard)
    return present_on_tiktok(brain, query=custom, user_asked=True)


def list_friend_searches() -> str:
    return ", ".join(p["title"] for p in FRIEND_SEARCH_PICKS)
