"""Apex im Vordergrund, Internet-Seite im Hintergrund (ohne Fokus zu klauen)."""

from __future__ import annotations

import ctypes
import os
import re
import subprocess
import time
from pathlib import Path
from urllib.parse import quote_plus

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

user32 = ctypes.windll.user32

SW_RESTORE = 9
SW_SHOWMINNOACTIVE = 7
_CREATE_NO_WINDOW = getattr(subprocess, "CREATE_NO_WINDOW", 0)

APEX_TITLE_HINTS = ("apex legends", "apex")
BROWSER_TITLE = re.compile(
    r"(chrome|edge|firefox|mozilla|msedge|browser|google|wikipedia|duckduckgo|bing)",
    re.I,
)

DEFAULT_URLS = (
    "https://www.google.com/search?q=apex+legends+tipps+deutsch",
    "https://apexlegendsstatus.com/",
    "https://www.ea.com/games/apex-legends",
)

KEEP_FOCUS_GAP_SEC = 5.0


def hears_apex_foreground_bg(text: str) -> bool:
    h = text.lower().replace("jam", " ")
    if "apex" not in h:
        return False
    fg = any(w in h for w in ("vordergrund", "foreground", "fokus", "vorne"))
    bg = any(
        w in h
        for w in ("hintergrund", "internet", "seite", "browser", "web", "hinten")
    )
    if fg and bg:
        return True
    if "apex im vordergrund" in h or "internet im hintergrund" in h:
        return True
    if "apex vordergrund" in h and "internet" in h:
        return True
    return False


def _enum_windows() -> list[tuple[int, str]]:
    out: list[tuple[int, str]] = []

    @ctypes.WINFUNCTYPE(ctypes.c_bool, ctypes.c_void_p, ctypes.c_void_p)
    def cb(hwnd, _lparam) -> bool:
        if not user32.IsWindowVisible(hwnd):
            return True
        length = user32.GetWindowTextLengthW(hwnd) + 1
        buf = ctypes.create_unicode_buffer(length)
        user32.GetWindowTextW(hwnd, buf, length)
        title = buf.value or ""
        if title.strip():
            out.append((int(hwnd), title))
        return True

    user32.EnumWindows(cb, 0)
    return out


def find_apex_hwnd() -> int | None:
    for hwnd, title in _enum_windows():
        tl = title.lower()
        if any(h in tl for h in APEX_TITLE_HINTS):
            if BROWSER_TITLE.search(tl):
                continue
            return hwnd
    return None


def is_apex_focused() -> bool:
    try:
        hwnd = user32.GetForegroundWindow()
        length = user32.GetWindowTextLengthW(hwnd) + 1
        buf = ctypes.create_unicode_buffer(length)
        user32.GetWindowTextW(hwnd, buf, length)
        tl = (buf.value or "").lower()
        return any(h in tl for h in APEX_TITLE_HINTS) and not BROWSER_TITLE.search(tl)
    except Exception:
        return False


def is_browser_foreground() -> bool:
    try:
        hwnd = user32.GetForegroundWindow()
        length = user32.GetWindowTextLengthW(hwnd) + 1
        buf = ctypes.create_unicode_buffer(length)
        user32.GetWindowTextW(hwnd, buf, length)
        return bool(BROWSER_TITLE.search(buf.value or ""))
    except Exception:
        return False


def focus_apex_window() -> bool:
    hwnd = find_apex_hwnd()
    if not hwnd:
        return False
    try:
        user32.ShowWindow(hwnd, SW_RESTORE)
        user32.SetForegroundWindow(hwnd)
        return True
    except Exception:
        return False


def _edge_path() -> Path | None:
    for p in (
        Path(os.environ.get("PROGRAMFILES", "")) / "Microsoft/Edge/Application/msedge.exe",
        Path(os.environ.get("PROGRAMFILES(X86)", ""))
        / "Microsoft/Edge/Application/msedge.exe",
        Path(os.environ.get("LOCALAPPDATA", ""))
        / "Microsoft/Edge/Application/msedge.exe",
    ):
        if p.is_file():
            return p
    return None


def open_url_background(url: str) -> bool:
    """Browser öffnen – minimiert / ohne Fokus."""
    url = url.strip()
    if not url.startswith("http"):
        url = "https://" + url
    edge = _edge_path()
    try:
        if edge:
            subprocess.Popen(
                [
                    str(edge),
                    "--new-window",
                    "--start-minimized",
                    url,
                ],
                creationflags=_CREATE_NO_WINDOW,
            )
            return True
        subprocess.Popen(
            ["cmd", "/c", "start", "/min", "", url],
            shell=False,
            creationflags=_CREATE_NO_WINDOW,
        )
        return True
    except OSError:
        try:
            os.startfile(url)
            return True
        except OSError:
            return False


def _pick_url(state: JamState, heard: str) -> str:
    h = heard.lower()
    if "wikipedia" in h or "wiki" in h:
        return "https://de.wikipedia.org/wiki/Apex_Legends"
    if "tipps" in h or "guide" in h:
        return DEFAULT_URLS[0]
    topic = "apex legends strategy"
    if "lern" in h:
        topic = "apex legends lernen deutsch"
    return f"https://www.google.com/search?q={quote_plus(topic)}"


def setup_apex_foreground_browser_background(
    brain: JamBrain,
    heard: str = "",
    *,
    url: str | None = None,
) -> str:
    """Internet im Hintergrund, Apex nach vorne."""
    from jam import game_launcher

    state = brain.state
    owner = owner_name(state)
    target = url or _pick_url(state, heard)

    open_url_background(target)
    state.last_bg_browser_url = target
    time.sleep(0.6)

    launch_msg = ""
    if not find_apex_hwnd():
        launch_msg = game_launcher.launch_game(brain, "apex") + " "
        for _ in range(24):
            time.sleep(0.5)
            if find_apex_hwnd():
                break

    focused = focus_apex_window()
    state.apex_foreground_mode = True
    state.last_apex_focus_at = time.time()
    state.remember(f"Apex Vordergrund + Web Hintergrund: {target[:60]}")
    state.last_action = "apex_focus"
    brain.add_xp(8)
    brain.save()

    if focused or is_apex_focused():
        return (
            f"{owner}, Internet läuft im Hintergrund (minimiert). "
            f"Apex ist im Vordergrund – zock los! {launch_msg}"
            f"Seite: {target[:70]}"
        )
    return (
        f"{owner}, Browser im Hintergrund geöffnet. {launch_msg}"
        "Starte Apex und klick ins Spiel – ich halte den Fokus auf Apex, sobald es läuft!"
    )


def maybe_keep_apex_foreground(brain: JamBrain) -> None:
    """Hält Apex vorne, wenn der Browser den Fokus klaut."""
    state = brain.state
    if not getattr(state, "apex_foreground_mode", False):
        return
    if time.time() - getattr(state, "last_apex_focus_at", 0.0) < KEEP_FOCUS_GAP_SEC:
        return
    if not find_apex_hwnd():
        return
    if is_browser_foreground() or not is_apex_focused():
        if focus_apex_window():
            state.last_apex_focus_at = time.time()
            brain.save()


def disable_keep_apex_foreground(brain: JamBrain) -> str:
    brain.state.apex_foreground_mode = False
    brain.save()
    return f"{owner_name(brain.state)}, ich lasse Apex-Fokus jetzt in Ruhe."


def handle_speech(brain: JamBrain, heard: str) -> str | None:
    h = heard.lower()
    if any(w in h for w in ("apex fokus aus", "fokus frei", "browser vordergrund")):
        return disable_keep_apex_foreground(brain)
    if not hears_apex_foreground_bg(heard):
        return None
    return setup_apex_foreground_browser_background(brain, heard)
